diff --git a/.gitattributes b/.gitattributes index bb5d205725..c8c7a66c9b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,20 @@ -# Git will understand that all files specified are not text, -# and it should not try to change them. -# This will prevent file formatting (such as `crlf` endings to `lf` endings) while commit. -* -text \ No newline at end of file +# 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. +# + +# Auto detect text files and perform LF normalization +* text=auto + +*.java text eol=lf \ No newline at end of file diff --git a/.github/workflows/build-and-test-3.yml b/.github/workflows/build-and-test-3.yml index 9225474848..a7a3f666f0 100644 --- a/.github/workflows/build-and-test-3.yml +++ b/.github/workflows/build-and-test-3.yml @@ -39,7 +39,25 @@ jobs: - name: "Build Dubbo with Maven" run: | cd ./dubbo - ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress clean source:jar install -Pjacoco,rat,checkstyle -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -Dmaven.test.skip=true -Dmaven.test.skip.exec=true + ./mvnw --batch-mode -U -e --no-transfer-progress clean source:jar install -Pjacoco,rat,checkstyle -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -Dmaven.test.skip=true -Dmaven.test.skip.exec=true + - name: "Pack rat file if failure" + if: failure() + run: 7z a ${{ github.workspace }}/rat.zip *rat.txt -r + - name: "Upload rat file if failure" + if: failure() + uses: actions/upload-artifact@v2 + with: + name: "rat-file" + path: ${{ github.workspace }}/rat.zip + - name: "Pack checkstyle file if failure" + if: failure() + run: 7z a ${{ github.workspace }}/checkstyle.zip *checkstyle* -r + - name: "Upload checkstyle file if failure" + if: failure() + uses: actions/upload-artifact@v2 + with: + name: "checkstyle-file" + path: ${{ github.workspace }}/checkstyle.zip - name: "Calculate Dubbo Version" id: dubbo-version run: | @@ -72,22 +90,13 @@ jobs: - name: "Test with Maven with Integration Tests" timeout-minutes: 40 if: ${{ startsWith( matrix.os, 'ubuntu') }} - run: ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress clean test verify -Pjacoco -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -DskipTests=false -DskipIntegrationTests=false -Dcheckstyle.skip=false -Drat.skip=false -Dmaven.javadoc.skip=true + run: ./mvnw --batch-mode -U -e --no-transfer-progress clean test verify -Pjacoco -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -DskipTests=false -DskipIntegrationTests=false -Dcheckstyle.skip=false -Dcheckstyle_unix.skip=false -Drat.skip=false -Dmaven.javadoc.skip=true - name: "Test with Maven without Integration Tests" env: DISABLE_FILE_SYSTEM_TEST: true timeout-minutes: 50 if: ${{ startsWith( matrix.os, 'windows') }} - run: ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress clean test verify -Pjacoco -D"http.keepAlive=false" -D"maven.wagon.http.pool=false" -D"maven.wagon.httpconnectionManager.ttlSeconds=120" -D"maven.wagon.http.retryHandler.count=5" -DskipTests=false -DskipIntegrationTests=true -D"checkstyle.skip=false" -D"rat.skip=false" -D"maven.javadoc.skip=true" - - name: "Pack rat file if failure" - if: failure() - run: 7z a ${{ github.workspace }}/rat.zip *rat.txt -r - - name: "Upload rat file if failure" - if: failure() - uses: actions/upload-artifact@v2 - with: - name: "rat-file-${{ matrix.os }}-JDK${{ matrix.jdk }}" - path: ${{ github.workspace }}/rat.zip + run: ./mvnw --batch-mode -U -e --no-transfer-progress clean test verify -Pjacoco -D"http.keepAlive=false" -D"maven.wagon.http.pool=false" -D"maven.wagon.httpconnectionManager.ttlSeconds=120" -D"maven.wagon.http.retryHandler.count=5" -DskipTests=false -DskipIntegrationTests=true -D"checkstyle.skip=false" -D"checkstyle_unix.skip=true" -D"rat.skip=false" -D"maven.javadoc.skip=true" - name: "Upload coverage to Codecov" uses: codecov/codecov-action@v1 diff --git a/LICENSE b/LICENSE index 89ce3a5434..4702175190 100644 --- a/LICENSE +++ b/LICENSE @@ -279,4 +279,4 @@ https://developers.google.com/protocol-buffers/ and is licensed under the follow Code generated by the Protocol Buffer compiler is owned by the owner of the input file used when generating it. This code is not standalone and requires a support library to be linked with it. This - support library is itself covered by the above license. \ No newline at end of file + support library is itself covered by the above license. diff --git a/NOTICE b/NOTICE index 9e952c6dff..7ea7a3ba1c 100644 --- a/NOTICE +++ b/NOTICE @@ -1,14 +1,14 @@ -Apache Dubbo -Copyright 2018-2021 The Apache Software Foundation - -This product includes software developed at -The Apache Software Foundation (http://www.apache.org/). - -This product contains code form the Netty Project: - -The Netty Project -================= -Please visit the Netty web site for more information: - * http://netty.io/ - -Copyright 2014 The Netty Project +Apache Dubbo +Copyright 2018-2021 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + +This product contains code form the Netty Project: + +The Netty Project +================= +Please visit the Netty web site for more information: + * http://netty.io/ + +Copyright 2014 The Netty Project diff --git a/codestyle/checkstyle-suppressions.xml b/codestyle/checkstyle-suppressions.xml index 1817cf762c..0b2fa10a02 100644 --- a/codestyle/checkstyle-suppressions.xml +++ b/codestyle/checkstyle-suppressions.xml @@ -4,5 +4,6 @@ "http://www.puppycrawl.com/dtds/suppressions_1_1.dtd"> + \ No newline at end of file diff --git a/codestyle/checkstyle.xml b/codestyle/checkstyle.xml index 050fbede37..413cc720f6 100644 --- a/codestyle/checkstyle.xml +++ b/codestyle/checkstyle.xml @@ -12,6 +12,10 @@ + + + + diff --git a/codestyle/checkstyle_unix.xml b/codestyle/checkstyle_unix.xml new file mode 100644 index 0000000000..589c7d7af6 --- /dev/null +++ b/codestyle/checkstyle_unix.xml @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/compiler/src/main/java/org/apache/dubbo/gen/dubbo/DubboGenerator.java b/compiler/src/main/java/org/apache/dubbo/gen/dubbo/DubboGenerator.java index 1c35f0a3ef..1abf2a0064 100644 --- a/compiler/src/main/java/org/apache/dubbo/gen/dubbo/DubboGenerator.java +++ b/compiler/src/main/java/org/apache/dubbo/gen/dubbo/DubboGenerator.java @@ -39,4 +39,4 @@ public class DubboGenerator extends AbstractGenerator { protected String getClassSuffix() { return "Dubbo"; } -} \ No newline at end of file +} diff --git a/dubbo-build-tools/pom.xml b/dubbo-build-tools/pom.xml index 966218d4da..a1a0c60df1 100644 --- a/dubbo-build-tools/pom.xml +++ b/dubbo-build-tools/pom.xml @@ -64,6 +64,7 @@ **/.classpath **/.project **/target/** + **/generated/** **/*.log CONTRIBUTING.md README.md diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/registry/AddressListener.java b/dubbo-cluster/src/main/java/org/apache/dubbo/registry/AddressListener.java index 684cb64732..bd1947a4e9 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/registry/AddressListener.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/registry/AddressListener.java @@ -38,4 +38,4 @@ public interface AddressListener { } -} \ No newline at end of file +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Cluster.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Cluster.java index 1fdadf8b21..04cc57339f 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Cluster.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Cluster.java @@ -1,59 +1,59 @@ -/* - * 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.rpc.cluster; - -import org.apache.dubbo.common.extension.Adaptive; -import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.common.extension.SPI; -import org.apache.dubbo.common.utils.StringUtils; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.RpcException; - -/** - * Cluster. (SPI, Singleton, ThreadSafe) - *

- * Cluster - * Fault-Tolerant - * - */ -@SPI(Cluster.DEFAULT) -public interface Cluster { - - String DEFAULT = "failover"; - - /** - * Merge the directory invokers to a virtual invoker. - * - * @param - * @param directory - * @return cluster invoker - * @throws RpcException - */ - @Adaptive - Invoker join(Directory directory) throws RpcException; - - static Cluster getCluster(String name) { - return getCluster(name, true); - } - - static Cluster getCluster(String name, boolean wrap) { - if (StringUtils.isEmpty(name)) { - name = Cluster.DEFAULT; - } - return ExtensionLoader.getExtensionLoader(Cluster.class).getExtension(name, wrap); - } -} +/* + * 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.rpc.cluster; + +import org.apache.dubbo.common.extension.Adaptive; +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.common.extension.SPI; +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.RpcException; + +/** + * Cluster. (SPI, Singleton, ThreadSafe) + *

+ * Cluster + * Fault-Tolerant + * + */ +@SPI(Cluster.DEFAULT) +public interface Cluster { + + String DEFAULT = "failover"; + + /** + * Merge the directory invokers to a virtual invoker. + * + * @param + * @param directory + * @return cluster invoker + * @throws RpcException + */ + @Adaptive + Invoker join(Directory directory) throws RpcException; + + static Cluster getCluster(String name) { + return getCluster(name, true); + } + + static Cluster getCluster(String name, boolean wrap) { + if (StringUtils.isEmpty(name)) { + name = Cluster.DEFAULT; + } + return ExtensionLoader.getExtensionLoader(Cluster.class).getExtension(name, wrap); + } +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Configurator.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Configurator.java index 2a69f6efb5..3b1d25e5c3 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Configurator.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Configurator.java @@ -1,119 +1,119 @@ -/* - * 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.rpc.cluster; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.common.utils.CollectionUtils; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; - -import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_KEY; -import static org.apache.dubbo.common.constants.RegistryConstants.EMPTY_PROTOCOL; -import static org.apache.dubbo.rpc.cluster.Constants.PRIORITY_KEY; - -/** - * Configurator. (SPI, Prototype, ThreadSafe) - * - */ -public interface Configurator extends Comparable { - - /** - * Get the configurator url. - * - * @return configurator url. - */ - URL getUrl(); - - /** - * Configure the provider url. - * - * @param url - old provider url. - * @return new provider url. - */ - URL configure(URL url); - - - /** - * Convert override urls to map for use when re-refer. Send all rules every time, the urls will be reassembled and - * calculated - * - * URL contract: - *

    - *
  1. override://0.0.0.0/...( or override://ip:port...?anyhost=true)¶1=value1... means global rules - * (all of the providers take effect)
  2. - *
  3. override://ip:port...?anyhost=false Special rules (only for a certain provider)
  4. - *
  5. override:// rule is not supported... ,needs to be calculated by registry itself
  6. - *
  7. override://0.0.0.0/ without parameters means clearing the override
  8. - *
- * - * @param urls URL list to convert - * @return converted configurator list - */ - static Optional> toConfigurators(List urls) { - if (CollectionUtils.isEmpty(urls)) { - return Optional.empty(); - } - - ConfiguratorFactory configuratorFactory = ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class) - .getAdaptiveExtension(); - - List configurators = new ArrayList<>(urls.size()); - for (URL url : urls) { - if (EMPTY_PROTOCOL.equals(url.getProtocol())) { - configurators.clear(); - break; - } - Map override = new HashMap<>(url.getParameters()); - //The anyhost parameter of override may be added automatically, it can't change the judgement of changing url - override.remove(ANYHOST_KEY); - if (CollectionUtils.isEmptyMap(override)) { - continue; - } - configurators.add(configuratorFactory.getConfigurator(url)); - } - Collections.sort(configurators); - return Optional.of(configurators); - } - - /** - * Sort by host, then by priority - * 1. the url with a specific host ip should have higher priority than 0.0.0.0 - * 2. if two url has the same host, compare by priority value; - */ - @Override - default int compareTo(Configurator o) { - if (o == null) { - return -1; - } - - int ipCompare = getUrl().getHost().compareTo(o.getUrl().getHost()); - // host is the same, sort by priority - if (ipCompare == 0) { - int i = getUrl().getParameter(PRIORITY_KEY, 0); - int j = o.getUrl().getParameter(PRIORITY_KEY, 0); - return Integer.compare(i, j); - } else { - return ipCompare; - } - } -} +/* + * 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.rpc.cluster; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.common.utils.CollectionUtils; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_KEY; +import static org.apache.dubbo.common.constants.RegistryConstants.EMPTY_PROTOCOL; +import static org.apache.dubbo.rpc.cluster.Constants.PRIORITY_KEY; + +/** + * Configurator. (SPI, Prototype, ThreadSafe) + * + */ +public interface Configurator extends Comparable { + + /** + * Get the configurator url. + * + * @return configurator url. + */ + URL getUrl(); + + /** + * Configure the provider url. + * + * @param url - old provider url. + * @return new provider url. + */ + URL configure(URL url); + + + /** + * Convert override urls to map for use when re-refer. Send all rules every time, the urls will be reassembled and + * calculated + * + * URL contract: + *
    + *
  1. override://0.0.0.0/...( or override://ip:port...?anyhost=true)¶1=value1... means global rules + * (all of the providers take effect)
  2. + *
  3. override://ip:port...?anyhost=false Special rules (only for a certain provider)
  4. + *
  5. override:// rule is not supported... ,needs to be calculated by registry itself
  6. + *
  7. override://0.0.0.0/ without parameters means clearing the override
  8. + *
+ * + * @param urls URL list to convert + * @return converted configurator list + */ + static Optional> toConfigurators(List urls) { + if (CollectionUtils.isEmpty(urls)) { + return Optional.empty(); + } + + ConfiguratorFactory configuratorFactory = ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class) + .getAdaptiveExtension(); + + List configurators = new ArrayList<>(urls.size()); + for (URL url : urls) { + if (EMPTY_PROTOCOL.equals(url.getProtocol())) { + configurators.clear(); + break; + } + Map override = new HashMap<>(url.getParameters()); + //The anyhost parameter of override may be added automatically, it can't change the judgement of changing url + override.remove(ANYHOST_KEY); + if (CollectionUtils.isEmptyMap(override)) { + continue; + } + configurators.add(configuratorFactory.getConfigurator(url)); + } + Collections.sort(configurators); + return Optional.of(configurators); + } + + /** + * Sort by host, then by priority + * 1. the url with a specific host ip should have higher priority than 0.0.0.0 + * 2. if two url has the same host, compare by priority value; + */ + @Override + default int compareTo(Configurator o) { + if (o == null) { + return -1; + } + + int ipCompare = getUrl().getHost().compareTo(o.getUrl().getHost()); + // host is the same, sort by priority + if (ipCompare == 0) { + int i = getUrl().getParameter(PRIORITY_KEY, 0); + int j = o.getUrl().getParameter(PRIORITY_KEY, 0); + return Integer.compare(i, j); + } else { + return ipCompare; + } + } +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/ConfiguratorFactory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/ConfiguratorFactory.java index 026d6f54ed..8b2722c29f 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/ConfiguratorFactory.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/ConfiguratorFactory.java @@ -1,39 +1,39 @@ -/* - * 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.rpc.cluster; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.extension.Adaptive; -import org.apache.dubbo.common.extension.SPI; - -/** - * ConfiguratorFactory. (SPI, Singleton, ThreadSafe) - * - */ -@SPI -public interface ConfiguratorFactory { - - /** - * get the configurator instance. - * - * @param url - configurator url. - * @return configurator instance. - */ - @Adaptive("protocol") - Configurator getConfigurator(URL url); - -} +/* + * 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.rpc.cluster; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.Adaptive; +import org.apache.dubbo.common.extension.SPI; + +/** + * ConfiguratorFactory. (SPI, Singleton, ThreadSafe) + * + */ +@SPI +public interface ConfiguratorFactory { + + /** + * get the configurator instance. + * + * @param url - configurator url. + * @return configurator instance. + */ + @Adaptive("protocol") + Configurator getConfigurator(URL url); + +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Directory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Directory.java index 5a92d97814..c797218029 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Directory.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Directory.java @@ -1,72 +1,72 @@ -/* - * 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.rpc.cluster; - -import org.apache.dubbo.common.Node; -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.utils.CollectionUtils; -import org.apache.dubbo.rpc.Invocation; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.RpcException; - -import java.util.List; - -/** - * Directory. (SPI, Prototype, ThreadSafe) - *

- * Directory Service - * - * @see org.apache.dubbo.rpc.cluster.Cluster#join(Directory) - */ -public interface Directory extends Node { - - /** - * get service type. - * - * @return service type. - */ - Class getInterface(); - - /** - * list invokers. - * - * @return invokers - */ - List> list(Invocation invocation) throws RpcException; - - List> getAllInvokers(); - - URL getConsumerUrl(); - - boolean isDestroyed(); - - default boolean isEmpty() { - return CollectionUtils.isEmpty(getAllInvokers()); - } - - default boolean isServiceDiscovery() { - return false; - } - - void discordAddresses(); - - RouterChain getRouterChain(); - - default boolean isNotificationReceived() { - return false; - } -} \ No newline at end of file +/* + * 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.rpc.cluster; + +import org.apache.dubbo.common.Node; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.RpcException; + +import java.util.List; + +/** + * Directory. (SPI, Prototype, ThreadSafe) + *

+ * Directory Service + * + * @see org.apache.dubbo.rpc.cluster.Cluster#join(Directory) + */ +public interface Directory extends Node { + + /** + * get service type. + * + * @return service type. + */ + Class getInterface(); + + /** + * list invokers. + * + * @return invokers + */ + List> list(Invocation invocation) throws RpcException; + + List> getAllInvokers(); + + URL getConsumerUrl(); + + boolean isDestroyed(); + + default boolean isEmpty() { + return CollectionUtils.isEmpty(getAllInvokers()); + } + + default boolean isServiceDiscovery() { + return false; + } + + void discordAddresses(); + + RouterChain getRouterChain(); + + default boolean isNotificationReceived() { + return false; + } +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/LoadBalance.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/LoadBalance.java index 4e6ced18a0..94b28a8bc3 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/LoadBalance.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/LoadBalance.java @@ -1,50 +1,50 @@ -/* - * 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.rpc.cluster; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.extension.Adaptive; -import org.apache.dubbo.common.extension.SPI; -import org.apache.dubbo.rpc.Invocation; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.RpcException; -import org.apache.dubbo.rpc.cluster.loadbalance.RandomLoadBalance; - -import java.util.List; - -/** - * LoadBalance. (SPI, Singleton, ThreadSafe) - *

- * Load-Balancing - * - * @see org.apache.dubbo.rpc.cluster.Cluster#join(Directory) - */ -@SPI(RandomLoadBalance.NAME) -public interface LoadBalance { - - /** - * select one invoker in list. - * - * @param invokers invokers. - * @param url refer url - * @param invocation invocation. - * @return selected invoker. - */ - @Adaptive("loadbalance") - Invoker select(List> invokers, URL url, Invocation invocation) throws RpcException; - -} \ No newline at end of file +/* + * 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.rpc.cluster; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.Adaptive; +import org.apache.dubbo.common.extension.SPI; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.cluster.loadbalance.RandomLoadBalance; + +import java.util.List; + +/** + * LoadBalance. (SPI, Singleton, ThreadSafe) + *

+ * Load-Balancing + * + * @see org.apache.dubbo.rpc.cluster.Cluster#join(Directory) + */ +@SPI(RandomLoadBalance.NAME) +public interface LoadBalance { + + /** + * select one invoker in list. + * + * @param invokers invokers. + * @param url refer url + * @param invocation invocation. + * @return selected invoker. + */ + @Adaptive("loadbalance") + Invoker select(List> invokers, URL url, Invocation invocation) throws RpcException; + +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Router.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Router.java index c412ff8f23..287701291e 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Router.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Router.java @@ -1,103 +1,103 @@ -/* - * 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.rpc.cluster; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.rpc.Invocation; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.RpcException; - -import java.util.List; - -/** - * Router. (SPI, Prototype, ThreadSafe) - *

- * Routing - * - * @see org.apache.dubbo.rpc.cluster.Cluster#join(Directory) - * @see org.apache.dubbo.rpc.cluster.Directory#list(Invocation) - */ -public interface Router extends Comparable { - - int DEFAULT_PRIORITY = Integer.MAX_VALUE; - - /** - * Get the router url. - * - * @return url - */ - URL getUrl(); - - /** - * Filter invokers with current routing rule and only return the invokers that comply with the rule. - * - * @param invokers invoker list - * @param url refer url - * @param invocation invocation - * @return routed invokers - * @throws RpcException - */ - List> route(List> invokers, URL url, Invocation invocation) throws RpcException; - - - /** - * Notify the router the invoker list. Invoker list may change from time to time. This method gives the router a - * chance to prepare before {@link Router#route(List, URL, Invocation)} gets called. - * - * @param invokers invoker list - * @param invoker's type - */ - default void notify(List> invokers) { - - } - - /** - * To decide whether this router need to execute every time an RPC comes or should only execute when addresses or - * rule change. - * - * @return true if the router need to execute every time. - */ - boolean isRuntime(); - - /** - * To decide whether this router should take effect when none of the invoker can match the router rule, which - * means the {@link #route(List, URL, Invocation)} would be empty. Most of time, most router implementation would - * default this value to false. - * - * @return true to execute if none of invokers matches the current router - */ - boolean isForce(); - - /** - * Router's priority, used to sort routers. - * - * @return router's priority - */ - int getPriority(); - - default void stop() { - //do nothing by default - } - - @Override - default int compareTo(Router o) { - if (o == null) { - throw new IllegalArgumentException(); - } - return Integer.compare(this.getPriority(), o.getPriority()); - } -} +/* + * 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.rpc.cluster; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.RpcException; + +import java.util.List; + +/** + * Router. (SPI, Prototype, ThreadSafe) + *

+ * Routing + * + * @see org.apache.dubbo.rpc.cluster.Cluster#join(Directory) + * @see org.apache.dubbo.rpc.cluster.Directory#list(Invocation) + */ +public interface Router extends Comparable { + + int DEFAULT_PRIORITY = Integer.MAX_VALUE; + + /** + * Get the router url. + * + * @return url + */ + URL getUrl(); + + /** + * Filter invokers with current routing rule and only return the invokers that comply with the rule. + * + * @param invokers invoker list + * @param url refer url + * @param invocation invocation + * @return routed invokers + * @throws RpcException + */ + List> route(List> invokers, URL url, Invocation invocation) throws RpcException; + + + /** + * Notify the router the invoker list. Invoker list may change from time to time. This method gives the router a + * chance to prepare before {@link Router#route(List, URL, Invocation)} gets called. + * + * @param invokers invoker list + * @param invoker's type + */ + default void notify(List> invokers) { + + } + + /** + * To decide whether this router need to execute every time an RPC comes or should only execute when addresses or + * rule change. + * + * @return true if the router need to execute every time. + */ + boolean isRuntime(); + + /** + * To decide whether this router should take effect when none of the invoker can match the router rule, which + * means the {@link #route(List, URL, Invocation)} would be empty. Most of time, most router implementation would + * default this value to false. + * + * @return true to execute if none of invokers matches the current router + */ + boolean isForce(); + + /** + * Router's priority, used to sort routers. + * + * @return router's priority + */ + int getPriority(); + + default void stop() { + //do nothing by default + } + + @Override + default int compareTo(Router o) { + if (o == null) { + throw new IllegalArgumentException(); + } + return Integer.compare(this.getPriority(), o.getPriority()); + } +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterFactory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterFactory.java index b7644b3459..3a98a587a3 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterFactory.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterFactory.java @@ -1,47 +1,47 @@ -/* - * 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.rpc.cluster; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.extension.Adaptive; -import org.apache.dubbo.common.extension.SPI; - -/** - * RouterFactory. (SPI, Singleton, ThreadSafe) - *

- * Routing - * - * @see org.apache.dubbo.rpc.cluster.Cluster#join(Directory) - * @see org.apache.dubbo.rpc.cluster.Directory#list(org.apache.dubbo.rpc.Invocation) - *

- * Note Router has a different behaviour since 2.7.0, for each type of Router, there will only has one Router instance - * for each service. See {@link CacheableRouterFactory} and {@link RouterChain} for how to extend a new Router or how - * the Router instances are loaded. - */ -@SPI -public interface RouterFactory { - - /** - * Create router. - * Since 2.7.0, most of the time, we will not use @Adaptive feature, so it's kept only for compatibility. - * - * @param url url - * @return router instance - */ - @Adaptive("protocol") - Router getRouter(URL url); -} +/* + * 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.rpc.cluster; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.Adaptive; +import org.apache.dubbo.common.extension.SPI; + +/** + * RouterFactory. (SPI, Singleton, ThreadSafe) + *

+ * Routing + * + * @see org.apache.dubbo.rpc.cluster.Cluster#join(Directory) + * @see org.apache.dubbo.rpc.cluster.Directory#list(org.apache.dubbo.rpc.Invocation) + *

+ * Note Router has a different behaviour since 2.7.0, for each type of Router, there will only has one Router instance + * for each service. See {@link CacheableRouterFactory} and {@link RouterChain} for how to extend a new Router or how + * the Router instances are loaded. + */ +@SPI +public interface RouterFactory { + + /** + * Create router. + * Since 2.7.0, most of the time, we will not use @Adaptive feature, so it's kept only for compatibility. + * + * @param url url + * @return router instance + */ + @Adaptive("protocol") + Router getRouter(URL url); +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/AbstractConfigurator.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/AbstractConfigurator.java index 751d284142..a61288983f 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/AbstractConfigurator.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/AbstractConfigurator.java @@ -1,170 +1,170 @@ -/* - * 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.rpc.cluster.configurator; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.utils.NetUtils; -import org.apache.dubbo.common.utils.StringUtils; -import org.apache.dubbo.remoting.Constants; -import org.apache.dubbo.rpc.cluster.Configurator; - -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_VALUE; -import static org.apache.dubbo.common.constants.CommonConstants.ANY_VALUE; -import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER; -import static org.apache.dubbo.common.constants.CommonConstants.ENABLED_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.INTERFACES; -import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER; -import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY; -import static org.apache.dubbo.common.constants.RegistryConstants.CATEGORY_KEY; -import static org.apache.dubbo.common.constants.RegistryConstants.COMPATIBLE_CONFIG_KEY; -import static org.apache.dubbo.common.constants.RegistryConstants.DYNAMIC_KEY; -import static org.apache.dubbo.rpc.cluster.Constants.CONFIG_VERSION_KEY; -import static org.apache.dubbo.rpc.cluster.Constants.OVERRIDE_PROVIDERS_KEY; - -/** - * AbstractOverrideConfigurator - */ -public abstract class AbstractConfigurator implements Configurator { - - private static final String TILDE = "~"; - - private final URL configuratorUrl; - - public AbstractConfigurator(URL url) { - if (url == null) { - throw new IllegalArgumentException("configurator url == null"); - } - this.configuratorUrl = url; - } - - @Override - public URL getUrl() { - return configuratorUrl; - } - - @Override - public URL configure(URL url) { - // If override url is not enabled or is invalid, just return. - if (!configuratorUrl.getParameter(ENABLED_KEY, true) || configuratorUrl.getHost() == null || url == null || url.getHost() == null) { - return url; - } - /* - * This if branch is created since 2.7.0. - */ - String apiVersion = configuratorUrl.getParameter(CONFIG_VERSION_KEY); - if (StringUtils.isNotEmpty(apiVersion)) { - String currentSide = url.getSide(); - String configuratorSide = configuratorUrl.getSide(); - if (currentSide.equals(configuratorSide) && CONSUMER.equals(configuratorSide) && 0 == configuratorUrl.getPort()) { - url = configureIfMatch(NetUtils.getLocalHost(), url); - } else if (currentSide.equals(configuratorSide) && PROVIDER.equals(configuratorSide) && - url.getPort() == configuratorUrl.getPort()) { - url = configureIfMatch(url.getHost(), url); - } - } - /* - * This else branch is deprecated and is left only to keep compatibility with versions before 2.7.0 - */ - else { - url = configureDeprecated(url); - } - return url; - } - - @Deprecated - private URL configureDeprecated(URL url) { - // If override url has port, means it is a provider address. We want to control a specific provider with this override url, it may take effect on the specific provider instance or on consumers holding this provider instance. - if (configuratorUrl.getPort() != 0) { - if (url.getPort() == configuratorUrl.getPort()) { - return configureIfMatch(url.getHost(), url); - } - } else { - /* - * override url don't have a port, means the ip override url specify is a consumer address or 0.0.0.0. - * 1.If it is a consumer ip address, the intention is to control a specific consumer instance, it must takes effect at the consumer side, any provider received this override url should ignore. - * 2.If the ip is 0.0.0.0, this override url can be used on consumer, and also can be used on provider. - */ - if (url.getSide(PROVIDER).equals(CONSUMER)) { - // NetUtils.getLocalHost is the ip address consumer registered to registry. - return configureIfMatch(NetUtils.getLocalHost(), url); - } else if (url.getSide(CONSUMER).equals(PROVIDER)) { - // take effect on all providers, so address must be 0.0.0.0, otherwise it won't flow to this if branch - return configureIfMatch(ANYHOST_VALUE, url); - } - } - return url; - } - - private URL configureIfMatch(String host, URL url) { - if (ANYHOST_VALUE.equals(configuratorUrl.getHost()) || host.equals(configuratorUrl.getHost())) { - // TODO, to support wildcards - String providers = configuratorUrl.getParameter(OVERRIDE_PROVIDERS_KEY); - if (StringUtils.isEmpty(providers) || providers.contains(url.getAddress()) || providers.contains(ANYHOST_VALUE)) { - String configApplication = configuratorUrl.getApplication(configuratorUrl.getUsername()); - String currentApplication = url.getApplication(url.getUsername()); - if (configApplication == null || ANY_VALUE.equals(configApplication) - || configApplication.equals(currentApplication)) { - Set conditionKeys = new HashSet(); - conditionKeys.add(CATEGORY_KEY); - conditionKeys.add(Constants.CHECK_KEY); - conditionKeys.add(DYNAMIC_KEY); - conditionKeys.add(ENABLED_KEY); - conditionKeys.add(GROUP_KEY); - conditionKeys.add(VERSION_KEY); - conditionKeys.add(APPLICATION_KEY); - conditionKeys.add(SIDE_KEY); - conditionKeys.add(CONFIG_VERSION_KEY); - conditionKeys.add(COMPATIBLE_CONFIG_KEY); - conditionKeys.add(INTERFACES); - for (Map.Entry entry : configuratorUrl.getParameters().entrySet()) { - String key = entry.getKey(); - String value = entry.getValue(); - boolean startWithTilde = startWithTilde(key); - if (startWithTilde || APPLICATION_KEY.equals(key) || SIDE_KEY.equals(key)) { - if (startWithTilde) { - conditionKeys.add(key); - } - if (value != null && !ANY_VALUE.equals(value) - && !value.equals(url.getParameter(startWithTilde ? key.substring(1) : key))) { - return url; - } - } - } - return doConfigure(url, configuratorUrl.removeParameters(conditionKeys)); - } - } - } - return url; - } - - private boolean startWithTilde(String key) { - if (StringUtils.isNotEmpty(key) && key.startsWith(TILDE)) { - return true; - } - return false; - } - - protected abstract URL doConfigure(URL currentUrl, URL configUrl); - -} +/* + * 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.rpc.cluster.configurator; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.utils.NetUtils; +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.remoting.Constants; +import org.apache.dubbo.rpc.cluster.Configurator; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_VALUE; +import static org.apache.dubbo.common.constants.CommonConstants.ANY_VALUE; +import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER; +import static org.apache.dubbo.common.constants.CommonConstants.ENABLED_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.INTERFACES; +import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER; +import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY; +import static org.apache.dubbo.common.constants.RegistryConstants.CATEGORY_KEY; +import static org.apache.dubbo.common.constants.RegistryConstants.COMPATIBLE_CONFIG_KEY; +import static org.apache.dubbo.common.constants.RegistryConstants.DYNAMIC_KEY; +import static org.apache.dubbo.rpc.cluster.Constants.CONFIG_VERSION_KEY; +import static org.apache.dubbo.rpc.cluster.Constants.OVERRIDE_PROVIDERS_KEY; + +/** + * AbstractOverrideConfigurator + */ +public abstract class AbstractConfigurator implements Configurator { + + private static final String TILDE = "~"; + + private final URL configuratorUrl; + + public AbstractConfigurator(URL url) { + if (url == null) { + throw new IllegalArgumentException("configurator url == null"); + } + this.configuratorUrl = url; + } + + @Override + public URL getUrl() { + return configuratorUrl; + } + + @Override + public URL configure(URL url) { + // If override url is not enabled or is invalid, just return. + if (!configuratorUrl.getParameter(ENABLED_KEY, true) || configuratorUrl.getHost() == null || url == null || url.getHost() == null) { + return url; + } + /* + * This if branch is created since 2.7.0. + */ + String apiVersion = configuratorUrl.getParameter(CONFIG_VERSION_KEY); + if (StringUtils.isNotEmpty(apiVersion)) { + String currentSide = url.getSide(); + String configuratorSide = configuratorUrl.getSide(); + if (currentSide.equals(configuratorSide) && CONSUMER.equals(configuratorSide) && 0 == configuratorUrl.getPort()) { + url = configureIfMatch(NetUtils.getLocalHost(), url); + } else if (currentSide.equals(configuratorSide) && PROVIDER.equals(configuratorSide) && + url.getPort() == configuratorUrl.getPort()) { + url = configureIfMatch(url.getHost(), url); + } + } + /* + * This else branch is deprecated and is left only to keep compatibility with versions before 2.7.0 + */ + else { + url = configureDeprecated(url); + } + return url; + } + + @Deprecated + private URL configureDeprecated(URL url) { + // If override url has port, means it is a provider address. We want to control a specific provider with this override url, it may take effect on the specific provider instance or on consumers holding this provider instance. + if (configuratorUrl.getPort() != 0) { + if (url.getPort() == configuratorUrl.getPort()) { + return configureIfMatch(url.getHost(), url); + } + } else { + /* + * override url don't have a port, means the ip override url specify is a consumer address or 0.0.0.0. + * 1.If it is a consumer ip address, the intention is to control a specific consumer instance, it must takes effect at the consumer side, any provider received this override url should ignore. + * 2.If the ip is 0.0.0.0, this override url can be used on consumer, and also can be used on provider. + */ + if (url.getSide(PROVIDER).equals(CONSUMER)) { + // NetUtils.getLocalHost is the ip address consumer registered to registry. + return configureIfMatch(NetUtils.getLocalHost(), url); + } else if (url.getSide(CONSUMER).equals(PROVIDER)) { + // take effect on all providers, so address must be 0.0.0.0, otherwise it won't flow to this if branch + return configureIfMatch(ANYHOST_VALUE, url); + } + } + return url; + } + + private URL configureIfMatch(String host, URL url) { + if (ANYHOST_VALUE.equals(configuratorUrl.getHost()) || host.equals(configuratorUrl.getHost())) { + // TODO, to support wildcards + String providers = configuratorUrl.getParameter(OVERRIDE_PROVIDERS_KEY); + if (StringUtils.isEmpty(providers) || providers.contains(url.getAddress()) || providers.contains(ANYHOST_VALUE)) { + String configApplication = configuratorUrl.getApplication(configuratorUrl.getUsername()); + String currentApplication = url.getApplication(url.getUsername()); + if (configApplication == null || ANY_VALUE.equals(configApplication) + || configApplication.equals(currentApplication)) { + Set conditionKeys = new HashSet(); + conditionKeys.add(CATEGORY_KEY); + conditionKeys.add(Constants.CHECK_KEY); + conditionKeys.add(DYNAMIC_KEY); + conditionKeys.add(ENABLED_KEY); + conditionKeys.add(GROUP_KEY); + conditionKeys.add(VERSION_KEY); + conditionKeys.add(APPLICATION_KEY); + conditionKeys.add(SIDE_KEY); + conditionKeys.add(CONFIG_VERSION_KEY); + conditionKeys.add(COMPATIBLE_CONFIG_KEY); + conditionKeys.add(INTERFACES); + for (Map.Entry entry : configuratorUrl.getParameters().entrySet()) { + String key = entry.getKey(); + String value = entry.getValue(); + boolean startWithTilde = startWithTilde(key); + if (startWithTilde || APPLICATION_KEY.equals(key) || SIDE_KEY.equals(key)) { + if (startWithTilde) { + conditionKeys.add(key); + } + if (value != null && !ANY_VALUE.equals(value) + && !value.equals(url.getParameter(startWithTilde ? key.substring(1) : key))) { + return url; + } + } + } + return doConfigure(url, configuratorUrl.removeParameters(conditionKeys)); + } + } + } + return url; + } + + private boolean startWithTilde(String key) { + if (StringUtils.isNotEmpty(key) && key.startsWith(TILDE)) { + return true; + } + return false; + } + + protected abstract URL doConfigure(URL currentUrl, URL configUrl); + +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/absent/AbsentConfigurator.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/absent/AbsentConfigurator.java index c81d9b8f1d..cb83b8b854 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/absent/AbsentConfigurator.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/absent/AbsentConfigurator.java @@ -1,37 +1,37 @@ -/* - * 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.rpc.cluster.configurator.absent; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.rpc.cluster.configurator.AbstractConfigurator; - -/** - * AbsentConfigurator - * - */ -public class AbsentConfigurator extends AbstractConfigurator { - - public AbsentConfigurator(URL url) { - super(url); - } - - @Override - public URL doConfigure(URL currentUrl, URL configUrl) { - return currentUrl.addParametersIfAbsent(configUrl.getParameters()); - } - -} +/* + * 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.rpc.cluster.configurator.absent; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.rpc.cluster.configurator.AbstractConfigurator; + +/** + * AbsentConfigurator + * + */ +public class AbsentConfigurator extends AbstractConfigurator { + + public AbsentConfigurator(URL url) { + super(url); + } + + @Override + public URL doConfigure(URL currentUrl, URL configUrl) { + return currentUrl.addParametersIfAbsent(configUrl.getParameters()); + } + +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/absent/AbsentConfiguratorFactory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/absent/AbsentConfiguratorFactory.java index 86b0e708b4..479eb5082a 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/absent/AbsentConfiguratorFactory.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/absent/AbsentConfiguratorFactory.java @@ -1,34 +1,34 @@ -/* - * 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.rpc.cluster.configurator.absent; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.rpc.cluster.Configurator; -import org.apache.dubbo.rpc.cluster.ConfiguratorFactory; - -/** - * AbsentConfiguratorFactory - * - */ -public class AbsentConfiguratorFactory implements ConfiguratorFactory { - - @Override - public Configurator getConfigurator(URL url) { - return new AbsentConfigurator(url); - } - -} +/* + * 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.rpc.cluster.configurator.absent; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.rpc.cluster.Configurator; +import org.apache.dubbo.rpc.cluster.ConfiguratorFactory; + +/** + * AbsentConfiguratorFactory + * + */ +public class AbsentConfiguratorFactory implements ConfiguratorFactory { + + @Override + public Configurator getConfigurator(URL url) { + return new AbsentConfigurator(url); + } + +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/override/OverrideConfigurator.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/override/OverrideConfigurator.java index bc9beb4f8b..23f0a8d8c3 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/override/OverrideConfigurator.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/override/OverrideConfigurator.java @@ -1,37 +1,37 @@ -/* - * 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.rpc.cluster.configurator.override; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.rpc.cluster.configurator.AbstractConfigurator; - -/** - * OverrideConfigurator - * - */ -public class OverrideConfigurator extends AbstractConfigurator { - - public OverrideConfigurator(URL url) { - super(url); - } - - @Override - public URL doConfigure(URL currentUrl, URL configUrl) { - return currentUrl.addParameters(configUrl.getParameters()); - } - -} +/* + * 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.rpc.cluster.configurator.override; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.rpc.cluster.configurator.AbstractConfigurator; + +/** + * OverrideConfigurator + * + */ +public class OverrideConfigurator extends AbstractConfigurator { + + public OverrideConfigurator(URL url) { + super(url); + } + + @Override + public URL doConfigure(URL currentUrl, URL configUrl) { + return currentUrl.addParameters(configUrl.getParameters()); + } + +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/override/OverrideConfiguratorFactory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/override/OverrideConfiguratorFactory.java index a63aa55004..504ae3b5d7 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/override/OverrideConfiguratorFactory.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/override/OverrideConfiguratorFactory.java @@ -1,34 +1,34 @@ -/* - * 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.rpc.cluster.configurator.override; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.rpc.cluster.Configurator; -import org.apache.dubbo.rpc.cluster.ConfiguratorFactory; - -/** - * OverrideConfiguratorFactory - * - */ -public class OverrideConfiguratorFactory implements ConfiguratorFactory { - - @Override - public Configurator getConfigurator(URL url) { - return new OverrideConfigurator(url); - } - -} +/* + * 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.rpc.cluster.configurator.override; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.rpc.cluster.Configurator; +import org.apache.dubbo.rpc.cluster.ConfiguratorFactory; + +/** + * OverrideConfiguratorFactory + * + */ +public class OverrideConfiguratorFactory implements ConfiguratorFactory { + + @Override + public Configurator getConfigurator(URL url) { + return new OverrideConfigurator(url); + } + +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/StaticDirectory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/StaticDirectory.java index 50110aa6ab..2b1a3d70ea 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/StaticDirectory.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/StaticDirectory.java @@ -1,114 +1,114 @@ -/* - * 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.rpc.cluster.directory; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.utils.CollectionUtils; -import org.apache.dubbo.rpc.Invocation; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.RpcException; -import org.apache.dubbo.rpc.cluster.RouterChain; - -import java.util.Collections; -import java.util.List; - -/** - * StaticDirectory - */ -public class StaticDirectory extends AbstractDirectory { - private static final Logger logger = LoggerFactory.getLogger(StaticDirectory.class); - - private final List> invokers; - - public StaticDirectory(List> invokers) { - this(null, invokers, null); - } - - public StaticDirectory(List> invokers, RouterChain routerChain) { - this(null, invokers, routerChain); - } - - public StaticDirectory(URL url, List> invokers) { - this(url, invokers, null); - } - - public StaticDirectory(URL url, List> invokers, RouterChain routerChain) { - super(url == null && CollectionUtils.isNotEmpty(invokers) ? invokers.get(0).getUrl() : url, routerChain, false); - if (CollectionUtils.isEmpty(invokers)) { - throw new IllegalArgumentException("invokers == null"); - } - this.invokers = invokers; - } - - @Override - public Class getInterface() { - return invokers.get(0).getInterface(); - } - - @Override - public List> getAllInvokers() { - return invokers; - } - - @Override - public boolean isAvailable() { - if (isDestroyed()) { - return false; - } - for (Invoker invoker : invokers) { - if (invoker.isAvailable()) { - return true; - } - } - return false; - } - - @Override - public void destroy() { - if (isDestroyed()) { - return; - } - super.destroy(); - for (Invoker invoker : invokers) { - invoker.destroy(); - } - invokers.clear(); - } - - public void buildRouterChain() { - RouterChain routerChain = RouterChain.buildChain(getUrl()); - routerChain.setInvokers(invokers); - routerChain.loop(true); - this.setRouterChain(routerChain); - } - - @Override - protected List> doList(Invocation invocation) throws RpcException { - List> finalInvokers = invokers; - if (routerChain != null) { - try { - finalInvokers = routerChain.route(getConsumerUrl(), invocation); - } catch (Throwable t) { - logger.error("Failed to execute router: " + getUrl() + ", cause: " + t.getMessage(), t); - } - } - return finalInvokers == null ? Collections.emptyList() : finalInvokers; - } - -} +/* + * 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.rpc.cluster.directory; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.cluster.RouterChain; + +import java.util.Collections; +import java.util.List; + +/** + * StaticDirectory + */ +public class StaticDirectory extends AbstractDirectory { + private static final Logger logger = LoggerFactory.getLogger(StaticDirectory.class); + + private final List> invokers; + + public StaticDirectory(List> invokers) { + this(null, invokers, null); + } + + public StaticDirectory(List> invokers, RouterChain routerChain) { + this(null, invokers, routerChain); + } + + public StaticDirectory(URL url, List> invokers) { + this(url, invokers, null); + } + + public StaticDirectory(URL url, List> invokers, RouterChain routerChain) { + super(url == null && CollectionUtils.isNotEmpty(invokers) ? invokers.get(0).getUrl() : url, routerChain, false); + if (CollectionUtils.isEmpty(invokers)) { + throw new IllegalArgumentException("invokers == null"); + } + this.invokers = invokers; + } + + @Override + public Class getInterface() { + return invokers.get(0).getInterface(); + } + + @Override + public List> getAllInvokers() { + return invokers; + } + + @Override + public boolean isAvailable() { + if (isDestroyed()) { + return false; + } + for (Invoker invoker : invokers) { + if (invoker.isAvailable()) { + return true; + } + } + return false; + } + + @Override + public void destroy() { + if (isDestroyed()) { + return; + } + super.destroy(); + for (Invoker invoker : invokers) { + invoker.destroy(); + } + invokers.clear(); + } + + public void buildRouterChain() { + RouterChain routerChain = RouterChain.buildChain(getUrl()); + routerChain.setInvokers(invokers); + routerChain.loop(true); + this.setRouterChain(routerChain); + } + + @Override + protected List> doList(Invocation invocation) throws RpcException { + List> finalInvokers = invokers; + if (routerChain != null) { + try { + finalInvokers = routerChain.route(getConsumerUrl(), invocation); + } catch (Throwable t) { + logger.error("Failed to execute router: " + getUrl() + ", cause: " + t.getMessage(), t); + } + } + return finalInvokers == null ? Collections.emptyList() : finalInvokers; + } + +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/AbstractLoadBalance.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/AbstractLoadBalance.java index e2c2a6f190..31024be6f3 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/AbstractLoadBalance.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/AbstractLoadBalance.java @@ -1,99 +1,99 @@ -/* - * 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.rpc.cluster.loadbalance; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.utils.CollectionUtils; -import org.apache.dubbo.rpc.Invocation; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.cluster.LoadBalance; - -import java.util.List; - -import static org.apache.dubbo.common.constants.CommonConstants.TIMESTAMP_KEY; -import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_KEY; -import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_SERVICE_REFERENCE_PATH; -import static org.apache.dubbo.rpc.cluster.Constants.DEFAULT_WARMUP; -import static org.apache.dubbo.rpc.cluster.Constants.DEFAULT_WEIGHT; -import static org.apache.dubbo.rpc.cluster.Constants.WARMUP_KEY; -import static org.apache.dubbo.rpc.cluster.Constants.WEIGHT_KEY; - -/** - * AbstractLoadBalance - */ -public abstract class AbstractLoadBalance implements LoadBalance { - /** - * Calculate the weight according to the uptime proportion of warmup time - * the new weight will be within 1(inclusive) to weight(inclusive) - * - * @param uptime the uptime in milliseconds - * @param warmup the warmup time in milliseconds - * @param weight the weight of an invoker - * @return weight which takes warmup into account - */ - static int calculateWarmupWeight(int uptime, int warmup, int weight) { - int ww = (int) ( uptime / ((float) warmup / weight)); - return ww < 1 ? 1 : (Math.min(ww, weight)); - } - - @Override - public Invoker select(List> invokers, URL url, Invocation invocation) { - if (CollectionUtils.isEmpty(invokers)) { - return null; - } - if (invokers.size() == 1) { - return invokers.get(0); - } - return doSelect(invokers, url, invocation); - } - - protected abstract Invoker doSelect(List> invokers, URL url, Invocation invocation); - - - /** - * Get the weight of the invoker's invocation which takes warmup time into account - * if the uptime is within the warmup time, the weight will be reduce proportionally - * - * @param invoker the invoker - * @param invocation the invocation of this invoker - * @return weight - */ - int getWeight(Invoker invoker, Invocation invocation) { - int weight; - URL url = invoker.getUrl(); - // Multiple registry scenario, load balance among multiple registries. - if (REGISTRY_SERVICE_REFERENCE_PATH.equals(url.getServiceInterface())) { - weight = url.getParameter(REGISTRY_KEY + "." + WEIGHT_KEY, DEFAULT_WEIGHT); - } else { - weight = url.getMethodParameter(invocation.getMethodName(), WEIGHT_KEY, DEFAULT_WEIGHT); - if (weight > 0) { - long timestamp = invoker.getUrl().getParameter(TIMESTAMP_KEY, 0L); - if (timestamp > 0L) { - long uptime = System.currentTimeMillis() - timestamp; - if (uptime < 0) { - return 1; - } - int warmup = invoker.getUrl().getParameter(WARMUP_KEY, DEFAULT_WARMUP); - if (uptime > 0 && uptime < warmup) { - weight = calculateWarmupWeight((int)uptime, warmup, weight); - } - } - } - } - return Math.max(weight, 0); - } -} +/* + * 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.rpc.cluster.loadbalance; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.cluster.LoadBalance; + +import java.util.List; + +import static org.apache.dubbo.common.constants.CommonConstants.TIMESTAMP_KEY; +import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_KEY; +import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_SERVICE_REFERENCE_PATH; +import static org.apache.dubbo.rpc.cluster.Constants.DEFAULT_WARMUP; +import static org.apache.dubbo.rpc.cluster.Constants.DEFAULT_WEIGHT; +import static org.apache.dubbo.rpc.cluster.Constants.WARMUP_KEY; +import static org.apache.dubbo.rpc.cluster.Constants.WEIGHT_KEY; + +/** + * AbstractLoadBalance + */ +public abstract class AbstractLoadBalance implements LoadBalance { + /** + * Calculate the weight according to the uptime proportion of warmup time + * the new weight will be within 1(inclusive) to weight(inclusive) + * + * @param uptime the uptime in milliseconds + * @param warmup the warmup time in milliseconds + * @param weight the weight of an invoker + * @return weight which takes warmup into account + */ + static int calculateWarmupWeight(int uptime, int warmup, int weight) { + int ww = (int) ( uptime / ((float) warmup / weight)); + return ww < 1 ? 1 : (Math.min(ww, weight)); + } + + @Override + public Invoker select(List> invokers, URL url, Invocation invocation) { + if (CollectionUtils.isEmpty(invokers)) { + return null; + } + if (invokers.size() == 1) { + return invokers.get(0); + } + return doSelect(invokers, url, invocation); + } + + protected abstract Invoker doSelect(List> invokers, URL url, Invocation invocation); + + + /** + * Get the weight of the invoker's invocation which takes warmup time into account + * if the uptime is within the warmup time, the weight will be reduce proportionally + * + * @param invoker the invoker + * @param invocation the invocation of this invoker + * @return weight + */ + int getWeight(Invoker invoker, Invocation invocation) { + int weight; + URL url = invoker.getUrl(); + // Multiple registry scenario, load balance among multiple registries. + if (REGISTRY_SERVICE_REFERENCE_PATH.equals(url.getServiceInterface())) { + weight = url.getParameter(REGISTRY_KEY + "." + WEIGHT_KEY, DEFAULT_WEIGHT); + } else { + weight = url.getMethodParameter(invocation.getMethodName(), WEIGHT_KEY, DEFAULT_WEIGHT); + if (weight > 0) { + long timestamp = invoker.getUrl().getParameter(TIMESTAMP_KEY, 0L); + if (timestamp > 0L) { + long uptime = System.currentTimeMillis() - timestamp; + if (uptime < 0) { + return 1; + } + int warmup = invoker.getUrl().getParameter(WARMUP_KEY, DEFAULT_WARMUP); + if (uptime > 0 && uptime < warmup) { + weight = calculateWarmupWeight((int)uptime, warmup, weight); + } + } + } + } + return Math.max(weight, 0); + } +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/ConsistentHashLoadBalance.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/ConsistentHashLoadBalance.java index 4f5859de2d..15c7066e06 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/ConsistentHashLoadBalance.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/ConsistentHashLoadBalance.java @@ -1,131 +1,131 @@ -/* - * 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.rpc.cluster.loadbalance; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.io.Bytes; -import org.apache.dubbo.rpc.Invocation; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.support.RpcUtils; - -import java.util.List; -import java.util.Map; -import java.util.TreeMap; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN; - -/** - * ConsistentHashLoadBalance - */ -public class ConsistentHashLoadBalance extends AbstractLoadBalance { - public static final String NAME = "consistenthash"; - - /** - * Hash nodes name - */ - public static final String HASH_NODES = "hash.nodes"; - - /** - * Hash arguments name - */ - public static final String HASH_ARGUMENTS = "hash.arguments"; - - private final ConcurrentMap> selectors = new ConcurrentHashMap>(); - - @SuppressWarnings("unchecked") - @Override - protected Invoker doSelect(List> invokers, URL url, Invocation invocation) { - String methodName = RpcUtils.getMethodName(invocation); - String key = invokers.get(0).getUrl().getServiceKey() + "." + methodName; - // using the hashcode of list to compute the hash only pay attention to the elements in the list - int invokersHashCode = invokers.hashCode(); - ConsistentHashSelector selector = (ConsistentHashSelector) selectors.get(key); - if (selector == null || selector.identityHashCode != invokersHashCode) { - selectors.put(key, new ConsistentHashSelector(invokers, methodName, invokersHashCode)); - selector = (ConsistentHashSelector) selectors.get(key); - } - return selector.select(invocation); - } - - private static final class ConsistentHashSelector { - - private final TreeMap> virtualInvokers; - - private final int replicaNumber; - - private final int identityHashCode; - - private final int[] argumentIndex; - - ConsistentHashSelector(List> invokers, String methodName, int identityHashCode) { - this.virtualInvokers = new TreeMap>(); - this.identityHashCode = identityHashCode; - URL url = invokers.get(0).getUrl(); - this.replicaNumber = url.getMethodParameter(methodName, HASH_NODES, 160); - String[] index = COMMA_SPLIT_PATTERN.split(url.getMethodParameter(methodName, HASH_ARGUMENTS, "0")); - argumentIndex = new int[index.length]; - for (int i = 0; i < index.length; i++) { - argumentIndex[i] = Integer.parseInt(index[i]); - } - for (Invoker invoker : invokers) { - String address = invoker.getUrl().getAddress(); - for (int i = 0; i < replicaNumber / 4; i++) { - byte[] digest = Bytes.getMD5(address + i); - for (int h = 0; h < 4; h++) { - long m = hash(digest, h); - virtualInvokers.put(m, invoker); - } - } - } - } - - public Invoker select(Invocation invocation) { - String key = toKey(invocation.getArguments()); - byte[] digest = Bytes.getMD5(key); - return selectForKey(hash(digest, 0)); - } - - private String toKey(Object[] args) { - StringBuilder buf = new StringBuilder(); - for (int i : argumentIndex) { - if (i >= 0 && i < args.length) { - buf.append(args[i]); - } - } - return buf.toString(); - } - - private Invoker selectForKey(long hash) { - Map.Entry> entry = virtualInvokers.ceilingEntry(hash); - if (entry == null) { - entry = virtualInvokers.firstEntry(); - } - return entry.getValue(); - } - - private long hash(byte[] digest, int number) { - return (((long) (digest[3 + number * 4] & 0xFF) << 24) - | ((long) (digest[2 + number * 4] & 0xFF) << 16) - | ((long) (digest[1 + number * 4] & 0xFF) << 8) - | (digest[number * 4] & 0xFF)) - & 0xFFFFFFFFL; - } - } - -} +/* + * 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.rpc.cluster.loadbalance; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.io.Bytes; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.support.RpcUtils; + +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN; + +/** + * ConsistentHashLoadBalance + */ +public class ConsistentHashLoadBalance extends AbstractLoadBalance { + public static final String NAME = "consistenthash"; + + /** + * Hash nodes name + */ + public static final String HASH_NODES = "hash.nodes"; + + /** + * Hash arguments name + */ + public static final String HASH_ARGUMENTS = "hash.arguments"; + + private final ConcurrentMap> selectors = new ConcurrentHashMap>(); + + @SuppressWarnings("unchecked") + @Override + protected Invoker doSelect(List> invokers, URL url, Invocation invocation) { + String methodName = RpcUtils.getMethodName(invocation); + String key = invokers.get(0).getUrl().getServiceKey() + "." + methodName; + // using the hashcode of list to compute the hash only pay attention to the elements in the list + int invokersHashCode = invokers.hashCode(); + ConsistentHashSelector selector = (ConsistentHashSelector) selectors.get(key); + if (selector == null || selector.identityHashCode != invokersHashCode) { + selectors.put(key, new ConsistentHashSelector(invokers, methodName, invokersHashCode)); + selector = (ConsistentHashSelector) selectors.get(key); + } + return selector.select(invocation); + } + + private static final class ConsistentHashSelector { + + private final TreeMap> virtualInvokers; + + private final int replicaNumber; + + private final int identityHashCode; + + private final int[] argumentIndex; + + ConsistentHashSelector(List> invokers, String methodName, int identityHashCode) { + this.virtualInvokers = new TreeMap>(); + this.identityHashCode = identityHashCode; + URL url = invokers.get(0).getUrl(); + this.replicaNumber = url.getMethodParameter(methodName, HASH_NODES, 160); + String[] index = COMMA_SPLIT_PATTERN.split(url.getMethodParameter(methodName, HASH_ARGUMENTS, "0")); + argumentIndex = new int[index.length]; + for (int i = 0; i < index.length; i++) { + argumentIndex[i] = Integer.parseInt(index[i]); + } + for (Invoker invoker : invokers) { + String address = invoker.getUrl().getAddress(); + for (int i = 0; i < replicaNumber / 4; i++) { + byte[] digest = Bytes.getMD5(address + i); + for (int h = 0; h < 4; h++) { + long m = hash(digest, h); + virtualInvokers.put(m, invoker); + } + } + } + } + + public Invoker select(Invocation invocation) { + String key = toKey(invocation.getArguments()); + byte[] digest = Bytes.getMD5(key); + return selectForKey(hash(digest, 0)); + } + + private String toKey(Object[] args) { + StringBuilder buf = new StringBuilder(); + for (int i : argumentIndex) { + if (i >= 0 && i < args.length) { + buf.append(args[i]); + } + } + return buf.toString(); + } + + private Invoker selectForKey(long hash) { + Map.Entry> entry = virtualInvokers.ceilingEntry(hash); + if (entry == null) { + entry = virtualInvokers.firstEntry(); + } + return entry.getValue(); + } + + private long hash(byte[] digest, int number) { + return (((long) (digest[3 + number * 4] & 0xFF) << 24) + | ((long) (digest[2 + number * 4] & 0xFF) << 16) + | ((long) (digest[1 + number * 4] & 0xFF) << 8) + | (digest[number * 4] & 0xFF)) + & 0xFFFFFFFFL; + } + } + +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveLoadBalance.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveLoadBalance.java index 6b1ac64b98..41c1bab569 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveLoadBalance.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveLoadBalance.java @@ -1,115 +1,115 @@ -/* - * 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.rpc.cluster.loadbalance; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.rpc.Invocation; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.RpcStatus; - -import java.util.List; -import java.util.concurrent.ThreadLocalRandom; - -/** - * LeastActiveLoadBalance - *

- * Filter the number of invokers with the least number of active calls and count the weights and quantities of these invokers. - * If there is only one invoker, use the invoker directly; - * if there are multiple invokers and the weights are not the same, then random according to the total weight; - * if there are multiple invokers and the same weight, then randomly called. - */ -public class LeastActiveLoadBalance extends AbstractLoadBalance { - - public static final String NAME = "leastactive"; - - @Override - protected Invoker doSelect(List> invokers, URL url, Invocation invocation) { - // Number of invokers - int length = invokers.size(); - // The least active value of all invokers - int leastActive = -1; - // The number of invokers having the same least active value (leastActive) - int leastCount = 0; - // The index of invokers having the same least active value (leastActive) - int[] leastIndexes = new int[length]; - // the weight of every invokers - int[] weights = new int[length]; - // The sum of the warmup weights of all the least active invokers - int totalWeight = 0; - // The weight of the first least active invoker - int firstWeight = 0; - // Every least active invoker has the same weight value? - boolean sameWeight = true; - - - // Filter out all the least active invokers - for (int i = 0; i < length; i++) { - Invoker invoker = invokers.get(i); - // Get the active number of the invoker - int active = RpcStatus.getStatus(invoker.getUrl(), invocation.getMethodName()).getActive(); - // Get the weight of the invoker's configuration. The default value is 100. - int afterWarmup = getWeight(invoker, invocation); - // save for later use - weights[i] = afterWarmup; - // If it is the first invoker or the active number of the invoker is less than the current least active number - if (leastActive == -1 || active < leastActive) { - // Reset the active number of the current invoker to the least active number - leastActive = active; - // Reset the number of least active invokers - leastCount = 1; - // Put the first least active invoker first in leastIndexes - leastIndexes[0] = i; - // Reset totalWeight - totalWeight = afterWarmup; - // Record the weight the first least active invoker - firstWeight = afterWarmup; - // Each invoke has the same weight (only one invoker here) - sameWeight = true; - // If current invoker's active value equals with leaseActive, then accumulating. - } else if (active == leastActive) { - // Record the index of the least active invoker in leastIndexes order - leastIndexes[leastCount++] = i; - // Accumulate the total weight of the least active invoker - totalWeight += afterWarmup; - // If every invoker has the same weight? - if (sameWeight && afterWarmup != firstWeight) { - sameWeight = false; - } - } - } - // Choose an invoker from all the least active invokers - if (leastCount == 1) { - // If we got exactly one invoker having the least active value, return this invoker directly. - return invokers.get(leastIndexes[0]); - } - if (!sameWeight && totalWeight > 0) { - // If (not every invoker has the same weight & at least one invoker's weight>0), select randomly based on - // totalWeight. - int offsetWeight = ThreadLocalRandom.current().nextInt(totalWeight); - // Return a invoker based on the random value. - for (int i = 0; i < leastCount; i++) { - int leastIndex = leastIndexes[i]; - offsetWeight -= weights[leastIndex]; - if (offsetWeight < 0) { - return invokers.get(leastIndex); - } - } - } - // If all invokers have the same weight value or totalWeight=0, return evenly. - return invokers.get(leastIndexes[ThreadLocalRandom.current().nextInt(leastCount)]); - } -} +/* + * 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.rpc.cluster.loadbalance; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.RpcStatus; + +import java.util.List; +import java.util.concurrent.ThreadLocalRandom; + +/** + * LeastActiveLoadBalance + *

+ * Filter the number of invokers with the least number of active calls and count the weights and quantities of these invokers. + * If there is only one invoker, use the invoker directly; + * if there are multiple invokers and the weights are not the same, then random according to the total weight; + * if there are multiple invokers and the same weight, then randomly called. + */ +public class LeastActiveLoadBalance extends AbstractLoadBalance { + + public static final String NAME = "leastactive"; + + @Override + protected Invoker doSelect(List> invokers, URL url, Invocation invocation) { + // Number of invokers + int length = invokers.size(); + // The least active value of all invokers + int leastActive = -1; + // The number of invokers having the same least active value (leastActive) + int leastCount = 0; + // The index of invokers having the same least active value (leastActive) + int[] leastIndexes = new int[length]; + // the weight of every invokers + int[] weights = new int[length]; + // The sum of the warmup weights of all the least active invokers + int totalWeight = 0; + // The weight of the first least active invoker + int firstWeight = 0; + // Every least active invoker has the same weight value? + boolean sameWeight = true; + + + // Filter out all the least active invokers + for (int i = 0; i < length; i++) { + Invoker invoker = invokers.get(i); + // Get the active number of the invoker + int active = RpcStatus.getStatus(invoker.getUrl(), invocation.getMethodName()).getActive(); + // Get the weight of the invoker's configuration. The default value is 100. + int afterWarmup = getWeight(invoker, invocation); + // save for later use + weights[i] = afterWarmup; + // If it is the first invoker or the active number of the invoker is less than the current least active number + if (leastActive == -1 || active < leastActive) { + // Reset the active number of the current invoker to the least active number + leastActive = active; + // Reset the number of least active invokers + leastCount = 1; + // Put the first least active invoker first in leastIndexes + leastIndexes[0] = i; + // Reset totalWeight + totalWeight = afterWarmup; + // Record the weight the first least active invoker + firstWeight = afterWarmup; + // Each invoke has the same weight (only one invoker here) + sameWeight = true; + // If current invoker's active value equals with leaseActive, then accumulating. + } else if (active == leastActive) { + // Record the index of the least active invoker in leastIndexes order + leastIndexes[leastCount++] = i; + // Accumulate the total weight of the least active invoker + totalWeight += afterWarmup; + // If every invoker has the same weight? + if (sameWeight && afterWarmup != firstWeight) { + sameWeight = false; + } + } + } + // Choose an invoker from all the least active invokers + if (leastCount == 1) { + // If we got exactly one invoker having the least active value, return this invoker directly. + return invokers.get(leastIndexes[0]); + } + if (!sameWeight && totalWeight > 0) { + // If (not every invoker has the same weight & at least one invoker's weight>0), select randomly based on + // totalWeight. + int offsetWeight = ThreadLocalRandom.current().nextInt(totalWeight); + // Return a invoker based on the random value. + for (int i = 0; i < leastCount; i++) { + int leastIndex = leastIndexes[i]; + offsetWeight -= weights[leastIndex]; + if (offsetWeight < 0) { + return invokers.get(leastIndex); + } + } + } + // If all invokers have the same weight value or totalWeight=0, return evenly. + return invokers.get(leastIndexes[ThreadLocalRandom.current().nextInt(leastCount)]); + } +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalance.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalance.java index ddb87fb473..b3e5adb9e6 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalance.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalance.java @@ -1,131 +1,131 @@ -/* - * 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.rpc.cluster.loadbalance; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.rpc.Invocation; -import org.apache.dubbo.rpc.Invoker; - -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.atomic.AtomicLong; - -/** - * Round robin load balance. - */ -public class RoundRobinLoadBalance extends AbstractLoadBalance { - public static final String NAME = "roundrobin"; - - private static final int RECYCLE_PERIOD = 60000; - - protected static class WeightedRoundRobin { - private int weight; - private AtomicLong current = new AtomicLong(0); - private long lastUpdate; - - public int getWeight() { - return weight; - } - - public void setWeight(int weight) { - this.weight = weight; - current.set(0); - } - - public long increaseCurrent() { - return current.addAndGet(weight); - } - - public void sel(int total) { - current.addAndGet(-1 * total); - } - - public long getLastUpdate() { - return lastUpdate; - } - - public void setLastUpdate(long lastUpdate) { - this.lastUpdate = lastUpdate; - } - } - - private ConcurrentMap> methodWeightMap = new ConcurrentHashMap>(); - - /** - * get invoker addr list cached for specified invocation - *

- * for unit test only - * - * @param invokers - * @param invocation - * @return - */ - protected Collection getInvokerAddrList(List> invokers, Invocation invocation) { - String key = invokers.get(0).getUrl().getServiceKey() + "." + invocation.getMethodName(); - Map map = methodWeightMap.get(key); - if (map != null) { - return map.keySet(); - } - return null; - } - - @Override - protected Invoker doSelect(List> invokers, URL url, Invocation invocation) { - String key = invokers.get(0).getUrl().getServiceKey() + "." + invocation.getMethodName(); - ConcurrentMap map = methodWeightMap.computeIfAbsent(key, k -> new ConcurrentHashMap<>()); - int totalWeight = 0; - long maxCurrent = Long.MIN_VALUE; - long now = System.currentTimeMillis(); - Invoker selectedInvoker = null; - WeightedRoundRobin selectedWRR = null; - for (Invoker invoker : invokers) { - String identifyString = invoker.getUrl().toIdentityString(); - int weight = getWeight(invoker, invocation); - WeightedRoundRobin weightedRoundRobin = map.computeIfAbsent(identifyString, k -> { - WeightedRoundRobin wrr = new WeightedRoundRobin(); - wrr.setWeight(weight); - return wrr; - }); - - if (weight != weightedRoundRobin.getWeight()) { - //weight changed - weightedRoundRobin.setWeight(weight); - } - long cur = weightedRoundRobin.increaseCurrent(); - weightedRoundRobin.setLastUpdate(now); - if (cur > maxCurrent) { - maxCurrent = cur; - selectedInvoker = invoker; - selectedWRR = weightedRoundRobin; - } - totalWeight += weight; - } - if (invokers.size() != map.size()) { - map.entrySet().removeIf(item -> now - item.getValue().getLastUpdate() > RECYCLE_PERIOD); - } - if (selectedInvoker != null) { - selectedWRR.sel(totalWeight); - return selectedInvoker; - } - // should not happen here - return invokers.get(0); - } - -} +/* + * 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.rpc.cluster.loadbalance; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.atomic.AtomicLong; + +/** + * Round robin load balance. + */ +public class RoundRobinLoadBalance extends AbstractLoadBalance { + public static final String NAME = "roundrobin"; + + private static final int RECYCLE_PERIOD = 60000; + + protected static class WeightedRoundRobin { + private int weight; + private AtomicLong current = new AtomicLong(0); + private long lastUpdate; + + public int getWeight() { + return weight; + } + + public void setWeight(int weight) { + this.weight = weight; + current.set(0); + } + + public long increaseCurrent() { + return current.addAndGet(weight); + } + + public void sel(int total) { + current.addAndGet(-1 * total); + } + + public long getLastUpdate() { + return lastUpdate; + } + + public void setLastUpdate(long lastUpdate) { + this.lastUpdate = lastUpdate; + } + } + + private ConcurrentMap> methodWeightMap = new ConcurrentHashMap>(); + + /** + * get invoker addr list cached for specified invocation + *

+ * for unit test only + * + * @param invokers + * @param invocation + * @return + */ + protected Collection getInvokerAddrList(List> invokers, Invocation invocation) { + String key = invokers.get(0).getUrl().getServiceKey() + "." + invocation.getMethodName(); + Map map = methodWeightMap.get(key); + if (map != null) { + return map.keySet(); + } + return null; + } + + @Override + protected Invoker doSelect(List> invokers, URL url, Invocation invocation) { + String key = invokers.get(0).getUrl().getServiceKey() + "." + invocation.getMethodName(); + ConcurrentMap map = methodWeightMap.computeIfAbsent(key, k -> new ConcurrentHashMap<>()); + int totalWeight = 0; + long maxCurrent = Long.MIN_VALUE; + long now = System.currentTimeMillis(); + Invoker selectedInvoker = null; + WeightedRoundRobin selectedWRR = null; + for (Invoker invoker : invokers) { + String identifyString = invoker.getUrl().toIdentityString(); + int weight = getWeight(invoker, invocation); + WeightedRoundRobin weightedRoundRobin = map.computeIfAbsent(identifyString, k -> { + WeightedRoundRobin wrr = new WeightedRoundRobin(); + wrr.setWeight(weight); + return wrr; + }); + + if (weight != weightedRoundRobin.getWeight()) { + //weight changed + weightedRoundRobin.setWeight(weight); + } + long cur = weightedRoundRobin.increaseCurrent(); + weightedRoundRobin.setLastUpdate(now); + if (cur > maxCurrent) { + maxCurrent = cur; + selectedInvoker = invoker; + selectedWRR = weightedRoundRobin; + } + totalWeight += weight; + } + if (invokers.size() != map.size()) { + map.entrySet().removeIf(item -> now - item.getValue().getLastUpdate() > RECYCLE_PERIOD); + } + if (selectedInvoker != null) { + selectedWRR.sel(totalWeight); + return selectedInvoker; + } + // should not happen here + return invokers.get(0); + } + +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouter.java index f6cfec2993..8a3564500e 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouter.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouter.java @@ -1,360 +1,360 @@ -/* - * 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.rpc.cluster.router.condition; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.utils.CollectionUtils; -import org.apache.dubbo.common.utils.NetUtils; -import org.apache.dubbo.common.utils.StringUtils; -import org.apache.dubbo.common.utils.UrlUtils; -import org.apache.dubbo.rpc.Invocation; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.RpcException; -import org.apache.dubbo.rpc.cluster.Constants; -import org.apache.dubbo.rpc.cluster.router.AbstractRouter; - -import java.text.ParseException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import static org.apache.dubbo.common.constants.CommonConstants.ENABLED_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.HOST_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.METHOD_KEY; -import static org.apache.dubbo.rpc.cluster.Constants.ADDRESS_KEY; -import static org.apache.dubbo.rpc.cluster.Constants.FORCE_KEY; -import static org.apache.dubbo.rpc.cluster.Constants.PRIORITY_KEY; -import static org.apache.dubbo.rpc.cluster.Constants.RULE_KEY; -import static org.apache.dubbo.rpc.cluster.Constants.RUNTIME_KEY; - -/** - * ConditionRouter - * It supports the conditional routing configured by "override://", in 2.6.x, - * refer to https://dubbo.apache.org/en/docs/v2.7/user/examples/routing-rule/ . - * For 2.7.x and later, please refer to {@link org.apache.dubbo.rpc.cluster.router.condition.config.ServiceRouter} - * and {@link org.apache.dubbo.rpc.cluster.router.condition.config.AppRouter} - * refer to https://dubbo.apache.org/zh/docs/v2.7/user/examples/routing-rule/ . - */ -public class ConditionRouter extends AbstractRouter { - public static final String NAME = "condition"; - - private static final Logger logger = LoggerFactory.getLogger(ConditionRouter.class); - protected static final Pattern ROUTE_PATTERN = Pattern.compile("([&!=,]*)\\s*([^&!=,\\s]+)"); - protected static Pattern ARGUMENTS_PATTERN = Pattern.compile("arguments\\[([0-9]+)\\]"); - protected Map whenCondition; - protected Map thenCondition; - - private boolean enabled; - - public ConditionRouter(String rule, boolean force, boolean enabled) { - this.force = force; - this.enabled = enabled; - if (enabled) { - this.init(rule); - } - } - - public ConditionRouter(URL url) { - this.url = url; - this.priority = url.getParameter(PRIORITY_KEY, 0); - this.force = url.getParameter(FORCE_KEY, false); - this.enabled = url.getParameter(ENABLED_KEY, true); - if (enabled) { - init(url.getParameterAndDecoded(RULE_KEY)); - } - } - - public void init(String rule) { - try { - if (rule == null || rule.trim().length() == 0) { - throw new IllegalArgumentException("Illegal route rule!"); - } - rule = rule.replace("consumer.", "").replace("provider.", ""); - int i = rule.indexOf("=>"); - String whenRule = i < 0 ? null : rule.substring(0, i).trim(); - String thenRule = i < 0 ? rule.trim() : rule.substring(i + 2).trim(); - Map when = StringUtils.isBlank(whenRule) || "true".equals(whenRule) ? new HashMap() : parseRule(whenRule); - Map then = StringUtils.isBlank(thenRule) || "false".equals(thenRule) ? null : parseRule(thenRule); - // NOTE: It should be determined on the business level whether the `When condition` can be empty or not. - this.whenCondition = when; - this.thenCondition = then; - } catch (ParseException e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - - private static Map parseRule(String rule) - throws ParseException { - Map condition = new HashMap(); - if (StringUtils.isBlank(rule)) { - return condition; - } - // Key-Value pair, stores both match and mismatch conditions - MatchPair pair = null; - // Multiple values - Set values = null; - final Matcher matcher = ROUTE_PATTERN.matcher(rule); - while (matcher.find()) { // Try to match one by one - String separator = matcher.group(1); - String content = matcher.group(2); - // Start part of the condition expression. - if (StringUtils.isEmpty(separator)) { - pair = new MatchPair(); - condition.put(content, pair); - } - // The KV part of the condition expression - else if ("&".equals(separator)) { - if (condition.get(content) == null) { - pair = new MatchPair(); - condition.put(content, pair); - } else { - pair = condition.get(content); - } - } - // The Value in the KV part. - else if ("=".equals(separator)) { - if (pair == null) { - throw new ParseException("Illegal route rule \"" - + rule + "\", The error char '" + separator - + "' at index " + matcher.start() + " before \"" - + content + "\".", matcher.start()); - } - - values = pair.matches; - values.add(content); - } - // The Value in the KV part. - else if ("!=".equals(separator)) { - if (pair == null) { - throw new ParseException("Illegal route rule \"" - + rule + "\", The error char '" + separator - + "' at index " + matcher.start() + " before \"" - + content + "\".", matcher.start()); - } - - values = pair.mismatches; - values.add(content); - } - // The Value in the KV part, if Value have more than one items. - else if (",".equals(separator)) { // Should be separated by ',' - if (values == null || values.isEmpty()) { - throw new ParseException("Illegal route rule \"" - + rule + "\", The error char '" + separator - + "' at index " + matcher.start() + " before \"" - + content + "\".", matcher.start()); - } - values.add(content); - } else { - throw new ParseException("Illegal route rule \"" + rule - + "\", The error char '" + separator + "' at index " - + matcher.start() + " before \"" + content + "\".", matcher.start()); - } - } - return condition; - } - - @Override - public List> route(List> invokers, URL url, Invocation invocation) - throws RpcException { - if (!enabled) { - return invokers; - } - - if (CollectionUtils.isEmpty(invokers)) { - return invokers; - } - try { - if (!matchWhen(url, invocation)) { - return invokers; - } - List> result = new ArrayList>(); - if (thenCondition == null) { - logger.warn("The current consumer in the service blacklist. consumer: " + NetUtils.getLocalHost() + ", service: " + url.getServiceKey()); - return result; - } - for (Invoker invoker : invokers) { - if (matchThen(invoker.getUrl(), url)) { - result.add(invoker); - } - } - if (!result.isEmpty()) { - return result; - } else if (force) { - logger.warn("The route result is empty and force execute. consumer: " + NetUtils.getLocalHost() + ", service: " + url.getServiceKey() + ", router: " + url.getParameterAndDecoded(RULE_KEY)); - return result; - } - } catch (Throwable t) { - logger.error("Failed to execute condition router rule: " + getUrl() + ", invokers: " + invokers + ", cause: " + t.getMessage(), t); - } - return invokers; - } - - @Override - public boolean isRuntime() { - // We always return true for previously defined Router, that is, old Router doesn't support cache anymore. -// return true; - return this.url.getParameter(RUNTIME_KEY, false); - } - - @Override - public URL getUrl() { - return url; - } - - boolean matchWhen(URL url, Invocation invocation) { - return CollectionUtils.isEmptyMap(whenCondition) || matchCondition(whenCondition, url, null, invocation); - } - - private boolean matchThen(URL url, URL param) { - return CollectionUtils.isNotEmptyMap(thenCondition) && matchCondition(thenCondition, url, param, null); - } - - private boolean matchCondition(Map condition, URL url, URL param, Invocation invocation) { - Map sample = url.toMap(); - boolean result = false; - for (Map.Entry matchPair : condition.entrySet()) { - String key = matchPair.getKey(); - - if (key.startsWith(Constants.ARGUMENTS)) { - if (!matchArguments(matchPair, invocation)) { - return false; - } else { - result = true; - continue; - } - } - - String sampleValue; - //get real invoked method name from invocation - if (invocation != null && (METHOD_KEY.equals(key) || METHODS_KEY.equals(key))) { - sampleValue = invocation.getMethodName(); - } else if (ADDRESS_KEY.equals(key)) { - sampleValue = url.getAddress(); - } else if (HOST_KEY.equals(key)) { - sampleValue = url.getHost(); - } else { - sampleValue = sample.get(key); - if (sampleValue == null) { - sampleValue = sample.get(key); - } - } - if (sampleValue != null) { - if (!matchPair.getValue().isMatch(sampleValue, param)) { - return false; - } else { - result = true; - } - } else { - //not pass the condition - if (!matchPair.getValue().matches.isEmpty()) { - return false; - } else { - result = true; - } - } - } - return result; - } - - /** - * analysis the arguments in the rule. - * Examples would be like this: - * "arguments[0]=1", whenCondition is that the first argument is equal to '1'. - * "arguments[1]=a", whenCondition is that the second argument is equal to 'a'. - * @param matchPair - * @param invocation - * @return - */ - public boolean matchArguments(Map.Entry matchPair, Invocation invocation) { - try { - // split the rule - String key = matchPair.getKey(); - String[] expressArray = key.split("\\."); - String argumentExpress = expressArray[0]; - final Matcher matcher = ARGUMENTS_PATTERN.matcher(argumentExpress); - if (!matcher.find()) { - return false; - } - - //extract the argument index - int index = Integer.parseInt(matcher.group(1)); - if (index < 0 || index > invocation.getArguments().length) { - return false; - } - - //extract the argument value - Object object = invocation.getArguments()[index]; - - if (matchPair.getValue().isMatch(String.valueOf(object), null)) { - return true; - } - } catch (Exception e) { - logger.warn("Arguments match failed, matchPair[]" + matchPair + "] invocation[" + invocation + "]", e); - } - - return false; - } - - protected static final class MatchPair { - final Set matches = new HashSet(); - final Set mismatches = new HashSet(); - - private boolean isMatch(String value, URL param) { - if (!matches.isEmpty() && mismatches.isEmpty()) { - for (String match : matches) { - if (UrlUtils.isMatchGlobPattern(match, value, param)) { - return true; - } - } - return false; - } - - if (!mismatches.isEmpty() && matches.isEmpty()) { - for (String mismatch : mismatches) { - if (UrlUtils.isMatchGlobPattern(mismatch, value, param)) { - return false; - } - } - return true; - } - - if (!matches.isEmpty() && !mismatches.isEmpty()) { - //when both mismatches and matches contain the same value, then using mismatches first - for (String mismatch : mismatches) { - if (UrlUtils.isMatchGlobPattern(mismatch, value, param)) { - return false; - } - } - for (String match : matches) { - if (UrlUtils.isMatchGlobPattern(match, value, param)) { - return true; - } - } - return false; - } - return false; - } - } -} +/* + * 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.rpc.cluster.router.condition; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.common.utils.NetUtils; +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.common.utils.UrlUtils; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.cluster.Constants; +import org.apache.dubbo.rpc.cluster.router.AbstractRouter; + +import java.text.ParseException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static org.apache.dubbo.common.constants.CommonConstants.ENABLED_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.HOST_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.METHOD_KEY; +import static org.apache.dubbo.rpc.cluster.Constants.ADDRESS_KEY; +import static org.apache.dubbo.rpc.cluster.Constants.FORCE_KEY; +import static org.apache.dubbo.rpc.cluster.Constants.PRIORITY_KEY; +import static org.apache.dubbo.rpc.cluster.Constants.RULE_KEY; +import static org.apache.dubbo.rpc.cluster.Constants.RUNTIME_KEY; + +/** + * ConditionRouter + * It supports the conditional routing configured by "override://", in 2.6.x, + * refer to https://dubbo.apache.org/en/docs/v2.7/user/examples/routing-rule/ . + * For 2.7.x and later, please refer to {@link org.apache.dubbo.rpc.cluster.router.condition.config.ServiceRouter} + * and {@link org.apache.dubbo.rpc.cluster.router.condition.config.AppRouter} + * refer to https://dubbo.apache.org/zh/docs/v2.7/user/examples/routing-rule/ . + */ +public class ConditionRouter extends AbstractRouter { + public static final String NAME = "condition"; + + private static final Logger logger = LoggerFactory.getLogger(ConditionRouter.class); + protected static final Pattern ROUTE_PATTERN = Pattern.compile("([&!=,]*)\\s*([^&!=,\\s]+)"); + protected static Pattern ARGUMENTS_PATTERN = Pattern.compile("arguments\\[([0-9]+)\\]"); + protected Map whenCondition; + protected Map thenCondition; + + private boolean enabled; + + public ConditionRouter(String rule, boolean force, boolean enabled) { + this.force = force; + this.enabled = enabled; + if (enabled) { + this.init(rule); + } + } + + public ConditionRouter(URL url) { + this.url = url; + this.priority = url.getParameter(PRIORITY_KEY, 0); + this.force = url.getParameter(FORCE_KEY, false); + this.enabled = url.getParameter(ENABLED_KEY, true); + if (enabled) { + init(url.getParameterAndDecoded(RULE_KEY)); + } + } + + public void init(String rule) { + try { + if (rule == null || rule.trim().length() == 0) { + throw new IllegalArgumentException("Illegal route rule!"); + } + rule = rule.replace("consumer.", "").replace("provider.", ""); + int i = rule.indexOf("=>"); + String whenRule = i < 0 ? null : rule.substring(0, i).trim(); + String thenRule = i < 0 ? rule.trim() : rule.substring(i + 2).trim(); + Map when = StringUtils.isBlank(whenRule) || "true".equals(whenRule) ? new HashMap() : parseRule(whenRule); + Map then = StringUtils.isBlank(thenRule) || "false".equals(thenRule) ? null : parseRule(thenRule); + // NOTE: It should be determined on the business level whether the `When condition` can be empty or not. + this.whenCondition = when; + this.thenCondition = then; + } catch (ParseException e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + private static Map parseRule(String rule) + throws ParseException { + Map condition = new HashMap(); + if (StringUtils.isBlank(rule)) { + return condition; + } + // Key-Value pair, stores both match and mismatch conditions + MatchPair pair = null; + // Multiple values + Set values = null; + final Matcher matcher = ROUTE_PATTERN.matcher(rule); + while (matcher.find()) { // Try to match one by one + String separator = matcher.group(1); + String content = matcher.group(2); + // Start part of the condition expression. + if (StringUtils.isEmpty(separator)) { + pair = new MatchPair(); + condition.put(content, pair); + } + // The KV part of the condition expression + else if ("&".equals(separator)) { + if (condition.get(content) == null) { + pair = new MatchPair(); + condition.put(content, pair); + } else { + pair = condition.get(content); + } + } + // The Value in the KV part. + else if ("=".equals(separator)) { + if (pair == null) { + throw new ParseException("Illegal route rule \"" + + rule + "\", The error char '" + separator + + "' at index " + matcher.start() + " before \"" + + content + "\".", matcher.start()); + } + + values = pair.matches; + values.add(content); + } + // The Value in the KV part. + else if ("!=".equals(separator)) { + if (pair == null) { + throw new ParseException("Illegal route rule \"" + + rule + "\", The error char '" + separator + + "' at index " + matcher.start() + " before \"" + + content + "\".", matcher.start()); + } + + values = pair.mismatches; + values.add(content); + } + // The Value in the KV part, if Value have more than one items. + else if (",".equals(separator)) { // Should be separated by ',' + if (values == null || values.isEmpty()) { + throw new ParseException("Illegal route rule \"" + + rule + "\", The error char '" + separator + + "' at index " + matcher.start() + " before \"" + + content + "\".", matcher.start()); + } + values.add(content); + } else { + throw new ParseException("Illegal route rule \"" + rule + + "\", The error char '" + separator + "' at index " + + matcher.start() + " before \"" + content + "\".", matcher.start()); + } + } + return condition; + } + + @Override + public List> route(List> invokers, URL url, Invocation invocation) + throws RpcException { + if (!enabled) { + return invokers; + } + + if (CollectionUtils.isEmpty(invokers)) { + return invokers; + } + try { + if (!matchWhen(url, invocation)) { + return invokers; + } + List> result = new ArrayList>(); + if (thenCondition == null) { + logger.warn("The current consumer in the service blacklist. consumer: " + NetUtils.getLocalHost() + ", service: " + url.getServiceKey()); + return result; + } + for (Invoker invoker : invokers) { + if (matchThen(invoker.getUrl(), url)) { + result.add(invoker); + } + } + if (!result.isEmpty()) { + return result; + } else if (force) { + logger.warn("The route result is empty and force execute. consumer: " + NetUtils.getLocalHost() + ", service: " + url.getServiceKey() + ", router: " + url.getParameterAndDecoded(RULE_KEY)); + return result; + } + } catch (Throwable t) { + logger.error("Failed to execute condition router rule: " + getUrl() + ", invokers: " + invokers + ", cause: " + t.getMessage(), t); + } + return invokers; + } + + @Override + public boolean isRuntime() { + // We always return true for previously defined Router, that is, old Router doesn't support cache anymore. +// return true; + return this.url.getParameter(RUNTIME_KEY, false); + } + + @Override + public URL getUrl() { + return url; + } + + boolean matchWhen(URL url, Invocation invocation) { + return CollectionUtils.isEmptyMap(whenCondition) || matchCondition(whenCondition, url, null, invocation); + } + + private boolean matchThen(URL url, URL param) { + return CollectionUtils.isNotEmptyMap(thenCondition) && matchCondition(thenCondition, url, param, null); + } + + private boolean matchCondition(Map condition, URL url, URL param, Invocation invocation) { + Map sample = url.toMap(); + boolean result = false; + for (Map.Entry matchPair : condition.entrySet()) { + String key = matchPair.getKey(); + + if (key.startsWith(Constants.ARGUMENTS)) { + if (!matchArguments(matchPair, invocation)) { + return false; + } else { + result = true; + continue; + } + } + + String sampleValue; + //get real invoked method name from invocation + if (invocation != null && (METHOD_KEY.equals(key) || METHODS_KEY.equals(key))) { + sampleValue = invocation.getMethodName(); + } else if (ADDRESS_KEY.equals(key)) { + sampleValue = url.getAddress(); + } else if (HOST_KEY.equals(key)) { + sampleValue = url.getHost(); + } else { + sampleValue = sample.get(key); + if (sampleValue == null) { + sampleValue = sample.get(key); + } + } + if (sampleValue != null) { + if (!matchPair.getValue().isMatch(sampleValue, param)) { + return false; + } else { + result = true; + } + } else { + //not pass the condition + if (!matchPair.getValue().matches.isEmpty()) { + return false; + } else { + result = true; + } + } + } + return result; + } + + /** + * analysis the arguments in the rule. + * Examples would be like this: + * "arguments[0]=1", whenCondition is that the first argument is equal to '1'. + * "arguments[1]=a", whenCondition is that the second argument is equal to 'a'. + * @param matchPair + * @param invocation + * @return + */ + public boolean matchArguments(Map.Entry matchPair, Invocation invocation) { + try { + // split the rule + String key = matchPair.getKey(); + String[] expressArray = key.split("\\."); + String argumentExpress = expressArray[0]; + final Matcher matcher = ARGUMENTS_PATTERN.matcher(argumentExpress); + if (!matcher.find()) { + return false; + } + + //extract the argument index + int index = Integer.parseInt(matcher.group(1)); + if (index < 0 || index > invocation.getArguments().length) { + return false; + } + + //extract the argument value + Object object = invocation.getArguments()[index]; + + if (matchPair.getValue().isMatch(String.valueOf(object), null)) { + return true; + } + } catch (Exception e) { + logger.warn("Arguments match failed, matchPair[]" + matchPair + "] invocation[" + invocation + "]", e); + } + + return false; + } + + protected static final class MatchPair { + final Set matches = new HashSet(); + final Set mismatches = new HashSet(); + + private boolean isMatch(String value, URL param) { + if (!matches.isEmpty() && mismatches.isEmpty()) { + for (String match : matches) { + if (UrlUtils.isMatchGlobPattern(match, value, param)) { + return true; + } + } + return false; + } + + if (!mismatches.isEmpty() && matches.isEmpty()) { + for (String mismatch : mismatches) { + if (UrlUtils.isMatchGlobPattern(mismatch, value, param)) { + return false; + } + } + return true; + } + + if (!matches.isEmpty() && !mismatches.isEmpty()) { + //when both mismatches and matches contain the same value, then using mismatches first + for (String mismatch : mismatches) { + if (UrlUtils.isMatchGlobPattern(mismatch, value, param)) { + return false; + } + } + for (String match : matches) { + if (UrlUtils.isMatchGlobPattern(match, value, param)) { + return true; + } + } + return false; + } + return false; + } + } +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouterFactory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouterFactory.java index 7701c4c62e..71df97c1c6 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouterFactory.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouterFactory.java @@ -1,36 +1,36 @@ -/* - * 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.rpc.cluster.router.condition; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.rpc.cluster.Router; -import org.apache.dubbo.rpc.cluster.RouterFactory; - -/** - * ConditionRouterFactory - * Load when "override://" is configured {@link ConditionRouter} - */ -public class ConditionRouterFactory implements RouterFactory { - - public static final String NAME = "condition"; - - @Override - public Router getRouter(URL url) { - return new ConditionRouter(url); - } - -} +/* + * 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.rpc.cluster.router.condition; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.rpc.cluster.Router; +import org.apache.dubbo.rpc.cluster.RouterFactory; + +/** + * ConditionRouterFactory + * Load when "override://" is configured {@link ConditionRouter} + */ +public class ConditionRouterFactory implements RouterFactory { + + public static final String NAME = "condition"; + + @Override + public Router getRouter(URL url) { + return new ConditionRouter(url); + } + +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouter.java index 4c2759689d..f7b1a6e6f0 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouter.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouter.java @@ -1,177 +1,177 @@ -/* - * 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.rpc.cluster.router.script; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.utils.StringUtils; -import org.apache.dubbo.rpc.Invocation; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.RpcContext; -import org.apache.dubbo.rpc.RpcException; -import org.apache.dubbo.rpc.cluster.router.AbstractRouter; - -import javax.script.Bindings; -import javax.script.Compilable; -import javax.script.CompiledScript; -import javax.script.ScriptEngine; -import javax.script.ScriptEngineManager; -import javax.script.ScriptException; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.CodeSource; -import java.security.Permissions; -import java.security.PrivilegedAction; -import java.security.ProtectionDomain; -import java.security.cert.Certificate; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; - -import static org.apache.dubbo.rpc.cluster.Constants.DEFAULT_SCRIPT_TYPE_KEY; -import static org.apache.dubbo.rpc.cluster.Constants.FORCE_KEY; -import static org.apache.dubbo.rpc.cluster.Constants.PRIORITY_KEY; -import static org.apache.dubbo.rpc.cluster.Constants.RULE_KEY; -import static org.apache.dubbo.rpc.cluster.Constants.RUNTIME_KEY; -import static org.apache.dubbo.rpc.cluster.Constants.TYPE_KEY; - -/** - * ScriptRouter - */ -public class ScriptRouter extends AbstractRouter { - public static final String NAME = "SCRIPT_ROUTER"; - private static final int SCRIPT_ROUTER_DEFAULT_PRIORITY = 0; - private static final Logger logger = LoggerFactory.getLogger(ScriptRouter.class); - - private static final Map ENGINES = new ConcurrentHashMap<>(); - - private final ScriptEngine engine; - - private final String rule; - - private CompiledScript function; - - private AccessControlContext accessControlContext; - - { - //Just give permission of reflect to access member. - Permissions perms = new Permissions(); - perms.add(new RuntimePermission("accessDeclaredMembers")); - // Cast to Certificate[] required because of ambiguity: - ProtectionDomain domain = new ProtectionDomain(new CodeSource(null, (Certificate[]) null), perms); - accessControlContext = new AccessControlContext(new ProtectionDomain[]{domain}); - } - - public ScriptRouter(URL url) { - this.url = url; - this.priority = url.getParameter(PRIORITY_KEY, SCRIPT_ROUTER_DEFAULT_PRIORITY); - - engine = getEngine(url); - rule = getRule(url); - try { - Compilable compilable = (Compilable) engine; - function = compilable.compile(rule); - } catch (ScriptException e) { - logger.error("route error, rule has been ignored. rule: " + rule + - ", url: " + RpcContext.getServiceContext().getUrl(), e); - } - } - - /** - * get rule from url parameters. - */ - private String getRule(URL url) { - String vRule = url.getParameterAndDecoded(RULE_KEY); - if (StringUtils.isEmpty(vRule)) { - throw new IllegalStateException("route rule can not be empty."); - } - return vRule; - } - - /** - * create ScriptEngine instance by type from url parameters, then cache it - */ - private ScriptEngine getEngine(URL url) { - String type = url.getParameter(TYPE_KEY, DEFAULT_SCRIPT_TYPE_KEY); - - return ENGINES.computeIfAbsent(type, t -> { - ScriptEngine scriptEngine = new ScriptEngineManager().getEngineByName(type); - if (scriptEngine == null) { - throw new IllegalStateException("unsupported route engine type: " + type); - } - return scriptEngine; - }); - } - - @Override - public List> route(List> invokers, URL url, Invocation invocation) throws RpcException { - if (engine == null || function == null) { - return invokers; - } - Bindings bindings = createBindings(invokers, invocation); - return getRoutedInvokers(AccessController.doPrivileged((PrivilegedAction) () -> { - try { - return function.eval(bindings); - } catch (ScriptException e) { - logger.error("route error, rule has been ignored. rule: " + rule + ", method:" + - invocation.getMethodName() + ", url: " + RpcContext.getContext().getUrl(), e); - return invokers; - } - }, accessControlContext)); - } - - /** - * get routed invokers from result of script rule evaluation - */ - @SuppressWarnings("unchecked") - protected List> getRoutedInvokers(Object obj) { - if (obj instanceof Invoker[]) { - return Arrays.asList((Invoker[]) obj); - } else if (obj instanceof Object[]) { - return Arrays.stream((Object[]) obj).map(item -> (Invoker) item).collect(Collectors.toList()); - } else { - return (List>) obj; - } - } - - /** - * create bindings for script engine - */ - private Bindings createBindings(List> invokers, Invocation invocation) { - Bindings bindings = engine.createBindings(); - // create a new List of invokers - bindings.put("invokers", new ArrayList<>(invokers)); - bindings.put("invocation", invocation); - bindings.put("context", RpcContext.getClientAttachment()); - return bindings; - } - - @Override - public boolean isRuntime() { - return this.url.getParameter(RUNTIME_KEY, false); - } - - @Override - public boolean isForce() { - return url.getParameter(FORCE_KEY, false); - } - -} +/* + * 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.rpc.cluster.router.script; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.RpcContext; +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.cluster.router.AbstractRouter; + +import javax.script.Bindings; +import javax.script.Compilable; +import javax.script.CompiledScript; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import javax.script.ScriptException; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.CodeSource; +import java.security.Permissions; +import java.security.PrivilegedAction; +import java.security.ProtectionDomain; +import java.security.cert.Certificate; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +import static org.apache.dubbo.rpc.cluster.Constants.DEFAULT_SCRIPT_TYPE_KEY; +import static org.apache.dubbo.rpc.cluster.Constants.FORCE_KEY; +import static org.apache.dubbo.rpc.cluster.Constants.PRIORITY_KEY; +import static org.apache.dubbo.rpc.cluster.Constants.RULE_KEY; +import static org.apache.dubbo.rpc.cluster.Constants.RUNTIME_KEY; +import static org.apache.dubbo.rpc.cluster.Constants.TYPE_KEY; + +/** + * ScriptRouter + */ +public class ScriptRouter extends AbstractRouter { + public static final String NAME = "SCRIPT_ROUTER"; + private static final int SCRIPT_ROUTER_DEFAULT_PRIORITY = 0; + private static final Logger logger = LoggerFactory.getLogger(ScriptRouter.class); + + private static final Map ENGINES = new ConcurrentHashMap<>(); + + private final ScriptEngine engine; + + private final String rule; + + private CompiledScript function; + + private AccessControlContext accessControlContext; + + { + //Just give permission of reflect to access member. + Permissions perms = new Permissions(); + perms.add(new RuntimePermission("accessDeclaredMembers")); + // Cast to Certificate[] required because of ambiguity: + ProtectionDomain domain = new ProtectionDomain(new CodeSource(null, (Certificate[]) null), perms); + accessControlContext = new AccessControlContext(new ProtectionDomain[]{domain}); + } + + public ScriptRouter(URL url) { + this.url = url; + this.priority = url.getParameter(PRIORITY_KEY, SCRIPT_ROUTER_DEFAULT_PRIORITY); + + engine = getEngine(url); + rule = getRule(url); + try { + Compilable compilable = (Compilable) engine; + function = compilable.compile(rule); + } catch (ScriptException e) { + logger.error("route error, rule has been ignored. rule: " + rule + + ", url: " + RpcContext.getServiceContext().getUrl(), e); + } + } + + /** + * get rule from url parameters. + */ + private String getRule(URL url) { + String vRule = url.getParameterAndDecoded(RULE_KEY); + if (StringUtils.isEmpty(vRule)) { + throw new IllegalStateException("route rule can not be empty."); + } + return vRule; + } + + /** + * create ScriptEngine instance by type from url parameters, then cache it + */ + private ScriptEngine getEngine(URL url) { + String type = url.getParameter(TYPE_KEY, DEFAULT_SCRIPT_TYPE_KEY); + + return ENGINES.computeIfAbsent(type, t -> { + ScriptEngine scriptEngine = new ScriptEngineManager().getEngineByName(type); + if (scriptEngine == null) { + throw new IllegalStateException("unsupported route engine type: " + type); + } + return scriptEngine; + }); + } + + @Override + public List> route(List> invokers, URL url, Invocation invocation) throws RpcException { + if (engine == null || function == null) { + return invokers; + } + Bindings bindings = createBindings(invokers, invocation); + return getRoutedInvokers(AccessController.doPrivileged((PrivilegedAction) () -> { + try { + return function.eval(bindings); + } catch (ScriptException e) { + logger.error("route error, rule has been ignored. rule: " + rule + ", method:" + + invocation.getMethodName() + ", url: " + RpcContext.getContext().getUrl(), e); + return invokers; + } + }, accessControlContext)); + } + + /** + * get routed invokers from result of script rule evaluation + */ + @SuppressWarnings("unchecked") + protected List> getRoutedInvokers(Object obj) { + if (obj instanceof Invoker[]) { + return Arrays.asList((Invoker[]) obj); + } else if (obj instanceof Object[]) { + return Arrays.stream((Object[]) obj).map(item -> (Invoker) item).collect(Collectors.toList()); + } else { + return (List>) obj; + } + } + + /** + * create bindings for script engine + */ + private Bindings createBindings(List> invokers, Invocation invocation) { + Bindings bindings = engine.createBindings(); + // create a new List of invokers + bindings.put("invokers", new ArrayList<>(invokers)); + bindings.put("invocation", invocation); + bindings.put("context", RpcContext.getClientAttachment()); + return bindings; + } + + @Override + public boolean isRuntime() { + return this.url.getParameter(RUNTIME_KEY, false); + } + + @Override + public boolean isForce() { + return url.getParameter(FORCE_KEY, false); + } + +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouterFactory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouterFactory.java index b29f25e23d..6621f05640 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouterFactory.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouterFactory.java @@ -1,45 +1,45 @@ -/* - * 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.rpc.cluster.router.script; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.rpc.cluster.Router; -import org.apache.dubbo.rpc.cluster.RouterFactory; - -/** - * ScriptRouterFactory - *

- * Example URLS used by Script Router Factory: - *

    - *
  1. script://registryAddress?type=js&rule=xxxx - *
  2. script:///path/to/routerfile.js?type=js&rule=xxxx - *
  3. script://D:\path\to\routerfile.js?type=js&rule=xxxx - *
  4. script://C:/path/to/routerfile.js?type=js&rule=xxxx - *
- * The host value in URL points out the address of the source content of the Script Router,Registry、File etc - * - */ -public class ScriptRouterFactory implements RouterFactory { - - public static final String NAME = "script"; - - @Override - public Router getRouter(URL url) { - return new ScriptRouter(url); - } - -} +/* + * 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.rpc.cluster.router.script; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.rpc.cluster.Router; +import org.apache.dubbo.rpc.cluster.RouterFactory; + +/** + * ScriptRouterFactory + *

+ * Example URLS used by Script Router Factory: + *

    + *
  1. script://registryAddress?type=js&rule=xxxx + *
  2. script:///path/to/routerfile.js?type=js&rule=xxxx + *
  3. script://D:\path\to\routerfile.js?type=js&rule=xxxx + *
  4. script://C:/path/to/routerfile.js?type=js&rule=xxxx + *
+ * The host value in URL points out the address of the source content of the Script Router,Registry、File etc + * + */ +public class ScriptRouterFactory implements RouterFactory { + + public static final String NAME = "script"; + + @Override + public Router getRouter(URL url) { + return new ScriptRouter(url); + } + +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/state/RouterCache.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/state/RouterCache.java index 0b7b499ce8..82ccf58a04 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/state/RouterCache.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/state/RouterCache.java @@ -46,4 +46,4 @@ public class RouterCache { public void setAddrMetadata(Object addrMetadata) { this.addrMetadata = addrMetadata; } -} \ No newline at end of file +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/state/StateRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/state/StateRouter.java index ee28459837..cf479b0d7c 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/state/StateRouter.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/state/StateRouter.java @@ -1,100 +1,100 @@ -/* - * 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.rpc.cluster.router.state; - -import java.util.List; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.rpc.Invocation; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.RpcException; -import org.apache.dubbo.rpc.cluster.Directory; - -/** - * State Router. (SPI, Prototype, ThreadSafe) - *

- * Routing - * - * @see org.apache.dubbo.rpc.cluster.Cluster#join(Directory) - * @see Directory#list(Invocation) - * @since 3.0 - */ -public interface StateRouter extends Comparable { - - int DEFAULT_PRIORITY = Integer.MAX_VALUE; - - /** - * Get the router url. - * - * @return url - */ - URL getUrl(); - - /*** - * Filter invokers with current routing rule and only return the invokers that comply with the rule. - * Caching address lists in BitMap mode improves routing performance. - * @param invokers invoker bit list - * @param cache router address cache - * @param url refer url - * @param invocation invocation - * @param - * @return routed invokers - * @throws RpcException - * @Since 3.0 - */ - BitList> route(BitList> invokers, RouterCache cache, URL url, Invocation invocation) - throws - RpcException; - - default void notify(List> invokers) { - - } - - /** - * To decide whether this router need to execute every time an RPC comes or should only execute when addresses or - * rule change. - * - * @return true if the router need to execute every time. - */ - boolean isRuntime(); - - boolean isEnable(); - - boolean isForce(); - - int getPriority(); - - @Override - default int compareTo(StateRouter o) { - if (o == null) { - throw new IllegalArgumentException(); - } - return Integer.compare(this.getPriority(), o.getPriority()); - } - - String getName(); - - boolean shouldRePool(); - - RouterCache pool(List> invokers); - - void pool(); - - default void stop() { - //do nothing by default - } -} +/* + * 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.rpc.cluster.router.state; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.cluster.Directory; + +import java.util.List; + +/** + * State Router. (SPI, Prototype, ThreadSafe) + *

+ * Routing + * + * @see org.apache.dubbo.rpc.cluster.Cluster#join(Directory) + * @see Directory#list(Invocation) + * @since 3.0 + */ +public interface StateRouter extends Comparable { + + int DEFAULT_PRIORITY = Integer.MAX_VALUE; + + /** + * Get the router url. + * + * @return url + */ + URL getUrl(); + + /*** + * Filter invokers with current routing rule and only return the invokers that comply with the rule. + * Caching address lists in BitMap mode improves routing performance. + * @param invokers invoker bit list + * @param cache router address cache + * @param url refer url + * @param invocation invocation + * @param + * @return routed invokers + * @throws RpcException + * @Since 3.0 + */ + BitList> route(BitList> invokers, RouterCache cache, URL url, Invocation invocation) + throws + RpcException; + + default void notify(List> invokers) { + + } + + /** + * To decide whether this router need to execute every time an RPC comes or should only execute when addresses or + * rule change. + * + * @return true if the router need to execute every time. + */ + boolean isRuntime(); + + boolean isEnable(); + + boolean isForce(); + + int getPriority(); + + @Override + default int compareTo(StateRouter o) { + if (o == null) { + throw new IllegalArgumentException(); + } + return Integer.compare(this.getPriority(), o.getPriority()); + } + + String getName(); + + boolean shouldRePool(); + + RouterCache pool(List> invokers); + + void pool(); + + default void stop() { + //do nothing by default + } +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/AvailableCluster.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/AvailableCluster.java index a2e353b4e4..6fcc03ce0b 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/AvailableCluster.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/AvailableCluster.java @@ -1,37 +1,37 @@ -/* - * 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.rpc.cluster.support; - -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.RpcException; -import org.apache.dubbo.rpc.cluster.Cluster; -import org.apache.dubbo.rpc.cluster.Directory; - -/** - * AvailableCluster - * - */ -public class AvailableCluster implements Cluster { - - public static final String NAME = "available"; - - @Override - public Invoker join(Directory directory) throws RpcException { - return new AvailableClusterInvoker<>(directory); - } - -} +/* + * 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.rpc.cluster.support; + +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.cluster.Cluster; +import org.apache.dubbo.rpc.cluster.Directory; + +/** + * AvailableCluster + * + */ +public class AvailableCluster implements Cluster { + + public static final String NAME = "available"; + + @Override + public Invoker join(Directory directory) throws RpcException { + return new AvailableClusterInvoker<>(directory); + } + +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/BroadcastCluster.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/BroadcastCluster.java index f5cab055b1..c9798de61a 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/BroadcastCluster.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/BroadcastCluster.java @@ -1,34 +1,34 @@ -/* - * 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.rpc.cluster.support; - -import org.apache.dubbo.rpc.RpcException; -import org.apache.dubbo.rpc.cluster.Directory; -import org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster; - -/** - * BroadcastCluster - * - */ -public class BroadcastCluster extends AbstractCluster { - - @Override - public AbstractClusterInvoker doJoin(Directory directory) throws RpcException { - return new BroadcastClusterInvoker<>(directory); - } - -} +/* + * 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.rpc.cluster.support; + +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.cluster.Directory; +import org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster; + +/** + * BroadcastCluster + * + */ +public class BroadcastCluster extends AbstractCluster { + + @Override + public AbstractClusterInvoker doJoin(Directory directory) throws RpcException { + return new BroadcastClusterInvoker<>(directory); + } + +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/BroadcastClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/BroadcastClusterInvoker.java index 268140a19b..af5884711a 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/BroadcastClusterInvoker.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/BroadcastClusterInvoker.java @@ -1,116 +1,116 @@ -/* - * 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.rpc.cluster.support; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.rpc.Invocation; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.Result; -import org.apache.dubbo.rpc.RpcContext; -import org.apache.dubbo.rpc.RpcException; -import org.apache.dubbo.rpc.cluster.Directory; -import org.apache.dubbo.rpc.cluster.LoadBalance; - -import java.util.List; - -/** - * BroadcastClusterInvoker - */ -public class BroadcastClusterInvoker extends AbstractClusterInvoker { - - private static final Logger logger = LoggerFactory.getLogger(BroadcastClusterInvoker.class); - private static final String BROADCAST_FAIL_PERCENT_KEY = "broadcast.fail.percent"; - private static final int MAX_BROADCAST_FAIL_PERCENT = 100; - private static final int MIN_BROADCAST_FAIL_PERCENT = 0; - - public BroadcastClusterInvoker(Directory directory) { - super(directory); - } - - @Override - @SuppressWarnings({"unchecked", "rawtypes"}) - public Result doInvoke(final Invocation invocation, List> invokers, LoadBalance loadbalance) throws RpcException { - checkInvokers(invokers, invocation); - RpcContext.getServiceContext().setInvokers((List) invokers); - RpcException exception = null; - Result result = null; - URL url = getUrl(); - // The value range of broadcast.fail.threshold must be 0~100. - // 100 means that an exception will be thrown last, and 0 means that as long as an exception occurs, it will be thrown. - // see https://github.com/apache/dubbo/pull/7174 - int broadcastFailPercent = url.getParameter(BROADCAST_FAIL_PERCENT_KEY, MAX_BROADCAST_FAIL_PERCENT); - - if (broadcastFailPercent < MIN_BROADCAST_FAIL_PERCENT || broadcastFailPercent > MAX_BROADCAST_FAIL_PERCENT) { - logger.info(String.format("The value corresponding to the broadcast.fail.percent parameter must be between 0 and 100. " + - "The current setting is %s, which is reset to 100.", broadcastFailPercent)); - broadcastFailPercent = MAX_BROADCAST_FAIL_PERCENT; - } - - int failThresholdIndex = invokers.size() * broadcastFailPercent / MAX_BROADCAST_FAIL_PERCENT; - int failIndex = 0; - for (Invoker invoker : invokers) { - try { - result = invokeWithContext(invoker, invocation); - if (null != result && result.hasException()) { - Throwable resultException = result.getException(); - if (null != resultException) { - exception = getRpcException(result.getException()); - logger.warn(exception.getMessage(), exception); - if (failIndex == failThresholdIndex) { - break; - } else { - failIndex++; - } - } - } - } catch (Throwable e) { - exception = getRpcException(e); - logger.warn(exception.getMessage(), exception); - if (failIndex == failThresholdIndex) { - break; - } else { - failIndex++; - } - } - } - - if (exception != null) { - if (failIndex == failThresholdIndex) { - logger.debug( - String.format("The number of BroadcastCluster call failures has reached the threshold %s", failThresholdIndex)); - } else { - logger.debug(String.format("The number of BroadcastCluster call failures has not reached the threshold %s, fail size is %s", - failIndex)); - } - throw exception; - } - - return result; - } - - private RpcException getRpcException(Throwable throwable) { - RpcException rpcException = null; - if (throwable instanceof RpcException) { - rpcException = (RpcException) throwable; - } else { - rpcException = new RpcException(throwable.getMessage(), throwable); - } - return rpcException; - } -} +/* + * 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.rpc.cluster.support; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.Result; +import org.apache.dubbo.rpc.RpcContext; +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.cluster.Directory; +import org.apache.dubbo.rpc.cluster.LoadBalance; + +import java.util.List; + +/** + * BroadcastClusterInvoker + */ +public class BroadcastClusterInvoker extends AbstractClusterInvoker { + + private static final Logger logger = LoggerFactory.getLogger(BroadcastClusterInvoker.class); + private static final String BROADCAST_FAIL_PERCENT_KEY = "broadcast.fail.percent"; + private static final int MAX_BROADCAST_FAIL_PERCENT = 100; + private static final int MIN_BROADCAST_FAIL_PERCENT = 0; + + public BroadcastClusterInvoker(Directory directory) { + super(directory); + } + + @Override + @SuppressWarnings({"unchecked", "rawtypes"}) + public Result doInvoke(final Invocation invocation, List> invokers, LoadBalance loadbalance) throws RpcException { + checkInvokers(invokers, invocation); + RpcContext.getServiceContext().setInvokers((List) invokers); + RpcException exception = null; + Result result = null; + URL url = getUrl(); + // The value range of broadcast.fail.threshold must be 0~100. + // 100 means that an exception will be thrown last, and 0 means that as long as an exception occurs, it will be thrown. + // see https://github.com/apache/dubbo/pull/7174 + int broadcastFailPercent = url.getParameter(BROADCAST_FAIL_PERCENT_KEY, MAX_BROADCAST_FAIL_PERCENT); + + if (broadcastFailPercent < MIN_BROADCAST_FAIL_PERCENT || broadcastFailPercent > MAX_BROADCAST_FAIL_PERCENT) { + logger.info(String.format("The value corresponding to the broadcast.fail.percent parameter must be between 0 and 100. " + + "The current setting is %s, which is reset to 100.", broadcastFailPercent)); + broadcastFailPercent = MAX_BROADCAST_FAIL_PERCENT; + } + + int failThresholdIndex = invokers.size() * broadcastFailPercent / MAX_BROADCAST_FAIL_PERCENT; + int failIndex = 0; + for (Invoker invoker : invokers) { + try { + result = invokeWithContext(invoker, invocation); + if (null != result && result.hasException()) { + Throwable resultException = result.getException(); + if (null != resultException) { + exception = getRpcException(result.getException()); + logger.warn(exception.getMessage(), exception); + if (failIndex == failThresholdIndex) { + break; + } else { + failIndex++; + } + } + } + } catch (Throwable e) { + exception = getRpcException(e); + logger.warn(exception.getMessage(), exception); + if (failIndex == failThresholdIndex) { + break; + } else { + failIndex++; + } + } + } + + if (exception != null) { + if (failIndex == failThresholdIndex) { + logger.debug( + String.format("The number of BroadcastCluster call failures has reached the threshold %s", failThresholdIndex)); + } else { + logger.debug(String.format("The number of BroadcastCluster call failures has not reached the threshold %s, fail size is %s", + failIndex)); + } + throw exception; + } + + return result; + } + + private RpcException getRpcException(Throwable throwable) { + RpcException rpcException = null; + if (throwable instanceof RpcException) { + rpcException = (RpcException) throwable; + } else { + rpcException = new RpcException(throwable.getMessage(), throwable); + } + return rpcException; + } +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ClusterUtils.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ClusterUtils.java index 55aff3e095..0ff3255c9c 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ClusterUtils.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ClusterUtils.java @@ -1,51 +1,51 @@ -/* - * 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.rpc.cluster.support; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.common.utils.StringUtils; -import org.apache.dubbo.rpc.cluster.ProviderURLMergeProcessor; - -import java.util.Map; - -import static org.apache.dubbo.common.constants.CommonConstants.URL_MERGE_PROCESSOR_KEY; - - -/** - * ClusterUtils - */ -public class ClusterUtils { - - private ClusterUtils() { - } - - public static URL mergeUrl(URL remoteUrl, Map localMap) { - - String ump = localMap.get(URL_MERGE_PROCESSOR_KEY); - ProviderURLMergeProcessor providerURLMergeProcessor; - - if (StringUtils.isNotEmpty(ump)) { - providerURLMergeProcessor = ExtensionLoader.getExtensionLoader(ProviderURLMergeProcessor.class).getExtension(ump); - } else { - providerURLMergeProcessor = ExtensionLoader.getExtensionLoader(ProviderURLMergeProcessor.class).getExtension("default"); - } - - return providerURLMergeProcessor.mergeUrl(remoteUrl, localMap); - } - -} \ No newline at end of file +/* + * 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.rpc.cluster.support; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.rpc.cluster.ProviderURLMergeProcessor; + +import java.util.Map; + +import static org.apache.dubbo.common.constants.CommonConstants.URL_MERGE_PROCESSOR_KEY; + + +/** + * ClusterUtils + */ +public class ClusterUtils { + + private ClusterUtils() { + } + + public static URL mergeUrl(URL remoteUrl, Map localMap) { + + String ump = localMap.get(URL_MERGE_PROCESSOR_KEY); + ProviderURLMergeProcessor providerURLMergeProcessor; + + if (StringUtils.isNotEmpty(ump)) { + providerURLMergeProcessor = ExtensionLoader.getExtensionLoader(ProviderURLMergeProcessor.class).getExtension(ump); + } else { + providerURLMergeProcessor = ExtensionLoader.getExtensionLoader(ProviderURLMergeProcessor.class).getExtension("default"); + } + + return providerURLMergeProcessor.mergeUrl(remoteUrl, localMap); + } + +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailbackCluster.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailbackCluster.java index 4f4400b3f3..0916f724bc 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailbackCluster.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailbackCluster.java @@ -1,36 +1,36 @@ -/* - * 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.rpc.cluster.support; - -import org.apache.dubbo.rpc.RpcException; -import org.apache.dubbo.rpc.cluster.Directory; -import org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster; - -/** - * {@link FailbackClusterInvoker} - * - */ -public class FailbackCluster extends AbstractCluster { - - public final static String NAME = "failback"; - - @Override - public AbstractClusterInvoker doJoin(Directory directory) throws RpcException { - return new FailbackClusterInvoker<>(directory); - } - -} +/* + * 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.rpc.cluster.support; + +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.cluster.Directory; +import org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster; + +/** + * {@link FailbackClusterInvoker} + * + */ +public class FailbackCluster extends AbstractCluster { + + public final static String NAME = "failback"; + + @Override + public AbstractClusterInvoker doJoin(Directory directory) throws RpcException { + return new FailbackClusterInvoker<>(directory); + } + +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailbackClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailbackClusterInvoker.java index 8bc4b1373b..72d5d30d79 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailbackClusterInvoker.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailbackClusterInvoker.java @@ -1,168 +1,168 @@ -/* - * 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.rpc.cluster.support; - -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.timer.HashedWheelTimer; -import org.apache.dubbo.common.timer.Timeout; -import org.apache.dubbo.common.timer.Timer; -import org.apache.dubbo.common.timer.TimerTask; -import org.apache.dubbo.common.utils.NamedThreadFactory; -import org.apache.dubbo.rpc.AsyncRpcResult; -import org.apache.dubbo.rpc.Invocation; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.Result; -import org.apache.dubbo.rpc.RpcException; -import org.apache.dubbo.rpc.cluster.Directory; -import org.apache.dubbo.rpc.cluster.LoadBalance; - -import java.util.Collections; -import java.util.List; -import java.util.concurrent.TimeUnit; - -import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_FAILBACK_TIMES; -import static org.apache.dubbo.common.constants.CommonConstants.RETRIES_KEY; -import static org.apache.dubbo.rpc.cluster.Constants.DEFAULT_FAILBACK_TASKS; -import static org.apache.dubbo.rpc.cluster.Constants.FAIL_BACK_TASKS_KEY; - -/** - * When fails, record failure requests and schedule for retry on a regular interval. - * Especially useful for services of notification. - * - * Failback - */ -public class FailbackClusterInvoker extends AbstractClusterInvoker { - - private static final Logger logger = LoggerFactory.getLogger(FailbackClusterInvoker.class); - - private static final long RETRY_FAILED_PERIOD = 5; - - private final int retries; - - private final int failbackTasks; - - private volatile Timer failTimer; - - public FailbackClusterInvoker(Directory directory) { - super(directory); - - int retriesConfig = getUrl().getParameter(RETRIES_KEY, DEFAULT_FAILBACK_TIMES); - if (retriesConfig <= 0) { - retriesConfig = DEFAULT_FAILBACK_TIMES; - } - int failbackTasksConfig = getUrl().getParameter(FAIL_BACK_TASKS_KEY, DEFAULT_FAILBACK_TASKS); - if (failbackTasksConfig <= 0) { - failbackTasksConfig = DEFAULT_FAILBACK_TASKS; - } - retries = retriesConfig; - failbackTasks = failbackTasksConfig; - } - - private void addFailed(LoadBalance loadbalance, Invocation invocation, List> invokers, Invoker lastInvoker) { - if (failTimer == null) { - synchronized (this) { - if (failTimer == null) { - failTimer = new HashedWheelTimer( - new NamedThreadFactory("failback-cluster-timer", true), - 1, - TimeUnit.SECONDS, 32, failbackTasks); - } - } - } - RetryTimerTask retryTimerTask = new RetryTimerTask(loadbalance, invocation, invokers, lastInvoker, retries, RETRY_FAILED_PERIOD); - try { - failTimer.newTimeout(retryTimerTask, RETRY_FAILED_PERIOD, TimeUnit.SECONDS); - } catch (Throwable e) { - logger.error("Failback background works error,invocation->" + invocation + ", exception: " + e.getMessage()); - } - } - - @Override - protected Result doInvoke(Invocation invocation, List> invokers, LoadBalance loadbalance) throws RpcException { - Invoker invoker = null; - try { - checkInvokers(invokers, invocation); - invoker = select(loadbalance, invocation, invokers, null); - return invokeWithContext(invoker, invocation); - } catch (Throwable e) { - logger.error("Failback to invoke method " + invocation.getMethodName() + ", wait for retry in background. Ignored exception: " - + e.getMessage() + ", ", e); - addFailed(loadbalance, invocation, invokers, invoker); - return AsyncRpcResult.newDefaultAsyncResult(null, null, invocation); // ignore - } - } - - @Override - public void destroy() { - super.destroy(); - if (failTimer != null) { - failTimer.stop(); - } - } - - /** - * RetryTimerTask - */ - private class RetryTimerTask implements TimerTask { - private final Invocation invocation; - private final LoadBalance loadbalance; - private final List> invokers; - private final int retries; - private final long tick; - private Invoker lastInvoker; - private int retryTimes = 0; - - RetryTimerTask(LoadBalance loadbalance, Invocation invocation, List> invokers, Invoker lastInvoker, int retries, long tick) { - this.loadbalance = loadbalance; - this.invocation = invocation; - this.invokers = invokers; - this.retries = retries; - this.tick = tick; - this.lastInvoker=lastInvoker; - } - - @Override - public void run(Timeout timeout) { - try { - Invoker retryInvoker = select(loadbalance, invocation, invokers, Collections.singletonList(lastInvoker)); - lastInvoker = retryInvoker; - invokeWithContext(retryInvoker, invocation); - } catch (Throwable e) { - logger.error("Failed retry to invoke method " + invocation.getMethodName() + ", waiting again.", e); - if ((++retryTimes) >= retries) { - logger.error("Failed retry times exceed threshold (" + retries + "), We have to abandon, invocation->" + invocation); - } else { - rePut(timeout); - } - } - } - - private void rePut(Timeout timeout) { - if (timeout == null) { - return; - } - - Timer timer = timeout.timer(); - if (timer.isStop() || timeout.isCancelled()) { - return; - } - - timer.newTimeout(timeout.task(), tick, TimeUnit.SECONDS); - } - } -} +/* + * 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.rpc.cluster.support; + +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.timer.HashedWheelTimer; +import org.apache.dubbo.common.timer.Timeout; +import org.apache.dubbo.common.timer.Timer; +import org.apache.dubbo.common.timer.TimerTask; +import org.apache.dubbo.common.utils.NamedThreadFactory; +import org.apache.dubbo.rpc.AsyncRpcResult; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.Result; +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.cluster.Directory; +import org.apache.dubbo.rpc.cluster.LoadBalance; + +import java.util.Collections; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_FAILBACK_TIMES; +import static org.apache.dubbo.common.constants.CommonConstants.RETRIES_KEY; +import static org.apache.dubbo.rpc.cluster.Constants.DEFAULT_FAILBACK_TASKS; +import static org.apache.dubbo.rpc.cluster.Constants.FAIL_BACK_TASKS_KEY; + +/** + * When fails, record failure requests and schedule for retry on a regular interval. + * Especially useful for services of notification. + * + * Failback + */ +public class FailbackClusterInvoker extends AbstractClusterInvoker { + + private static final Logger logger = LoggerFactory.getLogger(FailbackClusterInvoker.class); + + private static final long RETRY_FAILED_PERIOD = 5; + + private final int retries; + + private final int failbackTasks; + + private volatile Timer failTimer; + + public FailbackClusterInvoker(Directory directory) { + super(directory); + + int retriesConfig = getUrl().getParameter(RETRIES_KEY, DEFAULT_FAILBACK_TIMES); + if (retriesConfig <= 0) { + retriesConfig = DEFAULT_FAILBACK_TIMES; + } + int failbackTasksConfig = getUrl().getParameter(FAIL_BACK_TASKS_KEY, DEFAULT_FAILBACK_TASKS); + if (failbackTasksConfig <= 0) { + failbackTasksConfig = DEFAULT_FAILBACK_TASKS; + } + retries = retriesConfig; + failbackTasks = failbackTasksConfig; + } + + private void addFailed(LoadBalance loadbalance, Invocation invocation, List> invokers, Invoker lastInvoker) { + if (failTimer == null) { + synchronized (this) { + if (failTimer == null) { + failTimer = new HashedWheelTimer( + new NamedThreadFactory("failback-cluster-timer", true), + 1, + TimeUnit.SECONDS, 32, failbackTasks); + } + } + } + RetryTimerTask retryTimerTask = new RetryTimerTask(loadbalance, invocation, invokers, lastInvoker, retries, RETRY_FAILED_PERIOD); + try { + failTimer.newTimeout(retryTimerTask, RETRY_FAILED_PERIOD, TimeUnit.SECONDS); + } catch (Throwable e) { + logger.error("Failback background works error,invocation->" + invocation + ", exception: " + e.getMessage()); + } + } + + @Override + protected Result doInvoke(Invocation invocation, List> invokers, LoadBalance loadbalance) throws RpcException { + Invoker invoker = null; + try { + checkInvokers(invokers, invocation); + invoker = select(loadbalance, invocation, invokers, null); + return invokeWithContext(invoker, invocation); + } catch (Throwable e) { + logger.error("Failback to invoke method " + invocation.getMethodName() + ", wait for retry in background. Ignored exception: " + + e.getMessage() + ", ", e); + addFailed(loadbalance, invocation, invokers, invoker); + return AsyncRpcResult.newDefaultAsyncResult(null, null, invocation); // ignore + } + } + + @Override + public void destroy() { + super.destroy(); + if (failTimer != null) { + failTimer.stop(); + } + } + + /** + * RetryTimerTask + */ + private class RetryTimerTask implements TimerTask { + private final Invocation invocation; + private final LoadBalance loadbalance; + private final List> invokers; + private final int retries; + private final long tick; + private Invoker lastInvoker; + private int retryTimes = 0; + + RetryTimerTask(LoadBalance loadbalance, Invocation invocation, List> invokers, Invoker lastInvoker, int retries, long tick) { + this.loadbalance = loadbalance; + this.invocation = invocation; + this.invokers = invokers; + this.retries = retries; + this.tick = tick; + this.lastInvoker=lastInvoker; + } + + @Override + public void run(Timeout timeout) { + try { + Invoker retryInvoker = select(loadbalance, invocation, invokers, Collections.singletonList(lastInvoker)); + lastInvoker = retryInvoker; + invokeWithContext(retryInvoker, invocation); + } catch (Throwable e) { + logger.error("Failed retry to invoke method " + invocation.getMethodName() + ", waiting again.", e); + if ((++retryTimes) >= retries) { + logger.error("Failed retry times exceed threshold (" + retries + "), We have to abandon, invocation->" + invocation); + } else { + rePut(timeout); + } + } + } + + private void rePut(Timeout timeout) { + if (timeout == null) { + return; + } + + Timer timer = timeout.timer(); + if (timer.isStop() || timeout.isCancelled()) { + return; + } + + timer.newTimeout(timeout.task(), tick, TimeUnit.SECONDS); + } + } +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailfastCluster.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailfastCluster.java index 14a8565d20..2a04a1535b 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailfastCluster.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailfastCluster.java @@ -1,36 +1,36 @@ -/* - * 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.rpc.cluster.support; - -import org.apache.dubbo.rpc.RpcException; -import org.apache.dubbo.rpc.cluster.Directory; -import org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster; - -/** - * {@link FailfastClusterInvoker} - * - */ -public class FailfastCluster extends AbstractCluster { - - public final static String NAME = "failfast"; - - @Override - public AbstractClusterInvoker doJoin(Directory directory) throws RpcException { - return new FailfastClusterInvoker<>(directory); - } - -} +/* + * 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.rpc.cluster.support; + +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.cluster.Directory; +import org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster; + +/** + * {@link FailfastClusterInvoker} + * + */ +public class FailfastCluster extends AbstractCluster { + + public final static String NAME = "failfast"; + + @Override + public AbstractClusterInvoker doJoin(Directory directory) throws RpcException { + return new FailfastClusterInvoker<>(directory); + } + +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailfastClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailfastClusterInvoker.java index d349808717..60490ca26f 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailfastClusterInvoker.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailfastClusterInvoker.java @@ -1,62 +1,62 @@ -/* - * 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.rpc.cluster.support; - -import org.apache.dubbo.common.Version; -import org.apache.dubbo.common.utils.NetUtils; -import org.apache.dubbo.rpc.Invocation; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.Result; -import org.apache.dubbo.rpc.RpcException; -import org.apache.dubbo.rpc.cluster.Directory; -import org.apache.dubbo.rpc.cluster.LoadBalance; - -import java.util.List; - -/** - * Execute exactly once, which means this policy will throw an exception immediately in case of an invocation error. - * Usually used for non-idempotent write operations - * - * Fail-fast - * - */ -public class FailfastClusterInvoker extends AbstractClusterInvoker { - - public FailfastClusterInvoker(Directory directory) { - super(directory); - } - - @Override - public Result doInvoke(Invocation invocation, List> invokers, LoadBalance loadbalance) throws RpcException { - checkInvokers(invokers, invocation); - Invoker invoker = select(loadbalance, invocation, invokers, null); - try { - return invokeWithContext(invoker, invocation); - } catch (Throwable e) { - if (e instanceof RpcException && ((RpcException) e).isBiz()) { // biz exception. - throw (RpcException) e; - } - throw new RpcException(e instanceof RpcException ? ((RpcException) e).getCode() : 0, - "Failfast invoke providers " + invoker.getUrl() + " " + loadbalance.getClass().getSimpleName() - + " select from all providers " + invokers + " for service " + getInterface().getName() - + " method " + invocation.getMethodName() + " on consumer " + NetUtils.getLocalHost() - + " use dubbo version " + Version.getVersion() - + ", but no luck to perform the invocation. Last error is: " + e.getMessage(), - e.getCause() != null ? e.getCause() : e); - } - } -} +/* + * 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.rpc.cluster.support; + +import org.apache.dubbo.common.Version; +import org.apache.dubbo.common.utils.NetUtils; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.Result; +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.cluster.Directory; +import org.apache.dubbo.rpc.cluster.LoadBalance; + +import java.util.List; + +/** + * Execute exactly once, which means this policy will throw an exception immediately in case of an invocation error. + * Usually used for non-idempotent write operations + * + * Fail-fast + * + */ +public class FailfastClusterInvoker extends AbstractClusterInvoker { + + public FailfastClusterInvoker(Directory directory) { + super(directory); + } + + @Override + public Result doInvoke(Invocation invocation, List> invokers, LoadBalance loadbalance) throws RpcException { + checkInvokers(invokers, invocation); + Invoker invoker = select(loadbalance, invocation, invokers, null); + try { + return invokeWithContext(invoker, invocation); + } catch (Throwable e) { + if (e instanceof RpcException && ((RpcException) e).isBiz()) { // biz exception. + throw (RpcException) e; + } + throw new RpcException(e instanceof RpcException ? ((RpcException) e).getCode() : 0, + "Failfast invoke providers " + invoker.getUrl() + " " + loadbalance.getClass().getSimpleName() + + " select from all providers " + invokers + " for service " + getInterface().getName() + + " method " + invocation.getMethodName() + " on consumer " + NetUtils.getLocalHost() + + " use dubbo version " + Version.getVersion() + + ", but no luck to perform the invocation. Last error is: " + e.getMessage(), + e.getCause() != null ? e.getCause() : e); + } + } +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailoverCluster.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailoverCluster.java index 7f1bc54666..e9e6101b05 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailoverCluster.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailoverCluster.java @@ -1,36 +1,36 @@ -/* - * 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.rpc.cluster.support; - -import org.apache.dubbo.rpc.RpcException; -import org.apache.dubbo.rpc.cluster.Directory; -import org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster; - -/** - * {@link FailoverClusterInvoker} - * - */ -public class FailoverCluster extends AbstractCluster { - - public final static String NAME = "failover"; - - @Override - public AbstractClusterInvoker doJoin(Directory directory) throws RpcException { - return new FailoverClusterInvoker<>(directory); - } - -} +/* + * 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.rpc.cluster.support; + +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.cluster.Directory; +import org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster; + +/** + * {@link FailoverClusterInvoker} + * + */ +public class FailoverCluster extends AbstractCluster { + + public final static String NAME = "failover"; + + @Override + public AbstractClusterInvoker doJoin(Directory directory) throws RpcException { + return new FailoverClusterInvoker<>(directory); + } + +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvoker.java index a445d366b5..d3abeb299c 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvoker.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvoker.java @@ -1,128 +1,128 @@ -/* - * 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.rpc.cluster.support; - -import org.apache.dubbo.common.Version; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.utils.NetUtils; -import org.apache.dubbo.rpc.Invocation; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.Result; -import org.apache.dubbo.rpc.RpcContext; -import org.apache.dubbo.rpc.RpcException; -import org.apache.dubbo.rpc.cluster.Directory; -import org.apache.dubbo.rpc.cluster.LoadBalance; -import org.apache.dubbo.rpc.support.RpcUtils; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_RETRIES; -import static org.apache.dubbo.common.constants.CommonConstants.RETRIES_KEY; - -/** - * When invoke fails, log the initial error and retry other invokers (retry n times, which means at most n different invokers will be invoked) - * Note that retry causes latency. - *

- * Failover - * - */ -public class FailoverClusterInvoker extends AbstractClusterInvoker { - - private static final Logger logger = LoggerFactory.getLogger(FailoverClusterInvoker.class); - - public FailoverClusterInvoker(Directory directory) { - super(directory); - } - - @Override - @SuppressWarnings({"unchecked", "rawtypes"}) - public Result doInvoke(Invocation invocation, final List> invokers, LoadBalance loadbalance) throws RpcException { - List> copyInvokers = invokers; - checkInvokers(copyInvokers, invocation); - String methodName = RpcUtils.getMethodName(invocation); - int len = calculateInvokeTimes(methodName); - // retry loop. - RpcException le = null; // last exception. - List> invoked = new ArrayList>(copyInvokers.size()); // invoked invokers. - Set providers = new HashSet(len); - for (int i = 0; i < len; i++) { - //Reselect before retry to avoid a change of candidate `invokers`. - //NOTE: if `invokers` changed, then `invoked` also lose accuracy. - if (i > 0) { - checkWhetherDestroyed(); - copyInvokers = list(invocation); - // check again - checkInvokers(copyInvokers, invocation); - } - Invoker invoker = select(loadbalance, invocation, copyInvokers, invoked); - invoked.add(invoker); - RpcContext.getServiceContext().setInvokers((List) invoked); - try { - Result result = invokeWithContext(invoker, invocation); - if (le != null && logger.isWarnEnabled()) { - logger.warn("Although retry the method " + methodName - + " in the service " + getInterface().getName() - + " was successful by the provider " + invoker.getUrl().getAddress() - + ", but there have been failed providers " + providers - + " (" + providers.size() + "/" + copyInvokers.size() - + ") from the registry " + directory.getUrl().getAddress() - + " on the consumer " + NetUtils.getLocalHost() - + " using the dubbo version " + Version.getVersion() + ". Last error is: " - + le.getMessage(), le); - } - return result; - } catch (RpcException e) { - if (e.isBiz()) { // biz exception. - throw e; - } - le = e; - } catch (Throwable e) { - le = new RpcException(e.getMessage(), e); - } finally { - providers.add(invoker.getUrl().getAddress()); - } - } - throw new RpcException(le.getCode(), "Failed to invoke the method " - + methodName + " in the service " + getInterface().getName() - + ". Tried " + len + " times of the providers " + providers - + " (" + providers.size() + "/" + copyInvokers.size() - + ") from the registry " + directory.getUrl().getAddress() - + " on the consumer " + NetUtils.getLocalHost() + " using the dubbo version " - + Version.getVersion() + ". Last error is: " - + le.getMessage(), le.getCause() != null ? le.getCause() : le); - } - - private int calculateInvokeTimes(String methodName) { - int len = getUrl().getMethodParameter(methodName, RETRIES_KEY, DEFAULT_RETRIES) + 1; - RpcContext rpcContext = RpcContext.getClientAttachment(); - Object retry = rpcContext.getObjectAttachment(RETRIES_KEY); - if (retry instanceof Number) { - len = ((Number) retry).intValue() + 1; - rpcContext.removeAttachment(RETRIES_KEY); - } - if (len <= 0) { - len = 1; - } - - return len; - } - -} +/* + * 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.rpc.cluster.support; + +import org.apache.dubbo.common.Version; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.NetUtils; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.Result; +import org.apache.dubbo.rpc.RpcContext; +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.cluster.Directory; +import org.apache.dubbo.rpc.cluster.LoadBalance; +import org.apache.dubbo.rpc.support.RpcUtils; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_RETRIES; +import static org.apache.dubbo.common.constants.CommonConstants.RETRIES_KEY; + +/** + * When invoke fails, log the initial error and retry other invokers (retry n times, which means at most n different invokers will be invoked) + * Note that retry causes latency. + *

+ * Failover + * + */ +public class FailoverClusterInvoker extends AbstractClusterInvoker { + + private static final Logger logger = LoggerFactory.getLogger(FailoverClusterInvoker.class); + + public FailoverClusterInvoker(Directory directory) { + super(directory); + } + + @Override + @SuppressWarnings({"unchecked", "rawtypes"}) + public Result doInvoke(Invocation invocation, final List> invokers, LoadBalance loadbalance) throws RpcException { + List> copyInvokers = invokers; + checkInvokers(copyInvokers, invocation); + String methodName = RpcUtils.getMethodName(invocation); + int len = calculateInvokeTimes(methodName); + // retry loop. + RpcException le = null; // last exception. + List> invoked = new ArrayList>(copyInvokers.size()); // invoked invokers. + Set providers = new HashSet(len); + for (int i = 0; i < len; i++) { + //Reselect before retry to avoid a change of candidate `invokers`. + //NOTE: if `invokers` changed, then `invoked` also lose accuracy. + if (i > 0) { + checkWhetherDestroyed(); + copyInvokers = list(invocation); + // check again + checkInvokers(copyInvokers, invocation); + } + Invoker invoker = select(loadbalance, invocation, copyInvokers, invoked); + invoked.add(invoker); + RpcContext.getServiceContext().setInvokers((List) invoked); + try { + Result result = invokeWithContext(invoker, invocation); + if (le != null && logger.isWarnEnabled()) { + logger.warn("Although retry the method " + methodName + + " in the service " + getInterface().getName() + + " was successful by the provider " + invoker.getUrl().getAddress() + + ", but there have been failed providers " + providers + + " (" + providers.size() + "/" + copyInvokers.size() + + ") from the registry " + directory.getUrl().getAddress() + + " on the consumer " + NetUtils.getLocalHost() + + " using the dubbo version " + Version.getVersion() + ". Last error is: " + + le.getMessage(), le); + } + return result; + } catch (RpcException e) { + if (e.isBiz()) { // biz exception. + throw e; + } + le = e; + } catch (Throwable e) { + le = new RpcException(e.getMessage(), e); + } finally { + providers.add(invoker.getUrl().getAddress()); + } + } + throw new RpcException(le.getCode(), "Failed to invoke the method " + + methodName + " in the service " + getInterface().getName() + + ". Tried " + len + " times of the providers " + providers + + " (" + providers.size() + "/" + copyInvokers.size() + + ") from the registry " + directory.getUrl().getAddress() + + " on the consumer " + NetUtils.getLocalHost() + " using the dubbo version " + + Version.getVersion() + ". Last error is: " + + le.getMessage(), le.getCause() != null ? le.getCause() : le); + } + + private int calculateInvokeTimes(String methodName) { + int len = getUrl().getMethodParameter(methodName, RETRIES_KEY, DEFAULT_RETRIES) + 1; + RpcContext rpcContext = RpcContext.getClientAttachment(); + Object retry = rpcContext.getObjectAttachment(RETRIES_KEY); + if (retry instanceof Number) { + len = ((Number) retry).intValue() + 1; + rpcContext.removeAttachment(RETRIES_KEY); + } + if (len <= 0) { + len = 1; + } + + return len; + } + +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailsafeCluster.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailsafeCluster.java index 767ab316b8..7064950489 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailsafeCluster.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailsafeCluster.java @@ -1,36 +1,36 @@ -/* - * 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.rpc.cluster.support; - -import org.apache.dubbo.rpc.RpcException; -import org.apache.dubbo.rpc.cluster.Directory; -import org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster; - -/** - * {@link FailsafeClusterInvoker} - * - */ -public class FailsafeCluster extends AbstractCluster { - - public final static String NAME = "failsafe"; - - @Override - public AbstractClusterInvoker doJoin(Directory directory) throws RpcException { - return new FailsafeClusterInvoker<>(directory); - } - -} +/* + * 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.rpc.cluster.support; + +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.cluster.Directory; +import org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster; + +/** + * {@link FailsafeClusterInvoker} + * + */ +public class FailsafeCluster extends AbstractCluster { + + public final static String NAME = "failsafe"; + + @Override + public AbstractClusterInvoker doJoin(Directory directory) throws RpcException { + return new FailsafeClusterInvoker<>(directory); + } + +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailsafeClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailsafeClusterInvoker.java index 3548a679a8..edc9ec5ee3 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailsafeClusterInvoker.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailsafeClusterInvoker.java @@ -1,56 +1,56 @@ -/* - * 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.rpc.cluster.support; - -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.rpc.AsyncRpcResult; -import org.apache.dubbo.rpc.Invocation; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.Result; -import org.apache.dubbo.rpc.RpcException; -import org.apache.dubbo.rpc.cluster.Directory; -import org.apache.dubbo.rpc.cluster.LoadBalance; - -import java.util.List; - -/** - * When invoke fails, log the error message and ignore this error by returning an empty Result. - * Usually used to write audit logs and other operations - * - * Fail-safe - * - */ -public class FailsafeClusterInvoker extends AbstractClusterInvoker { - private static final Logger logger = LoggerFactory.getLogger(FailsafeClusterInvoker.class); - - public FailsafeClusterInvoker(Directory directory) { - super(directory); - } - - @Override - public Result doInvoke(Invocation invocation, List> invokers, LoadBalance loadbalance) throws RpcException { - try { - checkInvokers(invokers, invocation); - Invoker invoker = select(loadbalance, invocation, invokers, null); - return invokeWithContext(invoker, invocation); - } catch (Throwable e) { - logger.error("Failsafe ignore exception: " + e.getMessage(), e); - return AsyncRpcResult.newDefaultAsyncResult(null, null, invocation); // ignore - } - } -} +/* + * 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.rpc.cluster.support; + +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.rpc.AsyncRpcResult; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.Result; +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.cluster.Directory; +import org.apache.dubbo.rpc.cluster.LoadBalance; + +import java.util.List; + +/** + * When invoke fails, log the error message and ignore this error by returning an empty Result. + * Usually used to write audit logs and other operations + * + * Fail-safe + * + */ +public class FailsafeClusterInvoker extends AbstractClusterInvoker { + private static final Logger logger = LoggerFactory.getLogger(FailsafeClusterInvoker.class); + + public FailsafeClusterInvoker(Directory directory) { + super(directory); + } + + @Override + public Result doInvoke(Invocation invocation, List> invokers, LoadBalance loadbalance) throws RpcException { + try { + checkInvokers(invokers, invocation); + Invoker invoker = select(loadbalance, invocation, invokers, null); + return invokeWithContext(invoker, invocation); + } catch (Throwable e) { + logger.error("Failsafe ignore exception: " + e.getMessage(), e); + return AsyncRpcResult.newDefaultAsyncResult(null, null, invocation); // ignore + } + } +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ForkingCluster.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ForkingCluster.java index b28cffdd24..83ecbb8c3b 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ForkingCluster.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ForkingCluster.java @@ -1,36 +1,36 @@ -/* - * 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.rpc.cluster.support; - -import org.apache.dubbo.rpc.RpcException; -import org.apache.dubbo.rpc.cluster.Directory; -import org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster; - -/** - * {@link ForkingClusterInvoker} - * - */ -public class ForkingCluster extends AbstractCluster { - - public final static String NAME = "forking"; - - @Override - public AbstractClusterInvoker doJoin(Directory directory) throws RpcException { - return new ForkingClusterInvoker<>(directory); - } - -} +/* + * 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.rpc.cluster.support; + +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.cluster.Directory; +import org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster; + +/** + * {@link ForkingClusterInvoker} + * + */ +public class ForkingCluster extends AbstractCluster { + + public final static String NAME = "forking"; + + @Override + public AbstractClusterInvoker doJoin(Directory directory) throws RpcException { + return new ForkingClusterInvoker<>(directory); + } + +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/merger/DefaultProviderURLMergeProcessor.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/merger/DefaultProviderURLMergeProcessor.java index 93f25bdc93..8610bc893f 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/merger/DefaultProviderURLMergeProcessor.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/merger/DefaultProviderURLMergeProcessor.java @@ -120,4 +120,4 @@ public class DefaultProviderURLMergeProcessor implements ProviderURLMergeProcess return remoteUrl.clearParameters().addParameters(map); } -} \ No newline at end of file +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/registry/ZoneAwareCluster.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/registry/ZoneAwareCluster.java index 64e09b83f6..cfd36e1254 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/registry/ZoneAwareCluster.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/registry/ZoneAwareCluster.java @@ -30,4 +30,4 @@ public class ZoneAwareCluster extends AbstractCluster { return new ZoneAwareClusterInvoker(directory); } -} \ No newline at end of file +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/registry/ZoneAwareClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/registry/ZoneAwareClusterInvoker.java index 97b7a0b544..5e14b8729c 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/registry/ZoneAwareClusterInvoker.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/registry/ZoneAwareClusterInvoker.java @@ -102,4 +102,4 @@ public class ZoneAwareClusterInvoker extends AbstractClusterInvoker { return invokers.get(0).invoke(invocation); } -} \ No newline at end of file +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterInvoker.java index 51d0a49755..8dbf6f57ee 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterInvoker.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterInvoker.java @@ -1,195 +1,195 @@ -/* - * 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.rpc.cluster.support.wrapper; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.utils.CollectionUtils; -import org.apache.dubbo.common.utils.StringUtils; -import org.apache.dubbo.rpc.AsyncRpcResult; -import org.apache.dubbo.rpc.Invocation; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.Result; -import org.apache.dubbo.rpc.RpcException; -import org.apache.dubbo.rpc.RpcInvocation; -import org.apache.dubbo.rpc.cluster.ClusterInvoker; -import org.apache.dubbo.rpc.cluster.Directory; -import org.apache.dubbo.rpc.support.MockInvoker; - -import java.util.List; - -import static org.apache.dubbo.rpc.Constants.MOCK_KEY; -import static org.apache.dubbo.rpc.cluster.Constants.INVOCATION_NEED_MOCK; - -public class MockClusterInvoker implements ClusterInvoker { - - private static final Logger logger = LoggerFactory.getLogger(MockClusterInvoker.class); - - private final Directory directory; - - private final Invoker invoker; - - public MockClusterInvoker(Directory directory, Invoker invoker) { - this.directory = directory; - this.invoker = invoker; - } - - @Override - public URL getUrl() { - return directory.getConsumerUrl(); - } - - public URL getRegistryUrl() { - return directory.getUrl(); - } - - @Override - public Directory getDirectory() { - return directory; - } - - @Override - public boolean isDestroyed() { - return directory.isDestroyed(); - } - - @Override - public boolean isAvailable() { - return directory.isAvailable(); - } - - @Override - public void destroy() { - this.invoker.destroy(); - } - - @Override - public Class getInterface() { - return directory.getInterface(); - } - - @Override - public Result invoke(Invocation invocation) throws RpcException { - Result result = null; - - String value = getUrl().getMethodParameter(invocation.getMethodName(), MOCK_KEY, Boolean.FALSE.toString()).trim(); - if (value.length() == 0 || "false".equalsIgnoreCase(value)) { - //no mock - result = this.invoker.invoke(invocation); - } else if (value.startsWith("force")) { - if (logger.isWarnEnabled()) { - logger.warn("force-mock: " + invocation.getMethodName() + " force-mock enabled , url : " + getUrl()); - } - //force:direct mock - result = doMockInvoke(invocation, null); - } else { - //fail-mock - try { - result = this.invoker.invoke(invocation); - - //fix:#4585 - if(result.getException() != null && result.getException() instanceof RpcException){ - RpcException rpcException= (RpcException)result.getException(); - if(rpcException.isBiz()){ - throw rpcException; - }else { - result = doMockInvoke(invocation, rpcException); - } - } - - } catch (RpcException e) { - if (e.isBiz()) { - throw e; - } - - if (logger.isWarnEnabled()) { - logger.warn("fail-mock: " + invocation.getMethodName() + " fail-mock enabled , url : " + getUrl(), e); - } - result = doMockInvoke(invocation, e); - } - } - return result; - } - - @SuppressWarnings({"unchecked", "rawtypes"}) - private Result doMockInvoke(Invocation invocation, RpcException e) { - Result result = null; - Invoker minvoker; - - List> mockInvokers = selectMockInvoker(invocation); - if (CollectionUtils.isEmpty(mockInvokers)) { - minvoker = (Invoker) new MockInvoker(getUrl(), directory.getInterface()); - } else { - minvoker = mockInvokers.get(0); - } - try { - result = minvoker.invoke(invocation); - } catch (RpcException me) { - if (me.isBiz()) { - result = AsyncRpcResult.newDefaultAsyncResult(me.getCause(), invocation); - } else { - throw new RpcException(me.getCode(), getMockExceptionMessage(e, me), me.getCause()); - } - } catch (Throwable me) { - throw new RpcException(getMockExceptionMessage(e, me), me.getCause()); - } - return result; - } - - private String getMockExceptionMessage(Throwable t, Throwable mt) { - String msg = "mock error : " + mt.getMessage(); - if (t != null) { - msg = msg + ", invoke error is :" + StringUtils.toString(t); - } - return msg; - } - - /** - * Return MockInvoker - * Contract: - * directory.list() will return a list of normal invokers if Constants.INVOCATION_NEED_MOCK is absent or not true in invocation, otherwise, a list of mock invokers will return. - * if directory.list() returns more than one mock invoker, only one of them will be used. - * - * @param invocation - * @return - */ - private List> selectMockInvoker(Invocation invocation) { - List> invokers = null; - //TODO generic invoker? - if (invocation instanceof RpcInvocation) { - //Note the implicit contract (although the description is added to the interface declaration, but extensibility is a problem. The practice placed in the attachment needs to be improved) - ((RpcInvocation) invocation).setAttachment(INVOCATION_NEED_MOCK, Boolean.TRUE.toString()); - //directory will return a list of normal invokers if Constants.INVOCATION_NEED_MOCK is absent or not true in invocation, otherwise, a list of mock invokers will return. - try { - invokers = directory.list(invocation); - } catch (RpcException e) { - if (logger.isInfoEnabled()) { - logger.info("Exception when try to invoke mock. Get mock invokers error for service:" - + getUrl().getServiceInterface() + ", method:" + invocation.getMethodName() - + ", will construct a new mock with 'new MockInvoker()'.", e); - } - } - } - return invokers; - } - - @Override - public String toString() { - return "invoker :" + this.invoker + ",directory: " + this.directory; - } -} +/* + * 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.rpc.cluster.support.wrapper; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.rpc.AsyncRpcResult; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.Result; +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.RpcInvocation; +import org.apache.dubbo.rpc.cluster.ClusterInvoker; +import org.apache.dubbo.rpc.cluster.Directory; +import org.apache.dubbo.rpc.support.MockInvoker; + +import java.util.List; + +import static org.apache.dubbo.rpc.Constants.MOCK_KEY; +import static org.apache.dubbo.rpc.cluster.Constants.INVOCATION_NEED_MOCK; + +public class MockClusterInvoker implements ClusterInvoker { + + private static final Logger logger = LoggerFactory.getLogger(MockClusterInvoker.class); + + private final Directory directory; + + private final Invoker invoker; + + public MockClusterInvoker(Directory directory, Invoker invoker) { + this.directory = directory; + this.invoker = invoker; + } + + @Override + public URL getUrl() { + return directory.getConsumerUrl(); + } + + public URL getRegistryUrl() { + return directory.getUrl(); + } + + @Override + public Directory getDirectory() { + return directory; + } + + @Override + public boolean isDestroyed() { + return directory.isDestroyed(); + } + + @Override + public boolean isAvailable() { + return directory.isAvailable(); + } + + @Override + public void destroy() { + this.invoker.destroy(); + } + + @Override + public Class getInterface() { + return directory.getInterface(); + } + + @Override + public Result invoke(Invocation invocation) throws RpcException { + Result result = null; + + String value = getUrl().getMethodParameter(invocation.getMethodName(), MOCK_KEY, Boolean.FALSE.toString()).trim(); + if (value.length() == 0 || "false".equalsIgnoreCase(value)) { + //no mock + result = this.invoker.invoke(invocation); + } else if (value.startsWith("force")) { + if (logger.isWarnEnabled()) { + logger.warn("force-mock: " + invocation.getMethodName() + " force-mock enabled , url : " + getUrl()); + } + //force:direct mock + result = doMockInvoke(invocation, null); + } else { + //fail-mock + try { + result = this.invoker.invoke(invocation); + + //fix:#4585 + if(result.getException() != null && result.getException() instanceof RpcException){ + RpcException rpcException= (RpcException)result.getException(); + if(rpcException.isBiz()){ + throw rpcException; + }else { + result = doMockInvoke(invocation, rpcException); + } + } + + } catch (RpcException e) { + if (e.isBiz()) { + throw e; + } + + if (logger.isWarnEnabled()) { + logger.warn("fail-mock: " + invocation.getMethodName() + " fail-mock enabled , url : " + getUrl(), e); + } + result = doMockInvoke(invocation, e); + } + } + return result; + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + private Result doMockInvoke(Invocation invocation, RpcException e) { + Result result = null; + Invoker minvoker; + + List> mockInvokers = selectMockInvoker(invocation); + if (CollectionUtils.isEmpty(mockInvokers)) { + minvoker = (Invoker) new MockInvoker(getUrl(), directory.getInterface()); + } else { + minvoker = mockInvokers.get(0); + } + try { + result = minvoker.invoke(invocation); + } catch (RpcException me) { + if (me.isBiz()) { + result = AsyncRpcResult.newDefaultAsyncResult(me.getCause(), invocation); + } else { + throw new RpcException(me.getCode(), getMockExceptionMessage(e, me), me.getCause()); + } + } catch (Throwable me) { + throw new RpcException(getMockExceptionMessage(e, me), me.getCause()); + } + return result; + } + + private String getMockExceptionMessage(Throwable t, Throwable mt) { + String msg = "mock error : " + mt.getMessage(); + if (t != null) { + msg = msg + ", invoke error is :" + StringUtils.toString(t); + } + return msg; + } + + /** + * Return MockInvoker + * Contract: + * directory.list() will return a list of normal invokers if Constants.INVOCATION_NEED_MOCK is absent or not true in invocation, otherwise, a list of mock invokers will return. + * if directory.list() returns more than one mock invoker, only one of them will be used. + * + * @param invocation + * @return + */ + private List> selectMockInvoker(Invocation invocation) { + List> invokers = null; + //TODO generic invoker? + if (invocation instanceof RpcInvocation) { + //Note the implicit contract (although the description is added to the interface declaration, but extensibility is a problem. The practice placed in the attachment needs to be improved) + ((RpcInvocation) invocation).setAttachment(INVOCATION_NEED_MOCK, Boolean.TRUE.toString()); + //directory will return a list of normal invokers if Constants.INVOCATION_NEED_MOCK is absent or not true in invocation, otherwise, a list of mock invokers will return. + try { + invokers = directory.list(invocation); + } catch (RpcException e) { + if (logger.isInfoEnabled()) { + logger.info("Exception when try to invoke mock. Get mock invokers error for service:" + + getUrl().getServiceInterface() + ", method:" + invocation.getMethodName() + + ", will construct a new mock with 'new MockInvoker()'.", e); + } + } + } + return invokers; + } + + @Override + public String toString() { + return "invoker :" + this.invoker + ",directory: " + this.directory; + } +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterWrapper.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterWrapper.java index cfe8cece56..8aa23065c0 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterWrapper.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterWrapper.java @@ -1,42 +1,42 @@ -/* - * 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.rpc.cluster.support.wrapper; - -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.RpcException; -import org.apache.dubbo.rpc.cluster.Cluster; -import org.apache.dubbo.rpc.cluster.Directory; - -/** - * mock impl - * - */ -public class MockClusterWrapper implements Cluster { - - private Cluster cluster; - - public MockClusterWrapper(Cluster cluster) { - this.cluster = cluster; - } - - @Override - public Invoker join(Directory directory) throws RpcException { - return new MockClusterInvoker(directory, - this.cluster.join(directory)); - } - -} +/* + * 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.rpc.cluster.support.wrapper; + +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.cluster.Cluster; +import org.apache.dubbo.rpc.cluster.Directory; + +/** + * mock impl + * + */ +public class MockClusterWrapper implements Cluster { + + private Cluster cluster; + + public MockClusterWrapper(Cluster cluster) { + this.cluster = cluster; + } + + @Override + public Invoker join(Directory directory) throws RpcException { + return new MockClusterInvoker(directory, + this.cluster.join(directory)); + } + +} diff --git a/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.Cluster b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.Cluster index 5808d13a60..f9e2570702 100644 --- a/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.Cluster +++ b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.Cluster @@ -1,10 +1,10 @@ -mock=org.apache.dubbo.rpc.cluster.support.wrapper.MockClusterWrapper -failover=org.apache.dubbo.rpc.cluster.support.FailoverCluster -failfast=org.apache.dubbo.rpc.cluster.support.FailfastCluster -failsafe=org.apache.dubbo.rpc.cluster.support.FailsafeCluster -failback=org.apache.dubbo.rpc.cluster.support.FailbackCluster -forking=org.apache.dubbo.rpc.cluster.support.ForkingCluster -available=org.apache.dubbo.rpc.cluster.support.AvailableCluster -mergeable=org.apache.dubbo.rpc.cluster.support.MergeableCluster -broadcast=org.apache.dubbo.rpc.cluster.support.BroadcastCluster +mock=org.apache.dubbo.rpc.cluster.support.wrapper.MockClusterWrapper +failover=org.apache.dubbo.rpc.cluster.support.FailoverCluster +failfast=org.apache.dubbo.rpc.cluster.support.FailfastCluster +failsafe=org.apache.dubbo.rpc.cluster.support.FailsafeCluster +failback=org.apache.dubbo.rpc.cluster.support.FailbackCluster +forking=org.apache.dubbo.rpc.cluster.support.ForkingCluster +available=org.apache.dubbo.rpc.cluster.support.AvailableCluster +mergeable=org.apache.dubbo.rpc.cluster.support.MergeableCluster +broadcast=org.apache.dubbo.rpc.cluster.support.BroadcastCluster zone-aware=org.apache.dubbo.rpc.cluster.support.registry.ZoneAwareCluster \ No newline at end of file diff --git a/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.ConfiguratorFactory b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.ConfiguratorFactory index 000018773f..38597bd4c2 100644 --- a/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.ConfiguratorFactory +++ b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.ConfiguratorFactory @@ -1,2 +1,2 @@ -override=org.apache.dubbo.rpc.cluster.configurator.override.OverrideConfiguratorFactory +override=org.apache.dubbo.rpc.cluster.configurator.override.OverrideConfiguratorFactory absent=org.apache.dubbo.rpc.cluster.configurator.absent.AbsentConfiguratorFactory \ No newline at end of file diff --git a/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.LoadBalance b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.LoadBalance index 8a636a9d25..347ea10b57 100644 --- a/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.LoadBalance +++ b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.LoadBalance @@ -1,5 +1,5 @@ -random=org.apache.dubbo.rpc.cluster.loadbalance.RandomLoadBalance -roundrobin=org.apache.dubbo.rpc.cluster.loadbalance.RoundRobinLoadBalance -leastactive=org.apache.dubbo.rpc.cluster.loadbalance.LeastActiveLoadBalance -consistenthash=org.apache.dubbo.rpc.cluster.loadbalance.ConsistentHashLoadBalance +random=org.apache.dubbo.rpc.cluster.loadbalance.RandomLoadBalance +roundrobin=org.apache.dubbo.rpc.cluster.loadbalance.RoundRobinLoadBalance +leastactive=org.apache.dubbo.rpc.cluster.loadbalance.LeastActiveLoadBalance +consistenthash=org.apache.dubbo.rpc.cluster.loadbalance.ConsistentHashLoadBalance shortestresponse=org.apache.dubbo.rpc.cluster.loadbalance.ShortestResponseLoadBalance \ No newline at end of file diff --git a/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.Merger b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.Merger index 699decf96f..e3aeabb6d4 100644 --- a/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.Merger +++ b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.Merger @@ -1,11 +1,11 @@ -map=org.apache.dubbo.rpc.cluster.merger.MapMerger -set=org.apache.dubbo.rpc.cluster.merger.SetMerger -list=org.apache.dubbo.rpc.cluster.merger.ListMerger -byte=org.apache.dubbo.rpc.cluster.merger.ByteArrayMerger -char=org.apache.dubbo.rpc.cluster.merger.CharArrayMerger -short=org.apache.dubbo.rpc.cluster.merger.ShortArrayMerger -int=org.apache.dubbo.rpc.cluster.merger.IntArrayMerger -long=org.apache.dubbo.rpc.cluster.merger.LongArrayMerger -float=org.apache.dubbo.rpc.cluster.merger.FloatArrayMerger -double=org.apache.dubbo.rpc.cluster.merger.DoubleArrayMerger -boolean=org.apache.dubbo.rpc.cluster.merger.BooleanArrayMerger +map=org.apache.dubbo.rpc.cluster.merger.MapMerger +set=org.apache.dubbo.rpc.cluster.merger.SetMerger +list=org.apache.dubbo.rpc.cluster.merger.ListMerger +byte=org.apache.dubbo.rpc.cluster.merger.ByteArrayMerger +char=org.apache.dubbo.rpc.cluster.merger.CharArrayMerger +short=org.apache.dubbo.rpc.cluster.merger.ShortArrayMerger +int=org.apache.dubbo.rpc.cluster.merger.IntArrayMerger +long=org.apache.dubbo.rpc.cluster.merger.LongArrayMerger +float=org.apache.dubbo.rpc.cluster.merger.FloatArrayMerger +double=org.apache.dubbo.rpc.cluster.merger.DoubleArrayMerger +boolean=org.apache.dubbo.rpc.cluster.merger.BooleanArrayMerger diff --git a/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.RouterFactory b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.RouterFactory index 978415861b..e229f2ac92 100644 --- a/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.RouterFactory +++ b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.RouterFactory @@ -1,7 +1,7 @@ -file=org.apache.dubbo.rpc.cluster.router.file.FileRouterFactory -condition=org.apache.dubbo.rpc.cluster.router.condition.ConditionRouterFactory -service=org.apache.dubbo.rpc.cluster.router.condition.config.ServiceRouterFactory -app=org.apache.dubbo.rpc.cluster.router.condition.config.AppRouterFactory -tag=org.apache.dubbo.rpc.cluster.router.tag.TagRouterFactory -mock=org.apache.dubbo.rpc.cluster.router.mock.MockRouterFactory -mesh-rule=org.apache.dubbo.rpc.cluster.router.mesh.route.MeshRuleRouterFactory +file=org.apache.dubbo.rpc.cluster.router.file.FileRouterFactory +condition=org.apache.dubbo.rpc.cluster.router.condition.ConditionRouterFactory +service=org.apache.dubbo.rpc.cluster.router.condition.config.ServiceRouterFactory +app=org.apache.dubbo.rpc.cluster.router.condition.config.AppRouterFactory +tag=org.apache.dubbo.rpc.cluster.router.tag.TagRouterFactory +mock=org.apache.dubbo.rpc.cluster.router.mock.MockRouterFactory +mesh-rule=org.apache.dubbo.rpc.cluster.router.mesh.route.MeshRuleRouterFactory diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/configurator/absent/AbsentConfiguratorTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/configurator/absent/AbsentConfiguratorTest.java index 36ef868b13..3f017a34e2 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/configurator/absent/AbsentConfiguratorTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/configurator/absent/AbsentConfiguratorTest.java @@ -1,68 +1,68 @@ -/* - * 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.rpc.cluster.configurator.absent; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.utils.NetUtils; -import org.apache.dubbo.rpc.cluster.configurator.consts.UrlConstant; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -/** - * OverrideConfiguratorTest - */ -public class AbsentConfiguratorTest { - - - @Test - public void testOverrideApplication() { - AbsentConfigurator configurator = new AbsentConfigurator(URL.valueOf("override://foo@0.0.0.0/com.foo.BarService?timeout=200")); - - URL url = configurator.configure(URL.valueOf(UrlConstant.URL_CONSUMER)); - Assertions.assertEquals("200", url.getParameter("timeout")); - - url = configurator.configure(URL.valueOf(UrlConstant.URL_ONE)); - Assertions.assertEquals("1000", url.getParameter("timeout")); - - url = configurator.configure(URL.valueOf(UrlConstant.APPLICATION_BAR_SIDE_CONSUMER_11)); - Assertions.assertNull(url.getParameter("timeout")); - - url = configurator.configure(URL.valueOf(UrlConstant.TIMEOUT_1000_SIDE_CONSUMER_11)); - Assertions.assertEquals("1000", url.getParameter("timeout")); - } - - @Test - public void testOverrideHost() { - AbsentConfigurator configurator = new AbsentConfigurator(URL.valueOf("override://" + NetUtils.getLocalHost() + "/com.foo.BarService?timeout=200")); - - URL url = configurator.configure(URL.valueOf(UrlConstant.URL_CONSUMER)); - Assertions.assertEquals("200", url.getParameter("timeout")); - - url = configurator.configure(URL.valueOf(UrlConstant.URL_ONE)); - Assertions.assertEquals("1000", url.getParameter("timeout")); - - AbsentConfigurator configurator1 = new AbsentConfigurator(URL.valueOf(UrlConstant.SERVICE_TIMEOUT_200)); - - url = configurator1.configure(URL.valueOf(UrlConstant.APPLICATION_BAR_SIDE_CONSUMER_10)); - Assertions.assertNull(url.getParameter("timeout")); - - url = configurator1.configure(URL.valueOf(UrlConstant.TIMEOUT_1000_SIDE_CONSUMER_10)); - Assertions.assertEquals("1000", url.getParameter("timeout")); - } - -} +/* + * 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.rpc.cluster.configurator.absent; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.utils.NetUtils; +import org.apache.dubbo.rpc.cluster.configurator.consts.UrlConstant; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +/** + * OverrideConfiguratorTest + */ +public class AbsentConfiguratorTest { + + + @Test + public void testOverrideApplication() { + AbsentConfigurator configurator = new AbsentConfigurator(URL.valueOf("override://foo@0.0.0.0/com.foo.BarService?timeout=200")); + + URL url = configurator.configure(URL.valueOf(UrlConstant.URL_CONSUMER)); + Assertions.assertEquals("200", url.getParameter("timeout")); + + url = configurator.configure(URL.valueOf(UrlConstant.URL_ONE)); + Assertions.assertEquals("1000", url.getParameter("timeout")); + + url = configurator.configure(URL.valueOf(UrlConstant.APPLICATION_BAR_SIDE_CONSUMER_11)); + Assertions.assertNull(url.getParameter("timeout")); + + url = configurator.configure(URL.valueOf(UrlConstant.TIMEOUT_1000_SIDE_CONSUMER_11)); + Assertions.assertEquals("1000", url.getParameter("timeout")); + } + + @Test + public void testOverrideHost() { + AbsentConfigurator configurator = new AbsentConfigurator(URL.valueOf("override://" + NetUtils.getLocalHost() + "/com.foo.BarService?timeout=200")); + + URL url = configurator.configure(URL.valueOf(UrlConstant.URL_CONSUMER)); + Assertions.assertEquals("200", url.getParameter("timeout")); + + url = configurator.configure(URL.valueOf(UrlConstant.URL_ONE)); + Assertions.assertEquals("1000", url.getParameter("timeout")); + + AbsentConfigurator configurator1 = new AbsentConfigurator(URL.valueOf(UrlConstant.SERVICE_TIMEOUT_200)); + + url = configurator1.configure(URL.valueOf(UrlConstant.APPLICATION_BAR_SIDE_CONSUMER_10)); + Assertions.assertNull(url.getParameter("timeout")); + + url = configurator1.configure(URL.valueOf(UrlConstant.TIMEOUT_1000_SIDE_CONSUMER_10)); + Assertions.assertEquals("1000", url.getParameter("timeout")); + } + +} diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/configurator/override/OverrideConfiguratorTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/configurator/override/OverrideConfiguratorTest.java index f2b7d3d2ac..e289144fb4 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/configurator/override/OverrideConfiguratorTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/configurator/override/OverrideConfiguratorTest.java @@ -1,68 +1,68 @@ -/* - * 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.rpc.cluster.configurator.override; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.utils.NetUtils; -import org.apache.dubbo.rpc.cluster.configurator.absent.AbsentConfigurator; -import org.apache.dubbo.rpc.cluster.configurator.consts.UrlConstant; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -/** - * OverrideConfiguratorTest - */ -public class OverrideConfiguratorTest { - - @Test - public void testOverride_Application() { - OverrideConfigurator configurator = new OverrideConfigurator(URL.valueOf("override://foo@0.0.0.0/com.foo.BarService?timeout=200")); - - URL url = configurator.configure(URL.valueOf(UrlConstant.URL_CONSUMER)); - Assertions.assertEquals("200", url.getParameter("timeout")); - - url = configurator.configure(URL.valueOf(UrlConstant.URL_ONE)); - Assertions.assertEquals("200", url.getParameter("timeout")); - - url = configurator.configure(URL.valueOf(UrlConstant.APPLICATION_BAR_SIDE_CONSUMER_11)); - Assertions.assertNull(url.getParameter("timeout")); - - url = configurator.configure(URL.valueOf(UrlConstant.TIMEOUT_1000_SIDE_CONSUMER_11)); - Assertions.assertEquals("1000", url.getParameter("timeout")); - } - - @Test - public void testOverride_Host() { - OverrideConfigurator configurator = new OverrideConfigurator(URL.valueOf("override://" + NetUtils.getLocalHost() + "/com.foo.BarService?timeout=200")); - - URL url = configurator.configure(URL.valueOf(UrlConstant.URL_CONSUMER)); - Assertions.assertEquals("200", url.getParameter("timeout")); - - url = configurator.configure(URL.valueOf(UrlConstant.URL_ONE)); - Assertions.assertEquals("200", url.getParameter("timeout")); - - AbsentConfigurator configurator1 = new AbsentConfigurator(URL.valueOf("override://10.20.153.10/com.foo.BarService?timeout=200")); - - url = configurator1.configure(URL.valueOf(UrlConstant.APPLICATION_BAR_SIDE_CONSUMER_10)); - Assertions.assertNull(url.getParameter("timeout")); - - url = configurator1.configure(URL.valueOf(UrlConstant.TIMEOUT_1000_SIDE_CONSUMER_10)); - Assertions.assertEquals("1000", url.getParameter("timeout")); - } - -} +/* + * 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.rpc.cluster.configurator.override; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.utils.NetUtils; +import org.apache.dubbo.rpc.cluster.configurator.absent.AbsentConfigurator; +import org.apache.dubbo.rpc.cluster.configurator.consts.UrlConstant; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +/** + * OverrideConfiguratorTest + */ +public class OverrideConfiguratorTest { + + @Test + public void testOverride_Application() { + OverrideConfigurator configurator = new OverrideConfigurator(URL.valueOf("override://foo@0.0.0.0/com.foo.BarService?timeout=200")); + + URL url = configurator.configure(URL.valueOf(UrlConstant.URL_CONSUMER)); + Assertions.assertEquals("200", url.getParameter("timeout")); + + url = configurator.configure(URL.valueOf(UrlConstant.URL_ONE)); + Assertions.assertEquals("200", url.getParameter("timeout")); + + url = configurator.configure(URL.valueOf(UrlConstant.APPLICATION_BAR_SIDE_CONSUMER_11)); + Assertions.assertNull(url.getParameter("timeout")); + + url = configurator.configure(URL.valueOf(UrlConstant.TIMEOUT_1000_SIDE_CONSUMER_11)); + Assertions.assertEquals("1000", url.getParameter("timeout")); + } + + @Test + public void testOverride_Host() { + OverrideConfigurator configurator = new OverrideConfigurator(URL.valueOf("override://" + NetUtils.getLocalHost() + "/com.foo.BarService?timeout=200")); + + URL url = configurator.configure(URL.valueOf(UrlConstant.URL_CONSUMER)); + Assertions.assertEquals("200", url.getParameter("timeout")); + + url = configurator.configure(URL.valueOf(UrlConstant.URL_ONE)); + Assertions.assertEquals("200", url.getParameter("timeout")); + + AbsentConfigurator configurator1 = new AbsentConfigurator(URL.valueOf("override://10.20.153.10/com.foo.BarService?timeout=200")); + + url = configurator1.configure(URL.valueOf(UrlConstant.APPLICATION_BAR_SIDE_CONSUMER_10)); + Assertions.assertNull(url.getParameter("timeout")); + + url = configurator1.configure(URL.valueOf(UrlConstant.TIMEOUT_1000_SIDE_CONSUMER_10)); + Assertions.assertEquals("1000", url.getParameter("timeout")); + } + +} diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/directory/MockDirInvocation.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/directory/MockDirInvocation.java index bc237b91bb..392393744d 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/directory/MockDirInvocation.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/directory/MockDirInvocation.java @@ -156,4 +156,4 @@ public class MockDirInvocation implements Invocation { return result; } -} \ No newline at end of file +} diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/DemoService.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/DemoService.java index 258b8c8b77..6c8f7fff83 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/DemoService.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/DemoService.java @@ -1,27 +1,27 @@ -/* - * 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.rpc.cluster.filter; - -/** - * TestService - */ - -public interface DemoService { - String sayHello(String name); - - int plus(int a, int b); -} \ No newline at end of file +/* + * 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.rpc.cluster.filter; + +/** + * TestService + */ + +public interface DemoService { + String sayHello(String name); + + int plus(int a, int b); +} diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/DemoServiceLocal.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/DemoServiceLocal.java index e715ae6517..8b92a59621 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/DemoServiceLocal.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/DemoServiceLocal.java @@ -1,43 +1,43 @@ -/* - * 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.rpc.cluster.filter; - -/** - * TestService - */ - -public class DemoServiceLocal implements DemoService { - - public DemoServiceLocal(DemoService demoService) { - } - - public String sayHello(String name) { - return name; - } - - public int plus(int a, int b) { - return a + b; - } - - public void ondisconnect() { - - } - - public void onconnect() { - - } -} \ No newline at end of file +/* + * 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.rpc.cluster.filter; + +/** + * TestService + */ + +public class DemoServiceLocal implements DemoService { + + public DemoServiceLocal(DemoService demoService) { + } + + public String sayHello(String name) { + return name; + } + + public int plus(int a, int b) { + return a + b; + } + + public void ondisconnect() { + + } + + public void onconnect() { + + } +} diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/DemoServiceMock.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/DemoServiceMock.java index f888a1c02f..7b0898dfd3 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/DemoServiceMock.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/DemoServiceMock.java @@ -1,31 +1,31 @@ -/* - * 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.rpc.cluster.filter; - -/** - * MockService.java - * - */ -public class DemoServiceMock implements DemoService { - public String sayHello(String name) { - return name; - } - - public int plus(int a, int b) { - return a + b; - } -} \ No newline at end of file +/* + * 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.rpc.cluster.filter; + +/** + * MockService.java + * + */ +public class DemoServiceMock implements DemoService { + public String sayHello(String name) { + return name; + } + + public int plus(int a, int b) { + return a + b; + } +} diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/DemoServiceStub.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/DemoServiceStub.java index 02fda0aa0f..6217ed6e19 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/DemoServiceStub.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/DemoServiceStub.java @@ -1,35 +1,35 @@ -/* - * 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.rpc.cluster.filter; - -/** - * TestService - */ - -public class DemoServiceStub implements DemoService { - - public DemoServiceStub(DemoService demoService) { - } - - public String sayHello(String name) { - return name; - } - - public int plus(int a, int b) { - return a + b; - } -} \ No newline at end of file +/* + * 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.rpc.cluster.filter; + +/** + * TestService + */ + +public class DemoServiceStub implements DemoService { + + public DemoServiceStub(DemoService demoService) { + } + + public String sayHello(String name) { + return name; + } + + public int plus(int a, int b) { + return a + b; + } +} diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/MockService.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/MockService.java index e01d9a4fff..5ae968afbb 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/MockService.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/MockService.java @@ -1,31 +1,31 @@ -/* - * 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.rpc.cluster.filter; - -/** - * MockService.java - * - */ -public class MockService implements DemoService { - public String sayHello(String name) { - return name; - } - - public int plus(int a, int b) { - return a + b; - } -} \ No newline at end of file +/* + * 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.rpc.cluster.filter; + +/** + * MockService.java + * + */ +public class MockService implements DemoService { + public String sayHello(String name) { + return name; + } + + public int plus(int a, int b) { + return a + b; + } +} diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouterTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouterTest.java index 4637976309..ace3cdebb4 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouterTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouterTest.java @@ -1,348 +1,348 @@ -/* - * 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.rpc.cluster.router.condition; - - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.rpc.Invocation; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.RpcInvocation; -import org.apache.dubbo.rpc.cluster.Router; -import org.apache.dubbo.rpc.cluster.router.MockInvoker; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.ArrayList; -import java.util.List; - -import static org.apache.dubbo.rpc.cluster.Constants.FORCE_KEY; -import static org.apache.dubbo.rpc.cluster.Constants.RULE_KEY; - -public class ConditionRouterTest { - private static final String LOCAL_HOST = "127.0.0.1"; - private URL SCRIPT_URL = URL.valueOf("condition://0.0.0.0/com.foo.BarService"); - - @BeforeAll - public static void setUpBeforeClass() throws Exception { - } - - @BeforeEach - public void setUp() throws Exception { - } - - private URL getRouteUrl(String rule) { - return SCRIPT_URL.addParameterAndEncoded(RULE_KEY, rule); - } - - @Test - public void testRoute_matchWhen() { - Invocation invocation = new RpcInvocation(); - - Router router = new ConditionRouterFactory().getRouter(getRouteUrl(" => host = 1.2.3.4")); - boolean matchWhen = ((ConditionRouter) router).matchWhen(URL.valueOf("consumer://1.1.1.1/com.foo.BarService"), invocation); - Assertions.assertTrue(matchWhen); - - router = new ConditionRouterFactory().getRouter(getRouteUrl("host = 2.2.2.2,1.1.1.1,3.3.3.3 => host = 1.2.3.4")); - matchWhen = ((ConditionRouter) router).matchWhen(URL.valueOf("consumer://1.1.1.1/com.foo.BarService"), invocation); - Assertions.assertTrue(matchWhen); - - router = new ConditionRouterFactory().getRouter(getRouteUrl("host = 2.2.2.2,1.1.1.1,3.3.3.3 & host !=1.1.1.1 => host = 1.2.3.4")); - matchWhen = ((ConditionRouter) router).matchWhen(URL.valueOf("consumer://1.1.1.1/com.foo.BarService"), invocation); - Assertions.assertFalse(matchWhen); - - router = new ConditionRouterFactory().getRouter(getRouteUrl("host !=4.4.4.4 & host = 2.2.2.2,1.1.1.1,3.3.3.3 => host = 1.2.3.4")); - matchWhen = ((ConditionRouter) router).matchWhen(URL.valueOf("consumer://1.1.1.1/com.foo.BarService"), invocation); - Assertions.assertTrue(matchWhen); - - router = new ConditionRouterFactory().getRouter(getRouteUrl("host !=4.4.4.* & host = 2.2.2.2,1.1.1.1,3.3.3.3 => host = 1.2.3.4")); - matchWhen = ((ConditionRouter) router).matchWhen(URL.valueOf("consumer://1.1.1.1/com.foo.BarService"), invocation); - Assertions.assertTrue(matchWhen); - - router = new ConditionRouterFactory().getRouter(getRouteUrl("host = 2.2.2.2,1.1.1.*,3.3.3.3 & host != 1.1.1.1 => host = 1.2.3.4")); - matchWhen = ((ConditionRouter) router).matchWhen(URL.valueOf("consumer://1.1.1.1/com.foo.BarService"), invocation); - Assertions.assertFalse(matchWhen); - - router = new ConditionRouterFactory().getRouter(getRouteUrl("host = 2.2.2.2,1.1.1.*,3.3.3.3 & host != 1.1.1.2 => host = 1.2.3.4")); - matchWhen = ((ConditionRouter) router).matchWhen(URL.valueOf("consumer://1.1.1.1/com.foo.BarService"), invocation); - Assertions.assertTrue(matchWhen); - } - - @Test - public void testRoute_matchFilter() { - List> invokers = new ArrayList>(); - Invoker invoker1 = new MockInvoker(URL.valueOf( - "dubbo://10.20.3.3:20880/com.foo.BarService?serialization=fastjson")); - Invoker invoker2 = new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST - + ":20880/com.foo.BarService")); - Invoker invoker3 = new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST - + ":20880/com.foo.BarService")); - invokers.add(invoker1); - invokers.add(invoker2); - invokers.add(invoker3); - - System.err.println("The localhost address: " + invoker2.getUrl().getAddress()); - System.err.println(invoker3.getUrl().getAddress()); - - Router router1 = new ConditionRouterFactory().getRouter(getRouteUrl( - "host = " + LOCAL_HOST + " => " + " host = 10.20.3.3").addParameter(FORCE_KEY, - String.valueOf(true))); - Router router2 = new ConditionRouterFactory().getRouter(getRouteUrl( - "host = " + LOCAL_HOST + " => " + " host = 10.20.3.* & host != 10.20.3.3").addParameter( - FORCE_KEY, String.valueOf(true))); - Router router3 = new ConditionRouterFactory().getRouter(getRouteUrl( - "host = " + LOCAL_HOST + " => " + " host = 10.20.3.3 & host != 10.20.3.3").addParameter( - FORCE_KEY, String.valueOf(true))); - Router router4 = new ConditionRouterFactory().getRouter(getRouteUrl( - "host = " + LOCAL_HOST + " => " + " host = 10.20.3.2,10.20.3.3,10.20.3.4").addParameter( - FORCE_KEY, String.valueOf(true))); - Router router5 = new ConditionRouterFactory().getRouter(getRouteUrl( - "host = " + LOCAL_HOST + " => " + " host != 10.20.3.3").addParameter(FORCE_KEY, - String.valueOf(true))); - Router router6 = new ConditionRouterFactory().getRouter(getRouteUrl( - "host = " + LOCAL_HOST + " => " + " serialization = fastjson").addParameter( - FORCE_KEY, String.valueOf(true))); - - - - List> filteredInvokers1 = router1.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation()); - List> filteredInvokers2 = router2.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation()); - List> filteredInvokers3 = router3.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation()); - List> filteredInvokers4 = router4.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation()); - List> filteredInvokers5 = router5.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation()); - List> filteredInvokers6 = router6.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation()); - Assertions.assertEquals(1, filteredInvokers1.size()); - Assertions.assertEquals(0, filteredInvokers2.size()); - Assertions.assertEquals(0, filteredInvokers3.size()); - Assertions.assertEquals(1, filteredInvokers4.size()); - Assertions.assertEquals(2, filteredInvokers5.size()); - Assertions.assertEquals(1, filteredInvokers6.size()); - } - - @Test - public void testRoute_methodRoute() { - Invocation invocation = new RpcInvocation("getFoo", "com.foo.BarService", "", new Class[0], new Object[0]); - // More than one methods, mismatch - Router router = new ConditionRouterFactory().getRouter(getRouteUrl("methods=getFoo => host = 1.2.3.4")); - boolean matchWhen = ((ConditionRouter) router).matchWhen( - URL.valueOf("consumer://1.1.1.1/com.foo.BarService?methods=setFoo,getFoo,findFoo"), invocation); - Assertions.assertTrue(matchWhen); - // Exactly one method, match - matchWhen = ((ConditionRouter) router).matchWhen( - URL.valueOf("consumer://1.1.1.1/com.foo.BarService?methods=getFoo"), invocation); - Assertions.assertTrue(matchWhen); - // Method routing and Other condition routing can work together - Router router2 = new ConditionRouterFactory() - .getRouter(getRouteUrl("methods=getFoo & host!=1.1.1.1 => host = 1.2.3.4")); - matchWhen = ((ConditionRouter) router2).matchWhen( - URL.valueOf("consumer://1.1.1.1/com.foo.BarService?methods=getFoo"), invocation); - Assertions.assertFalse(matchWhen); - - Router router3 = new ConditionRouterFactory() - .getRouter(getRouteUrl("methods=getFoo & host=1.1.1.1 => host = 1.2.3.4")); - matchWhen = ((ConditionRouter) router3).matchWhen( - URL.valueOf("consumer://1.1.1.1/com.foo.BarService?methods=getFoo"), invocation); - Assertions.assertTrue(matchWhen); - // Test filter condition - List> invokers = new ArrayList>(); - Invoker invoker1 = new MockInvoker(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService")); - Invoker invoker2 = new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST - + ":20880/com.foo.BarService")); - Invoker invoker3 = new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST - + ":20880/com.foo.BarService")); - invokers.add(invoker1); - invokers.add(invoker2); - invokers.add(invoker3); - - Router router4 = new ConditionRouterFactory().getRouter(getRouteUrl( - "host = " + LOCAL_HOST + " & methods = getFoo => " + " host = 10.20.3.3").addParameter( - FORCE_KEY, String.valueOf(true))); - List> filteredInvokers1 = router4.route(invokers, - URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation); - Assertions.assertEquals(1, filteredInvokers1.size()); - - Router router5 = new ConditionRouterFactory().getRouter(getRouteUrl( - "host = " + LOCAL_HOST + " & methods = unvalidmethod => " + " host = 10.20.3.3") - .addParameter(FORCE_KEY, String.valueOf(true))); - List> filteredInvokers2 = router5.route(invokers, - URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation); - Assertions.assertEquals(3, filteredInvokers2.size()); - // Request a non-exists method - } - - @Test - public void testRoute_ReturnFalse() { - Router router = new ConditionRouterFactory().getRouter(getRouteUrl("host = " + LOCAL_HOST + " => false")); - List> invokers = new ArrayList>(); - invokers.add(new MockInvoker()); - invokers.add(new MockInvoker()); - invokers.add(new MockInvoker()); - List> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation()); - Assertions.assertEquals(0, filteredInvokers.size()); - } - - @Test - public void testRoute_ReturnEmpty() { - Router router = new ConditionRouterFactory().getRouter(getRouteUrl("host = " + LOCAL_HOST + " => ")); - List> invokers = new ArrayList>(); - invokers.add(new MockInvoker()); - invokers.add(new MockInvoker()); - invokers.add(new MockInvoker()); - List> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation()); - Assertions.assertEquals(0, filteredInvokers.size()); - } - - @Test - public void testRoute_ReturnAll() { - Router router = new ConditionRouterFactory().getRouter(getRouteUrl("host = " + LOCAL_HOST + " => " + " host = " + LOCAL_HOST)); - List> invokers = new ArrayList>(); - invokers.add(new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"))); - invokers.add(new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"))); - invokers.add(new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"))); - List> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation()); - Assertions.assertEquals(invokers, filteredInvokers); - } - - @Test - public void testRoute_HostFilter() { - Router router = new ConditionRouterFactory().getRouter(getRouteUrl("host = " + LOCAL_HOST + " => " + " host = " + LOCAL_HOST)); - List> invokers = new ArrayList>(); - Invoker invoker1 = new MockInvoker(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService")); - Invoker invoker2 = new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService")); - Invoker invoker3 = new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService")); - invokers.add(invoker1); - invokers.add(invoker2); - invokers.add(invoker3); - List> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation()); - Assertions.assertEquals(2, filteredInvokers.size()); - Assertions.assertEquals(invoker2, filteredInvokers.get(0)); - Assertions.assertEquals(invoker3, filteredInvokers.get(1)); - } - - @Test - public void testRoute_Empty_HostFilter() { - Router router = new ConditionRouterFactory().getRouter(getRouteUrl(" => " + " host = " + LOCAL_HOST)); - List> invokers = new ArrayList>(); - Invoker invoker1 = new MockInvoker(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService")); - Invoker invoker2 = new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService")); - Invoker invoker3 = new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService")); - invokers.add(invoker1); - invokers.add(invoker2); - invokers.add(invoker3); - List> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation()); - Assertions.assertEquals(2, filteredInvokers.size()); - Assertions.assertEquals(invoker2, filteredInvokers.get(0)); - Assertions.assertEquals(invoker3, filteredInvokers.get(1)); - } - - @Test - public void testRoute_False_HostFilter() { - Router router = new ConditionRouterFactory().getRouter(getRouteUrl("true => " + " host = " + LOCAL_HOST)); - List> invokers = new ArrayList>(); - Invoker invoker1 = new MockInvoker(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService")); - Invoker invoker2 = new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService")); - Invoker invoker3 = new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService")); - invokers.add(invoker1); - invokers.add(invoker2); - invokers.add(invoker3); - List> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation()); - Assertions.assertEquals(2, filteredInvokers.size()); - Assertions.assertEquals(invoker2, filteredInvokers.get(0)); - Assertions.assertEquals(invoker3, filteredInvokers.get(1)); - } - - @Test - public void testRoute_Placeholder() { - Router router = new ConditionRouterFactory().getRouter(getRouteUrl("host = " + LOCAL_HOST + " => " + " host = $host")); - List> invokers = new ArrayList>(); - Invoker invoker1 = new MockInvoker(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService")); - Invoker invoker2 = new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService")); - Invoker invoker3 = new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService")); - invokers.add(invoker1); - invokers.add(invoker2); - invokers.add(invoker3); - List> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation()); - Assertions.assertEquals(2, filteredInvokers.size()); - Assertions.assertEquals(invoker2, filteredInvokers.get(0)); - Assertions.assertEquals(invoker3, filteredInvokers.get(1)); - } - - @Test - public void testRoute_NoForce() { - Router router = new ConditionRouterFactory().getRouter(getRouteUrl("host = " + LOCAL_HOST + " => " + " host = 1.2.3.4")); - List> invokers = new ArrayList>(); - Invoker invoker1 = new MockInvoker(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService")); - Invoker invoker2 = new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService")); - Invoker invoker3 = new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService")); - invokers.add(invoker1); - invokers.add(invoker2); - invokers.add(invoker3); - List> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation()); - Assertions.assertEquals(invokers, filteredInvokers); - } - - @Test - public void testRoute_Force() { - Router router = new ConditionRouterFactory().getRouter(getRouteUrl("host = " + LOCAL_HOST + " => " + " host = 1.2.3.4").addParameter(FORCE_KEY, String.valueOf(true))); - List> invokers = new ArrayList>(); - Invoker invoker1 = new MockInvoker(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService")); - Invoker invoker2 = new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService")); - Invoker invoker3 = new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService")); - invokers.add(invoker1); - invokers.add(invoker2); - invokers.add(invoker3); - List> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation()); - Assertions.assertEquals(0, filteredInvokers.size()); - } - - @Test - public void testRoute_Arguments() { - Router router = new ConditionRouterFactory().getRouter(getRouteUrl("arguments[0] = a " + " => " + " host = 1.2.3.4").addParameter(FORCE_KEY, String.valueOf(true))); - List> invokers = new ArrayList<>(); - Invoker invoker1 = new MockInvoker<>(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService")); - Invoker invoker2 = new MockInvoker<>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService")); - Invoker invoker3 = new MockInvoker<>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService")); - invokers.add(invoker1); - invokers.add(invoker2); - invokers.add(invoker3); - RpcInvocation invocation = new RpcInvocation(); - String p = "a"; - invocation.setArguments(new Object[]{null}); - List> fileredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation); - Assertions.assertEquals(3, fileredInvokers.size()); - - invocation.setArguments(new Object[]{p}); - fileredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation); - Assertions.assertEquals(0, fileredInvokers.size()); - - router = new ConditionRouterFactory().getRouter(getRouteUrl("arguments = b " + " => " + " host = 1.2.3.4").addParameter(FORCE_KEY, String.valueOf(true))); - fileredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation); - Assertions.assertEquals(3, fileredInvokers.size()); - - router = new ConditionRouterFactory().getRouter(getRouteUrl("arguments[10].inner = a " + " => " + " host = 1.2.3.4").addParameter(FORCE_KEY, String.valueOf(true))); - fileredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation); - Assertions.assertEquals(3, fileredInvokers.size()); - - int integer = 1; - invocation.setArguments(new Object[]{integer}); - router = new ConditionRouterFactory().getRouter(getRouteUrl("arguments[0].inner = 1 " + " => " + " host = 1.2.3.4").addParameter(FORCE_KEY, String.valueOf(true))); - fileredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation); - Assertions.assertEquals(0, fileredInvokers.size()); - } -} +/* + * 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.rpc.cluster.router.condition; + + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.RpcInvocation; +import org.apache.dubbo.rpc.cluster.Router; +import org.apache.dubbo.rpc.cluster.router.MockInvoker; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.apache.dubbo.rpc.cluster.Constants.FORCE_KEY; +import static org.apache.dubbo.rpc.cluster.Constants.RULE_KEY; + +public class ConditionRouterTest { + private static final String LOCAL_HOST = "127.0.0.1"; + private URL SCRIPT_URL = URL.valueOf("condition://0.0.0.0/com.foo.BarService"); + + @BeforeAll + public static void setUpBeforeClass() throws Exception { + } + + @BeforeEach + public void setUp() throws Exception { + } + + private URL getRouteUrl(String rule) { + return SCRIPT_URL.addParameterAndEncoded(RULE_KEY, rule); + } + + @Test + public void testRoute_matchWhen() { + Invocation invocation = new RpcInvocation(); + + Router router = new ConditionRouterFactory().getRouter(getRouteUrl(" => host = 1.2.3.4")); + boolean matchWhen = ((ConditionRouter) router).matchWhen(URL.valueOf("consumer://1.1.1.1/com.foo.BarService"), invocation); + Assertions.assertTrue(matchWhen); + + router = new ConditionRouterFactory().getRouter(getRouteUrl("host = 2.2.2.2,1.1.1.1,3.3.3.3 => host = 1.2.3.4")); + matchWhen = ((ConditionRouter) router).matchWhen(URL.valueOf("consumer://1.1.1.1/com.foo.BarService"), invocation); + Assertions.assertTrue(matchWhen); + + router = new ConditionRouterFactory().getRouter(getRouteUrl("host = 2.2.2.2,1.1.1.1,3.3.3.3 & host !=1.1.1.1 => host = 1.2.3.4")); + matchWhen = ((ConditionRouter) router).matchWhen(URL.valueOf("consumer://1.1.1.1/com.foo.BarService"), invocation); + Assertions.assertFalse(matchWhen); + + router = new ConditionRouterFactory().getRouter(getRouteUrl("host !=4.4.4.4 & host = 2.2.2.2,1.1.1.1,3.3.3.3 => host = 1.2.3.4")); + matchWhen = ((ConditionRouter) router).matchWhen(URL.valueOf("consumer://1.1.1.1/com.foo.BarService"), invocation); + Assertions.assertTrue(matchWhen); + + router = new ConditionRouterFactory().getRouter(getRouteUrl("host !=4.4.4.* & host = 2.2.2.2,1.1.1.1,3.3.3.3 => host = 1.2.3.4")); + matchWhen = ((ConditionRouter) router).matchWhen(URL.valueOf("consumer://1.1.1.1/com.foo.BarService"), invocation); + Assertions.assertTrue(matchWhen); + + router = new ConditionRouterFactory().getRouter(getRouteUrl("host = 2.2.2.2,1.1.1.*,3.3.3.3 & host != 1.1.1.1 => host = 1.2.3.4")); + matchWhen = ((ConditionRouter) router).matchWhen(URL.valueOf("consumer://1.1.1.1/com.foo.BarService"), invocation); + Assertions.assertFalse(matchWhen); + + router = new ConditionRouterFactory().getRouter(getRouteUrl("host = 2.2.2.2,1.1.1.*,3.3.3.3 & host != 1.1.1.2 => host = 1.2.3.4")); + matchWhen = ((ConditionRouter) router).matchWhen(URL.valueOf("consumer://1.1.1.1/com.foo.BarService"), invocation); + Assertions.assertTrue(matchWhen); + } + + @Test + public void testRoute_matchFilter() { + List> invokers = new ArrayList>(); + Invoker invoker1 = new MockInvoker(URL.valueOf( + "dubbo://10.20.3.3:20880/com.foo.BarService?serialization=fastjson")); + Invoker invoker2 = new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST + + ":20880/com.foo.BarService")); + Invoker invoker3 = new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST + + ":20880/com.foo.BarService")); + invokers.add(invoker1); + invokers.add(invoker2); + invokers.add(invoker3); + + System.err.println("The localhost address: " + invoker2.getUrl().getAddress()); + System.err.println(invoker3.getUrl().getAddress()); + + Router router1 = new ConditionRouterFactory().getRouter(getRouteUrl( + "host = " + LOCAL_HOST + " => " + " host = 10.20.3.3").addParameter(FORCE_KEY, + String.valueOf(true))); + Router router2 = new ConditionRouterFactory().getRouter(getRouteUrl( + "host = " + LOCAL_HOST + " => " + " host = 10.20.3.* & host != 10.20.3.3").addParameter( + FORCE_KEY, String.valueOf(true))); + Router router3 = new ConditionRouterFactory().getRouter(getRouteUrl( + "host = " + LOCAL_HOST + " => " + " host = 10.20.3.3 & host != 10.20.3.3").addParameter( + FORCE_KEY, String.valueOf(true))); + Router router4 = new ConditionRouterFactory().getRouter(getRouteUrl( + "host = " + LOCAL_HOST + " => " + " host = 10.20.3.2,10.20.3.3,10.20.3.4").addParameter( + FORCE_KEY, String.valueOf(true))); + Router router5 = new ConditionRouterFactory().getRouter(getRouteUrl( + "host = " + LOCAL_HOST + " => " + " host != 10.20.3.3").addParameter(FORCE_KEY, + String.valueOf(true))); + Router router6 = new ConditionRouterFactory().getRouter(getRouteUrl( + "host = " + LOCAL_HOST + " => " + " serialization = fastjson").addParameter( + FORCE_KEY, String.valueOf(true))); + + + + List> filteredInvokers1 = router1.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation()); + List> filteredInvokers2 = router2.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation()); + List> filteredInvokers3 = router3.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation()); + List> filteredInvokers4 = router4.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation()); + List> filteredInvokers5 = router5.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation()); + List> filteredInvokers6 = router6.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation()); + Assertions.assertEquals(1, filteredInvokers1.size()); + Assertions.assertEquals(0, filteredInvokers2.size()); + Assertions.assertEquals(0, filteredInvokers3.size()); + Assertions.assertEquals(1, filteredInvokers4.size()); + Assertions.assertEquals(2, filteredInvokers5.size()); + Assertions.assertEquals(1, filteredInvokers6.size()); + } + + @Test + public void testRoute_methodRoute() { + Invocation invocation = new RpcInvocation("getFoo", "com.foo.BarService", "", new Class[0], new Object[0]); + // More than one methods, mismatch + Router router = new ConditionRouterFactory().getRouter(getRouteUrl("methods=getFoo => host = 1.2.3.4")); + boolean matchWhen = ((ConditionRouter) router).matchWhen( + URL.valueOf("consumer://1.1.1.1/com.foo.BarService?methods=setFoo,getFoo,findFoo"), invocation); + Assertions.assertTrue(matchWhen); + // Exactly one method, match + matchWhen = ((ConditionRouter) router).matchWhen( + URL.valueOf("consumer://1.1.1.1/com.foo.BarService?methods=getFoo"), invocation); + Assertions.assertTrue(matchWhen); + // Method routing and Other condition routing can work together + Router router2 = new ConditionRouterFactory() + .getRouter(getRouteUrl("methods=getFoo & host!=1.1.1.1 => host = 1.2.3.4")); + matchWhen = ((ConditionRouter) router2).matchWhen( + URL.valueOf("consumer://1.1.1.1/com.foo.BarService?methods=getFoo"), invocation); + Assertions.assertFalse(matchWhen); + + Router router3 = new ConditionRouterFactory() + .getRouter(getRouteUrl("methods=getFoo & host=1.1.1.1 => host = 1.2.3.4")); + matchWhen = ((ConditionRouter) router3).matchWhen( + URL.valueOf("consumer://1.1.1.1/com.foo.BarService?methods=getFoo"), invocation); + Assertions.assertTrue(matchWhen); + // Test filter condition + List> invokers = new ArrayList>(); + Invoker invoker1 = new MockInvoker(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService")); + Invoker invoker2 = new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST + + ":20880/com.foo.BarService")); + Invoker invoker3 = new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST + + ":20880/com.foo.BarService")); + invokers.add(invoker1); + invokers.add(invoker2); + invokers.add(invoker3); + + Router router4 = new ConditionRouterFactory().getRouter(getRouteUrl( + "host = " + LOCAL_HOST + " & methods = getFoo => " + " host = 10.20.3.3").addParameter( + FORCE_KEY, String.valueOf(true))); + List> filteredInvokers1 = router4.route(invokers, + URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation); + Assertions.assertEquals(1, filteredInvokers1.size()); + + Router router5 = new ConditionRouterFactory().getRouter(getRouteUrl( + "host = " + LOCAL_HOST + " & methods = unvalidmethod => " + " host = 10.20.3.3") + .addParameter(FORCE_KEY, String.valueOf(true))); + List> filteredInvokers2 = router5.route(invokers, + URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation); + Assertions.assertEquals(3, filteredInvokers2.size()); + // Request a non-exists method + } + + @Test + public void testRoute_ReturnFalse() { + Router router = new ConditionRouterFactory().getRouter(getRouteUrl("host = " + LOCAL_HOST + " => false")); + List> invokers = new ArrayList>(); + invokers.add(new MockInvoker()); + invokers.add(new MockInvoker()); + invokers.add(new MockInvoker()); + List> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation()); + Assertions.assertEquals(0, filteredInvokers.size()); + } + + @Test + public void testRoute_ReturnEmpty() { + Router router = new ConditionRouterFactory().getRouter(getRouteUrl("host = " + LOCAL_HOST + " => ")); + List> invokers = new ArrayList>(); + invokers.add(new MockInvoker()); + invokers.add(new MockInvoker()); + invokers.add(new MockInvoker()); + List> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation()); + Assertions.assertEquals(0, filteredInvokers.size()); + } + + @Test + public void testRoute_ReturnAll() { + Router router = new ConditionRouterFactory().getRouter(getRouteUrl("host = " + LOCAL_HOST + " => " + " host = " + LOCAL_HOST)); + List> invokers = new ArrayList>(); + invokers.add(new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"))); + invokers.add(new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"))); + invokers.add(new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"))); + List> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation()); + Assertions.assertEquals(invokers, filteredInvokers); + } + + @Test + public void testRoute_HostFilter() { + Router router = new ConditionRouterFactory().getRouter(getRouteUrl("host = " + LOCAL_HOST + " => " + " host = " + LOCAL_HOST)); + List> invokers = new ArrayList>(); + Invoker invoker1 = new MockInvoker(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService")); + Invoker invoker2 = new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService")); + Invoker invoker3 = new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService")); + invokers.add(invoker1); + invokers.add(invoker2); + invokers.add(invoker3); + List> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation()); + Assertions.assertEquals(2, filteredInvokers.size()); + Assertions.assertEquals(invoker2, filteredInvokers.get(0)); + Assertions.assertEquals(invoker3, filteredInvokers.get(1)); + } + + @Test + public void testRoute_Empty_HostFilter() { + Router router = new ConditionRouterFactory().getRouter(getRouteUrl(" => " + " host = " + LOCAL_HOST)); + List> invokers = new ArrayList>(); + Invoker invoker1 = new MockInvoker(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService")); + Invoker invoker2 = new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService")); + Invoker invoker3 = new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService")); + invokers.add(invoker1); + invokers.add(invoker2); + invokers.add(invoker3); + List> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation()); + Assertions.assertEquals(2, filteredInvokers.size()); + Assertions.assertEquals(invoker2, filteredInvokers.get(0)); + Assertions.assertEquals(invoker3, filteredInvokers.get(1)); + } + + @Test + public void testRoute_False_HostFilter() { + Router router = new ConditionRouterFactory().getRouter(getRouteUrl("true => " + " host = " + LOCAL_HOST)); + List> invokers = new ArrayList>(); + Invoker invoker1 = new MockInvoker(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService")); + Invoker invoker2 = new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService")); + Invoker invoker3 = new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService")); + invokers.add(invoker1); + invokers.add(invoker2); + invokers.add(invoker3); + List> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation()); + Assertions.assertEquals(2, filteredInvokers.size()); + Assertions.assertEquals(invoker2, filteredInvokers.get(0)); + Assertions.assertEquals(invoker3, filteredInvokers.get(1)); + } + + @Test + public void testRoute_Placeholder() { + Router router = new ConditionRouterFactory().getRouter(getRouteUrl("host = " + LOCAL_HOST + " => " + " host = $host")); + List> invokers = new ArrayList>(); + Invoker invoker1 = new MockInvoker(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService")); + Invoker invoker2 = new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService")); + Invoker invoker3 = new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService")); + invokers.add(invoker1); + invokers.add(invoker2); + invokers.add(invoker3); + List> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation()); + Assertions.assertEquals(2, filteredInvokers.size()); + Assertions.assertEquals(invoker2, filteredInvokers.get(0)); + Assertions.assertEquals(invoker3, filteredInvokers.get(1)); + } + + @Test + public void testRoute_NoForce() { + Router router = new ConditionRouterFactory().getRouter(getRouteUrl("host = " + LOCAL_HOST + " => " + " host = 1.2.3.4")); + List> invokers = new ArrayList>(); + Invoker invoker1 = new MockInvoker(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService")); + Invoker invoker2 = new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService")); + Invoker invoker3 = new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService")); + invokers.add(invoker1); + invokers.add(invoker2); + invokers.add(invoker3); + List> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation()); + Assertions.assertEquals(invokers, filteredInvokers); + } + + @Test + public void testRoute_Force() { + Router router = new ConditionRouterFactory().getRouter(getRouteUrl("host = " + LOCAL_HOST + " => " + " host = 1.2.3.4").addParameter(FORCE_KEY, String.valueOf(true))); + List> invokers = new ArrayList>(); + Invoker invoker1 = new MockInvoker(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService")); + Invoker invoker2 = new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService")); + Invoker invoker3 = new MockInvoker(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService")); + invokers.add(invoker1); + invokers.add(invoker2); + invokers.add(invoker3); + List> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation()); + Assertions.assertEquals(0, filteredInvokers.size()); + } + + @Test + public void testRoute_Arguments() { + Router router = new ConditionRouterFactory().getRouter(getRouteUrl("arguments[0] = a " + " => " + " host = 1.2.3.4").addParameter(FORCE_KEY, String.valueOf(true))); + List> invokers = new ArrayList<>(); + Invoker invoker1 = new MockInvoker<>(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService")); + Invoker invoker2 = new MockInvoker<>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService")); + Invoker invoker3 = new MockInvoker<>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService")); + invokers.add(invoker1); + invokers.add(invoker2); + invokers.add(invoker3); + RpcInvocation invocation = new RpcInvocation(); + String p = "a"; + invocation.setArguments(new Object[]{null}); + List> fileredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation); + Assertions.assertEquals(3, fileredInvokers.size()); + + invocation.setArguments(new Object[]{p}); + fileredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation); + Assertions.assertEquals(0, fileredInvokers.size()); + + router = new ConditionRouterFactory().getRouter(getRouteUrl("arguments = b " + " => " + " host = 1.2.3.4").addParameter(FORCE_KEY, String.valueOf(true))); + fileredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation); + Assertions.assertEquals(3, fileredInvokers.size()); + + router = new ConditionRouterFactory().getRouter(getRouteUrl("arguments[10].inner = a " + " => " + " host = 1.2.3.4").addParameter(FORCE_KEY, String.valueOf(true))); + fileredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation); + Assertions.assertEquals(3, fileredInvokers.size()); + + int integer = 1; + invocation.setArguments(new Object[]{integer}); + router = new ConditionRouterFactory().getRouter(getRouteUrl("arguments[0].inner = 1 " + " => " + " host = 1.2.3.4").addParameter(FORCE_KEY, String.valueOf(true))); + fileredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation); + Assertions.assertEquals(0, fileredInvokers.size()); + } +} diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshAppRuleListenerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshAppRuleListenerTest.java index 8b89daacd5..3da5ea0b00 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshAppRuleListenerTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshAppRuleListenerTest.java @@ -177,4 +177,4 @@ public class MeshAppRuleListenerTest { assertTrue(vsDestinationGroup1.getVirtualServiceRuleList().size() == 0); } -} \ No newline at end of file +} diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleManagerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleManagerTest.java index 7638c853dd..214a65b4e4 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleManagerTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleManagerTest.java @@ -157,4 +157,4 @@ public class MeshRuleManagerTest { ApplicationModel.getEnvironment().setDynamicConfiguration(before.orElse(null)); } } -} \ No newline at end of file +} diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouterFactoryTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouterFactoryTest.java index 7bdc47a2b6..1738093d5c 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouterFactoryTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouterFactoryTest.java @@ -33,4 +33,4 @@ public class MeshRuleRouterFactoryTest { when(url.getServiceKey()).thenReturn("demoService"); ruleRouterFactory.getRouter(url); } -} \ No newline at end of file +} diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouterTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouterTest.java index 8262cd6e44..554a875750 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouterTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouterTest.java @@ -1404,4 +1404,4 @@ public class MeshRuleRouterTest { assertNotNull(meshRuleRouter.route((List) inputInvokers, inputURL, invocation)); } } -} \ No newline at end of file +} diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/DestinationRuleTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/DestinationRuleTest.java index 91f5ac73ce..0ddb0e2f1a 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/DestinationRuleTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/DestinationRuleTest.java @@ -99,4 +99,4 @@ public class DestinationRuleTest { } } -} \ No newline at end of file +} diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/VirtualServiceRuleTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/VirtualServiceRuleTest.java index ddfb1271d9..9fa20982cd 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/VirtualServiceRuleTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/VirtualServiceRuleTest.java @@ -35,4 +35,4 @@ public class VirtualServiceRuleTest { assertNotNull(virtualServiceRule); } -} \ No newline at end of file +} diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/DubboMatchRequestTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/DubboMatchRequestTest.java index 9bb55b4251..69da8c497b 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/DubboMatchRequestTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/DubboMatchRequestTest.java @@ -137,4 +137,4 @@ public class DubboMatchRequestTest { assertFalse(DubboMatchRequest.isMatch(dubboMatchRequest, "sayHello", new String[]{}, new Object[]{}, inputSourceLablesMap, invokeEagleEyeContextMap, invokeDubboContextMap2, new HashMap())); } -} \ No newline at end of file +} diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/BoolMatchTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/BoolMatchTest.java index 72d47748de..336f5ca076 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/BoolMatchTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/BoolMatchTest.java @@ -39,4 +39,4 @@ public class BoolMatchTest { assertTrue(BoolMatch.isMatch(boolMatch,false)); } -} \ No newline at end of file +} diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DoubleMatchTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DoubleMatchTest.java index aba44bc10c..48dae5c63a 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DoubleMatchTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DoubleMatchTest.java @@ -98,4 +98,4 @@ public class DoubleMatchTest { assertTrue(DoubleMatch.isMatch(doubleMatch, 3.0)); } -} \ No newline at end of file +} diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboAttachmentMatchTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboAttachmentMatchTest.java index 99e704f3f3..208f064936 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboAttachmentMatchTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboAttachmentMatchTest.java @@ -175,4 +175,4 @@ public class DubboAttachmentMatchTest { assertFalse(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, invokeEagleEyeContextMap2, invokeDubboContextMap2)); } -} \ No newline at end of file +} diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboMethodMatchTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboMethodMatchTest.java index 7c7189bf17..600dd8e675 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboMethodMatchTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboMethodMatchTest.java @@ -153,4 +153,4 @@ public class DubboMethodMatchTest { assertTrue(DubboMethodMatch.isMatch(dubboMethodMatch, "test", new String[]{"int", "java.lang.String", "boolean"}, new Object[]{10, "sayHello", true})); assertFalse(DubboMethodMatch.isMatch(dubboMethodMatch, "test", new String[]{"int", "java.lang.String", "boolean"}, new Object[]{10, "sayHello", false})); } -} \ No newline at end of file +} diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListDoubleMatchTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListDoubleMatchTest.java index f3b30b1f09..90faaacf7a 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListDoubleMatchTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListDoubleMatchTest.java @@ -49,4 +49,4 @@ public class ListDoubleMatchTest { assertTrue(ListDoubleMatch.isMatch(listDoubleMatch, 11.0)); assertFalse(ListDoubleMatch.isMatch(listDoubleMatch, 12.0)); } -} \ No newline at end of file +} diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListStringMatchTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListStringMatchTest.java index 056105349d..b60c439618 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListStringMatchTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListStringMatchTest.java @@ -51,4 +51,4 @@ public class ListStringMatchTest { assertFalse(ListStringMatch.isMatch(listStringMatch, "3")); } -} \ No newline at end of file +} diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/StringMatchTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/StringMatchTest.java index 13d0225301..c25ab751dc 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/StringMatchTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/StringMatchTest.java @@ -78,4 +78,4 @@ public class StringMatchTest { assertFalse(StringMatch.isMatch(stringMatch, "")); assertFalse(StringMatch.isMatch(stringMatch, null)); } -} \ No newline at end of file +} diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/util/VsDestinationGroupRuleDispatcherTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/util/VsDestinationGroupRuleDispatcherTest.java index 5193c8d77a..d108a7986c 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/util/VsDestinationGroupRuleDispatcherTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/util/VsDestinationGroupRuleDispatcherTest.java @@ -71,4 +71,4 @@ class VsDestinationGroupRuleDispatcherTest { verify(vsDestinationGroupRuleListener, times(1)).onRuleChange(anyObject()); } -} \ No newline at end of file +} diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouterTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouterTest.java index f52347f0b8..fa86c00585 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouterTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouterTest.java @@ -96,15 +96,15 @@ public class ScriptRouterTest { invokers.add(invoker3); String script = "function route(invokers, invocation, context){ " + - " var result = new java.util.ArrayList(invokers.size()); " + - " var targetHost = new java.util.ArrayList(); " + - " targetHost.add(\"10.134.108.2\"); " + - " for (var i = 0; i < invokers.length; i++) { " + - " if(targetHost.contains(invokers[i].getUrl().getHost())){ " + - " result.add(invokers[i]); " + - " } " + - " } " + - " return result; " + + " var result = new java.util.ArrayList(invokers.size()); " + + " var targetHost = new java.util.ArrayList(); " + + " targetHost.add(\"10.134.108.2\"); " + + " for (var i = 0; i < invokers.length; i++) { " + + " if(targetHost.contains(invokers[i].getUrl().getHost())){ " + + " result.add(invokers[i]); " + + " } " + + " } " + + " return result; " + "} " + "route(invokers, invocation, context) "; diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailSafeClusterInvokerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailSafeClusterInvokerTest.java index c666fb8e96..c6f45c6d30 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailSafeClusterInvokerTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailSafeClusterInvokerTest.java @@ -1,122 +1,122 @@ -/* - * 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.rpc.cluster.support; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.utils.LogUtil; -import org.apache.dubbo.rpc.AppResponse; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.Result; -import org.apache.dubbo.rpc.RpcContext; -import org.apache.dubbo.rpc.RpcInvocation; -import org.apache.dubbo.rpc.cluster.Directory; -import org.apache.dubbo.rpc.cluster.filter.DemoService; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.ArrayList; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; - -/** - * FailfastClusterInvokerTest - * - */ -@SuppressWarnings("unchecked") -public class FailSafeClusterInvokerTest { - List> invokers = new ArrayList>(); - URL url = URL.valueOf("test://test:11/test"); - Invoker invoker = mock(Invoker.class); - RpcInvocation invocation = new RpcInvocation(); - Directory dic; - Result result = new AppResponse(); - - /** - * @throws java.lang.Exception - */ - - @BeforeEach - public void setUp() throws Exception { - - dic = mock(Directory.class); - - given(dic.getUrl()).willReturn(url); - given(dic.getConsumerUrl()).willReturn(url); - given(dic.list(invocation)).willReturn(invokers); - given(dic.getInterface()).willReturn(DemoService.class); - invocation.setMethodName("method1"); - - invokers.add(invoker); - } - - private void resetInvokerToException() { - given(invoker.invoke(invocation)).willThrow(new RuntimeException()); - given(invoker.getUrl()).willReturn(url); - given(invoker.getInterface()).willReturn(DemoService.class); - } - - private void resetInvokerToNoException() { - given(invoker.invoke(invocation)).willReturn(result); - given(invoker.getUrl()).willReturn(url); - given(invoker.getInterface()).willReturn(DemoService.class); - } - - //TODO assert error log - @Test - public void testInvokeExceptoin() { - resetInvokerToException(); - FailsafeClusterInvoker invoker = new FailsafeClusterInvoker(dic); - invoker.invoke(invocation); - Assertions.assertNull(RpcContext.getServiceContext().getInvoker()); - } - - @Test() - public void testInvokeNoExceptoin() { - - resetInvokerToNoException(); - - FailsafeClusterInvoker invoker = new FailsafeClusterInvoker(dic); - Result ret = invoker.invoke(invocation); - Assertions.assertSame(result, ret); - } - - @Test() - public void testNoInvoke() { - dic = mock(Directory.class); - - given(dic.getUrl()).willReturn(url); - given(dic.getConsumerUrl()).willReturn(url); - given(dic.list(invocation)).willReturn(null); - given(dic.getInterface()).willReturn(DemoService.class); - - invocation.setMethodName("method1"); - - resetInvokerToNoException(); - - FailsafeClusterInvoker invoker = new FailsafeClusterInvoker(dic); - LogUtil.start(); - invoker.invoke(invocation); - assertTrue(LogUtil.findMessage("No provider") > 0); - LogUtil.stop(); - } - -} \ No newline at end of file +/* + * 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.rpc.cluster.support; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.utils.LogUtil; +import org.apache.dubbo.rpc.AppResponse; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.Result; +import org.apache.dubbo.rpc.RpcContext; +import org.apache.dubbo.rpc.RpcInvocation; +import org.apache.dubbo.rpc.cluster.Directory; +import org.apache.dubbo.rpc.cluster.filter.DemoService; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; + +/** + * FailfastClusterInvokerTest + * + */ +@SuppressWarnings("unchecked") +public class FailSafeClusterInvokerTest { + List> invokers = new ArrayList>(); + URL url = URL.valueOf("test://test:11/test"); + Invoker invoker = mock(Invoker.class); + RpcInvocation invocation = new RpcInvocation(); + Directory dic; + Result result = new AppResponse(); + + /** + * @throws java.lang.Exception + */ + + @BeforeEach + public void setUp() throws Exception { + + dic = mock(Directory.class); + + given(dic.getUrl()).willReturn(url); + given(dic.getConsumerUrl()).willReturn(url); + given(dic.list(invocation)).willReturn(invokers); + given(dic.getInterface()).willReturn(DemoService.class); + invocation.setMethodName("method1"); + + invokers.add(invoker); + } + + private void resetInvokerToException() { + given(invoker.invoke(invocation)).willThrow(new RuntimeException()); + given(invoker.getUrl()).willReturn(url); + given(invoker.getInterface()).willReturn(DemoService.class); + } + + private void resetInvokerToNoException() { + given(invoker.invoke(invocation)).willReturn(result); + given(invoker.getUrl()).willReturn(url); + given(invoker.getInterface()).willReturn(DemoService.class); + } + + //TODO assert error log + @Test + public void testInvokeExceptoin() { + resetInvokerToException(); + FailsafeClusterInvoker invoker = new FailsafeClusterInvoker(dic); + invoker.invoke(invocation); + Assertions.assertNull(RpcContext.getServiceContext().getInvoker()); + } + + @Test() + public void testInvokeNoExceptoin() { + + resetInvokerToNoException(); + + FailsafeClusterInvoker invoker = new FailsafeClusterInvoker(dic); + Result ret = invoker.invoke(invocation); + Assertions.assertSame(result, ret); + } + + @Test() + public void testNoInvoke() { + dic = mock(Directory.class); + + given(dic.getUrl()).willReturn(url); + given(dic.getConsumerUrl()).willReturn(url); + given(dic.list(invocation)).willReturn(null); + given(dic.getInterface()).willReturn(DemoService.class); + + invocation.setMethodName("method1"); + + resetInvokerToNoException(); + + FailsafeClusterInvoker invoker = new FailsafeClusterInvoker(dic); + LogUtil.start(); + invoker.invoke(invocation); + assertTrue(LogUtil.findMessage("No provider") > 0); + LogUtil.stop(); + } + +} diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailbackClusterInvokerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailbackClusterInvokerTest.java index 84747b70da..032c1c7922 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailbackClusterInvokerTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailbackClusterInvokerTest.java @@ -1,177 +1,177 @@ - -/* - * 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.rpc.cluster.support; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.utils.DubboAppender; -import org.apache.dubbo.common.utils.LogUtil; -import org.apache.dubbo.rpc.AppResponse; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.Result; -import org.apache.dubbo.rpc.RpcContext; -import org.apache.dubbo.rpc.RpcInvocation; -import org.apache.dubbo.rpc.cluster.Directory; - -import org.apache.log4j.Level; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.MethodOrderer; -import org.junit.jupiter.api.Order; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestMethodOrder; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; - -/** - * FailbackClusterInvokerTest - *

- * add annotation @TestMethodOrder, the testARetryFailed Method must to first execution - */ -@TestMethodOrder(MethodOrderer.OrderAnnotation.class) -public class FailbackClusterInvokerTest { - - List> invokers = new ArrayList>(); - URL url = URL.valueOf("test://test:11/test?retries=2&failbacktasks=2"); - Invoker invoker = mock(Invoker.class); - RpcInvocation invocation = new RpcInvocation(); - Directory dic; - Result result = new AppResponse(); - - /** - * @throws java.lang.Exception - */ - - @BeforeEach - public void setUp() throws Exception { - - dic = mock(Directory.class); - given(dic.getUrl()).willReturn(url); - given(dic.getConsumerUrl()).willReturn(url); - given(dic.list(invocation)).willReturn(invokers); - given(dic.getInterface()).willReturn(FailbackClusterInvokerTest.class); - - invocation.setMethodName("method1"); - - invokers.add(invoker); - } - - @AfterEach - public void tearDown() { - - dic = null; - invocation = new RpcInvocation(); - invokers.clear(); - } - - - private void resetInvokerToException() { - given(invoker.invoke(invocation)).willThrow(new RuntimeException()); - given(invoker.getUrl()).willReturn(url); - given(invoker.getInterface()).willReturn(FailbackClusterInvokerTest.class); - } - - private void resetInvokerToNoException() { - given(invoker.invoke(invocation)).willReturn(result); - given(invoker.getUrl()).willReturn(url); - given(invoker.getInterface()).willReturn(FailbackClusterInvokerTest.class); - } - - @Test - @Order(1) - public void testInvokeException() { - resetInvokerToException(); - FailbackClusterInvoker invoker = new FailbackClusterInvoker( - dic); - invoker.invoke(invocation); - Assertions.assertNull(RpcContext.getServiceContext().getInvoker()); - DubboAppender.clear(); - } - - @Test - @Order(2) - public void testInvokeNoException() { - - resetInvokerToNoException(); - - FailbackClusterInvoker invoker = new FailbackClusterInvoker( - dic); - Result ret = invoker.invoke(invocation); - Assertions.assertSame(result, ret); - } - - @Test - @Order(3) - public void testNoInvoke() { - dic = mock(Directory.class); - - given(dic.getUrl()).willReturn(url); - given(dic.getConsumerUrl()).willReturn(url); - given(dic.list(invocation)).willReturn(null); - given(dic.getInterface()).willReturn(FailbackClusterInvokerTest.class); - - invocation.setMethodName("method1"); - - invokers.add(invoker); - - resetInvokerToNoException(); - - FailbackClusterInvoker invoker = new FailbackClusterInvoker( - dic); - LogUtil.start(); - DubboAppender.clear(); - invoker.invoke(invocation); - assertEquals(1, LogUtil.findMessage("Failback to invoke")); - LogUtil.stop(); - } - - @Disabled - @Test - @Order(4) - public void testARetryFailed() throws Exception { - //Test retries and - - resetInvokerToException(); - - FailbackClusterInvoker invoker = new FailbackClusterInvoker( - dic); - LogUtil.start(); - DubboAppender.clear(); - invoker.invoke(invocation); - invoker.invoke(invocation); - invoker.invoke(invocation); - Assertions.assertNull(RpcContext.getServiceContext().getInvoker()); -// invoker.retryFailed();// when retry the invoker which get from failed map already is not the mocked invoker,so - //Ensure that the main thread is online - CountDownLatch countDown = new CountDownLatch(1); - countDown.await(15000L, TimeUnit.MILLISECONDS); - LogUtil.stop(); - Assertions.assertEquals(4, LogUtil.findMessage(Level.ERROR, "Failed retry to invoke method"), "must have four error message "); - Assertions.assertEquals(2, LogUtil.findMessage(Level.ERROR, "Failed retry times exceed threshold"), "must have two error message "); - Assertions.assertEquals(1, LogUtil.findMessage(Level.ERROR, "Failback background works error"), "must have one error message "); - // it can be invoke successfully - } -} \ No newline at end of file + +/* + * 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.rpc.cluster.support; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.utils.DubboAppender; +import org.apache.dubbo.common.utils.LogUtil; +import org.apache.dubbo.rpc.AppResponse; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.Result; +import org.apache.dubbo.rpc.RpcContext; +import org.apache.dubbo.rpc.RpcInvocation; +import org.apache.dubbo.rpc.cluster.Directory; + +import org.apache.log4j.Level; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; + +/** + * FailbackClusterInvokerTest + *

+ * add annotation @TestMethodOrder, the testARetryFailed Method must to first execution + */ +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +public class FailbackClusterInvokerTest { + + List> invokers = new ArrayList>(); + URL url = URL.valueOf("test://test:11/test?retries=2&failbacktasks=2"); + Invoker invoker = mock(Invoker.class); + RpcInvocation invocation = new RpcInvocation(); + Directory dic; + Result result = new AppResponse(); + + /** + * @throws java.lang.Exception + */ + + @BeforeEach + public void setUp() throws Exception { + + dic = mock(Directory.class); + given(dic.getUrl()).willReturn(url); + given(dic.getConsumerUrl()).willReturn(url); + given(dic.list(invocation)).willReturn(invokers); + given(dic.getInterface()).willReturn(FailbackClusterInvokerTest.class); + + invocation.setMethodName("method1"); + + invokers.add(invoker); + } + + @AfterEach + public void tearDown() { + + dic = null; + invocation = new RpcInvocation(); + invokers.clear(); + } + + + private void resetInvokerToException() { + given(invoker.invoke(invocation)).willThrow(new RuntimeException()); + given(invoker.getUrl()).willReturn(url); + given(invoker.getInterface()).willReturn(FailbackClusterInvokerTest.class); + } + + private void resetInvokerToNoException() { + given(invoker.invoke(invocation)).willReturn(result); + given(invoker.getUrl()).willReturn(url); + given(invoker.getInterface()).willReturn(FailbackClusterInvokerTest.class); + } + + @Test + @Order(1) + public void testInvokeException() { + resetInvokerToException(); + FailbackClusterInvoker invoker = new FailbackClusterInvoker( + dic); + invoker.invoke(invocation); + Assertions.assertNull(RpcContext.getServiceContext().getInvoker()); + DubboAppender.clear(); + } + + @Test + @Order(2) + public void testInvokeNoException() { + + resetInvokerToNoException(); + + FailbackClusterInvoker invoker = new FailbackClusterInvoker( + dic); + Result ret = invoker.invoke(invocation); + Assertions.assertSame(result, ret); + } + + @Test + @Order(3) + public void testNoInvoke() { + dic = mock(Directory.class); + + given(dic.getUrl()).willReturn(url); + given(dic.getConsumerUrl()).willReturn(url); + given(dic.list(invocation)).willReturn(null); + given(dic.getInterface()).willReturn(FailbackClusterInvokerTest.class); + + invocation.setMethodName("method1"); + + invokers.add(invoker); + + resetInvokerToNoException(); + + FailbackClusterInvoker invoker = new FailbackClusterInvoker( + dic); + LogUtil.start(); + DubboAppender.clear(); + invoker.invoke(invocation); + assertEquals(1, LogUtil.findMessage("Failback to invoke")); + LogUtil.stop(); + } + + @Disabled + @Test + @Order(4) + public void testARetryFailed() throws Exception { + //Test retries and + + resetInvokerToException(); + + FailbackClusterInvoker invoker = new FailbackClusterInvoker( + dic); + LogUtil.start(); + DubboAppender.clear(); + invoker.invoke(invocation); + invoker.invoke(invocation); + invoker.invoke(invocation); + Assertions.assertNull(RpcContext.getServiceContext().getInvoker()); +// invoker.retryFailed();// when retry the invoker which get from failed map already is not the mocked invoker,so + //Ensure that the main thread is online + CountDownLatch countDown = new CountDownLatch(1); + countDown.await(15000L, TimeUnit.MILLISECONDS); + LogUtil.stop(); + Assertions.assertEquals(4, LogUtil.findMessage(Level.ERROR, "Failed retry to invoke method"), "must have four error message "); + Assertions.assertEquals(2, LogUtil.findMessage(Level.ERROR, "Failed retry times exceed threshold"), "must have two error message "); + Assertions.assertEquals(1, LogUtil.findMessage(Level.ERROR, "Failback background works error"), "must have one error message "); + // it can be invoke successfully + } +} diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailfastClusterInvokerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailfastClusterInvokerTest.java index 459dcfc147..525f898ad1 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailfastClusterInvokerTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailfastClusterInvokerTest.java @@ -124,4 +124,4 @@ public class FailfastClusterInvokerTest { } } -} \ No newline at end of file +} diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvokerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvokerTest.java index a162526292..b2742fbfd2 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvokerTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvokerTest.java @@ -1,290 +1,290 @@ -/* - * 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.rpc.cluster.support; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.rpc.AppResponse; -import org.apache.dubbo.rpc.AsyncRpcResult; -import org.apache.dubbo.rpc.Invocation; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.Result; -import org.apache.dubbo.rpc.RpcContext; -import org.apache.dubbo.rpc.RpcException; -import org.apache.dubbo.rpc.RpcInvocation; -import org.apache.dubbo.rpc.cluster.Directory; -import org.apache.dubbo.rpc.cluster.directory.StaticDirectory; -import org.apache.dubbo.rpc.protocol.AbstractInvoker; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Callable; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertSame; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; - -/** - * FailoverClusterInvokerTest - * - */ -@SuppressWarnings("unchecked") -public class FailoverClusterInvokerTest { - private List> invokers = new ArrayList>(); - private int retries = 5; - private URL url = URL.valueOf("test://test:11/test?retries=" + retries); - private Invoker invoker1 = mock(Invoker.class); - private Invoker invoker2 = mock(Invoker.class); - private RpcInvocation invocation = new RpcInvocation(); - private Directory dic; - private Result result = new AppResponse(); - - /** - * @throws java.lang.Exception - */ - - @BeforeEach - public void setUp() throws Exception { - - dic = mock(Directory.class); - - given(dic.getUrl()).willReturn(url); - given(dic.getConsumerUrl()).willReturn(url); - given(dic.list(invocation)).willReturn(invokers); - given(dic.getInterface()).willReturn(FailoverClusterInvokerTest.class); - invocation.setMethodName("method1"); - - invokers.add(invoker1); - invokers.add(invoker2); - } - - - @Test - public void testInvokeWithRuntimeException() { - given(invoker1.invoke(invocation)).willThrow(new RuntimeException()); - given(invoker1.isAvailable()).willReturn(true); - given(invoker1.getUrl()).willReturn(url); - given(invoker1.getInterface()).willReturn(FailoverClusterInvokerTest.class); - - given(invoker2.invoke(invocation)).willThrow(new RuntimeException()); - given(invoker2.isAvailable()).willReturn(true); - given(invoker2.getUrl()).willReturn(url); - given(invoker2.getInterface()).willReturn(FailoverClusterInvokerTest.class); - - FailoverClusterInvoker invoker = new FailoverClusterInvoker(dic); - try { - invoker.invoke(invocation); - fail(); - } catch (RpcException expected) { - assertEquals(0, expected.getCode()); - assertFalse(expected.getCause() instanceof RpcException); - } - } - - @Test() - public void testInvokeWithRPCException() { - given(invoker1.invoke(invocation)).willThrow(new RpcException()); - given(invoker1.isAvailable()).willReturn(true); - given(invoker1.getUrl()).willReturn(url); - given(invoker1.getInterface()).willReturn(FailoverClusterInvokerTest.class); - - given(invoker2.invoke(invocation)).willReturn(result); - given(invoker2.isAvailable()).willReturn(true); - given(invoker2.getUrl()).willReturn(url); - given(invoker2.getInterface()).willReturn(FailoverClusterInvokerTest.class); - - FailoverClusterInvoker invoker = new FailoverClusterInvoker(dic); - for (int i = 0; i < 100; i++) { - Result ret = invoker.invoke(invocation); - assertSame(result, ret); - } - } - - @Test() - public void testInvoke_retryTimes() { - given(invoker1.invoke(invocation)).willThrow(new RpcException(RpcException.TIMEOUT_EXCEPTION)); - given(invoker1.isAvailable()).willReturn(false); - given(invoker1.getUrl()).willReturn(url); - given(invoker1.getInterface()).willReturn(FailoverClusterInvokerTest.class); - - given(invoker2.invoke(invocation)).willThrow(new RpcException()); - given(invoker2.isAvailable()).willReturn(false); - given(invoker2.getUrl()).willReturn(url); - given(invoker2.getInterface()).willReturn(FailoverClusterInvokerTest.class); - - FailoverClusterInvoker invoker = new FailoverClusterInvoker(dic); - try { - Result ret = invoker.invoke(invocation); - assertSame(result, ret); - fail(); - } catch (RpcException expected) { - assertTrue((expected.isTimeout() || expected.getCode() == 0)); - assertTrue(expected.getMessage().indexOf((retries + 1) + " times") > 0); - } - } - - @Test() - public void testInvoke_retryTimes2() { - int finalRetries = 1; - given(invoker1.invoke(invocation)).willThrow(new RpcException(RpcException.TIMEOUT_EXCEPTION)); - given(invoker1.isAvailable()).willReturn(false); - given(invoker1.getUrl()).willReturn(url); - given(invoker1.getInterface()).willReturn(FailoverClusterInvokerTest.class); - - given(invoker2.invoke(invocation)).willThrow(new RpcException()); - given(invoker2.isAvailable()).willReturn(false); - given(invoker2.getUrl()).willReturn(url); - given(invoker2.getInterface()).willReturn(FailoverClusterInvokerTest.class); - - RpcContext rpcContext = RpcContext.getContext(); - rpcContext.setAttachment("retries", finalRetries); - - FailoverClusterInvoker invoker = new FailoverClusterInvoker(dic); - try { - Result ret = invoker.invoke(invocation); - assertSame(result, ret); - fail(); - } catch (RpcException expected) { - assertTrue((expected.isTimeout() || expected.getCode() == 0)); - assertTrue(expected.getMessage().indexOf((finalRetries+1) + " times") > 0); - } - } - - @Test() - public void testNoInvoke() { - dic = mock(Directory.class); - - given(dic.getUrl()).willReturn(url); - given(dic.getConsumerUrl()).willReturn(url); - given(dic.list(invocation)).willReturn(null); - given(dic.getInterface()).willReturn(FailoverClusterInvokerTest.class); - invocation.setMethodName("method1"); - - invokers.add(invoker1); - - - FailoverClusterInvoker invoker = new FailoverClusterInvoker(dic); - try { - invoker.invoke(invocation); - fail(); - } catch (RpcException expected) { - assertFalse(expected.getCause() instanceof RpcException); - } - } - - /** - * When invokers in directory changes after a failed request but just before a retry effort, - * then we should reselect from the latest invokers before retry. - */ - @Test - public void testInvokerDestroyAndReList() { - final URL url = URL.valueOf("test://localhost/" + Demo.class.getName() + "?loadbalance=roundrobin&retries=" + retries); - RpcException exception = new RpcException(RpcException.TIMEOUT_EXCEPTION); - MockInvoker invoker1 = new MockInvoker(Demo.class, url); - invoker1.setException(exception); - - MockInvoker invoker2 = new MockInvoker(Demo.class, url); - invoker2.setException(exception); - - final List> invokers = new ArrayList>(); - invokers.add(invoker1); - invokers.add(invoker2); - - Callable callable = () -> { - //Simulation: all invokers are destroyed - for (Invoker invoker : invokers) { - invoker.destroy(); - } - invokers.clear(); - MockInvoker invoker3 = new MockInvoker(Demo.class, url); - invoker3.setResult(AsyncRpcResult.newDefaultAsyncResult(null)); - invokers.add(invoker3); - return null; - }; - invoker1.setCallable(callable); - invoker2.setCallable(callable); - - RpcInvocation inv = new RpcInvocation(); - inv.setMethodName("test"); - - Directory dic = new MockDirectory(url, invokers); - - FailoverClusterInvoker clusterinvoker = new FailoverClusterInvoker(dic); - clusterinvoker.invoke(inv); - } - - public interface Demo { - } - - public static class MockInvoker extends AbstractInvoker { - URL url; - boolean available = true; - boolean destoryed = false; - Result result; - RpcException exception; - Callable callable; - - public MockInvoker(Class type, URL url) { - super(type, url); - } - - public void setResult(Result result) { - this.result = result; - } - - public void setException(RpcException exception) { - this.exception = exception; - } - - public void setCallable(Callable callable) { - this.callable = callable; - } - - @Override - protected Result doInvoke(Invocation invocation) throws Throwable { - if (callable != null) { - try { - callable.call(); - } catch (Exception e) { - throw new RpcException(e); - } - } - if (exception != null) { - throw exception; - } else { - return result; - } - } - } - - public class MockDirectory extends StaticDirectory { - public MockDirectory(URL url, List> invokers) { - super(url, invokers); - } - - @Override - protected List> doList(Invocation invocation) throws RpcException { - return new ArrayList>(super.doList(invocation)); - } - } -} \ No newline at end of file +/* + * 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.rpc.cluster.support; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.rpc.AppResponse; +import org.apache.dubbo.rpc.AsyncRpcResult; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.Result; +import org.apache.dubbo.rpc.RpcContext; +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.RpcInvocation; +import org.apache.dubbo.rpc.cluster.Directory; +import org.apache.dubbo.rpc.cluster.directory.StaticDirectory; +import org.apache.dubbo.rpc.protocol.AbstractInvoker; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; + +/** + * FailoverClusterInvokerTest + * + */ +@SuppressWarnings("unchecked") +public class FailoverClusterInvokerTest { + private List> invokers = new ArrayList>(); + private int retries = 5; + private URL url = URL.valueOf("test://test:11/test?retries=" + retries); + private Invoker invoker1 = mock(Invoker.class); + private Invoker invoker2 = mock(Invoker.class); + private RpcInvocation invocation = new RpcInvocation(); + private Directory dic; + private Result result = new AppResponse(); + + /** + * @throws java.lang.Exception + */ + + @BeforeEach + public void setUp() throws Exception { + + dic = mock(Directory.class); + + given(dic.getUrl()).willReturn(url); + given(dic.getConsumerUrl()).willReturn(url); + given(dic.list(invocation)).willReturn(invokers); + given(dic.getInterface()).willReturn(FailoverClusterInvokerTest.class); + invocation.setMethodName("method1"); + + invokers.add(invoker1); + invokers.add(invoker2); + } + + + @Test + public void testInvokeWithRuntimeException() { + given(invoker1.invoke(invocation)).willThrow(new RuntimeException()); + given(invoker1.isAvailable()).willReturn(true); + given(invoker1.getUrl()).willReturn(url); + given(invoker1.getInterface()).willReturn(FailoverClusterInvokerTest.class); + + given(invoker2.invoke(invocation)).willThrow(new RuntimeException()); + given(invoker2.isAvailable()).willReturn(true); + given(invoker2.getUrl()).willReturn(url); + given(invoker2.getInterface()).willReturn(FailoverClusterInvokerTest.class); + + FailoverClusterInvoker invoker = new FailoverClusterInvoker(dic); + try { + invoker.invoke(invocation); + fail(); + } catch (RpcException expected) { + assertEquals(0, expected.getCode()); + assertFalse(expected.getCause() instanceof RpcException); + } + } + + @Test() + public void testInvokeWithRPCException() { + given(invoker1.invoke(invocation)).willThrow(new RpcException()); + given(invoker1.isAvailable()).willReturn(true); + given(invoker1.getUrl()).willReturn(url); + given(invoker1.getInterface()).willReturn(FailoverClusterInvokerTest.class); + + given(invoker2.invoke(invocation)).willReturn(result); + given(invoker2.isAvailable()).willReturn(true); + given(invoker2.getUrl()).willReturn(url); + given(invoker2.getInterface()).willReturn(FailoverClusterInvokerTest.class); + + FailoverClusterInvoker invoker = new FailoverClusterInvoker(dic); + for (int i = 0; i < 100; i++) { + Result ret = invoker.invoke(invocation); + assertSame(result, ret); + } + } + + @Test() + public void testInvoke_retryTimes() { + given(invoker1.invoke(invocation)).willThrow(new RpcException(RpcException.TIMEOUT_EXCEPTION)); + given(invoker1.isAvailable()).willReturn(false); + given(invoker1.getUrl()).willReturn(url); + given(invoker1.getInterface()).willReturn(FailoverClusterInvokerTest.class); + + given(invoker2.invoke(invocation)).willThrow(new RpcException()); + given(invoker2.isAvailable()).willReturn(false); + given(invoker2.getUrl()).willReturn(url); + given(invoker2.getInterface()).willReturn(FailoverClusterInvokerTest.class); + + FailoverClusterInvoker invoker = new FailoverClusterInvoker(dic); + try { + Result ret = invoker.invoke(invocation); + assertSame(result, ret); + fail(); + } catch (RpcException expected) { + assertTrue((expected.isTimeout() || expected.getCode() == 0)); + assertTrue(expected.getMessage().indexOf((retries + 1) + " times") > 0); + } + } + + @Test() + public void testInvoke_retryTimes2() { + int finalRetries = 1; + given(invoker1.invoke(invocation)).willThrow(new RpcException(RpcException.TIMEOUT_EXCEPTION)); + given(invoker1.isAvailable()).willReturn(false); + given(invoker1.getUrl()).willReturn(url); + given(invoker1.getInterface()).willReturn(FailoverClusterInvokerTest.class); + + given(invoker2.invoke(invocation)).willThrow(new RpcException()); + given(invoker2.isAvailable()).willReturn(false); + given(invoker2.getUrl()).willReturn(url); + given(invoker2.getInterface()).willReturn(FailoverClusterInvokerTest.class); + + RpcContext rpcContext = RpcContext.getContext(); + rpcContext.setAttachment("retries", finalRetries); + + FailoverClusterInvoker invoker = new FailoverClusterInvoker(dic); + try { + Result ret = invoker.invoke(invocation); + assertSame(result, ret); + fail(); + } catch (RpcException expected) { + assertTrue((expected.isTimeout() || expected.getCode() == 0)); + assertTrue(expected.getMessage().indexOf((finalRetries+1) + " times") > 0); + } + } + + @Test() + public void testNoInvoke() { + dic = mock(Directory.class); + + given(dic.getUrl()).willReturn(url); + given(dic.getConsumerUrl()).willReturn(url); + given(dic.list(invocation)).willReturn(null); + given(dic.getInterface()).willReturn(FailoverClusterInvokerTest.class); + invocation.setMethodName("method1"); + + invokers.add(invoker1); + + + FailoverClusterInvoker invoker = new FailoverClusterInvoker(dic); + try { + invoker.invoke(invocation); + fail(); + } catch (RpcException expected) { + assertFalse(expected.getCause() instanceof RpcException); + } + } + + /** + * When invokers in directory changes after a failed request but just before a retry effort, + * then we should reselect from the latest invokers before retry. + */ + @Test + public void testInvokerDestroyAndReList() { + final URL url = URL.valueOf("test://localhost/" + Demo.class.getName() + "?loadbalance=roundrobin&retries=" + retries); + RpcException exception = new RpcException(RpcException.TIMEOUT_EXCEPTION); + MockInvoker invoker1 = new MockInvoker(Demo.class, url); + invoker1.setException(exception); + + MockInvoker invoker2 = new MockInvoker(Demo.class, url); + invoker2.setException(exception); + + final List> invokers = new ArrayList>(); + invokers.add(invoker1); + invokers.add(invoker2); + + Callable callable = () -> { + //Simulation: all invokers are destroyed + for (Invoker invoker : invokers) { + invoker.destroy(); + } + invokers.clear(); + MockInvoker invoker3 = new MockInvoker(Demo.class, url); + invoker3.setResult(AsyncRpcResult.newDefaultAsyncResult(null)); + invokers.add(invoker3); + return null; + }; + invoker1.setCallable(callable); + invoker2.setCallable(callable); + + RpcInvocation inv = new RpcInvocation(); + inv.setMethodName("test"); + + Directory dic = new MockDirectory(url, invokers); + + FailoverClusterInvoker clusterinvoker = new FailoverClusterInvoker(dic); + clusterinvoker.invoke(inv); + } + + public interface Demo { + } + + public static class MockInvoker extends AbstractInvoker { + URL url; + boolean available = true; + boolean destoryed = false; + Result result; + RpcException exception; + Callable callable; + + public MockInvoker(Class type, URL url) { + super(type, url); + } + + public void setResult(Result result) { + this.result = result; + } + + public void setException(RpcException exception) { + this.exception = exception; + } + + public void setCallable(Callable callable) { + this.callable = callable; + } + + @Override + protected Result doInvoke(Invocation invocation) throws Throwable { + if (callable != null) { + try { + callable.call(); + } catch (Exception e) { + throw new RpcException(e); + } + } + if (exception != null) { + throw exception; + } else { + return result; + } + } + } + + public class MockDirectory extends StaticDirectory { + public MockDirectory(URL url, List> invokers) { + super(url, invokers); + } + + @Override + protected List> doList(Invocation invocation) throws RpcException { + return new ArrayList>(super.doList(invocation)); + } + } +} diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/ForkingClusterInvokerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/ForkingClusterInvokerTest.java index 3c2699169d..c5469f1542 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/ForkingClusterInvokerTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/ForkingClusterInvokerTest.java @@ -154,4 +154,4 @@ public class ForkingClusterInvokerTest { Assertions.assertSame(result, ret); } -} \ No newline at end of file +} diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/wrapper/MyMockException.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/wrapper/MyMockException.java index d9a59cfb90..f353745cc7 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/wrapper/MyMockException.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/wrapper/MyMockException.java @@ -1,28 +1,28 @@ -/* - * 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.rpc.cluster.support.wrapper; - - -public class MyMockException extends RuntimeException { - - private static final long serialVersionUID = 2851692379597990457L; - - public MyMockException(String message) { - super(message); - } - -} +/* + * 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.rpc.cluster.support.wrapper; + + +public class MyMockException extends RuntimeException { + + private static final long serialVersionUID = 2851692379597990457L; + + public MyMockException(String message) { + super(message); + } + +} diff --git a/dubbo-cluster/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.RouterFactory b/dubbo-cluster/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.RouterFactory index dc43350460..95a85f3bfd 100644 --- a/dubbo-cluster/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.RouterFactory +++ b/dubbo-cluster/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.RouterFactory @@ -1 +1 @@ -script=org.apache.dubbo.rpc.cluster.router.script.ScriptRouterFactory +script=org.apache.dubbo.rpc.cluster.router.script.ScriptRouterFactory diff --git a/dubbo-cluster/src/test/resources/log4j.xml b/dubbo-cluster/src/test/resources/log4j.xml index eb0c9f105d..10680a3ed0 100644 --- a/dubbo-cluster/src/test/resources/log4j.xml +++ b/dubbo-cluster/src/test/resources/log4j.xml @@ -1,30 +1,30 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/Activate.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/Activate.java index 9aecbce000..1a739adeaf 100644 --- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/Activate.java +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/Activate.java @@ -42,4 +42,4 @@ public @interface Activate { String[] after() default {}; int order() default 0; -} \ No newline at end of file +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/Extension.java b/dubbo-common/src/main/java/org/apache/dubbo/common/Extension.java index 724a0d7dcd..4e4815bc13 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/Extension.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/Extension.java @@ -1,68 +1,68 @@ -/* - * 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.common; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Marker for extension interface - *

- * Changes on extension configuration file
- * Use Protocol as an example, its configuration file 'META-INF/dubbo/com.xxx.Protocol' is changes from:
- *

- *     com.foo.XxxProtocol
- *     com.foo.YyyProtocol
- * 
- *

- * to key-value pair
- *

- *     xxx=com.foo.XxxProtocol
- *     yyy=com.foo.YyyProtocol
- * 
- *
- * The reason for this change is: - *

- * If there's third party library referenced by static field or by method in extension implementation, its class will - * fail to initialize if the third party library doesn't exist. In this case, dubbo cannot figure out extension's id - * therefore cannot be able to map the exception information with the extension, if the previous format is used. - *

- * For example: - *

- * Fails to load Extension("mina"). When user configure to use mina, dubbo will complain the extension cannot be loaded, - * instead of reporting which extract extension implementation fails and the extract reason. - *

- * - * @deprecated because it's too general, switch to use {@link org.apache.dubbo.common.extension.SPI} - */ -@Deprecated -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) -public @interface Extension { - - /** - * @deprecated - */ - @Deprecated - String value() default ""; - -} \ No newline at end of file +/* + * 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.common; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Marker for extension interface + *

+ * Changes on extension configuration file
+ * Use Protocol as an example, its configuration file 'META-INF/dubbo/com.xxx.Protocol' is changes from:
+ *

+ *     com.foo.XxxProtocol
+ *     com.foo.YyyProtocol
+ * 
+ *

+ * to key-value pair
+ *

+ *     xxx=com.foo.XxxProtocol
+ *     yyy=com.foo.YyyProtocol
+ * 
+ *
+ * The reason for this change is: + *

+ * If there's third party library referenced by static field or by method in extension implementation, its class will + * fail to initialize if the third party library doesn't exist. In this case, dubbo cannot figure out extension's id + * therefore cannot be able to map the exception information with the extension, if the previous format is used. + *

+ * For example: + *

+ * Fails to load Extension("mina"). When user configure to use mina, dubbo will complain the extension cannot be loaded, + * instead of reporting which extract extension implementation fails and the extract reason. + *

+ * + * @deprecated because it's too general, switch to use {@link org.apache.dubbo.common.extension.SPI} + */ +@Deprecated +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +public @interface Extension { + + /** + * @deprecated + */ + @Deprecated + String value() default ""; + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/Node.java b/dubbo-common/src/main/java/org/apache/dubbo/common/Node.java index 7b097f72b2..1bd8c74e64 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/Node.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/Node.java @@ -1,43 +1,43 @@ -/* - * 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.common; - -/** - * Node. (API/SPI, Prototype, ThreadSafe) - */ -public interface Node { - - /** - * get url. - * - * @return url. - */ - URL getUrl(); - - /** - * is available. - * - * @return available. - */ - boolean isAvailable(); - - /** - * destroy. - */ - void destroy(); - -} \ No newline at end of file +/* + * 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.common; + +/** + * Node. (API/SPI, Prototype, ThreadSafe) + */ +public interface Node { + + /** + * get url. + * + * @return url. + */ + URL getUrl(); + + /** + * is available. + * + * @return available. + */ + boolean isAvailable(); + + /** + * destroy. + */ + void destroy(); + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/Parameters.java b/dubbo-common/src/main/java/org/apache/dubbo/common/Parameters.java index 790c476234..cdeaf29be4 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/Parameters.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/Parameters.java @@ -1,263 +1,263 @@ -/* - * 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.common; - -import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.utils.CollectionUtils; -import org.apache.dubbo.common.utils.StringUtils; - -import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY_PREFIX; -import static org.apache.dubbo.common.constants.CommonConstants.HIDE_KEY_PREFIX; - -/** - * Parameters for backward compatibility for version prior to 2.0.5 - * - * @deprecated - */ -@Deprecated -public class Parameters { - protected static final Logger logger = LoggerFactory.getLogger(Parameters.class); - private final Map parameters; - - public Parameters(String... pairs) { - this(toMap(pairs)); - } - - public Parameters(Map parameters) { - this.parameters = Collections.unmodifiableMap(parameters != null ? new HashMap<>(parameters) : new HashMap<>(0)); - } - - private static Map toMap(String... pairs) { - return CollectionUtils.toStringMap(pairs); - } - - public static Parameters parseParameters(String query) { - return new Parameters(StringUtils.parseQueryString(query)); - } - - public Map getParameters() { - return parameters; - } - - public T getExtension(Class type, String key) { - String name = getParameter(key); - return ExtensionLoader.getExtensionLoader(type).getExtension(name); - } - - public T getExtension(Class type, String key, String defaultValue) { - String name = getParameter(key, defaultValue); - return ExtensionLoader.getExtensionLoader(type).getExtension(name); - } - - public T getMethodExtension(Class type, String method, String key) { - String name = getMethodParameter(method, key); - return ExtensionLoader.getExtensionLoader(type).getExtension(name); - } - - public T getMethodExtension(Class type, String method, String key, String defaultValue) { - String name = getMethodParameter(method, key, defaultValue); - return ExtensionLoader.getExtensionLoader(type).getExtension(name); - } - - public String getDecodedParameter(String key) { - return getDecodedParameter(key, null); - } - - public String getDecodedParameter(String key, String defaultValue) { - String value = getParameter(key, defaultValue); - if (value != null && value.length() > 0) { - try { - value = URLDecoder.decode(value, "UTF-8"); - } catch (UnsupportedEncodingException e) { - logger.error(e.getMessage(), e); - } - } - return value; - } - - public String getParameter(String key) { - String value = parameters.get(key); - if (StringUtils.isEmpty(value)) { - value = parameters.get(HIDE_KEY_PREFIX + key); - } - if (StringUtils.isEmpty(value)) { - value = parameters.get(DEFAULT_KEY_PREFIX + key); - } - if (StringUtils.isEmpty(value)) { - value = parameters.get(HIDE_KEY_PREFIX + DEFAULT_KEY_PREFIX + key); - } - return value; - } - - public String getParameter(String key, String defaultValue) { - String value = getParameter(key); - if (StringUtils.isEmpty(value)) { - return defaultValue; - } - return value; - } - - public int getIntParameter(String key) { - String value = getParameter(key); - if (StringUtils.isEmpty(value)) { - return 0; - } - return Integer.parseInt(value); - } - - public int getIntParameter(String key, int defaultValue) { - String value = getParameter(key); - if (StringUtils.isEmpty(value)) { - return defaultValue; - } - return Integer.parseInt(value); - } - - public int getPositiveIntParameter(String key, int defaultValue) { - if (defaultValue <= 0) { - throw new IllegalArgumentException("defaultValue <= 0"); - } - String value = getParameter(key); - if (StringUtils.isEmpty(value)) { - return defaultValue; - } - int i = Integer.parseInt(value); - if (i > 0) { - return i; - } - return defaultValue; - } - - public boolean getBooleanParameter(String key) { - String value = getParameter(key); - if (StringUtils.isEmpty(value)) { - return false; - } - return Boolean.parseBoolean(value); - } - - public boolean getBooleanParameter(String key, boolean defaultValue) { - String value = getParameter(key); - if (StringUtils.isEmpty(value)) { - return defaultValue; - } - return Boolean.parseBoolean(value); - } - - public boolean hasParameter(String key) { - String value = getParameter(key); - return value != null && value.length() > 0; - } - - public String getMethodParameter(String method, String key) { - String value = parameters.get(method + "." + key); - if (StringUtils.isEmpty(value)) { - value = parameters.get(HIDE_KEY_PREFIX + method + "." + key); - } - if (StringUtils.isEmpty(value)) { - return getParameter(key); - } - return value; - } - - public String getMethodParameter(String method, String key, String defaultValue) { - String value = getMethodParameter(method, key); - if (StringUtils.isEmpty(value)) { - return defaultValue; - } - return value; - } - - public int getMethodIntParameter(String method, String key) { - String value = getMethodParameter(method, key); - if (StringUtils.isEmpty(value)) { - return 0; - } - return Integer.parseInt(value); - } - - public int getMethodIntParameter(String method, String key, int defaultValue) { - String value = getMethodParameter(method, key); - if (StringUtils.isEmpty(value)) { - return defaultValue; - } - return Integer.parseInt(value); - } - - public int getMethodPositiveIntParameter(String method, String key, int defaultValue) { - if (defaultValue <= 0) { - throw new IllegalArgumentException("defaultValue <= 0"); - } - String value = getMethodParameter(method, key); - if (StringUtils.isEmpty(value)) { - return defaultValue; - } - int i = Integer.parseInt(value); - if (i > 0) { - return i; - } - return defaultValue; - } - - public boolean getMethodBooleanParameter(String method, String key) { - String value = getMethodParameter(method, key); - if (StringUtils.isEmpty(value)) { - return false; - } - return Boolean.parseBoolean(value); - } - - public boolean getMethodBooleanParameter(String method, String key, boolean defaultValue) { - String value = getMethodParameter(method, key); - if (StringUtils.isEmpty(value)) { - return defaultValue; - } - return Boolean.parseBoolean(value); - } - - public boolean hasMethodParameter(String method, String key) { - String value = getMethodParameter(method, key); - return value != null && value.length() > 0; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - return parameters.equals(o); - } - - @Override - public int hashCode() { - return parameters.hashCode(); - } - - @Override - public String toString() { - return StringUtils.toQueryString(getParameters()); - } - -} +/* + * 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.common; + +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.common.utils.StringUtils; + +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY_PREFIX; +import static org.apache.dubbo.common.constants.CommonConstants.HIDE_KEY_PREFIX; + +/** + * Parameters for backward compatibility for version prior to 2.0.5 + * + * @deprecated + */ +@Deprecated +public class Parameters { + protected static final Logger logger = LoggerFactory.getLogger(Parameters.class); + private final Map parameters; + + public Parameters(String... pairs) { + this(toMap(pairs)); + } + + public Parameters(Map parameters) { + this.parameters = Collections.unmodifiableMap(parameters != null ? new HashMap<>(parameters) : new HashMap<>(0)); + } + + private static Map toMap(String... pairs) { + return CollectionUtils.toStringMap(pairs); + } + + public static Parameters parseParameters(String query) { + return new Parameters(StringUtils.parseQueryString(query)); + } + + public Map getParameters() { + return parameters; + } + + public T getExtension(Class type, String key) { + String name = getParameter(key); + return ExtensionLoader.getExtensionLoader(type).getExtension(name); + } + + public T getExtension(Class type, String key, String defaultValue) { + String name = getParameter(key, defaultValue); + return ExtensionLoader.getExtensionLoader(type).getExtension(name); + } + + public T getMethodExtension(Class type, String method, String key) { + String name = getMethodParameter(method, key); + return ExtensionLoader.getExtensionLoader(type).getExtension(name); + } + + public T getMethodExtension(Class type, String method, String key, String defaultValue) { + String name = getMethodParameter(method, key, defaultValue); + return ExtensionLoader.getExtensionLoader(type).getExtension(name); + } + + public String getDecodedParameter(String key) { + return getDecodedParameter(key, null); + } + + public String getDecodedParameter(String key, String defaultValue) { + String value = getParameter(key, defaultValue); + if (value != null && value.length() > 0) { + try { + value = URLDecoder.decode(value, "UTF-8"); + } catch (UnsupportedEncodingException e) { + logger.error(e.getMessage(), e); + } + } + return value; + } + + public String getParameter(String key) { + String value = parameters.get(key); + if (StringUtils.isEmpty(value)) { + value = parameters.get(HIDE_KEY_PREFIX + key); + } + if (StringUtils.isEmpty(value)) { + value = parameters.get(DEFAULT_KEY_PREFIX + key); + } + if (StringUtils.isEmpty(value)) { + value = parameters.get(HIDE_KEY_PREFIX + DEFAULT_KEY_PREFIX + key); + } + return value; + } + + public String getParameter(String key, String defaultValue) { + String value = getParameter(key); + if (StringUtils.isEmpty(value)) { + return defaultValue; + } + return value; + } + + public int getIntParameter(String key) { + String value = getParameter(key); + if (StringUtils.isEmpty(value)) { + return 0; + } + return Integer.parseInt(value); + } + + public int getIntParameter(String key, int defaultValue) { + String value = getParameter(key); + if (StringUtils.isEmpty(value)) { + return defaultValue; + } + return Integer.parseInt(value); + } + + public int getPositiveIntParameter(String key, int defaultValue) { + if (defaultValue <= 0) { + throw new IllegalArgumentException("defaultValue <= 0"); + } + String value = getParameter(key); + if (StringUtils.isEmpty(value)) { + return defaultValue; + } + int i = Integer.parseInt(value); + if (i > 0) { + return i; + } + return defaultValue; + } + + public boolean getBooleanParameter(String key) { + String value = getParameter(key); + if (StringUtils.isEmpty(value)) { + return false; + } + return Boolean.parseBoolean(value); + } + + public boolean getBooleanParameter(String key, boolean defaultValue) { + String value = getParameter(key); + if (StringUtils.isEmpty(value)) { + return defaultValue; + } + return Boolean.parseBoolean(value); + } + + public boolean hasParameter(String key) { + String value = getParameter(key); + return value != null && value.length() > 0; + } + + public String getMethodParameter(String method, String key) { + String value = parameters.get(method + "." + key); + if (StringUtils.isEmpty(value)) { + value = parameters.get(HIDE_KEY_PREFIX + method + "." + key); + } + if (StringUtils.isEmpty(value)) { + return getParameter(key); + } + return value; + } + + public String getMethodParameter(String method, String key, String defaultValue) { + String value = getMethodParameter(method, key); + if (StringUtils.isEmpty(value)) { + return defaultValue; + } + return value; + } + + public int getMethodIntParameter(String method, String key) { + String value = getMethodParameter(method, key); + if (StringUtils.isEmpty(value)) { + return 0; + } + return Integer.parseInt(value); + } + + public int getMethodIntParameter(String method, String key, int defaultValue) { + String value = getMethodParameter(method, key); + if (StringUtils.isEmpty(value)) { + return defaultValue; + } + return Integer.parseInt(value); + } + + public int getMethodPositiveIntParameter(String method, String key, int defaultValue) { + if (defaultValue <= 0) { + throw new IllegalArgumentException("defaultValue <= 0"); + } + String value = getMethodParameter(method, key); + if (StringUtils.isEmpty(value)) { + return defaultValue; + } + int i = Integer.parseInt(value); + if (i > 0) { + return i; + } + return defaultValue; + } + + public boolean getMethodBooleanParameter(String method, String key) { + String value = getMethodParameter(method, key); + if (StringUtils.isEmpty(value)) { + return false; + } + return Boolean.parseBoolean(value); + } + + public boolean getMethodBooleanParameter(String method, String key, boolean defaultValue) { + String value = getMethodParameter(method, key); + if (StringUtils.isEmpty(value)) { + return defaultValue; + } + return Boolean.parseBoolean(value); + } + + public boolean hasMethodParameter(String method, String key) { + String value = getMethodParameter(method, key); + return value != null && value.length() > 0; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + return parameters.equals(o); + } + + @Override + public int hashCode() { + return parameters.hashCode(); + } + + @Override + public String toString() { + return StringUtils.toQueryString(getParameters()); + } + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/Resetable.java b/dubbo-common/src/main/java/org/apache/dubbo/common/Resetable.java index 021cfbf257..873c0be17c 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/Resetable.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/Resetable.java @@ -28,4 +28,4 @@ public interface Resetable { */ void reset(URL url); -} \ No newline at end of file +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java b/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java index 404fd725af..675b373b80 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java @@ -1,1834 +1,1834 @@ -/* - * 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.common; - -import org.apache.dubbo.common.config.Configuration; -import org.apache.dubbo.common.config.InmemoryConfiguration; -import org.apache.dubbo.common.constants.RemotingConstants; -import org.apache.dubbo.common.url.component.PathURLAddress; -import org.apache.dubbo.common.url.component.ServiceConfigURL; -import org.apache.dubbo.common.url.component.URLAddress; -import org.apache.dubbo.common.url.component.URLParam; -import org.apache.dubbo.common.utils.ArrayUtils; -import org.apache.dubbo.common.utils.CollectionUtils; -import org.apache.dubbo.common.utils.LRUCache; -import org.apache.dubbo.common.utils.NetUtils; -import org.apache.dubbo.common.utils.StringUtils; - -import java.io.Serializable; -import java.io.UnsupportedEncodingException; -import java.net.InetSocketAddress; -import java.net.MalformedURLException; -import java.net.URLDecoder; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.TreeMap; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Predicate; - -import static org.apache.dubbo.common.BaseServiceMetadata.COLON_SEPARATOR; -import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_VALUE; -import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN; -import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.HOST_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.LOCALHOST_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.PASSWORD_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.PORT_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_APPLICATION_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.USERNAME_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY; -import static org.apache.dubbo.common.constants.RegistryConstants.CATEGORY_KEY; -import static org.apache.dubbo.common.convert.Converter.convertIfPossible; -import static org.apache.dubbo.common.utils.StringUtils.isBlank; - -/** - * URL - Uniform Resource Locator (Immutable, ThreadSafe) - *

- * url example: - *

    - *
  • http://www.facebook.com/friends?param1=value1&param2=value2 - *
  • http://username:password@10.20.130.230:8080/list?version=1.0.0 - *
  • ftp://username:password@192.168.1.7:21/1/read.txt - *
  • registry://192.168.1.7:9090/org.apache.dubbo.service1?param1=value1&param2=value2 - *
- *

- * Some strange example below: - *

    - *
  • 192.168.1.3:20880
    - * for this case, url protocol = null, url host = 192.168.1.3, port = 20880, url path = null - *
  • file:///home/user1/router.js?type=script
    - * for this case, url protocol = file, url host = null, url path = home/user1/router.js - *
  • file://home/user1/router.js?type=script
    - * for this case, url protocol = file, url host = home, url path = user1/router.js - *
  • file:///D:/1/router.js?type=script
    - * for this case, url protocol = file, url host = null, url path = D:/1/router.js - *
  • file:/D:/1/router.js?type=script
    - * same as above file:///D:/1/router.js?type=script - *
  • /home/user1/router.js?type=script
    - * for this case, url protocol = null, url host = null, url path = home/user1/router.js - *
  • home/user1/router.js?type=script
    - * for this case, url protocol = null, url host = home, url path = user1/router.js - *
- * - * @see java.net.URL - * @see java.net.URI - */ -public /*final**/ -class URL implements Serializable { - - private static final long serialVersionUID = -1985165475234910535L; - - private static Map cachedURLs = new LRUCache<>(); - - private final URLAddress urlAddress; - private final URLParam urlParam; - - // ==== cache ==== - - private volatile transient Map numbers; - - private volatile transient Map> methodNumbers; - - private volatile transient Map urls; - - private transient String serviceKey; - private transient String protocolServiceKey; - - protected URL() { - this.urlAddress = null; - this.urlParam = null; - } - - public URL(URLAddress urlAddress, URLParam urlParam) { - this.urlAddress = urlAddress; - this.urlParam = urlParam; - } - - public URL(String protocol, String host, int port) { - this(protocol, null, null, host, port, null, (Map) null); - } - - public URL(String protocol, String host, int port, String[] pairs) { // varargs ... conflict with the following path argument, use array instead. - this(protocol, null, null, host, port, null, CollectionUtils.toStringMap(pairs)); - } - - public URL(String protocol, String host, int port, Map parameters) { - this(protocol, null, null, host, port, null, parameters); - } - - public URL(String protocol, String host, int port, String path) { - this(protocol, null, null, host, port, path, (Map) null); - } - - public URL(String protocol, String host, int port, String path, String... pairs) { - this(protocol, null, null, host, port, path, CollectionUtils.toStringMap(pairs)); - } - - public URL(String protocol, String host, int port, String path, Map parameters) { - this(protocol, null, null, host, port, path, parameters); - } - - public URL(String protocol, String username, String password, String host, int port, String path) { - this(protocol, username, password, host, port, path, (Map) null); - } - - public URL(String protocol, String username, String password, String host, int port, String path, String... pairs) { - this(protocol, username, password, host, port, path, CollectionUtils.toStringMap(pairs)); - } - - public URL(String protocol, - String username, - String password, - String host, - int port, - String path, - Map parameters) { - if (StringUtils.isEmpty(username) - && StringUtils.isNotEmpty(password)) { - throw new IllegalArgumentException("Invalid url, password without username!"); - } - - this.urlAddress = new PathURLAddress(protocol, username, password, path, host, port); - this.urlParam = URLParam.parse(parameters); - } - - protected URL(String protocol, - String username, - String password, - String host, - int port, - String path, - Map parameters, - boolean modifiable) { - if (StringUtils.isEmpty(username) - && StringUtils.isNotEmpty(password)) { - throw new IllegalArgumentException("Invalid url, password without username!"); - } - - this.urlAddress = new PathURLAddress(protocol, username, password, path, host, port); - this.urlParam = URLParam.parse(parameters); - } - - public static URL cacheableValueOf(String url) { - URL cachedURL = cachedURLs.get(url); - if (cachedURL != null) { - return cachedURL; - } - cachedURL = valueOf(url, false); - cachedURLs.put(url, cachedURL); - return cachedURL; - } - - /** - * parse decoded url string, formatted dubbo://host:port/path?param=value, into strutted URL. - * - * @param url, decoded url string - * @return - */ - public static URL valueOf(String url) { - return valueOf(url, false); - } - - /** - * parse normal or encoded url string into strutted URL: - * - dubbo://host:port/path?param=value - * - URL.encode("dubbo://host:port/path?param=value") - * - * @param url, url string - * @param encoded, encoded or decoded - * @return - */ - public static URL valueOf(String url, boolean encoded) { - return valueOf(url, encoded, false); - } - - public static URL valueOf(String url, boolean encoded, boolean modifiable) { - if (encoded) { - return URLStrParser.parseEncodedStr(url, modifiable); - } - return URLStrParser.parseDecodedStr(url, modifiable); - } - - public static URL valueOf(String url, String... reserveParams) { - URL result = valueOf(url); - if (reserveParams == null || reserveParams.length == 0) { - return result; - } - Map newMap = new HashMap<>(reserveParams.length); - Map oldMap = result.getParameters(); - for (String reserveParam : reserveParams) { - String tmp = oldMap.get(reserveParam); - if (StringUtils.isNotEmpty(tmp)) { - newMap.put(reserveParam, tmp); - } - } - return result.clearParameters().addParameters(newMap); - } - - public static URL valueOf(URL url, String[] reserveParams, String[] reserveParamPrefixs) { - Map newMap = new HashMap<>(); - Map oldMap = url.getParameters(); - if (reserveParamPrefixs != null && reserveParamPrefixs.length != 0) { - for (Map.Entry entry : oldMap.entrySet()) { - for (String reserveParamPrefix : reserveParamPrefixs) { - if (entry.getKey().startsWith(reserveParamPrefix) && StringUtils.isNotEmpty(entry.getValue())) { - newMap.put(entry.getKey(), entry.getValue()); - } - } - } - } - - if (reserveParams != null) { - for (String reserveParam : reserveParams) { - String tmp = oldMap.get(reserveParam); - if (StringUtils.isNotEmpty(tmp)) { - newMap.put(reserveParam, tmp); - } - } - } - return newMap.isEmpty() ? new ServiceConfigURL(url.getProtocol(), url.getUsername(), url.getPassword(), url.getHost(), url.getPort(), url.getPath(), (Map) null) - : new ServiceConfigURL(url.getProtocol(), url.getUsername(), url.getPassword(), url.getHost(), url.getPort(), url.getPath(), newMap); - } - - public static String encode(String value) { - if (StringUtils.isEmpty(value)) { - return ""; - } - try { - return URLEncoder.encode(value, "UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e.getMessage(), e); - } - } - - public static String decode(String value) { - if (StringUtils.isEmpty(value)) { - return ""; - } - try { - return URLDecoder.decode(value, "UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e.getMessage(), e); - } - } - - static String appendDefaultPort(String address, int defaultPort) { - if (address != null && address.length() > 0 && defaultPort > 0) { - int i = address.indexOf(':'); - if (i < 0) { - return address + ":" + defaultPort; - } else if (Integer.parseInt(address.substring(i + 1)) == 0) { - return address.substring(0, i + 1) + defaultPort; - } - } - return address; - } - - public URLAddress getUrlAddress() { - return urlAddress; - } - - public URLParam getUrlParam() { - return urlParam; - } - - public String getProtocol() { - return urlAddress == null ? null : urlAddress.getProtocol(); - } - - public URL setProtocol(String protocol) { - URLAddress newURLAddress = urlAddress.setProtocol(protocol); - return returnURL(newURLAddress); - } - - public String getUsername() { - return urlAddress == null ? null : urlAddress.getUsername(); - } - - public URL setUsername(String username) { - URLAddress newURLAddress = urlAddress.setUsername(username); - return returnURL(newURLAddress); - } - - public String getPassword() { - return urlAddress == null ? null : urlAddress.getPassword(); - } - - public URL setPassword(String password) { - URLAddress newURLAddress = urlAddress.setPassword(password); - return returnURL(newURLAddress); - } - - public String getAuthority() { - if (StringUtils.isEmpty(getUsername()) - && StringUtils.isEmpty(getPassword())) { - return null; - } - return (getUsername() == null ? "" : getUsername()) - + ":" + (getPassword() == null ? "" : getPassword()); - } - - public String getHost() { - return urlAddress == null ? null : urlAddress.getHost(); - } - - public URL setHost(String host) { - URLAddress newURLAddress = urlAddress.setHost(host); - return returnURL(newURLAddress); - } - - - public int getPort() { - return urlAddress == null ? 0 : urlAddress.getPort(); - } - - public URL setPort(int port) { - URLAddress newURLAddress = urlAddress.setPort(port); - return returnURL(newURLAddress); - } - - public int getPort(int defaultPort) { - int port = getPort(); - return port <= 0 ? defaultPort : port; - } - - public String getAddress() { - return urlAddress.getAddress(); - } - - public URL setAddress(String address) { - int i = address.lastIndexOf(':'); - String host; - int port = this.getPort(); - if (i >= 0) { - host = address.substring(0, i); - port = Integer.parseInt(address.substring(i + 1)); - } else { - host = address; - } - URLAddress newURLAddress = urlAddress.setAddress(host, port); - return returnURL(newURLAddress); - } - - public String getIp() { - return urlAddress.getIp(); - } - - public String getBackupAddress() { - return getBackupAddress(0); - } - - public String getBackupAddress(int defaultPort) { - StringBuilder address = new StringBuilder(appendDefaultPort(getAddress(), defaultPort)); - String[] backups = getParameter(RemotingConstants.BACKUP_KEY, new String[0]); - if (ArrayUtils.isNotEmpty(backups)) { - for (String backup : backups) { - address.append(','); - address.append(appendDefaultPort(backup, defaultPort)); - } - } - return address.toString(); - } - - public List getBackupUrls() { - List urls = new ArrayList<>(); - urls.add(this); - String[] backups = getParameter(RemotingConstants.BACKUP_KEY, new String[0]); - if (backups != null && backups.length > 0) { - for (String backup : backups) { - urls.add(this.setAddress(backup)); - } - } - return urls; - } - - public String getPath() { - return urlAddress == null ? null : urlAddress.getPath(); - } - - public URL setPath(String path) { - URLAddress newURLAddress = urlAddress.setPath(path); - return returnURL(newURLAddress); - } - - public String getAbsolutePath() { - String path = getPath(); - if (path != null && !path.startsWith("/")) { - return "/" + path; - } - return path; - } - - public Map getParameters() { - return urlParam.getParameters(); - } - - /** - * Get the parameters to be selected(filtered) - * - * @param nameToSelect the {@link Predicate} to select the parameter name - * @return non-null {@link Map} - * @since 2.7.8 - */ - public Map getParameters(Predicate nameToSelect) { - Map selectedParameters = new LinkedHashMap<>(); - for (Map.Entry entry : getParameters().entrySet()) { - String name = entry.getKey(); - if (nameToSelect.test(name)) { - selectedParameters.put(name, entry.getValue()); - } - } - return Collections.unmodifiableMap(selectedParameters); - } - - public String getParameterAndDecoded(String key) { - return getParameterAndDecoded(key, null); - } - - public String getParameterAndDecoded(String key, String defaultValue) { - return decode(getParameter(key, defaultValue)); - } - - public String getParameter(String key) { - return urlParam.getParameter(key); - } - - public String getParameter(String key, String defaultValue) { - String value = getParameter(key); - return StringUtils.isEmpty(value) ? defaultValue : value; - } - - public String[] getParameter(String key, String[] defaultValue) { - String value = getParameter(key); - return StringUtils.isEmpty(value) ? defaultValue : COMMA_SPLIT_PATTERN.split(value); - } - - public List getParameter(String key, List defaultValue) { - String value = getParameter(key); - if (StringUtils.isEmpty(value)) { - return defaultValue; - } - String[] strArray = COMMA_SPLIT_PATTERN.split(value); - return Arrays.asList(strArray); - } - - /** - * Get parameter - * - * @param key the key of parameter - * @param valueType the type of parameter value - * @param the type of parameter value - * @return get the parameter if present, or null - * @since 2.7.8 - */ - public T getParameter(String key, Class valueType) { - return getParameter(key, valueType, null); - } - - /** - * Get parameter - * - * @param key the key of parameter - * @param valueType the type of parameter value - * @param defaultValue the default value if parameter is absent - * @param the type of parameter value - * @return get the parameter if present, or defaultValue will be used. - * @since 2.7.8 - */ - public T getParameter(String key, Class valueType, T defaultValue) { - String value = getParameter(key); - T result = null; - if (!isBlank(value)) { - result = convertIfPossible(value, valueType); - } - if (result == null) { - result = defaultValue; - } - return result; - } - - protected Map getNumbers() { - // concurrent initialization is tolerant - if (numbers == null) { - numbers = new ConcurrentHashMap<>(); - } - return numbers; - } - - protected Map> getMethodNumbers() { - if (methodNumbers == null) { // concurrent initialization is tolerant - methodNumbers = new ConcurrentHashMap<>(); - } - return methodNumbers; - } - - private Map getUrls() { - // concurrent initialization is tolerant - if (urls == null) { - urls = new ConcurrentHashMap<>(); - } - return urls; - } - - public URL getUrlParameter(String key) { - URL u = getUrls().get(key); - if (u != null) { - return u; - } - String value = getParameterAndDecoded(key); - if (StringUtils.isEmpty(value)) { - return null; - } - u = URL.valueOf(value); - getUrls().put(key, u); - return u; - } - - public double getParameter(String key, double defaultValue) { - Number n = getNumbers().get(key); - if (n != null) { - return n.doubleValue(); - } - String value = getParameter(key); - if (StringUtils.isEmpty(value)) { - return defaultValue; - } - double d = Double.parseDouble(value); - getNumbers().put(key, d); - return d; - } - - public float getParameter(String key, float defaultValue) { - Number n = getNumbers().get(key); - if (n != null) { - return n.floatValue(); - } - String value = getParameter(key); - if (StringUtils.isEmpty(value)) { - return defaultValue; - } - float f = Float.parseFloat(value); - getNumbers().put(key, f); - return f; - } - - public long getParameter(String key, long defaultValue) { - Number n = getNumbers().get(key); - if (n != null) { - return n.longValue(); - } - String value = getParameter(key); - if (StringUtils.isEmpty(value)) { - return defaultValue; - } - long l = Long.parseLong(value); - getNumbers().put(key, l); - return l; - } - - public int getParameter(String key, int defaultValue) { - Number n = getNumbers().get(key); - if (n != null) { - return n.intValue(); - } - String value = getParameter(key); - if (StringUtils.isEmpty(value)) { - return defaultValue; - } - int i = Integer.parseInt(value); - getNumbers().put(key, i); - return i; - } - - public short getParameter(String key, short defaultValue) { - Number n = getNumbers().get(key); - if (n != null) { - return n.shortValue(); - } - String value = getParameter(key); - if (StringUtils.isEmpty(value)) { - return defaultValue; - } - short s = Short.parseShort(value); - getNumbers().put(key, s); - return s; - } - - public byte getParameter(String key, byte defaultValue) { - Number n = getNumbers().get(key); - if (n != null) { - return n.byteValue(); - } - String value = getParameter(key); - if (StringUtils.isEmpty(value)) { - return defaultValue; - } - byte b = Byte.parseByte(value); - getNumbers().put(key, b); - return b; - } - - public float getPositiveParameter(String key, float defaultValue) { - if (defaultValue <= 0) { - throw new IllegalArgumentException("defaultValue <= 0"); - } - float value = getParameter(key, defaultValue); - return value <= 0 ? defaultValue : value; - } - - public double getPositiveParameter(String key, double defaultValue) { - if (defaultValue <= 0) { - throw new IllegalArgumentException("defaultValue <= 0"); - } - double value = getParameter(key, defaultValue); - return value <= 0 ? defaultValue : value; - } - - public long getPositiveParameter(String key, long defaultValue) { - if (defaultValue <= 0) { - throw new IllegalArgumentException("defaultValue <= 0"); - } - long value = getParameter(key, defaultValue); - return value <= 0 ? defaultValue : value; - } - - public int getPositiveParameter(String key, int defaultValue) { - if (defaultValue <= 0) { - throw new IllegalArgumentException("defaultValue <= 0"); - } - int value = getParameter(key, defaultValue); - return value <= 0 ? defaultValue : value; - } - - public short getPositiveParameter(String key, short defaultValue) { - if (defaultValue <= 0) { - throw new IllegalArgumentException("defaultValue <= 0"); - } - short value = getParameter(key, defaultValue); - return value <= 0 ? defaultValue : value; - } - - public byte getPositiveParameter(String key, byte defaultValue) { - if (defaultValue <= 0) { - throw new IllegalArgumentException("defaultValue <= 0"); - } - byte value = getParameter(key, defaultValue); - return value <= 0 ? defaultValue : value; - } - - public char getParameter(String key, char defaultValue) { - String value = getParameter(key); - return StringUtils.isEmpty(value) ? defaultValue : value.charAt(0); - } - - public boolean getParameter(String key, boolean defaultValue) { - String value = getParameter(key); - return StringUtils.isEmpty(value) ? defaultValue : Boolean.parseBoolean(value); - } - - public boolean hasParameter(String key) { - String value = getParameter(key); - return value != null && value.length() > 0; - } - - public String getMethodParameterAndDecoded(String method, String key) { - return URL.decode(getMethodParameter(method, key)); - } - - public String getMethodParameterAndDecoded(String method, String key, String defaultValue) { - return URL.decode(getMethodParameter(method, key, defaultValue)); - } - - public String getMethodParameter(String method, String key) { - return urlParam.getMethodParameter(method, key); - } - - public String getMethodParameterStrict(String method, String key) { - return urlParam.getMethodParameterStrict(method, key); - } - - public String getMethodParameter(String method, String key, String defaultValue) { - String value = getMethodParameter(method, key); - return StringUtils.isEmpty(value) ? defaultValue : value; - } - - public double getMethodParameter(String method, String key, double defaultValue) { - Number n = getCachedNumber(method, key); - if (n != null) { - return n.doubleValue(); - } - String value = getMethodParameter(method, key); - if (StringUtils.isEmpty(value)) { - return defaultValue; - } - double d = Double.parseDouble(value); - updateCachedNumber(method, key, d); - return d; - } - - public float getMethodParameter(String method, String key, float defaultValue) { - Number n = getCachedNumber(method, key); - if (n != null) { - return n.floatValue(); - } - String value = getMethodParameter(method, key); - if (StringUtils.isEmpty(value)) { - return defaultValue; - } - float f = Float.parseFloat(value); - updateCachedNumber(method, key, f); - return f; - } - - public long getMethodParameter(String method, String key, long defaultValue) { - Number n = getCachedNumber(method, key); - if (n != null) { - return n.longValue(); - } - String value = getMethodParameter(method, key); - if (StringUtils.isEmpty(value)) { - return defaultValue; - } - long l = Long.parseLong(value); - updateCachedNumber(method, key, l); - return l; - } - - public int getMethodParameter(String method, String key, int defaultValue) { - Number n = getCachedNumber(method, key); - if (n != null) { - return n.intValue(); - } - String value = getMethodParameter(method, key); - if (StringUtils.isEmpty(value)) { - return defaultValue; - } - int i = Integer.parseInt(value); - updateCachedNumber(method, key, i); - return i; - } - - public short getMethodParameter(String method, String key, short defaultValue) { - Number n = getCachedNumber(method, key); - if (n != null) { - return n.shortValue(); - } - String value = getMethodParameter(method, key); - if (StringUtils.isEmpty(value)) { - return defaultValue; - } - short s = Short.parseShort(value); - updateCachedNumber(method, key, s); - return s; - } - - public byte getMethodParameter(String method, String key, byte defaultValue) { - Number n = getCachedNumber(method, key); - if (n != null) { - return n.byteValue(); - } - String value = getMethodParameter(method, key); - if (StringUtils.isEmpty(value)) { - return defaultValue; - } - byte b = Byte.parseByte(value); - updateCachedNumber(method, key, b); - return b; - } - - private Number getCachedNumber(String method, String key) { - Map keyNumber = getMethodNumbers().get(method); - if (keyNumber != null) { - return keyNumber.get(key); - } - return null; - } - - private void updateCachedNumber(String method, String key, Number n) { - Map keyNumber = getMethodNumbers().computeIfAbsent(method, m -> new HashMap<>()); - keyNumber.put(key, n); - } - - public double getMethodPositiveParameter(String method, String key, double defaultValue) { - if (defaultValue <= 0) { - throw new IllegalArgumentException("defaultValue <= 0"); - } - double value = getMethodParameter(method, key, defaultValue); - return value <= 0 ? defaultValue : value; - } - - public float getMethodPositiveParameter(String method, String key, float defaultValue) { - if (defaultValue <= 0) { - throw new IllegalArgumentException("defaultValue <= 0"); - } - float value = getMethodParameter(method, key, defaultValue); - return value <= 0 ? defaultValue : value; - } - - public long getMethodPositiveParameter(String method, String key, long defaultValue) { - if (defaultValue <= 0) { - throw new IllegalArgumentException("defaultValue <= 0"); - } - long value = getMethodParameter(method, key, defaultValue); - return value <= 0 ? defaultValue : value; - } - - public int getMethodPositiveParameter(String method, String key, int defaultValue) { - if (defaultValue <= 0) { - throw new IllegalArgumentException("defaultValue <= 0"); - } - int value = getMethodParameter(method, key, defaultValue); - return value <= 0 ? defaultValue : value; - } - - public short getMethodPositiveParameter(String method, String key, short defaultValue) { - if (defaultValue <= 0) { - throw new IllegalArgumentException("defaultValue <= 0"); - } - short value = getMethodParameter(method, key, defaultValue); - return value <= 0 ? defaultValue : value; - } - - public byte getMethodPositiveParameter(String method, String key, byte defaultValue) { - if (defaultValue <= 0) { - throw new IllegalArgumentException("defaultValue <= 0"); - } - byte value = getMethodParameter(method, key, defaultValue); - return value <= 0 ? defaultValue : value; - } - - public char getMethodParameter(String method, String key, char defaultValue) { - String value = getMethodParameter(method, key); - return StringUtils.isEmpty(value) ? defaultValue : value.charAt(0); - } - - public boolean getMethodParameter(String method, String key, boolean defaultValue) { - String value = getMethodParameter(method, key); - return StringUtils.isEmpty(value) ? defaultValue : Boolean.parseBoolean(value); - } - - public boolean hasMethodParameter(String method, String key) { - if (method == null) { - String suffix = "." + key; - for (String fullKey : getParameters().keySet()) { - if (fullKey.endsWith(suffix)) { - return true; - } - } - return false; - } - if (key == null) { - String prefix = method + "."; - for (String fullKey : getParameters().keySet()) { - if (fullKey.startsWith(prefix)) { - return true; - } - } - return false; - } - String value = getMethodParameterStrict(method, key); - return StringUtils.isNotEmpty(value); - } - - public String getAnyMethodParameter(String key) { - return urlParam.getAnyMethodParameter(key); - } - - public boolean hasMethodParameter(String method) { - return urlParam.hasMethodParameter(method); - } - - public boolean isLocalHost() { - return NetUtils.isLocalHost(getHost()) || getParameter(LOCALHOST_KEY, false); - } - - public boolean isAnyHost() { - return ANYHOST_VALUE.equals(getHost()) || getParameter(ANYHOST_KEY, false); - } - - public URL addParameterAndEncoded(String key, String value) { - if (StringUtils.isEmpty(value)) { - return this; - } - return addParameter(key, encode(value)); - } - - public URL addParameter(String key, boolean value) { - return addParameter(key, String.valueOf(value)); - } - - public URL addParameter(String key, char value) { - return addParameter(key, String.valueOf(value)); - } - - public URL addParameter(String key, byte value) { - return addParameter(key, String.valueOf(value)); - } - - public URL addParameter(String key, short value) { - return addParameter(key, String.valueOf(value)); - } - - public URL addParameter(String key, int value) { - return addParameter(key, String.valueOf(value)); - } - - public URL addParameter(String key, long value) { - return addParameter(key, String.valueOf(value)); - } - - public URL addParameter(String key, float value) { - return addParameter(key, String.valueOf(value)); - } - - public URL addParameter(String key, double value) { - return addParameter(key, String.valueOf(value)); - } - - public URL addParameter(String key, Enum value) { - if (value == null) { - return this; - } - return addParameter(key, String.valueOf(value)); - } - - public URL addParameter(String key, Number value) { - if (value == null) { - return this; - } - return addParameter(key, String.valueOf(value)); - } - - public URL addParameter(String key, CharSequence value) { - if (value == null || value.length() == 0) { - return this; - } - return addParameter(key, String.valueOf(value)); - } - - public URL addParameter(String key, String value) { - URLParam newParam = urlParam.addParameter(key, value); - return returnURL(newParam); - } - - public URL addParameterIfAbsent(String key, String value) { - URLParam newParam = urlParam.addParameterIfAbsent(key, value); - return returnURL(newParam); - } - - /** - * Add parameters to a new url. - * - * @param parameters parameters in key-value pairs - * @return A new URL - */ - public URL addParameters(Map parameters) { - URLParam newParam = urlParam.addParameters(parameters); - return returnURL(newParam); - } - - public URL addParametersIfAbsent(Map parameters) { - URLParam newURLParam = urlParam.addParametersIfAbsent(parameters); - return returnURL(newURLParam); - } - - public URL addParameters(String... pairs) { - if (pairs == null || pairs.length == 0) { - return this; - } - if (pairs.length % 2 != 0) { - throw new IllegalArgumentException("Map pairs can not be odd numrer."); - } - Map map = new HashMap<>(); - int len = pairs.length / 2; - for (int i = 0; i < len; i++) { - map.put(pairs[2 * i], pairs[2 * i + 1]); - } - return addParameters(map); - } - - public URL addParameterString(String query) { - if (StringUtils.isEmpty(query)) { - return this; - } - return addParameters(StringUtils.parseQueryString(query)); - } - - public URL removeParameter(String key) { - if (StringUtils.isEmpty(key)) { - return this; - } - return removeParameters(key); - } - - public URL removeParameters(Collection keys) { - if (CollectionUtils.isEmpty(keys)) { - return this; - } - return removeParameters(keys.toArray(new String[0])); - } - - public URL removeParameters(String... keys) { - URLParam newURLParam = urlParam.removeParameters(keys); - return returnURL(newURLParam); - } - - public URL clearParameters() { - URLParam newURLParam = urlParam.clearParameters(); - return returnURL(newURLParam); - } - - public String getRawParameter(String key) { - if (PROTOCOL_KEY.equals(key)) { - return urlAddress.getProtocol(); - } - if (USERNAME_KEY.equals(key)) { - return urlAddress.getUsername(); - } - if (PASSWORD_KEY.equals(key)) { - return urlAddress.getPassword(); - } - if (HOST_KEY.equals(key)) { - return urlAddress.getHost(); - } - if (PORT_KEY.equals(key)) { - return String.valueOf(urlAddress.getPort()); - } - if (PATH_KEY.equals(key)) { - return urlAddress.getPath(); - } - return urlParam.getParameter(key); - } - - public Map toMap() { - Map map = new HashMap<>(getParameters()); - if (getProtocol() != null) { - map.put(PROTOCOL_KEY, getProtocol()); - } - if (getUsername() != null) { - map.put(USERNAME_KEY, getUsername()); - } - if (getPassword() != null) { - map.put(PASSWORD_KEY, getPassword()); - } - if (getHost() != null) { - map.put(HOST_KEY, getHost()); - } - if (getPort() > 0) { - map.put(PORT_KEY, String.valueOf(getPort())); - } - if (getPath() != null) { - map.put(PATH_KEY, getPath()); - } - return map; - } - - @Override - public String toString() { - return buildString(false, true); // no show username and password - } - - public String toString(String... parameters) { - return buildString(false, true, parameters); // no show username and password - } - - public String toIdentityString() { - return buildString(true, false); // only return identity message, see the method "equals" and "hashCode" - } - - public String toIdentityString(String... parameters) { - return buildString(true, false, parameters); // only return identity message, see the method "equals" and "hashCode" - } - - public String toFullString() { - return buildString(true, true); - } - - public String toFullString(String... parameters) { - return buildString(true, true, parameters); - } - - public String toParameterString() { - return toParameterString(new String[0]); - } - - public String toParameterString(String... parameters) { - StringBuilder buf = new StringBuilder(); - buildParameters(buf, false, parameters); - return buf.toString(); - } - - protected void buildParameters(StringBuilder buf, boolean concat, String[] parameters) { - if (CollectionUtils.isNotEmptyMap(getParameters())) { - List includes = (ArrayUtils.isEmpty(parameters) ? null : Arrays.asList(parameters)); - boolean first = true; - for (Map.Entry entry : new TreeMap<>(getParameters()).entrySet()) { - if (StringUtils.isNotEmpty(entry.getKey()) - && (includes == null || includes.contains(entry.getKey()))) { - if (first) { - if (concat) { - buf.append("?"); - } - first = false; - } else { - buf.append("&"); - } - buf.append(entry.getKey()); - buf.append("="); - buf.append(entry.getValue() == null ? "" : entry.getValue().trim()); - } - } - } - } - - private String buildString(boolean appendUser, boolean appendParameter, String... parameters) { - return buildString(appendUser, appendParameter, false, false, parameters); - } - - private String buildString(boolean appendUser, boolean appendParameter, boolean useIP, boolean useService, String... parameters) { - StringBuilder buf = new StringBuilder(); - if (StringUtils.isNotEmpty(getProtocol())) { - buf.append(getProtocol()); - buf.append("://"); - } - if (appendUser && StringUtils.isNotEmpty(getUsername())) { - buf.append(getUsername()); - if (StringUtils.isNotEmpty(getPassword())) { - buf.append(":"); - buf.append(getPassword()); - } - buf.append("@"); - } - String host; - if (useIP) { - host = urlAddress.getIp(); - } else { - host = getHost(); - } - if (StringUtils.isNotEmpty(host)) { - buf.append(host); - if (getPort() > 0) { - buf.append(":"); - buf.append(getPort()); - } - } - String path; - if (useService) { - path = getServiceKey(); - } else { - path = getPath(); - } - if (StringUtils.isNotEmpty(path)) { - buf.append("/"); - buf.append(path); - } - - if (appendParameter) { - buildParameters(buf, true, parameters); - } - return buf.toString(); - } - - public java.net.URL toJavaURL() { - try { - return new java.net.URL(toString()); - } catch (MalformedURLException e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - - public InetSocketAddress toInetSocketAddress() { - return new InetSocketAddress(getHost(), getPort()); - } - - /** - * The format is "{interface}:[version]:[group]" - * - * @return - */ - public String getColonSeparatedKey() { - StringBuilder serviceNameBuilder = new StringBuilder(); - serviceNameBuilder.append(this.getServiceInterface()); - append(serviceNameBuilder, VERSION_KEY, false); - append(serviceNameBuilder, GROUP_KEY, false); - return serviceNameBuilder.toString(); - } - - private void append(StringBuilder target, String parameterName, boolean first) { - String parameterValue = this.getParameter(parameterName); - if (!isBlank(parameterValue)) { - if (!first) { - target.append(":"); - } - target.append(parameterValue); - } else { - target.append(":"); - } - } - - /** - * The format of return value is '{group}/{interfaceName}:{version}' - * - * @return - */ - public String getServiceKey() { - if (serviceKey != null) { - return serviceKey; - } - String inf = getServiceInterface(); - if (inf == null) { - return null; - } - serviceKey = buildKey(inf, getGroup(), getVersion()); - return serviceKey; - } - - /** - * Format : interface:version - * - * @return - */ - public String getDisplayServiceKey() { - if (StringUtils.isEmpty(getVersion())) { - return getServiceInterface(); - } - return getServiceInterface() + - COLON_SEPARATOR + getVersion(); - } - - /** - * The format of return value is '{group}/{path/interfaceName}:{version}' - * - * @return - */ - public String getPathKey() { - String inf = StringUtils.isNotEmpty(getPath()) ? getPath() : getServiceInterface(); - if (inf == null) { - return null; - } - return buildKey(inf, getGroup(), getVersion()); - } - - public static String buildKey(String path, String group, String version) { - return BaseServiceMetadata.buildServiceKey(path, group, version); - } - - public String getProtocolServiceKey() { - if (protocolServiceKey != null) { - return protocolServiceKey; - } - this.protocolServiceKey = getServiceKey() + ":" + getProtocol(); - return protocolServiceKey; - } - - public String toServiceStringWithoutResolving() { - return buildString(true, false, false, true); - } - - public String toServiceString() { - return buildString(true, false, true, true); - } - - @Deprecated - public String getServiceName() { - return getServiceInterface(); - } - - public String getServiceInterface() { - return getParameter(INTERFACE_KEY, getPath()); - } - - public URL setServiceInterface(String service) { - return addParameter(INTERFACE_KEY, service); - } - - /** - * @see #getParameter(String, int) - * @deprecated Replace to getParameter(String, int) - */ - @Deprecated - public int getIntParameter(String key) { - return getParameter(key, 0); - } - - /** - * @see #getParameter(String, int) - * @deprecated Replace to getParameter(String, int) - */ - @Deprecated - public int getIntParameter(String key, int defaultValue) { - return getParameter(key, defaultValue); - } - - /** - * @see #getPositiveParameter(String, int) - * @deprecated Replace to getPositiveParameter(String, int) - */ - @Deprecated - public int getPositiveIntParameter(String key, int defaultValue) { - return getPositiveParameter(key, defaultValue); - } - - /** - * @see #getParameter(String, boolean) - * @deprecated Replace to getParameter(String, boolean) - */ - @Deprecated - public boolean getBooleanParameter(String key) { - return getParameter(key, false); - } - - /** - * @see #getParameter(String, boolean) - * @deprecated Replace to getParameter(String, boolean) - */ - @Deprecated - public boolean getBooleanParameter(String key, boolean defaultValue) { - return getParameter(key, defaultValue); - } - - /** - * @see #getMethodParameter(String, String, int) - * @deprecated Replace to getMethodParameter(String, String, int) - */ - @Deprecated - public int getMethodIntParameter(String method, String key) { - return getMethodParameter(method, key, 0); - } - - /** - * @see #getMethodParameter(String, String, int) - * @deprecated Replace to getMethodParameter(String, String, int) - */ - @Deprecated - public int getMethodIntParameter(String method, String key, int defaultValue) { - return getMethodParameter(method, key, defaultValue); - } - - /** - * @see #getMethodPositiveParameter(String, String, int) - * @deprecated Replace to getMethodPositiveParameter(String, String, int) - */ - @Deprecated - public int getMethodPositiveIntParameter(String method, String key, int defaultValue) { - return getMethodPositiveParameter(method, key, defaultValue); - } - - /** - * @see #getMethodParameter(String, String, boolean) - * @deprecated Replace to getMethodParameter(String, String, boolean) - */ - @Deprecated - public boolean getMethodBooleanParameter(String method, String key) { - return getMethodParameter(method, key, false); - } - - /** - * @see #getMethodParameter(String, String, boolean) - * @deprecated Replace to getMethodParameter(String, String, boolean) - */ - @Deprecated - public boolean getMethodBooleanParameter(String method, String key, boolean defaultValue) { - return getMethodParameter(method, key, defaultValue); - } - - public Configuration toConfiguration() { - InmemoryConfiguration configuration = new InmemoryConfiguration(); - configuration.addProperties(getParameters()); - return configuration; - } - - @Override - public int hashCode() { - return Objects.hash(urlAddress, urlParam); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof URL)) { - return false; - } - URL other = (URL) obj; - return Objects.equals(this.getUrlAddress(), other.getUrlAddress()) && Objects.equals(this.getUrlParam(), other.getUrlParam()); - } - - public static void putMethodParameter(String method, String key, String value, Map> methodParameters) { - Map subParameter = methodParameters.computeIfAbsent(method, k -> new HashMap<>()); - subParameter.put(key, value); - } - - protected T newURL(URLAddress urlAddress, URLParam urlParam) { - return (T) new ServiceConfigURL(urlAddress, urlParam, null); - } - - /* methods introduced for CompositeURL, CompositeURL must override to make the implementations meaningful */ - - public String getApplication(String defaultValue) { - String value = getApplication(); - return StringUtils.isEmpty(value) ? defaultValue : value; - } - - public String getApplication() { - return getParameter(APPLICATION_KEY); - } - - public String getRemoteApplication() { - return getParameter(REMOTE_APPLICATION_KEY); - } - - public String getGroup() { - return getParameter(GROUP_KEY); - } - - public String getGroup(String defaultValue) { - String value = getGroup(); - return StringUtils.isEmpty(value) ? defaultValue : value; - } - - public String getVersion() { - return getParameter(VERSION_KEY); - } - - public String getVersion(String defaultValue) { - String value = getVersion(); - return StringUtils.isEmpty(value) ? defaultValue : value; - } - - public String getConcatenatedParameter(String key) { - return getParameter(key); - } - - public String getCategory(String defaultValue) { - String value = getCategory(); - if (StringUtils.isEmpty(value)) { - value = defaultValue; - } - return value; - } - - public String[] getCategory(String[] defaultValue) { - String value = getCategory(); - return StringUtils.isEmpty(value) ? defaultValue : COMMA_SPLIT_PATTERN.split(value); - } - - public String getCategory() { - return getParameter(CATEGORY_KEY); - } - - public String getSide(String defaultValue) { - String value = getSide(); - return StringUtils.isEmpty(value) ? defaultValue : value; - } - - public String getSide() { - return getParameter(SIDE_KEY); - } - - /* Service Config URL, START*/ - public Map getAttributes() { - return new HashMap<>(); - } - - public URL addAttributes(Map attributes) { - return this; - } - - public Object getAttribute(String key) { - return null; - } - - public URL putAttribute(String key, Object obj) { - return this; - } - - public URL removeAttribute(String key) { - return this; - } - - public boolean hasAttribute(String key) { - return true; - } - - /* Service Config URL, END*/ - - private URL returnURL(URLAddress newURLAddress) { - if (urlAddress == newURLAddress) { - return this; - } - return newURL(newURLAddress, urlParam); - } - - private URL returnURL(URLParam newURLParam) { - if (urlParam == newURLParam) { - return this; - } - return newURL(urlAddress, newURLParam); - } - - /* add service scope operations, see InstanceAddressURL */ - public Map getServiceParameters(String service) { - return getParameters(); - } - - public String getServiceParameter(String service, String key) { - return getParameter(key); - } - - public String getServiceParameter(String service, String key, String defaultValue) { - String value = getServiceParameter(service, key); - return StringUtils.isEmpty(value) ? defaultValue : value; - } - - public int getServiceParameter(String service, String key, int defaultValue) { - return getParameter(key, defaultValue); - } - - public double getServiceParameter(String service, String key, double defaultValue) { - Number n = getServiceNumbers(service).get(key); - if (n != null) { - return n.doubleValue(); - } - String value = getServiceParameter(service, key); - if (StringUtils.isEmpty(value)) { - return defaultValue; - } - double d = Double.parseDouble(value); - getNumbers().put(key, d); - return d; - } - - public float getServiceParameter(String service, String key, float defaultValue) { - Number n = getNumbers().get(key); - if (n != null) { - return n.floatValue(); - } - String value = getServiceParameter(service, key); - if (StringUtils.isEmpty(value)) { - return defaultValue; - } - float f = Float.parseFloat(value); - getNumbers().put(key, f); - return f; - } - - public long getServiceParameter(String service, String key, long defaultValue) { - Number n = getNumbers().get(key); - if (n != null) { - return n.longValue(); - } - String value = getServiceParameter(service, key); - if (StringUtils.isEmpty(value)) { - return defaultValue; - } - long l = Long.parseLong(value); - getNumbers().put(key, l); - return l; - } - - public short getServiceParameter(String service, String key, short defaultValue) { - Number n = getNumbers().get(key); - if (n != null) { - return n.shortValue(); - } - String value = getServiceParameter(service, key); - if (StringUtils.isEmpty(value)) { - return defaultValue; - } - short s = Short.parseShort(value); - getNumbers().put(key, s); - return s; - } - - public byte getServiceParameter(String service, String key, byte defaultValue) { - Number n = getNumbers().get(key); - if (n != null) { - return n.byteValue(); - } - String value = getServiceParameter(service, key); - if (StringUtils.isEmpty(value)) { - return defaultValue; - } - byte b = Byte.parseByte(value); - getNumbers().put(key, b); - return b; - } - - public char getServiceParameter(String service, String key, char defaultValue) { - String value = getServiceParameter(service, key); - return StringUtils.isEmpty(value) ? defaultValue : value.charAt(0); - } - - public boolean getServiceParameter(String service, String key, boolean defaultValue) { - String value = getServiceParameter(service, key); - return StringUtils.isEmpty(value) ? defaultValue : Boolean.parseBoolean(value); - } - - public boolean hasServiceParameter(String service, String key) { - String value = getServiceParameter(service, key); - return value != null && value.length() > 0; - } - - public float getPositiveServiceParameter(String service, String key, float defaultValue) { - if (defaultValue <= 0) { - throw new IllegalArgumentException("defaultValue <= 0"); - } - float value = getServiceParameter(service, key, defaultValue); - return value <= 0 ? defaultValue : value; - } - - public double getPositiveServiceParameter(String service, String key, double defaultValue) { - if (defaultValue <= 0) { - throw new IllegalArgumentException("defaultValue <= 0"); - } - double value = getServiceParameter(service, key, defaultValue); - return value <= 0 ? defaultValue : value; - } - - public long getPositiveServiceParameter(String service, String key, long defaultValue) { - if (defaultValue <= 0) { - throw new IllegalArgumentException("defaultValue <= 0"); - } - long value = getServiceParameter(service, key, defaultValue); - return value <= 0 ? defaultValue : value; - } - - public int getPositiveServiceParameter(String service, String key, int defaultValue) { - if (defaultValue <= 0) { - throw new IllegalArgumentException("defaultValue <= 0"); - } - int value = getServiceParameter(service, key, defaultValue); - return value <= 0 ? defaultValue : value; - } - - public short getPositiveServiceParameter(String service, String key, short defaultValue) { - if (defaultValue <= 0) { - throw new IllegalArgumentException("defaultValue <= 0"); - } - short value = getServiceParameter(service, key, defaultValue); - return value <= 0 ? defaultValue : value; - } - - public byte getPositiveServiceParameter(String service, String key, byte defaultValue) { - if (defaultValue <= 0) { - throw new IllegalArgumentException("defaultValue <= 0"); - } - byte value = getServiceParameter(service, key, defaultValue); - return value <= 0 ? defaultValue : value; - } - - public String getServiceMethodParameterAndDecoded(String service, String method, String key) { - return URL.decode(getServiceMethodParameter(service, method, key)); - } - - public String getServiceMethodParameterAndDecoded(String service, String method, String key, String defaultValue) { - return URL.decode(getServiceMethodParameter(service, method, key, defaultValue)); - } - - public String getServiceMethodParameterStrict(String service, String method, String key) { - return getMethodParameterStrict(method, key); - } - - public String getServiceMethodParameter(String service, String method, String key) { - return getMethodParameter(method, key); - } - - public String getServiceMethodParameter(String service, String method, String key, String defaultValue) { - String value = getServiceMethodParameter(service, method, key); - return StringUtils.isEmpty(value) ? defaultValue : value; - } - - public double getServiceMethodParameter(String service, String method, String key, double defaultValue) { - Number n = getCachedNumber(method, key); - if (n != null) { - return n.doubleValue(); - } - String value = getServiceMethodParameter(service, method, key); - if (StringUtils.isEmpty(value)) { - return defaultValue; - } - double d = Double.parseDouble(value); - updateCachedNumber(method, key, d); - return d; - } - - public float getServiceMethodParameter(String service, String method, String key, float defaultValue) { - Number n = getCachedNumber(method, key); - if (n != null) { - return n.floatValue(); - } - String value = getServiceMethodParameter(service, method, key); - if (StringUtils.isEmpty(value)) { - return defaultValue; - } - float f = Float.parseFloat(value); - updateCachedNumber(method, key, f); - return f; - } - - public long getServiceMethodParameter(String service, String method, String key, long defaultValue) { - Number n = getCachedNumber(method, key); - if (n != null) { - return n.longValue(); - } - String value = getServiceMethodParameter(service, method, key); - if (StringUtils.isEmpty(value)) { - return defaultValue; - } - long l = Long.parseLong(value); - updateCachedNumber(method, key, l); - return l; - } - - public int getServiceMethodParameter(String service, String method, String key, int defaultValue) { - Number n = getCachedNumber(method, key); - if (n != null) { - return n.intValue(); - } - String value = getServiceMethodParameter(service, method, key); - if (StringUtils.isEmpty(value)) { - return defaultValue; - } - int i = Integer.parseInt(value); - updateCachedNumber(method, key, i); - return i; - } - - public short getMethodParameter(String service, String method, String key, short defaultValue) { - Number n = getCachedNumber(method, key); - if (n != null) { - return n.shortValue(); - } - String value = getServiceMethodParameter(service, method, key); - if (StringUtils.isEmpty(value)) { - return defaultValue; - } - short s = Short.parseShort(value); - updateCachedNumber(method, key, s); - return s; - } - - public byte getServiceMethodParameter(String service, String method, String key, byte defaultValue) { - Number n = getCachedNumber(method, key); - if (n != null) { - return n.byteValue(); - } - String value = getServiceMethodParameter(service, method, key); - if (StringUtils.isEmpty(value)) { - return defaultValue; - } - byte b = Byte.parseByte(value); - updateCachedNumber(method, key, b); - return b; - } - - public boolean hasServiceMethodParameter(String service, String method, String key) { - return hasMethodParameter(method, key); - } - - public boolean hasServiceMethodParameter(String service, String method) { - return hasMethodParameter(method); - } - - protected Map getServiceNumbers(String service) { - return getNumbers(); - } - - protected Map> getServiceMethodNumbers(String service) { - return getMethodNumbers(); - } - -} +/* + * 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.common; + +import org.apache.dubbo.common.config.Configuration; +import org.apache.dubbo.common.config.InmemoryConfiguration; +import org.apache.dubbo.common.constants.RemotingConstants; +import org.apache.dubbo.common.url.component.PathURLAddress; +import org.apache.dubbo.common.url.component.ServiceConfigURL; +import org.apache.dubbo.common.url.component.URLAddress; +import org.apache.dubbo.common.url.component.URLParam; +import org.apache.dubbo.common.utils.ArrayUtils; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.common.utils.LRUCache; +import org.apache.dubbo.common.utils.NetUtils; +import org.apache.dubbo.common.utils.StringUtils; + +import java.io.Serializable; +import java.io.UnsupportedEncodingException; +import java.net.InetSocketAddress; +import java.net.MalformedURLException; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.TreeMap; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Predicate; + +import static org.apache.dubbo.common.BaseServiceMetadata.COLON_SEPARATOR; +import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_VALUE; +import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN; +import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.HOST_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.LOCALHOST_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.PASSWORD_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.PORT_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_APPLICATION_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.USERNAME_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY; +import static org.apache.dubbo.common.constants.RegistryConstants.CATEGORY_KEY; +import static org.apache.dubbo.common.convert.Converter.convertIfPossible; +import static org.apache.dubbo.common.utils.StringUtils.isBlank; + +/** + * URL - Uniform Resource Locator (Immutable, ThreadSafe) + *

+ * url example: + *

    + *
  • http://www.facebook.com/friends?param1=value1&param2=value2 + *
  • http://username:password@10.20.130.230:8080/list?version=1.0.0 + *
  • ftp://username:password@192.168.1.7:21/1/read.txt + *
  • registry://192.168.1.7:9090/org.apache.dubbo.service1?param1=value1&param2=value2 + *
+ *

+ * Some strange example below: + *

    + *
  • 192.168.1.3:20880
    + * for this case, url protocol = null, url host = 192.168.1.3, port = 20880, url path = null + *
  • file:///home/user1/router.js?type=script
    + * for this case, url protocol = file, url host = null, url path = home/user1/router.js + *
  • file://home/user1/router.js?type=script
    + * for this case, url protocol = file, url host = home, url path = user1/router.js + *
  • file:///D:/1/router.js?type=script
    + * for this case, url protocol = file, url host = null, url path = D:/1/router.js + *
  • file:/D:/1/router.js?type=script
    + * same as above file:///D:/1/router.js?type=script + *
  • /home/user1/router.js?type=script
    + * for this case, url protocol = null, url host = null, url path = home/user1/router.js + *
  • home/user1/router.js?type=script
    + * for this case, url protocol = null, url host = home, url path = user1/router.js + *
+ * + * @see java.net.URL + * @see java.net.URI + */ +public /*final**/ +class URL implements Serializable { + + private static final long serialVersionUID = -1985165475234910535L; + + private static Map cachedURLs = new LRUCache<>(); + + private final URLAddress urlAddress; + private final URLParam urlParam; + + // ==== cache ==== + + private volatile transient Map numbers; + + private volatile transient Map> methodNumbers; + + private volatile transient Map urls; + + private transient String serviceKey; + private transient String protocolServiceKey; + + protected URL() { + this.urlAddress = null; + this.urlParam = null; + } + + public URL(URLAddress urlAddress, URLParam urlParam) { + this.urlAddress = urlAddress; + this.urlParam = urlParam; + } + + public URL(String protocol, String host, int port) { + this(protocol, null, null, host, port, null, (Map) null); + } + + public URL(String protocol, String host, int port, String[] pairs) { // varargs ... conflict with the following path argument, use array instead. + this(protocol, null, null, host, port, null, CollectionUtils.toStringMap(pairs)); + } + + public URL(String protocol, String host, int port, Map parameters) { + this(protocol, null, null, host, port, null, parameters); + } + + public URL(String protocol, String host, int port, String path) { + this(protocol, null, null, host, port, path, (Map) null); + } + + public URL(String protocol, String host, int port, String path, String... pairs) { + this(protocol, null, null, host, port, path, CollectionUtils.toStringMap(pairs)); + } + + public URL(String protocol, String host, int port, String path, Map parameters) { + this(protocol, null, null, host, port, path, parameters); + } + + public URL(String protocol, String username, String password, String host, int port, String path) { + this(protocol, username, password, host, port, path, (Map) null); + } + + public URL(String protocol, String username, String password, String host, int port, String path, String... pairs) { + this(protocol, username, password, host, port, path, CollectionUtils.toStringMap(pairs)); + } + + public URL(String protocol, + String username, + String password, + String host, + int port, + String path, + Map parameters) { + if (StringUtils.isEmpty(username) + && StringUtils.isNotEmpty(password)) { + throw new IllegalArgumentException("Invalid url, password without username!"); + } + + this.urlAddress = new PathURLAddress(protocol, username, password, path, host, port); + this.urlParam = URLParam.parse(parameters); + } + + protected URL(String protocol, + String username, + String password, + String host, + int port, + String path, + Map parameters, + boolean modifiable) { + if (StringUtils.isEmpty(username) + && StringUtils.isNotEmpty(password)) { + throw new IllegalArgumentException("Invalid url, password without username!"); + } + + this.urlAddress = new PathURLAddress(protocol, username, password, path, host, port); + this.urlParam = URLParam.parse(parameters); + } + + public static URL cacheableValueOf(String url) { + URL cachedURL = cachedURLs.get(url); + if (cachedURL != null) { + return cachedURL; + } + cachedURL = valueOf(url, false); + cachedURLs.put(url, cachedURL); + return cachedURL; + } + + /** + * parse decoded url string, formatted dubbo://host:port/path?param=value, into strutted URL. + * + * @param url, decoded url string + * @return + */ + public static URL valueOf(String url) { + return valueOf(url, false); + } + + /** + * parse normal or encoded url string into strutted URL: + * - dubbo://host:port/path?param=value + * - URL.encode("dubbo://host:port/path?param=value") + * + * @param url, url string + * @param encoded, encoded or decoded + * @return + */ + public static URL valueOf(String url, boolean encoded) { + return valueOf(url, encoded, false); + } + + public static URL valueOf(String url, boolean encoded, boolean modifiable) { + if (encoded) { + return URLStrParser.parseEncodedStr(url, modifiable); + } + return URLStrParser.parseDecodedStr(url, modifiable); + } + + public static URL valueOf(String url, String... reserveParams) { + URL result = valueOf(url); + if (reserveParams == null || reserveParams.length == 0) { + return result; + } + Map newMap = new HashMap<>(reserveParams.length); + Map oldMap = result.getParameters(); + for (String reserveParam : reserveParams) { + String tmp = oldMap.get(reserveParam); + if (StringUtils.isNotEmpty(tmp)) { + newMap.put(reserveParam, tmp); + } + } + return result.clearParameters().addParameters(newMap); + } + + public static URL valueOf(URL url, String[] reserveParams, String[] reserveParamPrefixs) { + Map newMap = new HashMap<>(); + Map oldMap = url.getParameters(); + if (reserveParamPrefixs != null && reserveParamPrefixs.length != 0) { + for (Map.Entry entry : oldMap.entrySet()) { + for (String reserveParamPrefix : reserveParamPrefixs) { + if (entry.getKey().startsWith(reserveParamPrefix) && StringUtils.isNotEmpty(entry.getValue())) { + newMap.put(entry.getKey(), entry.getValue()); + } + } + } + } + + if (reserveParams != null) { + for (String reserveParam : reserveParams) { + String tmp = oldMap.get(reserveParam); + if (StringUtils.isNotEmpty(tmp)) { + newMap.put(reserveParam, tmp); + } + } + } + return newMap.isEmpty() ? new ServiceConfigURL(url.getProtocol(), url.getUsername(), url.getPassword(), url.getHost(), url.getPort(), url.getPath(), (Map) null) + : new ServiceConfigURL(url.getProtocol(), url.getUsername(), url.getPassword(), url.getHost(), url.getPort(), url.getPath(), newMap); + } + + public static String encode(String value) { + if (StringUtils.isEmpty(value)) { + return ""; + } + try { + return URLEncoder.encode(value, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + public static String decode(String value) { + if (StringUtils.isEmpty(value)) { + return ""; + } + try { + return URLDecoder.decode(value, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + static String appendDefaultPort(String address, int defaultPort) { + if (address != null && address.length() > 0 && defaultPort > 0) { + int i = address.indexOf(':'); + if (i < 0) { + return address + ":" + defaultPort; + } else if (Integer.parseInt(address.substring(i + 1)) == 0) { + return address.substring(0, i + 1) + defaultPort; + } + } + return address; + } + + public URLAddress getUrlAddress() { + return urlAddress; + } + + public URLParam getUrlParam() { + return urlParam; + } + + public String getProtocol() { + return urlAddress == null ? null : urlAddress.getProtocol(); + } + + public URL setProtocol(String protocol) { + URLAddress newURLAddress = urlAddress.setProtocol(protocol); + return returnURL(newURLAddress); + } + + public String getUsername() { + return urlAddress == null ? null : urlAddress.getUsername(); + } + + public URL setUsername(String username) { + URLAddress newURLAddress = urlAddress.setUsername(username); + return returnURL(newURLAddress); + } + + public String getPassword() { + return urlAddress == null ? null : urlAddress.getPassword(); + } + + public URL setPassword(String password) { + URLAddress newURLAddress = urlAddress.setPassword(password); + return returnURL(newURLAddress); + } + + public String getAuthority() { + if (StringUtils.isEmpty(getUsername()) + && StringUtils.isEmpty(getPassword())) { + return null; + } + return (getUsername() == null ? "" : getUsername()) + + ":" + (getPassword() == null ? "" : getPassword()); + } + + public String getHost() { + return urlAddress == null ? null : urlAddress.getHost(); + } + + public URL setHost(String host) { + URLAddress newURLAddress = urlAddress.setHost(host); + return returnURL(newURLAddress); + } + + + public int getPort() { + return urlAddress == null ? 0 : urlAddress.getPort(); + } + + public URL setPort(int port) { + URLAddress newURLAddress = urlAddress.setPort(port); + return returnURL(newURLAddress); + } + + public int getPort(int defaultPort) { + int port = getPort(); + return port <= 0 ? defaultPort : port; + } + + public String getAddress() { + return urlAddress.getAddress(); + } + + public URL setAddress(String address) { + int i = address.lastIndexOf(':'); + String host; + int port = this.getPort(); + if (i >= 0) { + host = address.substring(0, i); + port = Integer.parseInt(address.substring(i + 1)); + } else { + host = address; + } + URLAddress newURLAddress = urlAddress.setAddress(host, port); + return returnURL(newURLAddress); + } + + public String getIp() { + return urlAddress.getIp(); + } + + public String getBackupAddress() { + return getBackupAddress(0); + } + + public String getBackupAddress(int defaultPort) { + StringBuilder address = new StringBuilder(appendDefaultPort(getAddress(), defaultPort)); + String[] backups = getParameter(RemotingConstants.BACKUP_KEY, new String[0]); + if (ArrayUtils.isNotEmpty(backups)) { + for (String backup : backups) { + address.append(','); + address.append(appendDefaultPort(backup, defaultPort)); + } + } + return address.toString(); + } + + public List getBackupUrls() { + List urls = new ArrayList<>(); + urls.add(this); + String[] backups = getParameter(RemotingConstants.BACKUP_KEY, new String[0]); + if (backups != null && backups.length > 0) { + for (String backup : backups) { + urls.add(this.setAddress(backup)); + } + } + return urls; + } + + public String getPath() { + return urlAddress == null ? null : urlAddress.getPath(); + } + + public URL setPath(String path) { + URLAddress newURLAddress = urlAddress.setPath(path); + return returnURL(newURLAddress); + } + + public String getAbsolutePath() { + String path = getPath(); + if (path != null && !path.startsWith("/")) { + return "/" + path; + } + return path; + } + + public Map getParameters() { + return urlParam.getParameters(); + } + + /** + * Get the parameters to be selected(filtered) + * + * @param nameToSelect the {@link Predicate} to select the parameter name + * @return non-null {@link Map} + * @since 2.7.8 + */ + public Map getParameters(Predicate nameToSelect) { + Map selectedParameters = new LinkedHashMap<>(); + for (Map.Entry entry : getParameters().entrySet()) { + String name = entry.getKey(); + if (nameToSelect.test(name)) { + selectedParameters.put(name, entry.getValue()); + } + } + return Collections.unmodifiableMap(selectedParameters); + } + + public String getParameterAndDecoded(String key) { + return getParameterAndDecoded(key, null); + } + + public String getParameterAndDecoded(String key, String defaultValue) { + return decode(getParameter(key, defaultValue)); + } + + public String getParameter(String key) { + return urlParam.getParameter(key); + } + + public String getParameter(String key, String defaultValue) { + String value = getParameter(key); + return StringUtils.isEmpty(value) ? defaultValue : value; + } + + public String[] getParameter(String key, String[] defaultValue) { + String value = getParameter(key); + return StringUtils.isEmpty(value) ? defaultValue : COMMA_SPLIT_PATTERN.split(value); + } + + public List getParameter(String key, List defaultValue) { + String value = getParameter(key); + if (StringUtils.isEmpty(value)) { + return defaultValue; + } + String[] strArray = COMMA_SPLIT_PATTERN.split(value); + return Arrays.asList(strArray); + } + + /** + * Get parameter + * + * @param key the key of parameter + * @param valueType the type of parameter value + * @param the type of parameter value + * @return get the parameter if present, or null + * @since 2.7.8 + */ + public T getParameter(String key, Class valueType) { + return getParameter(key, valueType, null); + } + + /** + * Get parameter + * + * @param key the key of parameter + * @param valueType the type of parameter value + * @param defaultValue the default value if parameter is absent + * @param the type of parameter value + * @return get the parameter if present, or defaultValue will be used. + * @since 2.7.8 + */ + public T getParameter(String key, Class valueType, T defaultValue) { + String value = getParameter(key); + T result = null; + if (!isBlank(value)) { + result = convertIfPossible(value, valueType); + } + if (result == null) { + result = defaultValue; + } + return result; + } + + protected Map getNumbers() { + // concurrent initialization is tolerant + if (numbers == null) { + numbers = new ConcurrentHashMap<>(); + } + return numbers; + } + + protected Map> getMethodNumbers() { + if (methodNumbers == null) { // concurrent initialization is tolerant + methodNumbers = new ConcurrentHashMap<>(); + } + return methodNumbers; + } + + private Map getUrls() { + // concurrent initialization is tolerant + if (urls == null) { + urls = new ConcurrentHashMap<>(); + } + return urls; + } + + public URL getUrlParameter(String key) { + URL u = getUrls().get(key); + if (u != null) { + return u; + } + String value = getParameterAndDecoded(key); + if (StringUtils.isEmpty(value)) { + return null; + } + u = URL.valueOf(value); + getUrls().put(key, u); + return u; + } + + public double getParameter(String key, double defaultValue) { + Number n = getNumbers().get(key); + if (n != null) { + return n.doubleValue(); + } + String value = getParameter(key); + if (StringUtils.isEmpty(value)) { + return defaultValue; + } + double d = Double.parseDouble(value); + getNumbers().put(key, d); + return d; + } + + public float getParameter(String key, float defaultValue) { + Number n = getNumbers().get(key); + if (n != null) { + return n.floatValue(); + } + String value = getParameter(key); + if (StringUtils.isEmpty(value)) { + return defaultValue; + } + float f = Float.parseFloat(value); + getNumbers().put(key, f); + return f; + } + + public long getParameter(String key, long defaultValue) { + Number n = getNumbers().get(key); + if (n != null) { + return n.longValue(); + } + String value = getParameter(key); + if (StringUtils.isEmpty(value)) { + return defaultValue; + } + long l = Long.parseLong(value); + getNumbers().put(key, l); + return l; + } + + public int getParameter(String key, int defaultValue) { + Number n = getNumbers().get(key); + if (n != null) { + return n.intValue(); + } + String value = getParameter(key); + if (StringUtils.isEmpty(value)) { + return defaultValue; + } + int i = Integer.parseInt(value); + getNumbers().put(key, i); + return i; + } + + public short getParameter(String key, short defaultValue) { + Number n = getNumbers().get(key); + if (n != null) { + return n.shortValue(); + } + String value = getParameter(key); + if (StringUtils.isEmpty(value)) { + return defaultValue; + } + short s = Short.parseShort(value); + getNumbers().put(key, s); + return s; + } + + public byte getParameter(String key, byte defaultValue) { + Number n = getNumbers().get(key); + if (n != null) { + return n.byteValue(); + } + String value = getParameter(key); + if (StringUtils.isEmpty(value)) { + return defaultValue; + } + byte b = Byte.parseByte(value); + getNumbers().put(key, b); + return b; + } + + public float getPositiveParameter(String key, float defaultValue) { + if (defaultValue <= 0) { + throw new IllegalArgumentException("defaultValue <= 0"); + } + float value = getParameter(key, defaultValue); + return value <= 0 ? defaultValue : value; + } + + public double getPositiveParameter(String key, double defaultValue) { + if (defaultValue <= 0) { + throw new IllegalArgumentException("defaultValue <= 0"); + } + double value = getParameter(key, defaultValue); + return value <= 0 ? defaultValue : value; + } + + public long getPositiveParameter(String key, long defaultValue) { + if (defaultValue <= 0) { + throw new IllegalArgumentException("defaultValue <= 0"); + } + long value = getParameter(key, defaultValue); + return value <= 0 ? defaultValue : value; + } + + public int getPositiveParameter(String key, int defaultValue) { + if (defaultValue <= 0) { + throw new IllegalArgumentException("defaultValue <= 0"); + } + int value = getParameter(key, defaultValue); + return value <= 0 ? defaultValue : value; + } + + public short getPositiveParameter(String key, short defaultValue) { + if (defaultValue <= 0) { + throw new IllegalArgumentException("defaultValue <= 0"); + } + short value = getParameter(key, defaultValue); + return value <= 0 ? defaultValue : value; + } + + public byte getPositiveParameter(String key, byte defaultValue) { + if (defaultValue <= 0) { + throw new IllegalArgumentException("defaultValue <= 0"); + } + byte value = getParameter(key, defaultValue); + return value <= 0 ? defaultValue : value; + } + + public char getParameter(String key, char defaultValue) { + String value = getParameter(key); + return StringUtils.isEmpty(value) ? defaultValue : value.charAt(0); + } + + public boolean getParameter(String key, boolean defaultValue) { + String value = getParameter(key); + return StringUtils.isEmpty(value) ? defaultValue : Boolean.parseBoolean(value); + } + + public boolean hasParameter(String key) { + String value = getParameter(key); + return value != null && value.length() > 0; + } + + public String getMethodParameterAndDecoded(String method, String key) { + return URL.decode(getMethodParameter(method, key)); + } + + public String getMethodParameterAndDecoded(String method, String key, String defaultValue) { + return URL.decode(getMethodParameter(method, key, defaultValue)); + } + + public String getMethodParameter(String method, String key) { + return urlParam.getMethodParameter(method, key); + } + + public String getMethodParameterStrict(String method, String key) { + return urlParam.getMethodParameterStrict(method, key); + } + + public String getMethodParameter(String method, String key, String defaultValue) { + String value = getMethodParameter(method, key); + return StringUtils.isEmpty(value) ? defaultValue : value; + } + + public double getMethodParameter(String method, String key, double defaultValue) { + Number n = getCachedNumber(method, key); + if (n != null) { + return n.doubleValue(); + } + String value = getMethodParameter(method, key); + if (StringUtils.isEmpty(value)) { + return defaultValue; + } + double d = Double.parseDouble(value); + updateCachedNumber(method, key, d); + return d; + } + + public float getMethodParameter(String method, String key, float defaultValue) { + Number n = getCachedNumber(method, key); + if (n != null) { + return n.floatValue(); + } + String value = getMethodParameter(method, key); + if (StringUtils.isEmpty(value)) { + return defaultValue; + } + float f = Float.parseFloat(value); + updateCachedNumber(method, key, f); + return f; + } + + public long getMethodParameter(String method, String key, long defaultValue) { + Number n = getCachedNumber(method, key); + if (n != null) { + return n.longValue(); + } + String value = getMethodParameter(method, key); + if (StringUtils.isEmpty(value)) { + return defaultValue; + } + long l = Long.parseLong(value); + updateCachedNumber(method, key, l); + return l; + } + + public int getMethodParameter(String method, String key, int defaultValue) { + Number n = getCachedNumber(method, key); + if (n != null) { + return n.intValue(); + } + String value = getMethodParameter(method, key); + if (StringUtils.isEmpty(value)) { + return defaultValue; + } + int i = Integer.parseInt(value); + updateCachedNumber(method, key, i); + return i; + } + + public short getMethodParameter(String method, String key, short defaultValue) { + Number n = getCachedNumber(method, key); + if (n != null) { + return n.shortValue(); + } + String value = getMethodParameter(method, key); + if (StringUtils.isEmpty(value)) { + return defaultValue; + } + short s = Short.parseShort(value); + updateCachedNumber(method, key, s); + return s; + } + + public byte getMethodParameter(String method, String key, byte defaultValue) { + Number n = getCachedNumber(method, key); + if (n != null) { + return n.byteValue(); + } + String value = getMethodParameter(method, key); + if (StringUtils.isEmpty(value)) { + return defaultValue; + } + byte b = Byte.parseByte(value); + updateCachedNumber(method, key, b); + return b; + } + + private Number getCachedNumber(String method, String key) { + Map keyNumber = getMethodNumbers().get(method); + if (keyNumber != null) { + return keyNumber.get(key); + } + return null; + } + + private void updateCachedNumber(String method, String key, Number n) { + Map keyNumber = getMethodNumbers().computeIfAbsent(method, m -> new HashMap<>()); + keyNumber.put(key, n); + } + + public double getMethodPositiveParameter(String method, String key, double defaultValue) { + if (defaultValue <= 0) { + throw new IllegalArgumentException("defaultValue <= 0"); + } + double value = getMethodParameter(method, key, defaultValue); + return value <= 0 ? defaultValue : value; + } + + public float getMethodPositiveParameter(String method, String key, float defaultValue) { + if (defaultValue <= 0) { + throw new IllegalArgumentException("defaultValue <= 0"); + } + float value = getMethodParameter(method, key, defaultValue); + return value <= 0 ? defaultValue : value; + } + + public long getMethodPositiveParameter(String method, String key, long defaultValue) { + if (defaultValue <= 0) { + throw new IllegalArgumentException("defaultValue <= 0"); + } + long value = getMethodParameter(method, key, defaultValue); + return value <= 0 ? defaultValue : value; + } + + public int getMethodPositiveParameter(String method, String key, int defaultValue) { + if (defaultValue <= 0) { + throw new IllegalArgumentException("defaultValue <= 0"); + } + int value = getMethodParameter(method, key, defaultValue); + return value <= 0 ? defaultValue : value; + } + + public short getMethodPositiveParameter(String method, String key, short defaultValue) { + if (defaultValue <= 0) { + throw new IllegalArgumentException("defaultValue <= 0"); + } + short value = getMethodParameter(method, key, defaultValue); + return value <= 0 ? defaultValue : value; + } + + public byte getMethodPositiveParameter(String method, String key, byte defaultValue) { + if (defaultValue <= 0) { + throw new IllegalArgumentException("defaultValue <= 0"); + } + byte value = getMethodParameter(method, key, defaultValue); + return value <= 0 ? defaultValue : value; + } + + public char getMethodParameter(String method, String key, char defaultValue) { + String value = getMethodParameter(method, key); + return StringUtils.isEmpty(value) ? defaultValue : value.charAt(0); + } + + public boolean getMethodParameter(String method, String key, boolean defaultValue) { + String value = getMethodParameter(method, key); + return StringUtils.isEmpty(value) ? defaultValue : Boolean.parseBoolean(value); + } + + public boolean hasMethodParameter(String method, String key) { + if (method == null) { + String suffix = "." + key; + for (String fullKey : getParameters().keySet()) { + if (fullKey.endsWith(suffix)) { + return true; + } + } + return false; + } + if (key == null) { + String prefix = method + "."; + for (String fullKey : getParameters().keySet()) { + if (fullKey.startsWith(prefix)) { + return true; + } + } + return false; + } + String value = getMethodParameterStrict(method, key); + return StringUtils.isNotEmpty(value); + } + + public String getAnyMethodParameter(String key) { + return urlParam.getAnyMethodParameter(key); + } + + public boolean hasMethodParameter(String method) { + return urlParam.hasMethodParameter(method); + } + + public boolean isLocalHost() { + return NetUtils.isLocalHost(getHost()) || getParameter(LOCALHOST_KEY, false); + } + + public boolean isAnyHost() { + return ANYHOST_VALUE.equals(getHost()) || getParameter(ANYHOST_KEY, false); + } + + public URL addParameterAndEncoded(String key, String value) { + if (StringUtils.isEmpty(value)) { + return this; + } + return addParameter(key, encode(value)); + } + + public URL addParameter(String key, boolean value) { + return addParameter(key, String.valueOf(value)); + } + + public URL addParameter(String key, char value) { + return addParameter(key, String.valueOf(value)); + } + + public URL addParameter(String key, byte value) { + return addParameter(key, String.valueOf(value)); + } + + public URL addParameter(String key, short value) { + return addParameter(key, String.valueOf(value)); + } + + public URL addParameter(String key, int value) { + return addParameter(key, String.valueOf(value)); + } + + public URL addParameter(String key, long value) { + return addParameter(key, String.valueOf(value)); + } + + public URL addParameter(String key, float value) { + return addParameter(key, String.valueOf(value)); + } + + public URL addParameter(String key, double value) { + return addParameter(key, String.valueOf(value)); + } + + public URL addParameter(String key, Enum value) { + if (value == null) { + return this; + } + return addParameter(key, String.valueOf(value)); + } + + public URL addParameter(String key, Number value) { + if (value == null) { + return this; + } + return addParameter(key, String.valueOf(value)); + } + + public URL addParameter(String key, CharSequence value) { + if (value == null || value.length() == 0) { + return this; + } + return addParameter(key, String.valueOf(value)); + } + + public URL addParameter(String key, String value) { + URLParam newParam = urlParam.addParameter(key, value); + return returnURL(newParam); + } + + public URL addParameterIfAbsent(String key, String value) { + URLParam newParam = urlParam.addParameterIfAbsent(key, value); + return returnURL(newParam); + } + + /** + * Add parameters to a new url. + * + * @param parameters parameters in key-value pairs + * @return A new URL + */ + public URL addParameters(Map parameters) { + URLParam newParam = urlParam.addParameters(parameters); + return returnURL(newParam); + } + + public URL addParametersIfAbsent(Map parameters) { + URLParam newURLParam = urlParam.addParametersIfAbsent(parameters); + return returnURL(newURLParam); + } + + public URL addParameters(String... pairs) { + if (pairs == null || pairs.length == 0) { + return this; + } + if (pairs.length % 2 != 0) { + throw new IllegalArgumentException("Map pairs can not be odd numrer."); + } + Map map = new HashMap<>(); + int len = pairs.length / 2; + for (int i = 0; i < len; i++) { + map.put(pairs[2 * i], pairs[2 * i + 1]); + } + return addParameters(map); + } + + public URL addParameterString(String query) { + if (StringUtils.isEmpty(query)) { + return this; + } + return addParameters(StringUtils.parseQueryString(query)); + } + + public URL removeParameter(String key) { + if (StringUtils.isEmpty(key)) { + return this; + } + return removeParameters(key); + } + + public URL removeParameters(Collection keys) { + if (CollectionUtils.isEmpty(keys)) { + return this; + } + return removeParameters(keys.toArray(new String[0])); + } + + public URL removeParameters(String... keys) { + URLParam newURLParam = urlParam.removeParameters(keys); + return returnURL(newURLParam); + } + + public URL clearParameters() { + URLParam newURLParam = urlParam.clearParameters(); + return returnURL(newURLParam); + } + + public String getRawParameter(String key) { + if (PROTOCOL_KEY.equals(key)) { + return urlAddress.getProtocol(); + } + if (USERNAME_KEY.equals(key)) { + return urlAddress.getUsername(); + } + if (PASSWORD_KEY.equals(key)) { + return urlAddress.getPassword(); + } + if (HOST_KEY.equals(key)) { + return urlAddress.getHost(); + } + if (PORT_KEY.equals(key)) { + return String.valueOf(urlAddress.getPort()); + } + if (PATH_KEY.equals(key)) { + return urlAddress.getPath(); + } + return urlParam.getParameter(key); + } + + public Map toMap() { + Map map = new HashMap<>(getParameters()); + if (getProtocol() != null) { + map.put(PROTOCOL_KEY, getProtocol()); + } + if (getUsername() != null) { + map.put(USERNAME_KEY, getUsername()); + } + if (getPassword() != null) { + map.put(PASSWORD_KEY, getPassword()); + } + if (getHost() != null) { + map.put(HOST_KEY, getHost()); + } + if (getPort() > 0) { + map.put(PORT_KEY, String.valueOf(getPort())); + } + if (getPath() != null) { + map.put(PATH_KEY, getPath()); + } + return map; + } + + @Override + public String toString() { + return buildString(false, true); // no show username and password + } + + public String toString(String... parameters) { + return buildString(false, true, parameters); // no show username and password + } + + public String toIdentityString() { + return buildString(true, false); // only return identity message, see the method "equals" and "hashCode" + } + + public String toIdentityString(String... parameters) { + return buildString(true, false, parameters); // only return identity message, see the method "equals" and "hashCode" + } + + public String toFullString() { + return buildString(true, true); + } + + public String toFullString(String... parameters) { + return buildString(true, true, parameters); + } + + public String toParameterString() { + return toParameterString(new String[0]); + } + + public String toParameterString(String... parameters) { + StringBuilder buf = new StringBuilder(); + buildParameters(buf, false, parameters); + return buf.toString(); + } + + protected void buildParameters(StringBuilder buf, boolean concat, String[] parameters) { + if (CollectionUtils.isNotEmptyMap(getParameters())) { + List includes = (ArrayUtils.isEmpty(parameters) ? null : Arrays.asList(parameters)); + boolean first = true; + for (Map.Entry entry : new TreeMap<>(getParameters()).entrySet()) { + if (StringUtils.isNotEmpty(entry.getKey()) + && (includes == null || includes.contains(entry.getKey()))) { + if (first) { + if (concat) { + buf.append("?"); + } + first = false; + } else { + buf.append("&"); + } + buf.append(entry.getKey()); + buf.append("="); + buf.append(entry.getValue() == null ? "" : entry.getValue().trim()); + } + } + } + } + + private String buildString(boolean appendUser, boolean appendParameter, String... parameters) { + return buildString(appendUser, appendParameter, false, false, parameters); + } + + private String buildString(boolean appendUser, boolean appendParameter, boolean useIP, boolean useService, String... parameters) { + StringBuilder buf = new StringBuilder(); + if (StringUtils.isNotEmpty(getProtocol())) { + buf.append(getProtocol()); + buf.append("://"); + } + if (appendUser && StringUtils.isNotEmpty(getUsername())) { + buf.append(getUsername()); + if (StringUtils.isNotEmpty(getPassword())) { + buf.append(":"); + buf.append(getPassword()); + } + buf.append("@"); + } + String host; + if (useIP) { + host = urlAddress.getIp(); + } else { + host = getHost(); + } + if (StringUtils.isNotEmpty(host)) { + buf.append(host); + if (getPort() > 0) { + buf.append(":"); + buf.append(getPort()); + } + } + String path; + if (useService) { + path = getServiceKey(); + } else { + path = getPath(); + } + if (StringUtils.isNotEmpty(path)) { + buf.append("/"); + buf.append(path); + } + + if (appendParameter) { + buildParameters(buf, true, parameters); + } + return buf.toString(); + } + + public java.net.URL toJavaURL() { + try { + return new java.net.URL(toString()); + } catch (MalformedURLException e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + public InetSocketAddress toInetSocketAddress() { + return new InetSocketAddress(getHost(), getPort()); + } + + /** + * The format is "{interface}:[version]:[group]" + * + * @return + */ + public String getColonSeparatedKey() { + StringBuilder serviceNameBuilder = new StringBuilder(); + serviceNameBuilder.append(this.getServiceInterface()); + append(serviceNameBuilder, VERSION_KEY, false); + append(serviceNameBuilder, GROUP_KEY, false); + return serviceNameBuilder.toString(); + } + + private void append(StringBuilder target, String parameterName, boolean first) { + String parameterValue = this.getParameter(parameterName); + if (!isBlank(parameterValue)) { + if (!first) { + target.append(":"); + } + target.append(parameterValue); + } else { + target.append(":"); + } + } + + /** + * The format of return value is '{group}/{interfaceName}:{version}' + * + * @return + */ + public String getServiceKey() { + if (serviceKey != null) { + return serviceKey; + } + String inf = getServiceInterface(); + if (inf == null) { + return null; + } + serviceKey = buildKey(inf, getGroup(), getVersion()); + return serviceKey; + } + + /** + * Format : interface:version + * + * @return + */ + public String getDisplayServiceKey() { + if (StringUtils.isEmpty(getVersion())) { + return getServiceInterface(); + } + return getServiceInterface() + + COLON_SEPARATOR + getVersion(); + } + + /** + * The format of return value is '{group}/{path/interfaceName}:{version}' + * + * @return + */ + public String getPathKey() { + String inf = StringUtils.isNotEmpty(getPath()) ? getPath() : getServiceInterface(); + if (inf == null) { + return null; + } + return buildKey(inf, getGroup(), getVersion()); + } + + public static String buildKey(String path, String group, String version) { + return BaseServiceMetadata.buildServiceKey(path, group, version); + } + + public String getProtocolServiceKey() { + if (protocolServiceKey != null) { + return protocolServiceKey; + } + this.protocolServiceKey = getServiceKey() + ":" + getProtocol(); + return protocolServiceKey; + } + + public String toServiceStringWithoutResolving() { + return buildString(true, false, false, true); + } + + public String toServiceString() { + return buildString(true, false, true, true); + } + + @Deprecated + public String getServiceName() { + return getServiceInterface(); + } + + public String getServiceInterface() { + return getParameter(INTERFACE_KEY, getPath()); + } + + public URL setServiceInterface(String service) { + return addParameter(INTERFACE_KEY, service); + } + + /** + * @see #getParameter(String, int) + * @deprecated Replace to getParameter(String, int) + */ + @Deprecated + public int getIntParameter(String key) { + return getParameter(key, 0); + } + + /** + * @see #getParameter(String, int) + * @deprecated Replace to getParameter(String, int) + */ + @Deprecated + public int getIntParameter(String key, int defaultValue) { + return getParameter(key, defaultValue); + } + + /** + * @see #getPositiveParameter(String, int) + * @deprecated Replace to getPositiveParameter(String, int) + */ + @Deprecated + public int getPositiveIntParameter(String key, int defaultValue) { + return getPositiveParameter(key, defaultValue); + } + + /** + * @see #getParameter(String, boolean) + * @deprecated Replace to getParameter(String, boolean) + */ + @Deprecated + public boolean getBooleanParameter(String key) { + return getParameter(key, false); + } + + /** + * @see #getParameter(String, boolean) + * @deprecated Replace to getParameter(String, boolean) + */ + @Deprecated + public boolean getBooleanParameter(String key, boolean defaultValue) { + return getParameter(key, defaultValue); + } + + /** + * @see #getMethodParameter(String, String, int) + * @deprecated Replace to getMethodParameter(String, String, int) + */ + @Deprecated + public int getMethodIntParameter(String method, String key) { + return getMethodParameter(method, key, 0); + } + + /** + * @see #getMethodParameter(String, String, int) + * @deprecated Replace to getMethodParameter(String, String, int) + */ + @Deprecated + public int getMethodIntParameter(String method, String key, int defaultValue) { + return getMethodParameter(method, key, defaultValue); + } + + /** + * @see #getMethodPositiveParameter(String, String, int) + * @deprecated Replace to getMethodPositiveParameter(String, String, int) + */ + @Deprecated + public int getMethodPositiveIntParameter(String method, String key, int defaultValue) { + return getMethodPositiveParameter(method, key, defaultValue); + } + + /** + * @see #getMethodParameter(String, String, boolean) + * @deprecated Replace to getMethodParameter(String, String, boolean) + */ + @Deprecated + public boolean getMethodBooleanParameter(String method, String key) { + return getMethodParameter(method, key, false); + } + + /** + * @see #getMethodParameter(String, String, boolean) + * @deprecated Replace to getMethodParameter(String, String, boolean) + */ + @Deprecated + public boolean getMethodBooleanParameter(String method, String key, boolean defaultValue) { + return getMethodParameter(method, key, defaultValue); + } + + public Configuration toConfiguration() { + InmemoryConfiguration configuration = new InmemoryConfiguration(); + configuration.addProperties(getParameters()); + return configuration; + } + + @Override + public int hashCode() { + return Objects.hash(urlAddress, urlParam); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof URL)) { + return false; + } + URL other = (URL) obj; + return Objects.equals(this.getUrlAddress(), other.getUrlAddress()) && Objects.equals(this.getUrlParam(), other.getUrlParam()); + } + + public static void putMethodParameter(String method, String key, String value, Map> methodParameters) { + Map subParameter = methodParameters.computeIfAbsent(method, k -> new HashMap<>()); + subParameter.put(key, value); + } + + protected T newURL(URLAddress urlAddress, URLParam urlParam) { + return (T) new ServiceConfigURL(urlAddress, urlParam, null); + } + + /* methods introduced for CompositeURL, CompositeURL must override to make the implementations meaningful */ + + public String getApplication(String defaultValue) { + String value = getApplication(); + return StringUtils.isEmpty(value) ? defaultValue : value; + } + + public String getApplication() { + return getParameter(APPLICATION_KEY); + } + + public String getRemoteApplication() { + return getParameter(REMOTE_APPLICATION_KEY); + } + + public String getGroup() { + return getParameter(GROUP_KEY); + } + + public String getGroup(String defaultValue) { + String value = getGroup(); + return StringUtils.isEmpty(value) ? defaultValue : value; + } + + public String getVersion() { + return getParameter(VERSION_KEY); + } + + public String getVersion(String defaultValue) { + String value = getVersion(); + return StringUtils.isEmpty(value) ? defaultValue : value; + } + + public String getConcatenatedParameter(String key) { + return getParameter(key); + } + + public String getCategory(String defaultValue) { + String value = getCategory(); + if (StringUtils.isEmpty(value)) { + value = defaultValue; + } + return value; + } + + public String[] getCategory(String[] defaultValue) { + String value = getCategory(); + return StringUtils.isEmpty(value) ? defaultValue : COMMA_SPLIT_PATTERN.split(value); + } + + public String getCategory() { + return getParameter(CATEGORY_KEY); + } + + public String getSide(String defaultValue) { + String value = getSide(); + return StringUtils.isEmpty(value) ? defaultValue : value; + } + + public String getSide() { + return getParameter(SIDE_KEY); + } + + /* Service Config URL, START*/ + public Map getAttributes() { + return new HashMap<>(); + } + + public URL addAttributes(Map attributes) { + return this; + } + + public Object getAttribute(String key) { + return null; + } + + public URL putAttribute(String key, Object obj) { + return this; + } + + public URL removeAttribute(String key) { + return this; + } + + public boolean hasAttribute(String key) { + return true; + } + + /* Service Config URL, END*/ + + private URL returnURL(URLAddress newURLAddress) { + if (urlAddress == newURLAddress) { + return this; + } + return newURL(newURLAddress, urlParam); + } + + private URL returnURL(URLParam newURLParam) { + if (urlParam == newURLParam) { + return this; + } + return newURL(urlAddress, newURLParam); + } + + /* add service scope operations, see InstanceAddressURL */ + public Map getServiceParameters(String service) { + return getParameters(); + } + + public String getServiceParameter(String service, String key) { + return getParameter(key); + } + + public String getServiceParameter(String service, String key, String defaultValue) { + String value = getServiceParameter(service, key); + return StringUtils.isEmpty(value) ? defaultValue : value; + } + + public int getServiceParameter(String service, String key, int defaultValue) { + return getParameter(key, defaultValue); + } + + public double getServiceParameter(String service, String key, double defaultValue) { + Number n = getServiceNumbers(service).get(key); + if (n != null) { + return n.doubleValue(); + } + String value = getServiceParameter(service, key); + if (StringUtils.isEmpty(value)) { + return defaultValue; + } + double d = Double.parseDouble(value); + getNumbers().put(key, d); + return d; + } + + public float getServiceParameter(String service, String key, float defaultValue) { + Number n = getNumbers().get(key); + if (n != null) { + return n.floatValue(); + } + String value = getServiceParameter(service, key); + if (StringUtils.isEmpty(value)) { + return defaultValue; + } + float f = Float.parseFloat(value); + getNumbers().put(key, f); + return f; + } + + public long getServiceParameter(String service, String key, long defaultValue) { + Number n = getNumbers().get(key); + if (n != null) { + return n.longValue(); + } + String value = getServiceParameter(service, key); + if (StringUtils.isEmpty(value)) { + return defaultValue; + } + long l = Long.parseLong(value); + getNumbers().put(key, l); + return l; + } + + public short getServiceParameter(String service, String key, short defaultValue) { + Number n = getNumbers().get(key); + if (n != null) { + return n.shortValue(); + } + String value = getServiceParameter(service, key); + if (StringUtils.isEmpty(value)) { + return defaultValue; + } + short s = Short.parseShort(value); + getNumbers().put(key, s); + return s; + } + + public byte getServiceParameter(String service, String key, byte defaultValue) { + Number n = getNumbers().get(key); + if (n != null) { + return n.byteValue(); + } + String value = getServiceParameter(service, key); + if (StringUtils.isEmpty(value)) { + return defaultValue; + } + byte b = Byte.parseByte(value); + getNumbers().put(key, b); + return b; + } + + public char getServiceParameter(String service, String key, char defaultValue) { + String value = getServiceParameter(service, key); + return StringUtils.isEmpty(value) ? defaultValue : value.charAt(0); + } + + public boolean getServiceParameter(String service, String key, boolean defaultValue) { + String value = getServiceParameter(service, key); + return StringUtils.isEmpty(value) ? defaultValue : Boolean.parseBoolean(value); + } + + public boolean hasServiceParameter(String service, String key) { + String value = getServiceParameter(service, key); + return value != null && value.length() > 0; + } + + public float getPositiveServiceParameter(String service, String key, float defaultValue) { + if (defaultValue <= 0) { + throw new IllegalArgumentException("defaultValue <= 0"); + } + float value = getServiceParameter(service, key, defaultValue); + return value <= 0 ? defaultValue : value; + } + + public double getPositiveServiceParameter(String service, String key, double defaultValue) { + if (defaultValue <= 0) { + throw new IllegalArgumentException("defaultValue <= 0"); + } + double value = getServiceParameter(service, key, defaultValue); + return value <= 0 ? defaultValue : value; + } + + public long getPositiveServiceParameter(String service, String key, long defaultValue) { + if (defaultValue <= 0) { + throw new IllegalArgumentException("defaultValue <= 0"); + } + long value = getServiceParameter(service, key, defaultValue); + return value <= 0 ? defaultValue : value; + } + + public int getPositiveServiceParameter(String service, String key, int defaultValue) { + if (defaultValue <= 0) { + throw new IllegalArgumentException("defaultValue <= 0"); + } + int value = getServiceParameter(service, key, defaultValue); + return value <= 0 ? defaultValue : value; + } + + public short getPositiveServiceParameter(String service, String key, short defaultValue) { + if (defaultValue <= 0) { + throw new IllegalArgumentException("defaultValue <= 0"); + } + short value = getServiceParameter(service, key, defaultValue); + return value <= 0 ? defaultValue : value; + } + + public byte getPositiveServiceParameter(String service, String key, byte defaultValue) { + if (defaultValue <= 0) { + throw new IllegalArgumentException("defaultValue <= 0"); + } + byte value = getServiceParameter(service, key, defaultValue); + return value <= 0 ? defaultValue : value; + } + + public String getServiceMethodParameterAndDecoded(String service, String method, String key) { + return URL.decode(getServiceMethodParameter(service, method, key)); + } + + public String getServiceMethodParameterAndDecoded(String service, String method, String key, String defaultValue) { + return URL.decode(getServiceMethodParameter(service, method, key, defaultValue)); + } + + public String getServiceMethodParameterStrict(String service, String method, String key) { + return getMethodParameterStrict(method, key); + } + + public String getServiceMethodParameter(String service, String method, String key) { + return getMethodParameter(method, key); + } + + public String getServiceMethodParameter(String service, String method, String key, String defaultValue) { + String value = getServiceMethodParameter(service, method, key); + return StringUtils.isEmpty(value) ? defaultValue : value; + } + + public double getServiceMethodParameter(String service, String method, String key, double defaultValue) { + Number n = getCachedNumber(method, key); + if (n != null) { + return n.doubleValue(); + } + String value = getServiceMethodParameter(service, method, key); + if (StringUtils.isEmpty(value)) { + return defaultValue; + } + double d = Double.parseDouble(value); + updateCachedNumber(method, key, d); + return d; + } + + public float getServiceMethodParameter(String service, String method, String key, float defaultValue) { + Number n = getCachedNumber(method, key); + if (n != null) { + return n.floatValue(); + } + String value = getServiceMethodParameter(service, method, key); + if (StringUtils.isEmpty(value)) { + return defaultValue; + } + float f = Float.parseFloat(value); + updateCachedNumber(method, key, f); + return f; + } + + public long getServiceMethodParameter(String service, String method, String key, long defaultValue) { + Number n = getCachedNumber(method, key); + if (n != null) { + return n.longValue(); + } + String value = getServiceMethodParameter(service, method, key); + if (StringUtils.isEmpty(value)) { + return defaultValue; + } + long l = Long.parseLong(value); + updateCachedNumber(method, key, l); + return l; + } + + public int getServiceMethodParameter(String service, String method, String key, int defaultValue) { + Number n = getCachedNumber(method, key); + if (n != null) { + return n.intValue(); + } + String value = getServiceMethodParameter(service, method, key); + if (StringUtils.isEmpty(value)) { + return defaultValue; + } + int i = Integer.parseInt(value); + updateCachedNumber(method, key, i); + return i; + } + + public short getMethodParameter(String service, String method, String key, short defaultValue) { + Number n = getCachedNumber(method, key); + if (n != null) { + return n.shortValue(); + } + String value = getServiceMethodParameter(service, method, key); + if (StringUtils.isEmpty(value)) { + return defaultValue; + } + short s = Short.parseShort(value); + updateCachedNumber(method, key, s); + return s; + } + + public byte getServiceMethodParameter(String service, String method, String key, byte defaultValue) { + Number n = getCachedNumber(method, key); + if (n != null) { + return n.byteValue(); + } + String value = getServiceMethodParameter(service, method, key); + if (StringUtils.isEmpty(value)) { + return defaultValue; + } + byte b = Byte.parseByte(value); + updateCachedNumber(method, key, b); + return b; + } + + public boolean hasServiceMethodParameter(String service, String method, String key) { + return hasMethodParameter(method, key); + } + + public boolean hasServiceMethodParameter(String service, String method) { + return hasMethodParameter(method); + } + + protected Map getServiceNumbers(String service) { + return getNumbers(); + } + + protected Map> getServiceMethodNumbers(String service) { + return getMethodNumbers(); + } + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/URLBuilder.java b/dubbo-common/src/main/java/org/apache/dubbo/common/URLBuilder.java index 1ecf648a14..ce6e8e7552 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/URLBuilder.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/URLBuilder.java @@ -1,436 +1,436 @@ -/* - * 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.common; - -import org.apache.dubbo.common.url.component.ServiceConfigURL; -import org.apache.dubbo.common.utils.CollectionUtils; -import org.apache.dubbo.common.utils.StringUtils; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; - -public final class URLBuilder extends ServiceConfigURL { - private String protocol; - - private String username; - - private String password; - - // by default, host to registry - private String host; - - // by default, port to registry - private int port; - - private String path; - - private Map parameters; - - private Map attributes; - - private Map> methodParameters; - - public URLBuilder() { - protocol = null; - username = null; - password = null; - host = null; - port = 0; - path = null; - parameters = new HashMap<>(); - attributes = new HashMap<>(); - methodParameters = new HashMap<>(); - } - - public URLBuilder(String protocol, String host, int port) { - this(protocol, null, null, host, port, null, null); - } - - public URLBuilder(String protocol, String host, int port, String[] pairs) { - this(protocol, null, null, host, port, null, CollectionUtils.toStringMap(pairs)); - } - - public URLBuilder(String protocol, String host, int port, Map parameters) { - this(protocol, null, null, host, port, null, parameters); - } - - public URLBuilder(String protocol, String host, int port, String path) { - this(protocol, null, null, host, port, path, null); - } - - public URLBuilder(String protocol, String host, int port, String path, String... pairs) { - this(protocol, null, null, host, port, path, CollectionUtils.toStringMap(pairs)); - } - - public URLBuilder(String protocol, String host, int port, String path, Map parameters) { - this(protocol, null, null, host, port, path, parameters); - } - - public URLBuilder(String protocol, - String username, - String password, - String host, - int port, - String path, - Map parameters) { - this(protocol, username, password, host, port, path, parameters, null); - } - - public URLBuilder(String protocol, - String username, - String password, - String host, - int port, - String path, - Map parameters, - Map attributes) { - this.protocol = protocol; - this.username = username; - this.password = password; - this.host = host; - this.port = port; - this.path = path; - this.parameters = parameters != null ? parameters : new HashMap<>(); - this.attributes = attributes != null ? attributes : new HashMap<>(); - } - - public static URLBuilder from(URL url) { - String protocol = url.getProtocol(); - String username = url.getUsername(); - String password = url.getPassword(); - String host = url.getHost(); - int port = url.getPort(); - String path = url.getPath(); - Map parameters = new HashMap<>(url.getParameters()); - Map attributes = new HashMap<>(url.getAttributes()); - return new URLBuilder( - protocol, - username, - password, - host, - port, - path, - parameters, - attributes); - } - - public ServiceConfigURL build() { - if (StringUtils.isEmpty(username) && StringUtils.isNotEmpty(password)) { - throw new IllegalArgumentException("Invalid url, password without username!"); - } - port = Math.max(port, 0); - // trim the leading "/" - int firstNonSlash = 0; - if (path != null) { - while (firstNonSlash < path.length() && path.charAt(firstNonSlash) == '/') { - firstNonSlash++; - } - if (firstNonSlash >= path.length()) { - path = ""; - } else if (firstNonSlash > 0) { - path = path.substring(firstNonSlash); - } - } - return new ServiceConfigURL(protocol, username, password, host, port, path, parameters, attributes); - } - - @Override - public URLBuilder putAttribute(String key, Object obj) { - attributes.put(key, obj); - return this; - } - - public URLBuilder setProtocol(String protocol) { - this.protocol = protocol; - return this; - } - - public URLBuilder setUsername(String username) { - this.username = username; - return this; - } - - public URLBuilder setPassword(String password) { - this.password = password; - return this; - } - - public URLBuilder setHost(String host) { - this.host = host; - return this; - } - - public URLBuilder setPort(int port) { - this.port = port; - return this; - } - - public URLBuilder setAddress(String address) { - int i = address.lastIndexOf(':'); - String host; - int port = this.port; - if (i >= 0) { - host = address.substring(0, i); - port = Integer.parseInt(address.substring(i + 1)); - } else { - host = address; - } - this.host = host; - this.port = port; - return this; - } - - public URLBuilder setPath(String path) { - this.path = path; - return this; - } - - public URLBuilder addParameterAndEncoded(String key, String value) { - if (StringUtils.isEmpty(value)) { - return this; - } - return addParameter(key, URL.encode(value)); - } - - public URLBuilder addParameter(String key, boolean value) { - return addParameter(key, String.valueOf(value)); - } - - public URLBuilder addParameter(String key, char value) { - return addParameter(key, String.valueOf(value)); - } - - public URLBuilder addParameter(String key, byte value) { - return addParameter(key, String.valueOf(value)); - } - - public URLBuilder addParameter(String key, short value) { - return addParameter(key, String.valueOf(value)); - } - - public URLBuilder addParameter(String key, int value) { - return addParameter(key, String.valueOf(value)); - } - - public URLBuilder addParameter(String key, long value) { - return addParameter(key, String.valueOf(value)); - } - - public URLBuilder addParameter(String key, float value) { - return addParameter(key, String.valueOf(value)); - } - - public URLBuilder addParameter(String key, double value) { - return addParameter(key, String.valueOf(value)); - } - - public URLBuilder addParameter(String key, Enum value) { - if (value == null) { - return this; - } - return addParameter(key, String.valueOf(value)); - } - - public URLBuilder addParameter(String key, Number value) { - if (value == null) { - return this; - } - return addParameter(key, String.valueOf(value)); - } - - public URLBuilder addParameter(String key, CharSequence value) { - if (value == null || value.length() == 0) { - return this; - } - return addParameter(key, String.valueOf(value)); - } - - public URLBuilder addParameter(String key, String value) { - if (StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) { - return this; - } - - parameters.put(key, value); - return this; - } - - public URLBuilder addMethodParameter(String method, String key, String value) { - if (StringUtils.isEmpty(method) || StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) { - return this; - } - URL.putMethodParameter(method, key, value, methodParameters); - return this; - } - - public URLBuilder addParameterIfAbsent(String key, String value) { - if (StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) { - return this; - } - if (hasParameter(key)) { - return this; - } - parameters.put(key, value); - return this; - } - - public URLBuilder addMethodParameterIfAbsent(String method, String key, String value) { - if (StringUtils.isEmpty(method) || StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) { - return this; - } - if (hasMethodParameter(method, key)) { - return this; - } - URL.putMethodParameter(method, key, value, methodParameters); - return this; - } - - public URLBuilder addParameters(Map parameters) { - if (CollectionUtils.isEmptyMap(parameters)) { - return this; - } - - boolean hasAndEqual = true; - for (Map.Entry entry : parameters.entrySet()) { - String oldValue = this.parameters.get(entry.getKey()); - String newValue = entry.getValue(); - if (!Objects.equals(oldValue, newValue)) { - hasAndEqual = false; - break; - } - } - // return immediately if there's no change - if (hasAndEqual) { - return this; - } - - this.parameters.putAll(parameters); - return this; - } - - public URLBuilder addMethodParameters(Map> methodParameters) { - if (CollectionUtils.isEmptyMap(methodParameters)) { - return this; - } - - this.methodParameters.putAll(methodParameters); - return this; - } - - public URLBuilder addParametersIfAbsent(Map parameters) { - if (CollectionUtils.isEmptyMap(parameters)) { - return this; - } - for(Map.Entry entry : parameters.entrySet()) { - this.parameters.putIfAbsent(entry.getKey(), entry.getValue()); - } - return this; - } - - public URLBuilder addParameters(String... pairs) { - if (pairs == null || pairs.length == 0) { - return this; - } - if (pairs.length % 2 != 0) { - throw new IllegalArgumentException("Map pairs can not be odd number."); - } - Map map = new HashMap<>(); - int len = pairs.length / 2; - for (int i = 0; i < len; i++) { - map.put(pairs[2 * i], pairs[2 * i + 1]); - } - return addParameters(map); - } - - public URLBuilder addParameterString(String query) { - if (StringUtils.isEmpty(query)) { - return this; - } - return addParameters(StringUtils.parseQueryString(query)); - } - - public URLBuilder removeParameter(String key) { - if (StringUtils.isEmpty(key)) { - return this; - } - return removeParameters(key); - } - - public URLBuilder removeParameters(Collection keys) { - if (CollectionUtils.isEmpty(keys)) { - return this; - } - return removeParameters(keys.toArray(new String[0])); - } - - public URLBuilder removeParameters(String... keys) { - if (keys == null || keys.length == 0) { - return this; - } - for (String key : keys) { - parameters.remove(key); - } - return this; - } - - public URLBuilder clearParameters() { - parameters.clear(); - return this; - } - - public boolean hasParameter(String key) { - String value = getParameter(key); - return StringUtils.isNotEmpty(value); - } - - public boolean hasMethodParameter(String method, String key) { - if (method == null) { - String suffix = "." + key; - for (String fullKey : parameters.keySet()) { - if (fullKey.endsWith(suffix)) { - return true; - } - } - return false; - } - if (key == null) { - String prefix = method + "."; - for (String fullKey : parameters.keySet()) { - if (fullKey.startsWith(prefix)) { - return true; - } - } - return false; - } - String value = getMethodParameter(method, key); - return value != null && value.length() > 0; - } - - public String getParameter(String key) { - return parameters.get(key); - } - - public String getMethodParameter(String method, String key) { - Map keyMap = methodParameters.get(method); - String value = null; - if (keyMap != null) { - value = keyMap.get(key); - } - return value; - } -} +/* + * 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.common; + +import org.apache.dubbo.common.url.component.ServiceConfigURL; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.common.utils.StringUtils; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +public final class URLBuilder extends ServiceConfigURL { + private String protocol; + + private String username; + + private String password; + + // by default, host to registry + private String host; + + // by default, port to registry + private int port; + + private String path; + + private Map parameters; + + private Map attributes; + + private Map> methodParameters; + + public URLBuilder() { + protocol = null; + username = null; + password = null; + host = null; + port = 0; + path = null; + parameters = new HashMap<>(); + attributes = new HashMap<>(); + methodParameters = new HashMap<>(); + } + + public URLBuilder(String protocol, String host, int port) { + this(protocol, null, null, host, port, null, null); + } + + public URLBuilder(String protocol, String host, int port, String[] pairs) { + this(protocol, null, null, host, port, null, CollectionUtils.toStringMap(pairs)); + } + + public URLBuilder(String protocol, String host, int port, Map parameters) { + this(protocol, null, null, host, port, null, parameters); + } + + public URLBuilder(String protocol, String host, int port, String path) { + this(protocol, null, null, host, port, path, null); + } + + public URLBuilder(String protocol, String host, int port, String path, String... pairs) { + this(protocol, null, null, host, port, path, CollectionUtils.toStringMap(pairs)); + } + + public URLBuilder(String protocol, String host, int port, String path, Map parameters) { + this(protocol, null, null, host, port, path, parameters); + } + + public URLBuilder(String protocol, + String username, + String password, + String host, + int port, + String path, + Map parameters) { + this(protocol, username, password, host, port, path, parameters, null); + } + + public URLBuilder(String protocol, + String username, + String password, + String host, + int port, + String path, + Map parameters, + Map attributes) { + this.protocol = protocol; + this.username = username; + this.password = password; + this.host = host; + this.port = port; + this.path = path; + this.parameters = parameters != null ? parameters : new HashMap<>(); + this.attributes = attributes != null ? attributes : new HashMap<>(); + } + + public static URLBuilder from(URL url) { + String protocol = url.getProtocol(); + String username = url.getUsername(); + String password = url.getPassword(); + String host = url.getHost(); + int port = url.getPort(); + String path = url.getPath(); + Map parameters = new HashMap<>(url.getParameters()); + Map attributes = new HashMap<>(url.getAttributes()); + return new URLBuilder( + protocol, + username, + password, + host, + port, + path, + parameters, + attributes); + } + + public ServiceConfigURL build() { + if (StringUtils.isEmpty(username) && StringUtils.isNotEmpty(password)) { + throw new IllegalArgumentException("Invalid url, password without username!"); + } + port = Math.max(port, 0); + // trim the leading "/" + int firstNonSlash = 0; + if (path != null) { + while (firstNonSlash < path.length() && path.charAt(firstNonSlash) == '/') { + firstNonSlash++; + } + if (firstNonSlash >= path.length()) { + path = ""; + } else if (firstNonSlash > 0) { + path = path.substring(firstNonSlash); + } + } + return new ServiceConfigURL(protocol, username, password, host, port, path, parameters, attributes); + } + + @Override + public URLBuilder putAttribute(String key, Object obj) { + attributes.put(key, obj); + return this; + } + + public URLBuilder setProtocol(String protocol) { + this.protocol = protocol; + return this; + } + + public URLBuilder setUsername(String username) { + this.username = username; + return this; + } + + public URLBuilder setPassword(String password) { + this.password = password; + return this; + } + + public URLBuilder setHost(String host) { + this.host = host; + return this; + } + + public URLBuilder setPort(int port) { + this.port = port; + return this; + } + + public URLBuilder setAddress(String address) { + int i = address.lastIndexOf(':'); + String host; + int port = this.port; + if (i >= 0) { + host = address.substring(0, i); + port = Integer.parseInt(address.substring(i + 1)); + } else { + host = address; + } + this.host = host; + this.port = port; + return this; + } + + public URLBuilder setPath(String path) { + this.path = path; + return this; + } + + public URLBuilder addParameterAndEncoded(String key, String value) { + if (StringUtils.isEmpty(value)) { + return this; + } + return addParameter(key, URL.encode(value)); + } + + public URLBuilder addParameter(String key, boolean value) { + return addParameter(key, String.valueOf(value)); + } + + public URLBuilder addParameter(String key, char value) { + return addParameter(key, String.valueOf(value)); + } + + public URLBuilder addParameter(String key, byte value) { + return addParameter(key, String.valueOf(value)); + } + + public URLBuilder addParameter(String key, short value) { + return addParameter(key, String.valueOf(value)); + } + + public URLBuilder addParameter(String key, int value) { + return addParameter(key, String.valueOf(value)); + } + + public URLBuilder addParameter(String key, long value) { + return addParameter(key, String.valueOf(value)); + } + + public URLBuilder addParameter(String key, float value) { + return addParameter(key, String.valueOf(value)); + } + + public URLBuilder addParameter(String key, double value) { + return addParameter(key, String.valueOf(value)); + } + + public URLBuilder addParameter(String key, Enum value) { + if (value == null) { + return this; + } + return addParameter(key, String.valueOf(value)); + } + + public URLBuilder addParameter(String key, Number value) { + if (value == null) { + return this; + } + return addParameter(key, String.valueOf(value)); + } + + public URLBuilder addParameter(String key, CharSequence value) { + if (value == null || value.length() == 0) { + return this; + } + return addParameter(key, String.valueOf(value)); + } + + public URLBuilder addParameter(String key, String value) { + if (StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) { + return this; + } + + parameters.put(key, value); + return this; + } + + public URLBuilder addMethodParameter(String method, String key, String value) { + if (StringUtils.isEmpty(method) || StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) { + return this; + } + URL.putMethodParameter(method, key, value, methodParameters); + return this; + } + + public URLBuilder addParameterIfAbsent(String key, String value) { + if (StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) { + return this; + } + if (hasParameter(key)) { + return this; + } + parameters.put(key, value); + return this; + } + + public URLBuilder addMethodParameterIfAbsent(String method, String key, String value) { + if (StringUtils.isEmpty(method) || StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) { + return this; + } + if (hasMethodParameter(method, key)) { + return this; + } + URL.putMethodParameter(method, key, value, methodParameters); + return this; + } + + public URLBuilder addParameters(Map parameters) { + if (CollectionUtils.isEmptyMap(parameters)) { + return this; + } + + boolean hasAndEqual = true; + for (Map.Entry entry : parameters.entrySet()) { + String oldValue = this.parameters.get(entry.getKey()); + String newValue = entry.getValue(); + if (!Objects.equals(oldValue, newValue)) { + hasAndEqual = false; + break; + } + } + // return immediately if there's no change + if (hasAndEqual) { + return this; + } + + this.parameters.putAll(parameters); + return this; + } + + public URLBuilder addMethodParameters(Map> methodParameters) { + if (CollectionUtils.isEmptyMap(methodParameters)) { + return this; + } + + this.methodParameters.putAll(methodParameters); + return this; + } + + public URLBuilder addParametersIfAbsent(Map parameters) { + if (CollectionUtils.isEmptyMap(parameters)) { + return this; + } + for(Map.Entry entry : parameters.entrySet()) { + this.parameters.putIfAbsent(entry.getKey(), entry.getValue()); + } + return this; + } + + public URLBuilder addParameters(String... pairs) { + if (pairs == null || pairs.length == 0) { + return this; + } + if (pairs.length % 2 != 0) { + throw new IllegalArgumentException("Map pairs can not be odd number."); + } + Map map = new HashMap<>(); + int len = pairs.length / 2; + for (int i = 0; i < len; i++) { + map.put(pairs[2 * i], pairs[2 * i + 1]); + } + return addParameters(map); + } + + public URLBuilder addParameterString(String query) { + if (StringUtils.isEmpty(query)) { + return this; + } + return addParameters(StringUtils.parseQueryString(query)); + } + + public URLBuilder removeParameter(String key) { + if (StringUtils.isEmpty(key)) { + return this; + } + return removeParameters(key); + } + + public URLBuilder removeParameters(Collection keys) { + if (CollectionUtils.isEmpty(keys)) { + return this; + } + return removeParameters(keys.toArray(new String[0])); + } + + public URLBuilder removeParameters(String... keys) { + if (keys == null || keys.length == 0) { + return this; + } + for (String key : keys) { + parameters.remove(key); + } + return this; + } + + public URLBuilder clearParameters() { + parameters.clear(); + return this; + } + + public boolean hasParameter(String key) { + String value = getParameter(key); + return StringUtils.isNotEmpty(value); + } + + public boolean hasMethodParameter(String method, String key) { + if (method == null) { + String suffix = "." + key; + for (String fullKey : parameters.keySet()) { + if (fullKey.endsWith(suffix)) { + return true; + } + } + return false; + } + if (key == null) { + String prefix = method + "."; + for (String fullKey : parameters.keySet()) { + if (fullKey.startsWith(prefix)) { + return true; + } + } + return false; + } + String value = getMethodParameter(method, key); + return value != null && value.length() > 0; + } + + public String getParameter(String key) { + return parameters.get(key); + } + + public String getMethodParameter(String method, String key) { + Map keyMap = methodParameters.get(method); + String value = null; + if (keyMap != null) { + value = keyMap.get(key); + } + return value; + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/ClassGenerator.java b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/ClassGenerator.java index 252c3aa719..48a1c56cb8 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/ClassGenerator.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/ClassGenerator.java @@ -385,4 +385,4 @@ public final class ClassGenerator { public static interface DC { } // dynamic class tag interface. -} \ No newline at end of file +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Mixin.java b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Mixin.java index cd16d381ad..e3cedbaf8d 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Mixin.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Mixin.java @@ -1,227 +1,227 @@ -/* - * 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.common.bytecode; - -import org.apache.dubbo.common.utils.ClassUtils; -import org.apache.dubbo.common.utils.ReflectUtils; - -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.atomic.AtomicLong; - -/** - * Mixin - */ -public abstract class Mixin { - private static final String PACKAGE_NAME = Mixin.class.getPackage().getName(); - private static AtomicLong MIXIN_CLASS_COUNTER = new AtomicLong(0); - - protected Mixin() { - } - - /** - * mixin interface and delegates. - * all class must be public. - * - * @param ics interface class array. - * @param dc delegate class. - * @return Mixin instance. - */ - public static Mixin mixin(Class[] ics, Class dc) { - return mixin(ics, new Class[]{dc}); - } - - /** - * mixin interface and delegates. - * all class must be public. - * - * @param ics interface class array. - * @param dc delegate class. - * @param cl class loader. - * @return Mixin instance. - */ - public static Mixin mixin(Class[] ics, Class dc, ClassLoader cl) { - return mixin(ics, new Class[]{dc}, cl); - } - - /** - * mixin interface and delegates. - * all class must be public. - * - * @param ics interface class array. - * @param dcs delegate class array. - * @return Mixin instance. - */ - public static Mixin mixin(Class[] ics, Class[] dcs) { - return mixin(ics, dcs, ClassUtils.getCallerClassLoader(Mixin.class)); - } - - /** - * mixin interface and delegates. - * all class must be public. - * - * @param ics interface class array. - * @param dcs delegate class array. - * @param cl class loader. - * @return Mixin instance. - */ - public static Mixin mixin(Class[] ics, Class[] dcs, ClassLoader cl) { - assertInterfaceArray(ics); - - long id = MIXIN_CLASS_COUNTER.getAndIncrement(); - String pkg = null; - ClassGenerator ccp = null, ccm = null; - try { - ccp = ClassGenerator.newInstance(cl); - - // impl constructor - StringBuilder code = new StringBuilder(); - for (int i = 0; i < dcs.length; i++) { - if (!Modifier.isPublic(dcs[i].getModifiers())) { - String npkg = dcs[i].getPackage().getName(); - if (pkg == null) { - pkg = npkg; - } else { - if (!pkg.equals(npkg)) { - throw new IllegalArgumentException("non-public interfaces class from different packages"); - } - } - } - - ccp.addField("private " + dcs[i].getName() + " d" + i + ";"); - - code.append("d").append(i).append(" = (").append(dcs[i].getName()).append(")$1[").append(i).append("];\n"); - if (MixinAware.class.isAssignableFrom(dcs[i])) { - code.append("d").append(i).append(".setMixinInstance(this);\n"); - } - } - ccp.addConstructor(Modifier.PUBLIC, new Class[]{Object[].class}, code.toString()); - - // impl methods. - Set worked = new HashSet(); - for (int i = 0; i < ics.length; i++) { - if (!Modifier.isPublic(ics[i].getModifiers())) { - String npkg = ics[i].getPackage().getName(); - if (pkg == null) { - pkg = npkg; - } else { - if (!pkg.equals(npkg)) { - throw new IllegalArgumentException("non-public delegate class from different packages"); - } - } - } - - ccp.addInterface(ics[i]); - - for (Method method : ics[i].getMethods()) { - if ("java.lang.Object".equals(method.getDeclaringClass().getName())) { - continue; - } - - String desc = ReflectUtils.getDesc(method); - if (worked.contains(desc)) { - continue; - } - worked.add(desc); - - int ix = findMethod(dcs, desc); - if (ix < 0) { - throw new RuntimeException("Missing method [" + desc + "] implement."); - } - - Class rt = method.getReturnType(); - String mn = method.getName(); - if (Void.TYPE.equals(rt)) { - ccp.addMethod(mn, method.getModifiers(), rt, method.getParameterTypes(), method.getExceptionTypes(), - "d" + ix + "." + mn + "($$);"); - } else { - ccp.addMethod(mn, method.getModifiers(), rt, method.getParameterTypes(), method.getExceptionTypes(), - "return ($r)d" + ix + "." + mn + "($$);"); - } - } - } - - if (pkg == null) { - pkg = PACKAGE_NAME; - } - - // create MixinInstance class. - String micn = pkg + ".mixin" + id; - ccp.setClassName(micn); - ccp.toClass(); - - // create Mixin class. - String fcn = Mixin.class.getName() + id; - ccm = ClassGenerator.newInstance(cl); - ccm.setClassName(fcn); - ccm.addDefaultConstructor(); - ccm.setSuperClass(Mixin.class.getName()); - ccm.addMethod("public Object newInstance(Object[] delegates){ return new " + micn + "($1); }"); - Class mixin = ccm.toClass(); - return (Mixin) mixin.getDeclaredConstructor().newInstance(); - } catch (RuntimeException e) { - throw e; - } catch (Exception e) { - throw new RuntimeException(e.getMessage(), e); - } finally { - // release ClassGenerator - if (ccp != null) { - ccp.release(); - } - if (ccm != null) { - ccm.release(); - } - } - } - - private static int findMethod(Class[] dcs, String desc) { - Class cl; - Method[] methods; - for (int i = 0; i < dcs.length; i++) { - cl = dcs[i]; - methods = cl.getMethods(); - for (Method method : methods) { - if (desc.equals(ReflectUtils.getDesc(method))) { - return i; - } - } - } - return -1; - } - - private static void assertInterfaceArray(Class[] ics) { - for (int i = 0; i < ics.length; i++) { - if (!ics[i].isInterface()) { - throw new RuntimeException("Class " + ics[i].getName() + " is not a interface."); - } - } - } - - /** - * new Mixin instance. - * - * @param ds delegates instance. - * @return instance. - */ - abstract public Object newInstance(Object[] ds); - - public static interface MixinAware { - void setMixinInstance(Object instance); - } -} \ No newline at end of file +/* + * 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.common.bytecode; + +import org.apache.dubbo.common.utils.ClassUtils; +import org.apache.dubbo.common.utils.ReflectUtils; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.atomic.AtomicLong; + +/** + * Mixin + */ +public abstract class Mixin { + private static final String PACKAGE_NAME = Mixin.class.getPackage().getName(); + private static AtomicLong MIXIN_CLASS_COUNTER = new AtomicLong(0); + + protected Mixin() { + } + + /** + * mixin interface and delegates. + * all class must be public. + * + * @param ics interface class array. + * @param dc delegate class. + * @return Mixin instance. + */ + public static Mixin mixin(Class[] ics, Class dc) { + return mixin(ics, new Class[]{dc}); + } + + /** + * mixin interface and delegates. + * all class must be public. + * + * @param ics interface class array. + * @param dc delegate class. + * @param cl class loader. + * @return Mixin instance. + */ + public static Mixin mixin(Class[] ics, Class dc, ClassLoader cl) { + return mixin(ics, new Class[]{dc}, cl); + } + + /** + * mixin interface and delegates. + * all class must be public. + * + * @param ics interface class array. + * @param dcs delegate class array. + * @return Mixin instance. + */ + public static Mixin mixin(Class[] ics, Class[] dcs) { + return mixin(ics, dcs, ClassUtils.getCallerClassLoader(Mixin.class)); + } + + /** + * mixin interface and delegates. + * all class must be public. + * + * @param ics interface class array. + * @param dcs delegate class array. + * @param cl class loader. + * @return Mixin instance. + */ + public static Mixin mixin(Class[] ics, Class[] dcs, ClassLoader cl) { + assertInterfaceArray(ics); + + long id = MIXIN_CLASS_COUNTER.getAndIncrement(); + String pkg = null; + ClassGenerator ccp = null, ccm = null; + try { + ccp = ClassGenerator.newInstance(cl); + + // impl constructor + StringBuilder code = new StringBuilder(); + for (int i = 0; i < dcs.length; i++) { + if (!Modifier.isPublic(dcs[i].getModifiers())) { + String npkg = dcs[i].getPackage().getName(); + if (pkg == null) { + pkg = npkg; + } else { + if (!pkg.equals(npkg)) { + throw new IllegalArgumentException("non-public interfaces class from different packages"); + } + } + } + + ccp.addField("private " + dcs[i].getName() + " d" + i + ";"); + + code.append("d").append(i).append(" = (").append(dcs[i].getName()).append(")$1[").append(i).append("];\n"); + if (MixinAware.class.isAssignableFrom(dcs[i])) { + code.append("d").append(i).append(".setMixinInstance(this);\n"); + } + } + ccp.addConstructor(Modifier.PUBLIC, new Class[]{Object[].class}, code.toString()); + + // impl methods. + Set worked = new HashSet(); + for (int i = 0; i < ics.length; i++) { + if (!Modifier.isPublic(ics[i].getModifiers())) { + String npkg = ics[i].getPackage().getName(); + if (pkg == null) { + pkg = npkg; + } else { + if (!pkg.equals(npkg)) { + throw new IllegalArgumentException("non-public delegate class from different packages"); + } + } + } + + ccp.addInterface(ics[i]); + + for (Method method : ics[i].getMethods()) { + if ("java.lang.Object".equals(method.getDeclaringClass().getName())) { + continue; + } + + String desc = ReflectUtils.getDesc(method); + if (worked.contains(desc)) { + continue; + } + worked.add(desc); + + int ix = findMethod(dcs, desc); + if (ix < 0) { + throw new RuntimeException("Missing method [" + desc + "] implement."); + } + + Class rt = method.getReturnType(); + String mn = method.getName(); + if (Void.TYPE.equals(rt)) { + ccp.addMethod(mn, method.getModifiers(), rt, method.getParameterTypes(), method.getExceptionTypes(), + "d" + ix + "." + mn + "($$);"); + } else { + ccp.addMethod(mn, method.getModifiers(), rt, method.getParameterTypes(), method.getExceptionTypes(), + "return ($r)d" + ix + "." + mn + "($$);"); + } + } + } + + if (pkg == null) { + pkg = PACKAGE_NAME; + } + + // create MixinInstance class. + String micn = pkg + ".mixin" + id; + ccp.setClassName(micn); + ccp.toClass(); + + // create Mixin class. + String fcn = Mixin.class.getName() + id; + ccm = ClassGenerator.newInstance(cl); + ccm.setClassName(fcn); + ccm.addDefaultConstructor(); + ccm.setSuperClass(Mixin.class.getName()); + ccm.addMethod("public Object newInstance(Object[] delegates){ return new " + micn + "($1); }"); + Class mixin = ccm.toClass(); + return (Mixin) mixin.getDeclaredConstructor().newInstance(); + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } finally { + // release ClassGenerator + if (ccp != null) { + ccp.release(); + } + if (ccm != null) { + ccm.release(); + } + } + } + + private static int findMethod(Class[] dcs, String desc) { + Class cl; + Method[] methods; + for (int i = 0; i < dcs.length; i++) { + cl = dcs[i]; + methods = cl.getMethods(); + for (Method method : methods) { + if (desc.equals(ReflectUtils.getDesc(method))) { + return i; + } + } + } + return -1; + } + + private static void assertInterfaceArray(Class[] ics) { + for (int i = 0; i < ics.length; i++) { + if (!ics[i].isInterface()) { + throw new RuntimeException("Class " + ics[i].getName() + " is not a interface."); + } + } + } + + /** + * new Mixin instance. + * + * @param ds delegates instance. + * @return instance. + */ + abstract public Object newInstance(Object[] ds); + + public static interface MixinAware { + void setMixinInstance(Object instance); + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/NoSuchMethodException.java b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/NoSuchMethodException.java index 56061a2baf..31679daa70 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/NoSuchMethodException.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/NoSuchMethodException.java @@ -1,33 +1,33 @@ -/* - * 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.common.bytecode; - -/** - * NoSuchMethodException. - */ - -public class NoSuchMethodException extends RuntimeException { - private static final long serialVersionUID = -2725364246023268766L; - - public NoSuchMethodException() { - super(); - } - - public NoSuchMethodException(String msg) { - super(msg); - } -} \ No newline at end of file +/* + * 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.common.bytecode; + +/** + * NoSuchMethodException. + */ + +public class NoSuchMethodException extends RuntimeException { + private static final long serialVersionUID = -2725364246023268766L; + + public NoSuchMethodException() { + super(); + } + + public NoSuchMethodException(String msg) { + super(msg); + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/NoSuchPropertyException.java b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/NoSuchPropertyException.java index 0a2f21244e..7b6f8ecef3 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/NoSuchPropertyException.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/NoSuchPropertyException.java @@ -1,33 +1,33 @@ -/* - * 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.common.bytecode; - -/** - * NoSuchPropertyException. - */ - -public class NoSuchPropertyException extends RuntimeException { - private static final long serialVersionUID = -2725364246023268766L; - - public NoSuchPropertyException() { - super(); - } - - public NoSuchPropertyException(String msg) { - super(msg); - } -} \ No newline at end of file +/* + * 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.common.bytecode; + +/** + * NoSuchPropertyException. + */ + +public class NoSuchPropertyException extends RuntimeException { + private static final long serialVersionUID = -2725364246023268766L; + + public NoSuchPropertyException() { + super(); + } + + public NoSuchPropertyException(String msg) { + super(msg); + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Proxy.java b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Proxy.java index 4c435a8f77..8d2f73362c 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Proxy.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Proxy.java @@ -1,307 +1,307 @@ -/* - * 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.common.bytecode; - -import org.apache.dubbo.common.utils.ClassUtils; -import org.apache.dubbo.common.utils.ReflectUtils; - -import java.lang.ref.Reference; -import java.lang.ref.SoftReference; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.WeakHashMap; -import java.util.concurrent.atomic.AtomicLong; - -import static org.apache.dubbo.common.constants.CommonConstants.MAX_PROXY_COUNT; - -/** - * Proxy. - */ - -public abstract class Proxy { - public static final InvocationHandler RETURN_NULL_INVOKER = (proxy, method, args) -> null; - public static final InvocationHandler THROW_UNSUPPORTED_INVOKER = new InvocationHandler() { - @Override - public Object invoke(Object proxy, Method method, Object[] args) { - throw new UnsupportedOperationException("Method [" + ReflectUtils.getName(method) + "] unimplemented."); - } - }; - private static final AtomicLong PROXY_CLASS_COUNTER = new AtomicLong(0); - private static final String PACKAGE_NAME = Proxy.class.getPackage().getName(); - private static final Map> PROXY_CACHE_MAP = new WeakHashMap>(); - // cache class, avoid PermGen OOM. - private static final Map> PROXY_CLASS_MAP = new WeakHashMap>(); - - private static final Object PENDING_GENERATION_MARKER = new Object(); - - protected Proxy() { - } - - /** - * Get proxy. - * - * @param ics interface class array. - * @return Proxy instance. - */ - public static Proxy getProxy(Class... ics) { - return getProxy(ClassUtils.getClassLoader(Proxy.class), ics); - } - - /** - * Get proxy. - * - * @param cl class loader. - * @param ics interface class array. - * @return Proxy instance. - */ - public static Proxy getProxy(ClassLoader cl, Class... ics) { - if (ics.length > MAX_PROXY_COUNT) { - throw new IllegalArgumentException("interface limit exceeded"); - } - - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < ics.length; i++) { - String itf = ics[i].getName(); - if (!ics[i].isInterface()) { - throw new RuntimeException(itf + " is not a interface."); - } - - Class tmp = null; - try { - tmp = Class.forName(itf, false, cl); - } catch (ClassNotFoundException e) { - } - - if (tmp != ics[i]) { - throw new IllegalArgumentException(ics[i] + " is not visible from class loader"); - } - - sb.append(itf).append(';'); - } - - // use interface class name list as key. - String key = sb.toString(); - - // get cache by class loader. - final Map cache; - // cache class - final Map classCache; - synchronized (PROXY_CACHE_MAP) { - cache = PROXY_CACHE_MAP.computeIfAbsent(cl, k -> new HashMap<>()); - classCache = PROXY_CLASS_MAP.computeIfAbsent(cl, k -> new HashMap<>()); - } - - Proxy proxy = null; - synchronized (cache) { - do { - Object value = cache.get(key); - if (value instanceof Reference) { - proxy = (Proxy) ((Reference) value).get(); - if (proxy != null) { - return proxy; - } - } - - // get Class by key. - Object clazzObj = classCache.get(key); - if (null == clazzObj || clazzObj instanceof Reference) { - Class clazz = null; - if (clazzObj instanceof Reference) { - clazz = (Class) ((Reference) clazzObj).get(); - } - - if (null == clazz) { - if (value == PENDING_GENERATION_MARKER) { - try { - cache.wait(); - } catch (InterruptedException e) { - } - } else { - cache.put(key, PENDING_GENERATION_MARKER); - break; - } - } else { - try { - proxy = (Proxy) clazz.newInstance(); - return proxy; - } catch (InstantiationException | IllegalAccessException e) { - throw new RuntimeException(e); - } finally { - if (null == proxy) { - cache.remove(key); - } else { - cache.put(key, new SoftReference<>(proxy)); - } - } - } - } - } - while (true); - } - - long id = PROXY_CLASS_COUNTER.getAndIncrement(); - String pkg = null; - ClassGenerator ccp = null, ccm = null; - try { - ccp = ClassGenerator.newInstance(cl); - - Set worked = new HashSet<>(); - List methods = new ArrayList<>(); - - for (int i = 0; i < ics.length; i++) { - if (!Modifier.isPublic(ics[i].getModifiers())) { - String npkg = ics[i].getPackage().getName(); - if (pkg == null) { - pkg = npkg; - } else { - if (!pkg.equals(npkg)) { - throw new IllegalArgumentException("non-public interfaces from different packages"); - } - } - } - ccp.addInterface(ics[i]); - - for (Method method : ics[i].getMethods()) { - String desc = ReflectUtils.getDesc(method); - if (worked.contains(desc) || Modifier.isStatic(method.getModifiers())) { - continue; - } - worked.add(desc); - - int ix = methods.size(); - Class rt = method.getReturnType(); - Class[] pts = method.getParameterTypes(); - - StringBuilder code = new StringBuilder("Object[] args = new Object[").append(pts.length).append("];"); - for (int j = 0; j < pts.length; j++) { - code.append(" args[").append(j).append("] = ($w)$").append(j + 1).append(";"); - } - code.append(" Object ret = handler.invoke(this, methods[").append(ix).append("], args);"); - if (!Void.TYPE.equals(rt)) { - code.append(" return ").append(asArgument(rt, "ret")).append(";"); - } - - methods.add(method); - ccp.addMethod(method.getName(), method.getModifiers(), rt, pts, method.getExceptionTypes(), code.toString()); - } - } - - if (pkg == null) { - pkg = PACKAGE_NAME; - } - - // create ProxyInstance class. - String pcn = pkg + ".proxy" + id; - ccp.setClassName(pcn); - ccp.addField("public static java.lang.reflect.Method[] methods;"); - ccp.addField("private " + InvocationHandler.class.getName() + " handler;"); - ccp.addConstructor(Modifier.PUBLIC, new Class[] {InvocationHandler.class}, new Class[0], "handler=$1;"); - ccp.addDefaultConstructor(); - Class clazz = ccp.toClass(); - clazz.getField("methods").set(null, methods.toArray(new Method[0])); - - // create Proxy class. - String fcn = Proxy.class.getName() + id; - ccm = ClassGenerator.newInstance(cl); - ccm.setClassName(fcn); - ccm.addDefaultConstructor(); - ccm.setSuperClass(Proxy.class); - ccm.addMethod("public Object newInstance(" + InvocationHandler.class.getName() + " h){ return new " + pcn + "($1); }"); - Class pc = ccm.toClass(); - proxy = (Proxy) pc.newInstance(); - - synchronized (classCache) { - classCache.put(key, new SoftReference>(pc)); - } - } catch (RuntimeException e) { - throw e; - } catch (Exception e) { - throw new RuntimeException(e.getMessage(), e); - } finally { - // release ClassGenerator - if (ccp != null) { - ccp.release(); - } - if (ccm != null) { - ccm.release(); - } - synchronized (cache) { - if (proxy == null) { - cache.remove(key); - } else { - cache.put(key, new SoftReference(proxy)); - } - cache.notifyAll(); - } - } - return proxy; - } - - private static String asArgument(Class cl, String name) { - if (cl.isPrimitive()) { - if (Boolean.TYPE == cl) { - return name + "==null?false:((Boolean)" + name + ").booleanValue()"; - } - if (Byte.TYPE == cl) { - return name + "==null?(byte)0:((Byte)" + name + ").byteValue()"; - } - if (Character.TYPE == cl) { - return name + "==null?(char)0:((Character)" + name + ").charValue()"; - } - if (Double.TYPE == cl) { - return name + "==null?(double)0:((Double)" + name + ").doubleValue()"; - } - if (Float.TYPE == cl) { - return name + "==null?(float)0:((Float)" + name + ").floatValue()"; - } - if (Integer.TYPE == cl) { - return name + "==null?(int)0:((Integer)" + name + ").intValue()"; - } - if (Long.TYPE == cl) { - return name + "==null?(long)0:((Long)" + name + ").longValue()"; - } - if (Short.TYPE == cl) { - return name + "==null?(short)0:((Short)" + name + ").shortValue()"; - } - throw new RuntimeException(name + " is unknown primitive type."); - } - return "(" + ReflectUtils.getName(cl) + ")" + name; - } - - /** - * get instance with default handler. - * - * @return instance. - */ - public Object newInstance() { - return newInstance(THROW_UNSUPPORTED_INVOKER); - } - - /** - * get instance with special handler. - * - * @return instance. - */ - abstract public Object newInstance(InvocationHandler handler); -} +/* + * 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.common.bytecode; + +import org.apache.dubbo.common.utils.ClassUtils; +import org.apache.dubbo.common.utils.ReflectUtils; + +import java.lang.ref.Reference; +import java.lang.ref.SoftReference; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.WeakHashMap; +import java.util.concurrent.atomic.AtomicLong; + +import static org.apache.dubbo.common.constants.CommonConstants.MAX_PROXY_COUNT; + +/** + * Proxy. + */ + +public abstract class Proxy { + public static final InvocationHandler RETURN_NULL_INVOKER = (proxy, method, args) -> null; + public static final InvocationHandler THROW_UNSUPPORTED_INVOKER = new InvocationHandler() { + @Override + public Object invoke(Object proxy, Method method, Object[] args) { + throw new UnsupportedOperationException("Method [" + ReflectUtils.getName(method) + "] unimplemented."); + } + }; + private static final AtomicLong PROXY_CLASS_COUNTER = new AtomicLong(0); + private static final String PACKAGE_NAME = Proxy.class.getPackage().getName(); + private static final Map> PROXY_CACHE_MAP = new WeakHashMap>(); + // cache class, avoid PermGen OOM. + private static final Map> PROXY_CLASS_MAP = new WeakHashMap>(); + + private static final Object PENDING_GENERATION_MARKER = new Object(); + + protected Proxy() { + } + + /** + * Get proxy. + * + * @param ics interface class array. + * @return Proxy instance. + */ + public static Proxy getProxy(Class... ics) { + return getProxy(ClassUtils.getClassLoader(Proxy.class), ics); + } + + /** + * Get proxy. + * + * @param cl class loader. + * @param ics interface class array. + * @return Proxy instance. + */ + public static Proxy getProxy(ClassLoader cl, Class... ics) { + if (ics.length > MAX_PROXY_COUNT) { + throw new IllegalArgumentException("interface limit exceeded"); + } + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < ics.length; i++) { + String itf = ics[i].getName(); + if (!ics[i].isInterface()) { + throw new RuntimeException(itf + " is not a interface."); + } + + Class tmp = null; + try { + tmp = Class.forName(itf, false, cl); + } catch (ClassNotFoundException e) { + } + + if (tmp != ics[i]) { + throw new IllegalArgumentException(ics[i] + " is not visible from class loader"); + } + + sb.append(itf).append(';'); + } + + // use interface class name list as key. + String key = sb.toString(); + + // get cache by class loader. + final Map cache; + // cache class + final Map classCache; + synchronized (PROXY_CACHE_MAP) { + cache = PROXY_CACHE_MAP.computeIfAbsent(cl, k -> new HashMap<>()); + classCache = PROXY_CLASS_MAP.computeIfAbsent(cl, k -> new HashMap<>()); + } + + Proxy proxy = null; + synchronized (cache) { + do { + Object value = cache.get(key); + if (value instanceof Reference) { + proxy = (Proxy) ((Reference) value).get(); + if (proxy != null) { + return proxy; + } + } + + // get Class by key. + Object clazzObj = classCache.get(key); + if (null == clazzObj || clazzObj instanceof Reference) { + Class clazz = null; + if (clazzObj instanceof Reference) { + clazz = (Class) ((Reference) clazzObj).get(); + } + + if (null == clazz) { + if (value == PENDING_GENERATION_MARKER) { + try { + cache.wait(); + } catch (InterruptedException e) { + } + } else { + cache.put(key, PENDING_GENERATION_MARKER); + break; + } + } else { + try { + proxy = (Proxy) clazz.newInstance(); + return proxy; + } catch (InstantiationException | IllegalAccessException e) { + throw new RuntimeException(e); + } finally { + if (null == proxy) { + cache.remove(key); + } else { + cache.put(key, new SoftReference<>(proxy)); + } + } + } + } + } + while (true); + } + + long id = PROXY_CLASS_COUNTER.getAndIncrement(); + String pkg = null; + ClassGenerator ccp = null, ccm = null; + try { + ccp = ClassGenerator.newInstance(cl); + + Set worked = new HashSet<>(); + List methods = new ArrayList<>(); + + for (int i = 0; i < ics.length; i++) { + if (!Modifier.isPublic(ics[i].getModifiers())) { + String npkg = ics[i].getPackage().getName(); + if (pkg == null) { + pkg = npkg; + } else { + if (!pkg.equals(npkg)) { + throw new IllegalArgumentException("non-public interfaces from different packages"); + } + } + } + ccp.addInterface(ics[i]); + + for (Method method : ics[i].getMethods()) { + String desc = ReflectUtils.getDesc(method); + if (worked.contains(desc) || Modifier.isStatic(method.getModifiers())) { + continue; + } + worked.add(desc); + + int ix = methods.size(); + Class rt = method.getReturnType(); + Class[] pts = method.getParameterTypes(); + + StringBuilder code = new StringBuilder("Object[] args = new Object[").append(pts.length).append("];"); + for (int j = 0; j < pts.length; j++) { + code.append(" args[").append(j).append("] = ($w)$").append(j + 1).append(";"); + } + code.append(" Object ret = handler.invoke(this, methods[").append(ix).append("], args);"); + if (!Void.TYPE.equals(rt)) { + code.append(" return ").append(asArgument(rt, "ret")).append(";"); + } + + methods.add(method); + ccp.addMethod(method.getName(), method.getModifiers(), rt, pts, method.getExceptionTypes(), code.toString()); + } + } + + if (pkg == null) { + pkg = PACKAGE_NAME; + } + + // create ProxyInstance class. + String pcn = pkg + ".proxy" + id; + ccp.setClassName(pcn); + ccp.addField("public static java.lang.reflect.Method[] methods;"); + ccp.addField("private " + InvocationHandler.class.getName() + " handler;"); + ccp.addConstructor(Modifier.PUBLIC, new Class[] {InvocationHandler.class}, new Class[0], "handler=$1;"); + ccp.addDefaultConstructor(); + Class clazz = ccp.toClass(); + clazz.getField("methods").set(null, methods.toArray(new Method[0])); + + // create Proxy class. + String fcn = Proxy.class.getName() + id; + ccm = ClassGenerator.newInstance(cl); + ccm.setClassName(fcn); + ccm.addDefaultConstructor(); + ccm.setSuperClass(Proxy.class); + ccm.addMethod("public Object newInstance(" + InvocationHandler.class.getName() + " h){ return new " + pcn + "($1); }"); + Class pc = ccm.toClass(); + proxy = (Proxy) pc.newInstance(); + + synchronized (classCache) { + classCache.put(key, new SoftReference>(pc)); + } + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } finally { + // release ClassGenerator + if (ccp != null) { + ccp.release(); + } + if (ccm != null) { + ccm.release(); + } + synchronized (cache) { + if (proxy == null) { + cache.remove(key); + } else { + cache.put(key, new SoftReference(proxy)); + } + cache.notifyAll(); + } + } + return proxy; + } + + private static String asArgument(Class cl, String name) { + if (cl.isPrimitive()) { + if (Boolean.TYPE == cl) { + return name + "==null?false:((Boolean)" + name + ").booleanValue()"; + } + if (Byte.TYPE == cl) { + return name + "==null?(byte)0:((Byte)" + name + ").byteValue()"; + } + if (Character.TYPE == cl) { + return name + "==null?(char)0:((Character)" + name + ").charValue()"; + } + if (Double.TYPE == cl) { + return name + "==null?(double)0:((Double)" + name + ").doubleValue()"; + } + if (Float.TYPE == cl) { + return name + "==null?(float)0:((Float)" + name + ").floatValue()"; + } + if (Integer.TYPE == cl) { + return name + "==null?(int)0:((Integer)" + name + ").intValue()"; + } + if (Long.TYPE == cl) { + return name + "==null?(long)0:((Long)" + name + ").longValue()"; + } + if (Short.TYPE == cl) { + return name + "==null?(short)0:((Short)" + name + ").shortValue()"; + } + throw new RuntimeException(name + " is unknown primitive type."); + } + return "(" + ReflectUtils.getName(cl) + ")" + name; + } + + /** + * get instance with default handler. + * + * @return instance. + */ + public Object newInstance() { + return newInstance(THROW_UNSUPPORTED_INVOKER); + } + + /** + * get instance with special handler. + * + * @return instance. + */ + abstract public Object newInstance(InvocationHandler handler); +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Wrapper.java b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Wrapper.java index 11257e9cc1..16539e5cec 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Wrapper.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Wrapper.java @@ -1,474 +1,474 @@ -/* - * 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.common.bytecode; - -import org.apache.dubbo.common.utils.ClassUtils; -import org.apache.dubbo.common.utils.ReflectUtils; - -import javassist.ClassPool; -import javassist.CtMethod; - -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicLong; -import java.util.regex.Matcher; -import java.util.stream.Collectors; - -/** - * Wrapper. - */ -public abstract class Wrapper { - private static final Map, Wrapper> WRAPPER_MAP = new ConcurrentHashMap, Wrapper>(); //class wrapper map - private static final String[] EMPTY_STRING_ARRAY = new String[0]; - private static final String[] OBJECT_METHODS = new String[]{"getClass", "hashCode", "toString", "equals"}; - private static final Wrapper OBJECT_WRAPPER = new Wrapper() { - @Override - public String[] getMethodNames() { - return OBJECT_METHODS; - } - - @Override - public String[] getDeclaredMethodNames() { - return OBJECT_METHODS; - } - - @Override - public String[] getPropertyNames() { - return EMPTY_STRING_ARRAY; - } - - @Override - public Class getPropertyType(String pn) { - return null; - } - - @Override - public Object getPropertyValue(Object instance, String pn) throws NoSuchPropertyException { - throw new NoSuchPropertyException("Property [" + pn + "] not found."); - } - - @Override - public void setPropertyValue(Object instance, String pn, Object pv) throws NoSuchPropertyException { - throw new NoSuchPropertyException("Property [" + pn + "] not found."); - } - - @Override - public boolean hasProperty(String name) { - return false; - } - - @Override - public Object invokeMethod(Object instance, String mn, Class[] types, Object[] args) throws NoSuchMethodException { - if ("getClass".equals(mn)) { - return instance.getClass(); - } - if ("hashCode".equals(mn)) { - return instance.hashCode(); - } - if ("toString".equals(mn)) { - return instance.toString(); - } - if ("equals".equals(mn)) { - if (args.length == 1) { - return instance.equals(args[0]); - } - throw new IllegalArgumentException("Invoke method [" + mn + "] argument number error."); - } - throw new NoSuchMethodException("Method [" + mn + "] not found."); - } - }; - private static AtomicLong WRAPPER_CLASS_COUNTER = new AtomicLong(0); - - /** - * get wrapper. - * - * @param c Class instance. - * @return Wrapper instance(not null). - */ - public static Wrapper getWrapper(Class c) { - while (ClassGenerator.isDynamicClass(c)) // can not wrapper on dynamic class. - { - c = c.getSuperclass(); - } - - if (c == Object.class) { - return OBJECT_WRAPPER; - } - - return WRAPPER_MAP.computeIfAbsent(c, Wrapper::makeWrapper); - } - - private static Wrapper makeWrapper(Class c) { - if (c.isPrimitive()) { - throw new IllegalArgumentException("Can not create wrapper for primitive type: " + c); - } - - String name = c.getName(); - ClassLoader cl = ClassUtils.getClassLoader(c); - - StringBuilder c1 = new StringBuilder("public void setPropertyValue(Object o, String n, Object v){ "); - StringBuilder c2 = new StringBuilder("public Object getPropertyValue(Object o, String n){ "); - StringBuilder c3 = new StringBuilder("public Object invokeMethod(Object o, String n, Class[] p, Object[] v) throws " + InvocationTargetException.class.getName() + "{ "); - - c1.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }"); - c2.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }"); - c3.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }"); - - Map> pts = new HashMap<>(); // - Map ms = new LinkedHashMap<>(); // - List mns = new ArrayList<>(); // method names. - List dmns = new ArrayList<>(); // declaring method names. - - // get all public field. - for (Field f : c.getFields()) { - String fn = f.getName(); - Class ft = f.getType(); - if (Modifier.isStatic(f.getModifiers()) || Modifier.isTransient(f.getModifiers())) { - continue; - } - - c1.append(" if( $2.equals(\"").append(fn).append("\") ){ w.").append(fn).append("=").append(arg(ft, "$3")).append("; return; }"); - c2.append(" if( $2.equals(\"").append(fn).append("\") ){ return ($w)w.").append(fn).append("; }"); - pts.put(fn, ft); - } - - final ClassPool classPool = new ClassPool(ClassPool.getDefault()); - classPool.appendClassPath(new CustomizedLoaderClassPath(cl)); - - List allMethod = new ArrayList<>(); - try { - final CtMethod[] ctMethods = classPool.get(c.getName()).getMethods(); - for (CtMethod method : ctMethods) { - allMethod.add(ReflectUtils.getDesc(method)); - } - } catch (Exception e) { - throw new RuntimeException(e); - } - - Method[] methods = Arrays.stream(c.getMethods()) - .filter(method -> allMethod.contains(ReflectUtils.getDesc(method))) - .collect(Collectors.toList()) - .toArray(new Method[] {}); - // get all public method. - boolean hasMethod = hasMethods(methods); - if (hasMethod) { - Map sameNameMethodCount = new HashMap<>((int) (methods.length / 0.75f) + 1); - for (Method m : methods) { - sameNameMethodCount.compute(m.getName(), - (key, oldValue) -> oldValue == null ? 1 : oldValue + 1); - } - - c3.append(" try{"); - for (Method m : methods) { - //ignore Object's method. - if (m.getDeclaringClass() == Object.class) { - continue; - } - - String mn = m.getName(); - c3.append(" if( \"").append(mn).append("\".equals( $2 ) "); - int len = m.getParameterTypes().length; - c3.append(" && ").append(" $3.length == ").append(len); - - boolean overload = sameNameMethodCount.get(m.getName()) > 1; - if (overload) { - if (len > 0) { - for (int l = 0; l < len; l++) { - c3.append(" && ").append(" $3[").append(l).append("].getName().equals(\"") - .append(m.getParameterTypes()[l].getName()).append("\")"); - } - } - } - - c3.append(" ) { "); - - if (m.getReturnType() == Void.TYPE) { - c3.append(" w.").append(mn).append('(').append(args(m.getParameterTypes(), "$4")).append(");").append(" return null;"); - } else { - c3.append(" return ($w)w.").append(mn).append('(').append(args(m.getParameterTypes(), "$4")).append(");"); - } - - c3.append(" }"); - - mns.add(mn); - if (m.getDeclaringClass() == c) { - dmns.add(mn); - } - ms.put(ReflectUtils.getDesc(m), m); - } - c3.append(" } catch(Throwable e) { "); - c3.append(" throw new java.lang.reflect.InvocationTargetException(e); "); - c3.append(" }"); - } - - c3.append(" throw new " + NoSuchMethodException.class.getName() + "(\"Not found method \\\"\"+$2+\"\\\" in class " + c.getName() + ".\"); }"); - - // deal with get/set method. - Matcher matcher; - for (Map.Entry entry : ms.entrySet()) { - String md = entry.getKey(); - Method method = entry.getValue(); - if ((matcher = ReflectUtils.GETTER_METHOD_DESC_PATTERN.matcher(md)).matches()) { - String pn = propertyName(matcher.group(1)); - c2.append(" if( $2.equals(\"").append(pn).append("\") ){ return ($w)w.").append(method.getName()).append("(); }"); - pts.put(pn, method.getReturnType()); - } else if ((matcher = ReflectUtils.IS_HAS_CAN_METHOD_DESC_PATTERN.matcher(md)).matches()) { - String pn = propertyName(matcher.group(1)); - c2.append(" if( $2.equals(\"").append(pn).append("\") ){ return ($w)w.").append(method.getName()).append("(); }"); - pts.put(pn, method.getReturnType()); - } else if ((matcher = ReflectUtils.SETTER_METHOD_DESC_PATTERN.matcher(md)).matches()) { - Class pt = method.getParameterTypes()[0]; - String pn = propertyName(matcher.group(1)); - c1.append(" if( $2.equals(\"").append(pn).append("\") ){ w.").append(method.getName()).append("(").append(arg(pt, "$3")).append("); return; }"); - pts.put(pn, pt); - } - } - c1.append(" throw new " + NoSuchPropertyException.class.getName() + "(\"Not found property \\\"\"+$2+\"\\\" field or setter method in class " + c.getName() + ".\"); }"); - c2.append(" throw new " + NoSuchPropertyException.class.getName() + "(\"Not found property \\\"\"+$2+\"\\\" field or getter method in class " + c.getName() + ".\"); }"); - - // make class - long id = WRAPPER_CLASS_COUNTER.getAndIncrement(); - ClassGenerator cc = ClassGenerator.newInstance(cl); - cc.setClassName((Modifier.isPublic(c.getModifiers()) ? Wrapper.class.getName() : c.getName() + "$sw") + id); - cc.setSuperClass(Wrapper.class); - - cc.addDefaultConstructor(); - cc.addField("public static String[] pns;"); // property name array. - cc.addField("public static " + Map.class.getName() + " pts;"); // property type map. - cc.addField("public static String[] mns;"); // all method name array. - cc.addField("public static String[] dmns;"); // declared method name array. - for (int i = 0, len = ms.size(); i < len; i++) { - cc.addField("public static Class[] mts" + i + ";"); - } - - cc.addMethod("public String[] getPropertyNames(){ return pns; }"); - cc.addMethod("public boolean hasProperty(String n){ return pts.containsKey($1); }"); - cc.addMethod("public Class getPropertyType(String n){ return (Class)pts.get($1); }"); - cc.addMethod("public String[] getMethodNames(){ return mns; }"); - cc.addMethod("public String[] getDeclaredMethodNames(){ return dmns; }"); - cc.addMethod(c1.toString()); - cc.addMethod(c2.toString()); - cc.addMethod(c3.toString()); - - try { - Class wc = cc.toClass(); - // setup static field. - wc.getField("pts").set(null, pts); - wc.getField("pns").set(null, pts.keySet().toArray(new String[0])); - wc.getField("mns").set(null, mns.toArray(new String[0])); - wc.getField("dmns").set(null, dmns.toArray(new String[0])); - int ix = 0; - for (Method m : ms.values()) { - wc.getField("mts" + ix++).set(null, m.getParameterTypes()); - } - return (Wrapper) wc.getDeclaredConstructor().newInstance(); - } catch (RuntimeException e) { - throw e; - } catch (Throwable e) { - throw new RuntimeException(e.getMessage(), e); - } finally { - cc.release(); - ms.clear(); - mns.clear(); - dmns.clear(); - } - } - - private static String arg(Class cl, String name) { - if (cl.isPrimitive()) { - if (cl == Boolean.TYPE) { - return "((Boolean)" + name + ").booleanValue()"; - } - if (cl == Byte.TYPE) { - return "((Byte)" + name + ").byteValue()"; - } - if (cl == Character.TYPE) { - return "((Character)" + name + ").charValue()"; - } - if (cl == Double.TYPE) { - return "((Number)" + name + ").doubleValue()"; - } - if (cl == Float.TYPE) { - return "((Number)" + name + ").floatValue()"; - } - if (cl == Integer.TYPE) { - return "((Number)" + name + ").intValue()"; - } - if (cl == Long.TYPE) { - return "((Number)" + name + ").longValue()"; - } - if (cl == Short.TYPE) { - return "((Number)" + name + ").shortValue()"; - } - throw new RuntimeException("Unknown primitive type: " + cl.getName()); - } - return "(" + ReflectUtils.getName(cl) + ")" + name; - } - - private static String args(Class[] cs, String name) { - int len = cs.length; - if (len == 0) { - return ""; - } - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < len; i++) { - if (i > 0) { - sb.append(','); - } - sb.append(arg(cs[i], name + "[" + i + "]")); - } - return sb.toString(); - } - - private static String propertyName(String pn) { - return pn.length() == 1 || Character.isLowerCase(pn.charAt(1)) ? Character.toLowerCase(pn.charAt(0)) + pn.substring(1) : pn; - } - - private static boolean hasMethods(Method[] methods) { - if (methods == null || methods.length == 0) { - return false; - } - for (Method m : methods) { - if (m.getDeclaringClass() != Object.class) { - return true; - } - } - return false; - } - - /** - * get property name array. - * - * @return property name array. - */ - abstract public String[] getPropertyNames(); - - /** - * get property type. - * - * @param pn property name. - * @return Property type or nul. - */ - abstract public Class getPropertyType(String pn); - - /** - * has property. - * - * @param name property name. - * @return has or has not. - */ - abstract public boolean hasProperty(String name); - - /** - * get property value. - * - * @param instance instance. - * @param pn property name. - * @return value. - */ - abstract public Object getPropertyValue(Object instance, String pn) throws NoSuchPropertyException, IllegalArgumentException; - - /** - * set property value. - * - * @param instance instance. - * @param pn property name. - * @param pv property value. - */ - abstract public void setPropertyValue(Object instance, String pn, Object pv) throws NoSuchPropertyException, IllegalArgumentException; - - /** - * get property value. - * - * @param instance instance. - * @param pns property name array. - * @return value array. - */ - public Object[] getPropertyValues(Object instance, String[] pns) throws NoSuchPropertyException, IllegalArgumentException { - Object[] ret = new Object[pns.length]; - for (int i = 0; i < ret.length; i++) { - ret[i] = getPropertyValue(instance, pns[i]); - } - return ret; - } - - /** - * set property value. - * - * @param instance instance. - * @param pns property name array. - * @param pvs property value array. - */ - public void setPropertyValues(Object instance, String[] pns, Object[] pvs) throws NoSuchPropertyException, IllegalArgumentException { - if (pns.length != pvs.length) { - throw new IllegalArgumentException("pns.length != pvs.length"); - } - - for (int i = 0; i < pns.length; i++) { - setPropertyValue(instance, pns[i], pvs[i]); - } - } - - /** - * get method name array. - * - * @return method name array. - */ - abstract public String[] getMethodNames(); - - /** - * get method name array. - * - * @return method name array. - */ - abstract public String[] getDeclaredMethodNames(); - - /** - * has method. - * - * @param name method name. - * @return has or has not. - */ - public boolean hasMethod(String name) { - for (String mn : getMethodNames()) { - if (mn.equals(name)) { - return true; - } - } - return false; - } - - /** - * invoke method. - * - * @param instance instance. - * @param mn method name. - * @param types - * @param args argument array. - * @return return value. - */ - abstract public Object invokeMethod(Object instance, String mn, Class[] types, Object[] args) throws NoSuchMethodException, InvocationTargetException; -} +/* + * 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.common.bytecode; + +import org.apache.dubbo.common.utils.ClassUtils; +import org.apache.dubbo.common.utils.ReflectUtils; + +import javassist.ClassPool; +import javassist.CtMethod; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; +import java.util.regex.Matcher; +import java.util.stream.Collectors; + +/** + * Wrapper. + */ +public abstract class Wrapper { + private static final Map, Wrapper> WRAPPER_MAP = new ConcurrentHashMap, Wrapper>(); //class wrapper map + private static final String[] EMPTY_STRING_ARRAY = new String[0]; + private static final String[] OBJECT_METHODS = new String[]{"getClass", "hashCode", "toString", "equals"}; + private static final Wrapper OBJECT_WRAPPER = new Wrapper() { + @Override + public String[] getMethodNames() { + return OBJECT_METHODS; + } + + @Override + public String[] getDeclaredMethodNames() { + return OBJECT_METHODS; + } + + @Override + public String[] getPropertyNames() { + return EMPTY_STRING_ARRAY; + } + + @Override + public Class getPropertyType(String pn) { + return null; + } + + @Override + public Object getPropertyValue(Object instance, String pn) throws NoSuchPropertyException { + throw new NoSuchPropertyException("Property [" + pn + "] not found."); + } + + @Override + public void setPropertyValue(Object instance, String pn, Object pv) throws NoSuchPropertyException { + throw new NoSuchPropertyException("Property [" + pn + "] not found."); + } + + @Override + public boolean hasProperty(String name) { + return false; + } + + @Override + public Object invokeMethod(Object instance, String mn, Class[] types, Object[] args) throws NoSuchMethodException { + if ("getClass".equals(mn)) { + return instance.getClass(); + } + if ("hashCode".equals(mn)) { + return instance.hashCode(); + } + if ("toString".equals(mn)) { + return instance.toString(); + } + if ("equals".equals(mn)) { + if (args.length == 1) { + return instance.equals(args[0]); + } + throw new IllegalArgumentException("Invoke method [" + mn + "] argument number error."); + } + throw new NoSuchMethodException("Method [" + mn + "] not found."); + } + }; + private static AtomicLong WRAPPER_CLASS_COUNTER = new AtomicLong(0); + + /** + * get wrapper. + * + * @param c Class instance. + * @return Wrapper instance(not null). + */ + public static Wrapper getWrapper(Class c) { + while (ClassGenerator.isDynamicClass(c)) // can not wrapper on dynamic class. + { + c = c.getSuperclass(); + } + + if (c == Object.class) { + return OBJECT_WRAPPER; + } + + return WRAPPER_MAP.computeIfAbsent(c, Wrapper::makeWrapper); + } + + private static Wrapper makeWrapper(Class c) { + if (c.isPrimitive()) { + throw new IllegalArgumentException("Can not create wrapper for primitive type: " + c); + } + + String name = c.getName(); + ClassLoader cl = ClassUtils.getClassLoader(c); + + StringBuilder c1 = new StringBuilder("public void setPropertyValue(Object o, String n, Object v){ "); + StringBuilder c2 = new StringBuilder("public Object getPropertyValue(Object o, String n){ "); + StringBuilder c3 = new StringBuilder("public Object invokeMethod(Object o, String n, Class[] p, Object[] v) throws " + InvocationTargetException.class.getName() + "{ "); + + c1.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }"); + c2.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }"); + c3.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }"); + + Map> pts = new HashMap<>(); // + Map ms = new LinkedHashMap<>(); // + List mns = new ArrayList<>(); // method names. + List dmns = new ArrayList<>(); // declaring method names. + + // get all public field. + for (Field f : c.getFields()) { + String fn = f.getName(); + Class ft = f.getType(); + if (Modifier.isStatic(f.getModifiers()) || Modifier.isTransient(f.getModifiers())) { + continue; + } + + c1.append(" if( $2.equals(\"").append(fn).append("\") ){ w.").append(fn).append("=").append(arg(ft, "$3")).append("; return; }"); + c2.append(" if( $2.equals(\"").append(fn).append("\") ){ return ($w)w.").append(fn).append("; }"); + pts.put(fn, ft); + } + + final ClassPool classPool = new ClassPool(ClassPool.getDefault()); + classPool.appendClassPath(new CustomizedLoaderClassPath(cl)); + + List allMethod = new ArrayList<>(); + try { + final CtMethod[] ctMethods = classPool.get(c.getName()).getMethods(); + for (CtMethod method : ctMethods) { + allMethod.add(ReflectUtils.getDesc(method)); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + + Method[] methods = Arrays.stream(c.getMethods()) + .filter(method -> allMethod.contains(ReflectUtils.getDesc(method))) + .collect(Collectors.toList()) + .toArray(new Method[] {}); + // get all public method. + boolean hasMethod = hasMethods(methods); + if (hasMethod) { + Map sameNameMethodCount = new HashMap<>((int) (methods.length / 0.75f) + 1); + for (Method m : methods) { + sameNameMethodCount.compute(m.getName(), + (key, oldValue) -> oldValue == null ? 1 : oldValue + 1); + } + + c3.append(" try{"); + for (Method m : methods) { + //ignore Object's method. + if (m.getDeclaringClass() == Object.class) { + continue; + } + + String mn = m.getName(); + c3.append(" if( \"").append(mn).append("\".equals( $2 ) "); + int len = m.getParameterTypes().length; + c3.append(" && ").append(" $3.length == ").append(len); + + boolean overload = sameNameMethodCount.get(m.getName()) > 1; + if (overload) { + if (len > 0) { + for (int l = 0; l < len; l++) { + c3.append(" && ").append(" $3[").append(l).append("].getName().equals(\"") + .append(m.getParameterTypes()[l].getName()).append("\")"); + } + } + } + + c3.append(" ) { "); + + if (m.getReturnType() == Void.TYPE) { + c3.append(" w.").append(mn).append('(').append(args(m.getParameterTypes(), "$4")).append(");").append(" return null;"); + } else { + c3.append(" return ($w)w.").append(mn).append('(').append(args(m.getParameterTypes(), "$4")).append(");"); + } + + c3.append(" }"); + + mns.add(mn); + if (m.getDeclaringClass() == c) { + dmns.add(mn); + } + ms.put(ReflectUtils.getDesc(m), m); + } + c3.append(" } catch(Throwable e) { "); + c3.append(" throw new java.lang.reflect.InvocationTargetException(e); "); + c3.append(" }"); + } + + c3.append(" throw new " + NoSuchMethodException.class.getName() + "(\"Not found method \\\"\"+$2+\"\\\" in class " + c.getName() + ".\"); }"); + + // deal with get/set method. + Matcher matcher; + for (Map.Entry entry : ms.entrySet()) { + String md = entry.getKey(); + Method method = entry.getValue(); + if ((matcher = ReflectUtils.GETTER_METHOD_DESC_PATTERN.matcher(md)).matches()) { + String pn = propertyName(matcher.group(1)); + c2.append(" if( $2.equals(\"").append(pn).append("\") ){ return ($w)w.").append(method.getName()).append("(); }"); + pts.put(pn, method.getReturnType()); + } else if ((matcher = ReflectUtils.IS_HAS_CAN_METHOD_DESC_PATTERN.matcher(md)).matches()) { + String pn = propertyName(matcher.group(1)); + c2.append(" if( $2.equals(\"").append(pn).append("\") ){ return ($w)w.").append(method.getName()).append("(); }"); + pts.put(pn, method.getReturnType()); + } else if ((matcher = ReflectUtils.SETTER_METHOD_DESC_PATTERN.matcher(md)).matches()) { + Class pt = method.getParameterTypes()[0]; + String pn = propertyName(matcher.group(1)); + c1.append(" if( $2.equals(\"").append(pn).append("\") ){ w.").append(method.getName()).append("(").append(arg(pt, "$3")).append("); return; }"); + pts.put(pn, pt); + } + } + c1.append(" throw new " + NoSuchPropertyException.class.getName() + "(\"Not found property \\\"\"+$2+\"\\\" field or setter method in class " + c.getName() + ".\"); }"); + c2.append(" throw new " + NoSuchPropertyException.class.getName() + "(\"Not found property \\\"\"+$2+\"\\\" field or getter method in class " + c.getName() + ".\"); }"); + + // make class + long id = WRAPPER_CLASS_COUNTER.getAndIncrement(); + ClassGenerator cc = ClassGenerator.newInstance(cl); + cc.setClassName((Modifier.isPublic(c.getModifiers()) ? Wrapper.class.getName() : c.getName() + "$sw") + id); + cc.setSuperClass(Wrapper.class); + + cc.addDefaultConstructor(); + cc.addField("public static String[] pns;"); // property name array. + cc.addField("public static " + Map.class.getName() + " pts;"); // property type map. + cc.addField("public static String[] mns;"); // all method name array. + cc.addField("public static String[] dmns;"); // declared method name array. + for (int i = 0, len = ms.size(); i < len; i++) { + cc.addField("public static Class[] mts" + i + ";"); + } + + cc.addMethod("public String[] getPropertyNames(){ return pns; }"); + cc.addMethod("public boolean hasProperty(String n){ return pts.containsKey($1); }"); + cc.addMethod("public Class getPropertyType(String n){ return (Class)pts.get($1); }"); + cc.addMethod("public String[] getMethodNames(){ return mns; }"); + cc.addMethod("public String[] getDeclaredMethodNames(){ return dmns; }"); + cc.addMethod(c1.toString()); + cc.addMethod(c2.toString()); + cc.addMethod(c3.toString()); + + try { + Class wc = cc.toClass(); + // setup static field. + wc.getField("pts").set(null, pts); + wc.getField("pns").set(null, pts.keySet().toArray(new String[0])); + wc.getField("mns").set(null, mns.toArray(new String[0])); + wc.getField("dmns").set(null, dmns.toArray(new String[0])); + int ix = 0; + for (Method m : ms.values()) { + wc.getField("mts" + ix++).set(null, m.getParameterTypes()); + } + return (Wrapper) wc.getDeclaredConstructor().newInstance(); + } catch (RuntimeException e) { + throw e; + } catch (Throwable e) { + throw new RuntimeException(e.getMessage(), e); + } finally { + cc.release(); + ms.clear(); + mns.clear(); + dmns.clear(); + } + } + + private static String arg(Class cl, String name) { + if (cl.isPrimitive()) { + if (cl == Boolean.TYPE) { + return "((Boolean)" + name + ").booleanValue()"; + } + if (cl == Byte.TYPE) { + return "((Byte)" + name + ").byteValue()"; + } + if (cl == Character.TYPE) { + return "((Character)" + name + ").charValue()"; + } + if (cl == Double.TYPE) { + return "((Number)" + name + ").doubleValue()"; + } + if (cl == Float.TYPE) { + return "((Number)" + name + ").floatValue()"; + } + if (cl == Integer.TYPE) { + return "((Number)" + name + ").intValue()"; + } + if (cl == Long.TYPE) { + return "((Number)" + name + ").longValue()"; + } + if (cl == Short.TYPE) { + return "((Number)" + name + ").shortValue()"; + } + throw new RuntimeException("Unknown primitive type: " + cl.getName()); + } + return "(" + ReflectUtils.getName(cl) + ")" + name; + } + + private static String args(Class[] cs, String name) { + int len = cs.length; + if (len == 0) { + return ""; + } + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < len; i++) { + if (i > 0) { + sb.append(','); + } + sb.append(arg(cs[i], name + "[" + i + "]")); + } + return sb.toString(); + } + + private static String propertyName(String pn) { + return pn.length() == 1 || Character.isLowerCase(pn.charAt(1)) ? Character.toLowerCase(pn.charAt(0)) + pn.substring(1) : pn; + } + + private static boolean hasMethods(Method[] methods) { + if (methods == null || methods.length == 0) { + return false; + } + for (Method m : methods) { + if (m.getDeclaringClass() != Object.class) { + return true; + } + } + return false; + } + + /** + * get property name array. + * + * @return property name array. + */ + abstract public String[] getPropertyNames(); + + /** + * get property type. + * + * @param pn property name. + * @return Property type or nul. + */ + abstract public Class getPropertyType(String pn); + + /** + * has property. + * + * @param name property name. + * @return has or has not. + */ + abstract public boolean hasProperty(String name); + + /** + * get property value. + * + * @param instance instance. + * @param pn property name. + * @return value. + */ + abstract public Object getPropertyValue(Object instance, String pn) throws NoSuchPropertyException, IllegalArgumentException; + + /** + * set property value. + * + * @param instance instance. + * @param pn property name. + * @param pv property value. + */ + abstract public void setPropertyValue(Object instance, String pn, Object pv) throws NoSuchPropertyException, IllegalArgumentException; + + /** + * get property value. + * + * @param instance instance. + * @param pns property name array. + * @return value array. + */ + public Object[] getPropertyValues(Object instance, String[] pns) throws NoSuchPropertyException, IllegalArgumentException { + Object[] ret = new Object[pns.length]; + for (int i = 0; i < ret.length; i++) { + ret[i] = getPropertyValue(instance, pns[i]); + } + return ret; + } + + /** + * set property value. + * + * @param instance instance. + * @param pns property name array. + * @param pvs property value array. + */ + public void setPropertyValues(Object instance, String[] pns, Object[] pvs) throws NoSuchPropertyException, IllegalArgumentException { + if (pns.length != pvs.length) { + throw new IllegalArgumentException("pns.length != pvs.length"); + } + + for (int i = 0; i < pns.length; i++) { + setPropertyValue(instance, pns[i], pvs[i]); + } + } + + /** + * get method name array. + * + * @return method name array. + */ + abstract public String[] getMethodNames(); + + /** + * get method name array. + * + * @return method name array. + */ + abstract public String[] getDeclaredMethodNames(); + + /** + * has method. + * + * @param name method name. + * @return has or has not. + */ + public boolean hasMethod(String name) { + for (String mn : getMethodNames()) { + if (mn.equals(name)) { + return true; + } + } + return false; + } + + /** + * invoke method. + * + * @param instance instance. + * @param mn method name. + * @param types + * @param args argument array. + * @return return value. + */ + abstract public Object invokeMethod(Object instance, String mn, Class[] types, Object[] args) throws NoSuchMethodException, InvocationTargetException; +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/Compiler.java b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/Compiler.java index 3b8961d83f..acac7bdd2e 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/Compiler.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/Compiler.java @@ -1,36 +1,36 @@ -/* - * 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.common.compiler; - -import org.apache.dubbo.common.extension.SPI; - -/** - * Compiler. (SPI, Singleton, ThreadSafe) - */ -@SPI("javassist") -public interface Compiler { - - /** - * Compile java source code. - * - * @param code Java source code - * @param classLoader classloader - * @return Compiled class - */ - Class compile(String code, ClassLoader classLoader); - -} +/* + * 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.common.compiler; + +import org.apache.dubbo.common.extension.SPI; + +/** + * Compiler. (SPI, Singleton, ThreadSafe) + */ +@SPI("javassist") +public interface Compiler { + + /** + * Compile java source code. + * + * @param code Java source code + * @param classLoader classloader + * @return Compiled class + */ + Class compile(String code, ClassLoader classLoader); + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/AbstractCompiler.java b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/AbstractCompiler.java index f079430284..2df52ca5c5 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/AbstractCompiler.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/AbstractCompiler.java @@ -1,69 +1,69 @@ -/* - * 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.common.compiler.support; - -import org.apache.dubbo.common.compiler.Compiler; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Abstract compiler. (SPI, Prototype, ThreadSafe) - */ -public abstract class AbstractCompiler implements Compiler { - - private static final Pattern PACKAGE_PATTERN = Pattern.compile("package\\s+([$_a-zA-Z][$_a-zA-Z0-9\\.]*);"); - - private static final Pattern CLASS_PATTERN = Pattern.compile("class\\s+([$_a-zA-Z][$_a-zA-Z0-9]*)\\s+"); - - @Override - public Class compile(String code, ClassLoader classLoader) { - code = code.trim(); - Matcher matcher = PACKAGE_PATTERN.matcher(code); - String pkg; - if (matcher.find()) { - pkg = matcher.group(1); - } else { - pkg = ""; - } - matcher = CLASS_PATTERN.matcher(code); - String cls; - if (matcher.find()) { - cls = matcher.group(1); - } else { - throw new IllegalArgumentException("No such class name in " + code); - } - String className = pkg != null && pkg.length() > 0 ? pkg + "." + cls : cls; - try { - return Class.forName(className, true, org.apache.dubbo.common.utils.ClassUtils.getCallerClassLoader(getClass())); - } catch (ClassNotFoundException e) { - if (!code.endsWith("}")) { - throw new IllegalStateException("The java code not endsWith \"}\", code: \n" + code + "\n"); - } - try { - return doCompile(className, code); - } catch (RuntimeException t) { - throw t; - } catch (Throwable t) { - throw new IllegalStateException("Failed to compile class, cause: " + t.getMessage() + ", class: " + className + ", code: \n" + code + "\n, stack: " + ClassUtils.toString(t)); - } - } - } - - protected abstract Class doCompile(String name, String source) throws Throwable; - -} +/* + * 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.common.compiler.support; + +import org.apache.dubbo.common.compiler.Compiler; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Abstract compiler. (SPI, Prototype, ThreadSafe) + */ +public abstract class AbstractCompiler implements Compiler { + + private static final Pattern PACKAGE_PATTERN = Pattern.compile("package\\s+([$_a-zA-Z][$_a-zA-Z0-9\\.]*);"); + + private static final Pattern CLASS_PATTERN = Pattern.compile("class\\s+([$_a-zA-Z][$_a-zA-Z0-9]*)\\s+"); + + @Override + public Class compile(String code, ClassLoader classLoader) { + code = code.trim(); + Matcher matcher = PACKAGE_PATTERN.matcher(code); + String pkg; + if (matcher.find()) { + pkg = matcher.group(1); + } else { + pkg = ""; + } + matcher = CLASS_PATTERN.matcher(code); + String cls; + if (matcher.find()) { + cls = matcher.group(1); + } else { + throw new IllegalArgumentException("No such class name in " + code); + } + String className = pkg != null && pkg.length() > 0 ? pkg + "." + cls : cls; + try { + return Class.forName(className, true, org.apache.dubbo.common.utils.ClassUtils.getCallerClassLoader(getClass())); + } catch (ClassNotFoundException e) { + if (!code.endsWith("}")) { + throw new IllegalStateException("The java code not endsWith \"}\", code: \n" + code + "\n"); + } + try { + return doCompile(className, code); + } catch (RuntimeException t) { + throw t; + } catch (Throwable t) { + throw new IllegalStateException("Failed to compile class, cause: " + t.getMessage() + ", class: " + className + ", code: \n" + code + "\n, stack: " + ClassUtils.toString(t)); + } + } + } + + protected abstract Class doCompile(String name, String source) throws Throwable; + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/AdaptiveCompiler.java b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/AdaptiveCompiler.java index a0c5cc6b41..ccc8db5402 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/AdaptiveCompiler.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/AdaptiveCompiler.java @@ -1,48 +1,48 @@ -/* - * 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.common.compiler.support; - -import org.apache.dubbo.common.compiler.Compiler; -import org.apache.dubbo.common.extension.Adaptive; -import org.apache.dubbo.common.extension.ExtensionLoader; - -/** - * AdaptiveCompiler. (SPI, Singleton, ThreadSafe) - */ -@Adaptive -public class AdaptiveCompiler implements Compiler { - - private static volatile String DEFAULT_COMPILER; - - public static void setDefaultCompiler(String compiler) { - DEFAULT_COMPILER = compiler; - } - - @Override - public Class compile(String code, ClassLoader classLoader) { - Compiler compiler; - ExtensionLoader loader = ExtensionLoader.getExtensionLoader(Compiler.class); - String name = DEFAULT_COMPILER; // copy reference - if (name != null && name.length() > 0) { - compiler = loader.getExtension(name); - } else { - compiler = loader.getDefaultExtension(); - } - return compiler.compile(code, classLoader); - } - -} +/* + * 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.common.compiler.support; + +import org.apache.dubbo.common.compiler.Compiler; +import org.apache.dubbo.common.extension.Adaptive; +import org.apache.dubbo.common.extension.ExtensionLoader; + +/** + * AdaptiveCompiler. (SPI, Singleton, ThreadSafe) + */ +@Adaptive +public class AdaptiveCompiler implements Compiler { + + private static volatile String DEFAULT_COMPILER; + + public static void setDefaultCompiler(String compiler) { + DEFAULT_COMPILER = compiler; + } + + @Override + public Class compile(String code, ClassLoader classLoader) { + Compiler compiler; + ExtensionLoader loader = ExtensionLoader.getExtensionLoader(Compiler.class); + String name = DEFAULT_COMPILER; // copy reference + if (name != null && name.length() > 0) { + compiler = loader.getExtension(name); + } else { + compiler = loader.getDefaultExtension(); + } + return compiler.compile(code, classLoader); + } + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/ClassUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/ClassUtils.java index d09afadcce..f0ecf67997 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/ClassUtils.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/ClassUtils.java @@ -1,445 +1,445 @@ -/* - * 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.common.compiler.support; - -import org.apache.dubbo.common.utils.StringUtils; - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.lang.reflect.Array; -import java.lang.reflect.GenericArrayType; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -/** - * ClassUtils. (Tool, Static, ThreadSafe) - */ -public class ClassUtils { - - public static final String CLASS_EXTENSION = ".class"; - - public static final String JAVA_EXTENSION = ".java"; - private static final int JIT_LIMIT = 5 * 1024; - - private ClassUtils() { - } - - public static Object newInstance(String name) { - try { - return forName(name).getDeclaredConstructor().newInstance(); - } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - - public static Class forName(String[] packages, String className) { - try { - return classForName(className); - } catch (ClassNotFoundException e) { - if (packages != null && packages.length > 0) { - for (String pkg : packages) { - try { - return classForName(pkg + "." + className); - } catch (ClassNotFoundException ignore) { - } - } - } - throw new IllegalStateException(e.getMessage(), e); - } - } - - public static Class forName(String className) { - try { - return classForName(className); - } catch (ClassNotFoundException e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - - public static Class classForName(String className) throws ClassNotFoundException { - switch (className) { - case "boolean": - return boolean.class; - case "byte": - return byte.class; - case "char": - return char.class; - case "short": - return short.class; - case "int": - return int.class; - case "long": - return long.class; - case "float": - return float.class; - case "double": - return double.class; - case "boolean[]": - return boolean[].class; - case "byte[]": - return byte[].class; - case "char[]": - return char[].class; - case "short[]": - return short[].class; - case "int[]": - return int[].class; - case "long[]": - return long[].class; - case "float[]": - return float[].class; - case "double[]": - return double[].class; - default: - } - try { - return arrayForName(className); - } catch (ClassNotFoundException e) { - // try to load from java.lang package - if (className.indexOf('.') == -1) { - try { - return arrayForName("java.lang." + className); - } catch (ClassNotFoundException ignore) { - // ignore, let the original exception be thrown - } - } - throw e; - } - } - - private static Class arrayForName(String className) throws ClassNotFoundException { - return Class.forName(className.endsWith("[]") - ? "[L" + className.substring(0, className.length() - 2) + ";" - : className, true, Thread.currentThread().getContextClassLoader()); - } - - public static Class getBoxedClass(Class type) { - if (type == boolean.class) { - return Boolean.class; - } else if (type == char.class) { - return Character.class; - } else if (type == byte.class) { - return Byte.class; - } else if (type == short.class) { - return Short.class; - } else if (type == int.class) { - return Integer.class; - } else if (type == long.class) { - return Long.class; - } else if (type == float.class) { - return Float.class; - } else if (type == double.class) { - return Double.class; - } else { - return type; - } - } - - public static Boolean boxed(boolean v) { - return Boolean.valueOf(v); - } - - public static Character boxed(char v) { - return Character.valueOf(v); - } - - public static Byte boxed(byte v) { - return Byte.valueOf(v); - } - - public static Short boxed(short v) { - return Short.valueOf(v); - } - - public static Integer boxed(int v) { - return Integer.valueOf(v); - } - - public static Long boxed(long v) { - return Long.valueOf(v); - } - - public static Float boxed(float v) { - return Float.valueOf(v); - } - - public static Double boxed(double v) { - return Double.valueOf(v); - } - - public static Object boxed(Object v) { - return v; - } - - public static boolean unboxed(Boolean v) { - return v == null ? false : v.booleanValue(); - } - - public static char unboxed(Character v) { - return v == null ? '\0' : v.charValue(); - } - - public static byte unboxed(Byte v) { - return v == null ? 0 : v.byteValue(); - } - - public static short unboxed(Short v) { - return v == null ? 0 : v.shortValue(); - } - - public static int unboxed(Integer v) { - return v == null ? 0 : v.intValue(); - } - - public static long unboxed(Long v) { - return v == null ? 0 : v.longValue(); - } - - public static float unboxed(Float v) { - return v == null ? 0 : v.floatValue(); - } - - public static double unboxed(Double v) { - return v == null ? 0 : v.doubleValue(); - } - - public static Object unboxed(Object v) { - return v; - } - - public static boolean isNotEmpty(Object object) { - return getSize(object) > 0; - } - - public static int getSize(Object object) { - if (object == null) { - return 0; - } - if (object instanceof Collection) { - return ((Collection) object).size(); - } else if (object instanceof Map) { - return ((Map) object).size(); - } else if (object.getClass().isArray()) { - return Array.getLength(object); - } else { - return -1; - } - } - - public static URI toURI(String name) { - try { - return new URI(name); - } catch (URISyntaxException e) { - throw new RuntimeException(e); - } - } - - public static Class getGenericClass(Class cls) { - return getGenericClass(cls, 0); - } - - public static Class getGenericClass(Class cls, int i) { - try { - ParameterizedType parameterizedType = ((ParameterizedType) cls.getGenericInterfaces()[0]); - Object genericClass = parameterizedType.getActualTypeArguments()[i]; - if (genericClass instanceof ParameterizedType) { - return (Class) ((ParameterizedType) genericClass).getRawType(); - } else if (genericClass instanceof GenericArrayType) { - Type type = ((GenericArrayType) genericClass).getGenericComponentType(); - if (type instanceof TypeVariable) { - return type.getClass(); - } - return (((GenericArrayType) genericClass).getGenericComponentType() instanceof Class) - ? (Class) ((GenericArrayType) genericClass).getGenericComponentType() - : ((GenericArrayType) genericClass).getGenericComponentType().getClass(); - } else if (genericClass != null) { - if (genericClass instanceof TypeVariable) { - return genericClass.getClass(); - } - return (Class) genericClass; - } - } catch (Throwable e) { - - } - if (cls.getSuperclass() != null) { - return getGenericClass(cls.getSuperclass(), i); - } else { - throw new IllegalArgumentException(cls.getName() + " generic type undefined!"); - } - } - - public static boolean isBeforeJava5(String javaVersion) { - return (StringUtils.isEmpty(javaVersion) || "1.0".equals(javaVersion) - || "1.1".equals(javaVersion) || "1.2".equals(javaVersion) - || "1.3".equals(javaVersion) || "1.4".equals(javaVersion)); - } - - public static boolean isBeforeJava6(String javaVersion) { - return isBeforeJava5(javaVersion) || "1.5".equals(javaVersion); - } - - public static String toString(Throwable e) { - StringWriter w = new StringWriter(); - PrintWriter p = new PrintWriter(w); - p.print(e.getClass().getName() + ": "); - if (e.getMessage() != null) { - p.print(e.getMessage() + "\n"); - } - p.println(); - try { - e.printStackTrace(p); - return w.toString(); - } finally { - p.close(); - } - } - - public static void checkBytecode(String name, byte[] bytecode) { - if (bytecode.length > JIT_LIMIT) { - System.err.println("The template bytecode too long, may be affect the JIT compiler. template class: " + name); - } - } - - public static String getSizeMethod(Class cls) { - try { - return cls.getMethod("size", new Class[0]).getName() + "()"; - } catch (NoSuchMethodException e) { - try { - return cls.getMethod("length", new Class[0]).getName() + "()"; - } catch (NoSuchMethodException e2) { - try { - return cls.getMethod("getSize", new Class[0]).getName() + "()"; - } catch (NoSuchMethodException e3) { - try { - return cls.getMethod("getLength", new Class[0]).getName() + "()"; - } catch (NoSuchMethodException e4) { - return null; - } - } - } - } - } - - public static String getMethodName(Method method, Class[] parameterClasses, String rightCode) { - if (method.getParameterTypes().length > parameterClasses.length) { - Class[] types = method.getParameterTypes(); - StringBuilder buf = new StringBuilder(rightCode); - for (int i = parameterClasses.length; i < types.length; i++) { - if (buf.length() > 0) { - buf.append(","); - } - Class type = types[i]; - String def; - if (type == boolean.class) { - def = "false"; - } else if (type == char.class) { - def = "\'\\0\'"; - } else if (type == byte.class - || type == short.class - || type == int.class - || type == long.class - || type == float.class - || type == double.class) { - def = "0"; - } else { - def = "null"; - } - buf.append(def); - } - } - return method.getName() + "(" + rightCode + ")"; - } - - public static Method searchMethod(Class currentClass, String name, Class[] parameterTypes) throws NoSuchMethodException { - if (currentClass == null) { - throw new NoSuchMethodException("class == null"); - } - try { - return currentClass.getMethod(name, parameterTypes); - } catch (NoSuchMethodException e) { - for (Method method : currentClass.getMethods()) { - if (method.getName().equals(name) - && parameterTypes.length == method.getParameterTypes().length - && Modifier.isPublic(method.getModifiers())) { - if (parameterTypes.length > 0) { - Class[] types = method.getParameterTypes(); - boolean match = true; - for (int i = 0; i < parameterTypes.length; i++) { - if (!types[i].isAssignableFrom(parameterTypes[i])) { - match = false; - break; - } - } - if (!match) { - continue; - } - } - return method; - } - } - throw e; - } - } - - public static String getInitCode(Class type) { - if (byte.class.equals(type) - || short.class.equals(type) - || int.class.equals(type) - || long.class.equals(type) - || float.class.equals(type) - || double.class.equals(type)) { - return "0"; - } else if (char.class.equals(type)) { - return "'\\0'"; - } else if (boolean.class.equals(type)) { - return "false"; - } else { - return "null"; - } - } - - public static Map toMap(Map.Entry[] entries) { - Map map = new HashMap(); - if (entries != null && entries.length > 0) { - for (Map.Entry entry : entries) { - map.put(entry.getKey(), entry.getValue()); - } - } - return map; - } - - /** - * get simple class name from qualified class name - */ - public static String getSimpleClassName(String qualifiedName) { - if (null == qualifiedName) { - return null; - } - int i = qualifiedName.lastIndexOf('.'); - return i < 0 ? qualifiedName : qualifiedName.substring(i + 1); - } - -} +/* + * 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.common.compiler.support; + +import org.apache.dubbo.common.utils.StringUtils; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.lang.reflect.Array; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +/** + * ClassUtils. (Tool, Static, ThreadSafe) + */ +public class ClassUtils { + + public static final String CLASS_EXTENSION = ".class"; + + public static final String JAVA_EXTENSION = ".java"; + private static final int JIT_LIMIT = 5 * 1024; + + private ClassUtils() { + } + + public static Object newInstance(String name) { + try { + return forName(name).getDeclaredConstructor().newInstance(); + } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + public static Class forName(String[] packages, String className) { + try { + return classForName(className); + } catch (ClassNotFoundException e) { + if (packages != null && packages.length > 0) { + for (String pkg : packages) { + try { + return classForName(pkg + "." + className); + } catch (ClassNotFoundException ignore) { + } + } + } + throw new IllegalStateException(e.getMessage(), e); + } + } + + public static Class forName(String className) { + try { + return classForName(className); + } catch (ClassNotFoundException e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + public static Class classForName(String className) throws ClassNotFoundException { + switch (className) { + case "boolean": + return boolean.class; + case "byte": + return byte.class; + case "char": + return char.class; + case "short": + return short.class; + case "int": + return int.class; + case "long": + return long.class; + case "float": + return float.class; + case "double": + return double.class; + case "boolean[]": + return boolean[].class; + case "byte[]": + return byte[].class; + case "char[]": + return char[].class; + case "short[]": + return short[].class; + case "int[]": + return int[].class; + case "long[]": + return long[].class; + case "float[]": + return float[].class; + case "double[]": + return double[].class; + default: + } + try { + return arrayForName(className); + } catch (ClassNotFoundException e) { + // try to load from java.lang package + if (className.indexOf('.') == -1) { + try { + return arrayForName("java.lang." + className); + } catch (ClassNotFoundException ignore) { + // ignore, let the original exception be thrown + } + } + throw e; + } + } + + private static Class arrayForName(String className) throws ClassNotFoundException { + return Class.forName(className.endsWith("[]") + ? "[L" + className.substring(0, className.length() - 2) + ";" + : className, true, Thread.currentThread().getContextClassLoader()); + } + + public static Class getBoxedClass(Class type) { + if (type == boolean.class) { + return Boolean.class; + } else if (type == char.class) { + return Character.class; + } else if (type == byte.class) { + return Byte.class; + } else if (type == short.class) { + return Short.class; + } else if (type == int.class) { + return Integer.class; + } else if (type == long.class) { + return Long.class; + } else if (type == float.class) { + return Float.class; + } else if (type == double.class) { + return Double.class; + } else { + return type; + } + } + + public static Boolean boxed(boolean v) { + return Boolean.valueOf(v); + } + + public static Character boxed(char v) { + return Character.valueOf(v); + } + + public static Byte boxed(byte v) { + return Byte.valueOf(v); + } + + public static Short boxed(short v) { + return Short.valueOf(v); + } + + public static Integer boxed(int v) { + return Integer.valueOf(v); + } + + public static Long boxed(long v) { + return Long.valueOf(v); + } + + public static Float boxed(float v) { + return Float.valueOf(v); + } + + public static Double boxed(double v) { + return Double.valueOf(v); + } + + public static Object boxed(Object v) { + return v; + } + + public static boolean unboxed(Boolean v) { + return v == null ? false : v.booleanValue(); + } + + public static char unboxed(Character v) { + return v == null ? '\0' : v.charValue(); + } + + public static byte unboxed(Byte v) { + return v == null ? 0 : v.byteValue(); + } + + public static short unboxed(Short v) { + return v == null ? 0 : v.shortValue(); + } + + public static int unboxed(Integer v) { + return v == null ? 0 : v.intValue(); + } + + public static long unboxed(Long v) { + return v == null ? 0 : v.longValue(); + } + + public static float unboxed(Float v) { + return v == null ? 0 : v.floatValue(); + } + + public static double unboxed(Double v) { + return v == null ? 0 : v.doubleValue(); + } + + public static Object unboxed(Object v) { + return v; + } + + public static boolean isNotEmpty(Object object) { + return getSize(object) > 0; + } + + public static int getSize(Object object) { + if (object == null) { + return 0; + } + if (object instanceof Collection) { + return ((Collection) object).size(); + } else if (object instanceof Map) { + return ((Map) object).size(); + } else if (object.getClass().isArray()) { + return Array.getLength(object); + } else { + return -1; + } + } + + public static URI toURI(String name) { + try { + return new URI(name); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } + + public static Class getGenericClass(Class cls) { + return getGenericClass(cls, 0); + } + + public static Class getGenericClass(Class cls, int i) { + try { + ParameterizedType parameterizedType = ((ParameterizedType) cls.getGenericInterfaces()[0]); + Object genericClass = parameterizedType.getActualTypeArguments()[i]; + if (genericClass instanceof ParameterizedType) { + return (Class) ((ParameterizedType) genericClass).getRawType(); + } else if (genericClass instanceof GenericArrayType) { + Type type = ((GenericArrayType) genericClass).getGenericComponentType(); + if (type instanceof TypeVariable) { + return type.getClass(); + } + return (((GenericArrayType) genericClass).getGenericComponentType() instanceof Class) + ? (Class) ((GenericArrayType) genericClass).getGenericComponentType() + : ((GenericArrayType) genericClass).getGenericComponentType().getClass(); + } else if (genericClass != null) { + if (genericClass instanceof TypeVariable) { + return genericClass.getClass(); + } + return (Class) genericClass; + } + } catch (Throwable e) { + + } + if (cls.getSuperclass() != null) { + return getGenericClass(cls.getSuperclass(), i); + } else { + throw new IllegalArgumentException(cls.getName() + " generic type undefined!"); + } + } + + public static boolean isBeforeJava5(String javaVersion) { + return (StringUtils.isEmpty(javaVersion) || "1.0".equals(javaVersion) + || "1.1".equals(javaVersion) || "1.2".equals(javaVersion) + || "1.3".equals(javaVersion) || "1.4".equals(javaVersion)); + } + + public static boolean isBeforeJava6(String javaVersion) { + return isBeforeJava5(javaVersion) || "1.5".equals(javaVersion); + } + + public static String toString(Throwable e) { + StringWriter w = new StringWriter(); + PrintWriter p = new PrintWriter(w); + p.print(e.getClass().getName() + ": "); + if (e.getMessage() != null) { + p.print(e.getMessage() + "\n"); + } + p.println(); + try { + e.printStackTrace(p); + return w.toString(); + } finally { + p.close(); + } + } + + public static void checkBytecode(String name, byte[] bytecode) { + if (bytecode.length > JIT_LIMIT) { + System.err.println("The template bytecode too long, may be affect the JIT compiler. template class: " + name); + } + } + + public static String getSizeMethod(Class cls) { + try { + return cls.getMethod("size", new Class[0]).getName() + "()"; + } catch (NoSuchMethodException e) { + try { + return cls.getMethod("length", new Class[0]).getName() + "()"; + } catch (NoSuchMethodException e2) { + try { + return cls.getMethod("getSize", new Class[0]).getName() + "()"; + } catch (NoSuchMethodException e3) { + try { + return cls.getMethod("getLength", new Class[0]).getName() + "()"; + } catch (NoSuchMethodException e4) { + return null; + } + } + } + } + } + + public static String getMethodName(Method method, Class[] parameterClasses, String rightCode) { + if (method.getParameterTypes().length > parameterClasses.length) { + Class[] types = method.getParameterTypes(); + StringBuilder buf = new StringBuilder(rightCode); + for (int i = parameterClasses.length; i < types.length; i++) { + if (buf.length() > 0) { + buf.append(","); + } + Class type = types[i]; + String def; + if (type == boolean.class) { + def = "false"; + } else if (type == char.class) { + def = "\'\\0\'"; + } else if (type == byte.class + || type == short.class + || type == int.class + || type == long.class + || type == float.class + || type == double.class) { + def = "0"; + } else { + def = "null"; + } + buf.append(def); + } + } + return method.getName() + "(" + rightCode + ")"; + } + + public static Method searchMethod(Class currentClass, String name, Class[] parameterTypes) throws NoSuchMethodException { + if (currentClass == null) { + throw new NoSuchMethodException("class == null"); + } + try { + return currentClass.getMethod(name, parameterTypes); + } catch (NoSuchMethodException e) { + for (Method method : currentClass.getMethods()) { + if (method.getName().equals(name) + && parameterTypes.length == method.getParameterTypes().length + && Modifier.isPublic(method.getModifiers())) { + if (parameterTypes.length > 0) { + Class[] types = method.getParameterTypes(); + boolean match = true; + for (int i = 0; i < parameterTypes.length; i++) { + if (!types[i].isAssignableFrom(parameterTypes[i])) { + match = false; + break; + } + } + if (!match) { + continue; + } + } + return method; + } + } + throw e; + } + } + + public static String getInitCode(Class type) { + if (byte.class.equals(type) + || short.class.equals(type) + || int.class.equals(type) + || long.class.equals(type) + || float.class.equals(type) + || double.class.equals(type)) { + return "0"; + } else if (char.class.equals(type)) { + return "'\\0'"; + } else if (boolean.class.equals(type)) { + return "false"; + } else { + return "null"; + } + } + + public static Map toMap(Map.Entry[] entries) { + Map map = new HashMap(); + if (entries != null && entries.length > 0) { + for (Map.Entry entry : entries) { + map.put(entry.getKey(), entry.getValue()); + } + } + return map; + } + + /** + * get simple class name from qualified class name + */ + public static String getSimpleClassName(String qualifiedName) { + if (null == qualifiedName) { + return null; + } + int i = qualifiedName.lastIndexOf('.'); + return i < 0 ? qualifiedName : qualifiedName.substring(i + 1); + } + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/CtClassBuilder.java b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/CtClassBuilder.java index 7e01df30be..e28386ac15 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/CtClassBuilder.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/CtClassBuilder.java @@ -1,174 +1,174 @@ -/* - * 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.common.compiler.support; - -import javassist.CannotCompileException; -import javassist.ClassPool; -import javassist.CtClass; -import javassist.CtField; -import javassist.CtNewConstructor; -import javassist.CtNewMethod; -import javassist.LoaderClassPath; -import javassist.NotFoundException; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * CtClassBuilder is builder for CtClass - *

- * contains all the information, including: - *

- * class name, imported packages, super class name, implemented interfaces, constructors, fields, methods. - */ -public class CtClassBuilder { - - private String className; - - private String superClassName = "java.lang.Object"; - - private final List imports = new ArrayList<>(); - - private final Map fullNames = new HashMap<>(); - - private final List ifaces = new ArrayList<>(); - - private final List constructors = new ArrayList<>(); - - private final List fields = new ArrayList<>(); - - private final List methods = new ArrayList<>(); - - public String getClassName() { - return className; - } - - public void setClassName(String className) { - this.className = className; - } - - public String getSuperClassName() { - return superClassName; - } - - public void setSuperClassName(String superClassName) { - this.superClassName = getQualifiedClassName(superClassName); - } - - public List getImports() { - return imports; - } - - public void addImports(String pkg) { - int pi = pkg.lastIndexOf('.'); - if (pi > 0) { - String pkgName = pkg.substring(0, pi); - this.imports.add(pkgName); - if (!pkg.endsWith(".*")) { - fullNames.put(pkg.substring(pi + 1), pkg); - } - } - } - - public List getInterfaces() { - return ifaces; - } - - public void addInterface(String iface) { - this.ifaces.add(getQualifiedClassName(iface)); - } - - public List getConstructors() { - return constructors; - } - - public void addConstructor(String constructor) { - this.constructors.add(constructor); - } - - public List getFields() { - return fields; - } - - public void addField(String field) { - this.fields.add(field); - } - - public List getMethods() { - return methods; - } - - public void addMethod(String method) { - this.methods.add(method); - } - - /** - * get full qualified class name - * - * @param className super class name, maybe qualified or not - */ - protected String getQualifiedClassName(String className) { - if (className.contains(".")) { - return className; - } - - if (fullNames.containsKey(className)) { - return fullNames.get(className); - } - - return ClassUtils.forName(imports.toArray(new String[0]), className).getName(); - } - - /** - * build CtClass object - */ - public CtClass build(ClassLoader classLoader) throws NotFoundException, CannotCompileException { - ClassPool pool = new ClassPool(true); - pool.appendClassPath(new LoaderClassPath(classLoader)); - - // create class - CtClass ctClass = pool.makeClass(className, pool.get(superClassName)); - - // add imported packages - imports.forEach(pool::importPackage); - - // add implemented interfaces - for (String iface : ifaces) { - ctClass.addInterface(pool.get(iface)); - } - - // add constructors - for (String constructor : constructors) { - ctClass.addConstructor(CtNewConstructor.make(constructor, ctClass)); - } - - // add fields - for (String field : fields) { - ctClass.addField(CtField.make(field, ctClass)); - } - - // add methods - for (String method : methods) { - ctClass.addMethod(CtNewMethod.make(method, ctClass)); - } - - return ctClass; - } - -} +/* + * 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.common.compiler.support; + +import javassist.CannotCompileException; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.CtField; +import javassist.CtNewConstructor; +import javassist.CtNewMethod; +import javassist.LoaderClassPath; +import javassist.NotFoundException; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * CtClassBuilder is builder for CtClass + *

+ * contains all the information, including: + *

+ * class name, imported packages, super class name, implemented interfaces, constructors, fields, methods. + */ +public class CtClassBuilder { + + private String className; + + private String superClassName = "java.lang.Object"; + + private final List imports = new ArrayList<>(); + + private final Map fullNames = new HashMap<>(); + + private final List ifaces = new ArrayList<>(); + + private final List constructors = new ArrayList<>(); + + private final List fields = new ArrayList<>(); + + private final List methods = new ArrayList<>(); + + public String getClassName() { + return className; + } + + public void setClassName(String className) { + this.className = className; + } + + public String getSuperClassName() { + return superClassName; + } + + public void setSuperClassName(String superClassName) { + this.superClassName = getQualifiedClassName(superClassName); + } + + public List getImports() { + return imports; + } + + public void addImports(String pkg) { + int pi = pkg.lastIndexOf('.'); + if (pi > 0) { + String pkgName = pkg.substring(0, pi); + this.imports.add(pkgName); + if (!pkg.endsWith(".*")) { + fullNames.put(pkg.substring(pi + 1), pkg); + } + } + } + + public List getInterfaces() { + return ifaces; + } + + public void addInterface(String iface) { + this.ifaces.add(getQualifiedClassName(iface)); + } + + public List getConstructors() { + return constructors; + } + + public void addConstructor(String constructor) { + this.constructors.add(constructor); + } + + public List getFields() { + return fields; + } + + public void addField(String field) { + this.fields.add(field); + } + + public List getMethods() { + return methods; + } + + public void addMethod(String method) { + this.methods.add(method); + } + + /** + * get full qualified class name + * + * @param className super class name, maybe qualified or not + */ + protected String getQualifiedClassName(String className) { + if (className.contains(".")) { + return className; + } + + if (fullNames.containsKey(className)) { + return fullNames.get(className); + } + + return ClassUtils.forName(imports.toArray(new String[0]), className).getName(); + } + + /** + * build CtClass object + */ + public CtClass build(ClassLoader classLoader) throws NotFoundException, CannotCompileException { + ClassPool pool = new ClassPool(true); + pool.appendClassPath(new LoaderClassPath(classLoader)); + + // create class + CtClass ctClass = pool.makeClass(className, pool.get(superClassName)); + + // add imported packages + imports.forEach(pool::importPackage); + + // add implemented interfaces + for (String iface : ifaces) { + ctClass.addInterface(pool.get(iface)); + } + + // add constructors + for (String constructor : constructors) { + ctClass.addConstructor(CtNewConstructor.make(constructor, ctClass)); + } + + // add fields + for (String field : fields) { + ctClass.addField(CtField.make(field, ctClass)); + } + + // add methods + for (String method : methods) { + ctClass.addMethod(CtNewMethod.make(method, ctClass)); + } + + return ctClass; + } + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JavassistCompiler.java b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JavassistCompiler.java index 3a058849d8..a15d51701f 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JavassistCompiler.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JavassistCompiler.java @@ -1,85 +1,85 @@ -/* - * 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.common.compiler.support; - - -import javassist.CtClass; - -import java.util.Arrays; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * JavassistCompiler. (SPI, Singleton, ThreadSafe) - */ -public class JavassistCompiler extends AbstractCompiler { - - private static final Pattern IMPORT_PATTERN = Pattern.compile("import\\s+([\\w\\.\\*]+);\n"); - - private static final Pattern EXTENDS_PATTERN = Pattern.compile("\\s+extends\\s+([\\w\\.]+)[^\\{]*\\{\n"); - - private static final Pattern IMPLEMENTS_PATTERN = Pattern.compile("\\s+implements\\s+([\\w\\.]+)\\s*\\{\n"); - - private static final Pattern METHODS_PATTERN = Pattern.compile("\n(private|public|protected)\\s+"); - - private static final Pattern FIELD_PATTERN = Pattern.compile("[^\n]+=[^\n]+;"); - - @Override - public Class doCompile(String name, String source) throws Throwable { - CtClassBuilder builder = new CtClassBuilder(); - builder.setClassName(name); - - // process imported classes - Matcher matcher = IMPORT_PATTERN.matcher(source); - while (matcher.find()) { - builder.addImports(matcher.group(1).trim()); - } - - // process extended super class - matcher = EXTENDS_PATTERN.matcher(source); - if (matcher.find()) { - builder.setSuperClassName(matcher.group(1).trim()); - } - - // process implemented interfaces - matcher = IMPLEMENTS_PATTERN.matcher(source); - if (matcher.find()) { - String[] ifaces = matcher.group(1).trim().split("\\,"); - Arrays.stream(ifaces).forEach(i -> builder.addInterface(i.trim())); - } - - // process constructors, fields, methods - String body = source.substring(source.indexOf('{') + 1, source.length() - 1); - String[] methods = METHODS_PATTERN.split(body); - String className = ClassUtils.getSimpleClassName(name); - Arrays.stream(methods).map(String::trim).filter(m -> !m.isEmpty()).forEach(method -> { - if (method.startsWith(className)) { - builder.addConstructor("public " + method); - } else if (FIELD_PATTERN.matcher(method).matches()) { - builder.addField("private " + method); - } else { - builder.addMethod("public " + method); - } - }); - - // compile - ClassLoader classLoader = org.apache.dubbo.common.utils.ClassUtils.getCallerClassLoader(getClass()); - CtClass cls = builder.build(classLoader); - return cls.toClass(classLoader, JavassistCompiler.class.getProtectionDomain()); - } - -} +/* + * 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.common.compiler.support; + + +import javassist.CtClass; + +import java.util.Arrays; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * JavassistCompiler. (SPI, Singleton, ThreadSafe) + */ +public class JavassistCompiler extends AbstractCompiler { + + private static final Pattern IMPORT_PATTERN = Pattern.compile("import\\s+([\\w\\.\\*]+);\n"); + + private static final Pattern EXTENDS_PATTERN = Pattern.compile("\\s+extends\\s+([\\w\\.]+)[^\\{]*\\{\n"); + + private static final Pattern IMPLEMENTS_PATTERN = Pattern.compile("\\s+implements\\s+([\\w\\.]+)\\s*\\{\n"); + + private static final Pattern METHODS_PATTERN = Pattern.compile("\n(private|public|protected)\\s+"); + + private static final Pattern FIELD_PATTERN = Pattern.compile("[^\n]+=[^\n]+;"); + + @Override + public Class doCompile(String name, String source) throws Throwable { + CtClassBuilder builder = new CtClassBuilder(); + builder.setClassName(name); + + // process imported classes + Matcher matcher = IMPORT_PATTERN.matcher(source); + while (matcher.find()) { + builder.addImports(matcher.group(1).trim()); + } + + // process extended super class + matcher = EXTENDS_PATTERN.matcher(source); + if (matcher.find()) { + builder.setSuperClassName(matcher.group(1).trim()); + } + + // process implemented interfaces + matcher = IMPLEMENTS_PATTERN.matcher(source); + if (matcher.find()) { + String[] ifaces = matcher.group(1).trim().split("\\,"); + Arrays.stream(ifaces).forEach(i -> builder.addInterface(i.trim())); + } + + // process constructors, fields, methods + String body = source.substring(source.indexOf('{') + 1, source.length() - 1); + String[] methods = METHODS_PATTERN.split(body); + String className = ClassUtils.getSimpleClassName(name); + Arrays.stream(methods).map(String::trim).filter(m -> !m.isEmpty()).forEach(method -> { + if (method.startsWith(className)) { + builder.addConstructor("public " + method); + } else if (FIELD_PATTERN.matcher(method).matches()) { + builder.addField("private " + method); + } else { + builder.addMethod("public " + method); + } + }); + + // compile + ClassLoader classLoader = org.apache.dubbo.common.utils.ClassUtils.getCallerClassLoader(getClass()); + CtClass cls = builder.build(classLoader); + return cls.toClass(classLoader, JavassistCompiler.class.getProtectionDomain()); + } + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JdkCompiler.java b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JdkCompiler.java index c82e48dd4c..8d270196df 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JdkCompiler.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JdkCompiler.java @@ -1,302 +1,302 @@ -/* - * 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.common.compiler.support; - - -import javax.tools.DiagnosticCollector; -import javax.tools.FileObject; -import javax.tools.ForwardingJavaFileManager; -import javax.tools.JavaCompiler; -import javax.tools.JavaFileManager; -import javax.tools.JavaFileObject; -import javax.tools.JavaFileObject.Kind; -import javax.tools.SimpleJavaFileObject; -import javax.tools.StandardJavaFileManager; -import javax.tools.StandardLocation; -import javax.tools.ToolProvider; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.URI; -import java.net.URL; -import java.net.URLClassLoader; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * JdkCompiler. (SPI, Singleton, ThreadSafe) - */ -public class JdkCompiler extends AbstractCompiler { - - private final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); - - private final DiagnosticCollector diagnosticCollector = new DiagnosticCollector(); - - private final ClassLoaderImpl classLoader; - - private final JavaFileManagerImpl javaFileManager; - - private final List options; - - private static final String DEFAULT_JAVA_VERSION = "1.8"; - - private static List buildDefaultOptions(String javaVersion) { - return Arrays.asList( - "-source", javaVersion, "-target", javaVersion - ); - } - - private static List buildDefaultOptions() { - return buildDefaultOptions(DEFAULT_JAVA_VERSION); - } - - public JdkCompiler(List options) { - this.options = new ArrayList<>(options); - StandardJavaFileManager manager = compiler.getStandardFileManager(diagnosticCollector, null, null); - final ClassLoader loader = Thread.currentThread().getContextClassLoader(); - if (loader instanceof URLClassLoader - && (!"sun.misc.Launcher$AppClassLoader".equals(loader.getClass().getName()))) { - try { - URLClassLoader urlClassLoader = (URLClassLoader) loader; - List files = new ArrayList(); - for (URL url : urlClassLoader.getURLs()) { - files.add(new File(url.getFile())); - } - manager.setLocation(StandardLocation.CLASS_PATH, files); - } catch (IOException e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - classLoader = AccessController.doPrivileged(new PrivilegedAction() { - @Override - public ClassLoaderImpl run() { - return new ClassLoaderImpl(loader); - } - }); - javaFileManager = new JavaFileManagerImpl(manager, classLoader); - } - - public JdkCompiler() { - this(buildDefaultOptions()); - } - - public JdkCompiler(String javaVersion) { - this(buildDefaultOptions(javaVersion)); - } - - @Override - public Class doCompile(String name, String sourceCode) throws Throwable { - int i = name.lastIndexOf('.'); - String packageName = i < 0 ? "" : name.substring(0, i); - String className = i < 0 ? name : name.substring(i + 1); - JavaFileObjectImpl javaFileObject = new JavaFileObjectImpl(className, sourceCode); - javaFileManager.putFileForInput(StandardLocation.SOURCE_PATH, packageName, - className + ClassUtils.JAVA_EXTENSION, javaFileObject); - Boolean result = compiler.getTask(null, javaFileManager, diagnosticCollector, options, - null, Collections.singletonList(javaFileObject)).call(); - if (result == null || !result) { - throw new IllegalStateException("Compilation failed. class: " + name + ", diagnostics: " + diagnosticCollector); - } - return classLoader.loadClass(name); - } - - private static final class JavaFileObjectImpl extends SimpleJavaFileObject { - - private final CharSequence source; - private ByteArrayOutputStream bytecode; - - public JavaFileObjectImpl(final String baseName, final CharSequence source) { - super(ClassUtils.toURI(baseName + ClassUtils.JAVA_EXTENSION), Kind.SOURCE); - this.source = source; - } - - JavaFileObjectImpl(final String name, final Kind kind) { - super(ClassUtils.toURI(name), kind); - source = null; - } - - public JavaFileObjectImpl(URI uri, Kind kind) { - super(uri, kind); - source = null; - } - - @Override - public CharSequence getCharContent(final boolean ignoreEncodingErrors) throws UnsupportedOperationException { - if (source == null) { - throw new UnsupportedOperationException("source == null"); - } - return source; - } - - @Override - public InputStream openInputStream() { - return new ByteArrayInputStream(getByteCode()); - } - - @Override - public OutputStream openOutputStream() { - return bytecode = new ByteArrayOutputStream(); - } - - public byte[] getByteCode() { - return bytecode.toByteArray(); - } - } - - private static final class JavaFileManagerImpl extends ForwardingJavaFileManager { - - private final ClassLoaderImpl classLoader; - - private final Map fileObjects = new HashMap(); - - public JavaFileManagerImpl(JavaFileManager fileManager, ClassLoaderImpl classLoader) { - super(fileManager); - this.classLoader = classLoader; - } - - @Override - public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException { - FileObject o = fileObjects.get(uri(location, packageName, relativeName)); - if (o != null) { - return o; - } - return super.getFileForInput(location, packageName, relativeName); - } - - public void putFileForInput(StandardLocation location, String packageName, String relativeName, JavaFileObject file) { - fileObjects.put(uri(location, packageName, relativeName), file); - } - - private URI uri(Location location, String packageName, String relativeName) { - return ClassUtils.toURI(location.getName() + '/' + packageName + '/' + relativeName); - } - - @Override - public JavaFileObject getJavaFileForOutput(Location location, String qualifiedName, Kind kind, FileObject outputFile) - throws IOException { - JavaFileObject file = new JavaFileObjectImpl(qualifiedName, kind); - classLoader.add(qualifiedName, file); - return file; - } - - @Override - public ClassLoader getClassLoader(JavaFileManager.Location location) { - return classLoader; - } - - @Override - public String inferBinaryName(Location loc, JavaFileObject file) { - if (file instanceof JavaFileObjectImpl) { - return file.getName(); - } - return super.inferBinaryName(loc, file); - } - - @Override - public Iterable list(Location location, String packageName, Set kinds, boolean recurse) - throws IOException { - Iterable result = super.list(location, packageName, kinds, recurse); - - ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); - - ArrayList files = new ArrayList(); - - if (location == StandardLocation.CLASS_PATH && kinds.contains(JavaFileObject.Kind.CLASS)) { - for (JavaFileObject file : fileObjects.values()) { - if (file.getKind() == Kind.CLASS && file.getName().startsWith(packageName)) { - files.add(file); - } - } - - files.addAll(classLoader.files()); - } else if (location == StandardLocation.SOURCE_PATH && kinds.contains(JavaFileObject.Kind.SOURCE)) { - for (JavaFileObject file : fileObjects.values()) { - if (file.getKind() == Kind.SOURCE && file.getName().startsWith(packageName)) { - files.add(file); - } - } - } - - for (JavaFileObject file : result) { - files.add(file); - } - - return files; - } - } - - private static final class ClassLoaderImpl extends ClassLoader { - - private final Map classes = new HashMap(); - - ClassLoaderImpl(final ClassLoader parentClassLoader) { - super(parentClassLoader); - } - - Collection files() { - return Collections.unmodifiableCollection(classes.values()); - } - - @Override - protected Class findClass(final String qualifiedClassName) throws ClassNotFoundException { - JavaFileObject file = classes.get(qualifiedClassName); - if (file != null) { - byte[] bytes = ((JavaFileObjectImpl) file).getByteCode(); - return defineClass(qualifiedClassName, bytes, 0, bytes.length); - } - try { - return org.apache.dubbo.common.utils.ClassUtils.forNameWithCallerClassLoader(qualifiedClassName, getClass()); - } catch (ClassNotFoundException nf) { - return super.findClass(qualifiedClassName); - } - } - - void add(final String qualifiedClassName, final JavaFileObject javaFile) { - classes.put(qualifiedClassName, javaFile); - } - - @Override - protected synchronized Class loadClass(final String name, final boolean resolve) throws ClassNotFoundException { - return super.loadClass(name, resolve); - } - - @Override - public InputStream getResourceAsStream(final String name) { - if (name.endsWith(ClassUtils.CLASS_EXTENSION)) { - String qualifiedClassName = name.substring(0, name.length() - ClassUtils.CLASS_EXTENSION.length()).replace('/', '.'); - JavaFileObjectImpl file = (JavaFileObjectImpl) classes.get(qualifiedClassName); - if (file != null) { - return new ByteArrayInputStream(file.getByteCode()); - } - } - return super.getResourceAsStream(name); - } - } - - -} +/* + * 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.common.compiler.support; + + +import javax.tools.DiagnosticCollector; +import javax.tools.FileObject; +import javax.tools.ForwardingJavaFileManager; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileObject; +import javax.tools.JavaFileObject.Kind; +import javax.tools.SimpleJavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.StandardLocation; +import javax.tools.ToolProvider; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URI; +import java.net.URL; +import java.net.URLClassLoader; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * JdkCompiler. (SPI, Singleton, ThreadSafe) + */ +public class JdkCompiler extends AbstractCompiler { + + private final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + + private final DiagnosticCollector diagnosticCollector = new DiagnosticCollector(); + + private final ClassLoaderImpl classLoader; + + private final JavaFileManagerImpl javaFileManager; + + private final List options; + + private static final String DEFAULT_JAVA_VERSION = "1.8"; + + private static List buildDefaultOptions(String javaVersion) { + return Arrays.asList( + "-source", javaVersion, "-target", javaVersion + ); + } + + private static List buildDefaultOptions() { + return buildDefaultOptions(DEFAULT_JAVA_VERSION); + } + + public JdkCompiler(List options) { + this.options = new ArrayList<>(options); + StandardJavaFileManager manager = compiler.getStandardFileManager(diagnosticCollector, null, null); + final ClassLoader loader = Thread.currentThread().getContextClassLoader(); + if (loader instanceof URLClassLoader + && (!"sun.misc.Launcher$AppClassLoader".equals(loader.getClass().getName()))) { + try { + URLClassLoader urlClassLoader = (URLClassLoader) loader; + List files = new ArrayList(); + for (URL url : urlClassLoader.getURLs()) { + files.add(new File(url.getFile())); + } + manager.setLocation(StandardLocation.CLASS_PATH, files); + } catch (IOException e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + classLoader = AccessController.doPrivileged(new PrivilegedAction() { + @Override + public ClassLoaderImpl run() { + return new ClassLoaderImpl(loader); + } + }); + javaFileManager = new JavaFileManagerImpl(manager, classLoader); + } + + public JdkCompiler() { + this(buildDefaultOptions()); + } + + public JdkCompiler(String javaVersion) { + this(buildDefaultOptions(javaVersion)); + } + + @Override + public Class doCompile(String name, String sourceCode) throws Throwable { + int i = name.lastIndexOf('.'); + String packageName = i < 0 ? "" : name.substring(0, i); + String className = i < 0 ? name : name.substring(i + 1); + JavaFileObjectImpl javaFileObject = new JavaFileObjectImpl(className, sourceCode); + javaFileManager.putFileForInput(StandardLocation.SOURCE_PATH, packageName, + className + ClassUtils.JAVA_EXTENSION, javaFileObject); + Boolean result = compiler.getTask(null, javaFileManager, diagnosticCollector, options, + null, Collections.singletonList(javaFileObject)).call(); + if (result == null || !result) { + throw new IllegalStateException("Compilation failed. class: " + name + ", diagnostics: " + diagnosticCollector); + } + return classLoader.loadClass(name); + } + + private static final class JavaFileObjectImpl extends SimpleJavaFileObject { + + private final CharSequence source; + private ByteArrayOutputStream bytecode; + + public JavaFileObjectImpl(final String baseName, final CharSequence source) { + super(ClassUtils.toURI(baseName + ClassUtils.JAVA_EXTENSION), Kind.SOURCE); + this.source = source; + } + + JavaFileObjectImpl(final String name, final Kind kind) { + super(ClassUtils.toURI(name), kind); + source = null; + } + + public JavaFileObjectImpl(URI uri, Kind kind) { + super(uri, kind); + source = null; + } + + @Override + public CharSequence getCharContent(final boolean ignoreEncodingErrors) throws UnsupportedOperationException { + if (source == null) { + throw new UnsupportedOperationException("source == null"); + } + return source; + } + + @Override + public InputStream openInputStream() { + return new ByteArrayInputStream(getByteCode()); + } + + @Override + public OutputStream openOutputStream() { + return bytecode = new ByteArrayOutputStream(); + } + + public byte[] getByteCode() { + return bytecode.toByteArray(); + } + } + + private static final class JavaFileManagerImpl extends ForwardingJavaFileManager { + + private final ClassLoaderImpl classLoader; + + private final Map fileObjects = new HashMap(); + + public JavaFileManagerImpl(JavaFileManager fileManager, ClassLoaderImpl classLoader) { + super(fileManager); + this.classLoader = classLoader; + } + + @Override + public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException { + FileObject o = fileObjects.get(uri(location, packageName, relativeName)); + if (o != null) { + return o; + } + return super.getFileForInput(location, packageName, relativeName); + } + + public void putFileForInput(StandardLocation location, String packageName, String relativeName, JavaFileObject file) { + fileObjects.put(uri(location, packageName, relativeName), file); + } + + private URI uri(Location location, String packageName, String relativeName) { + return ClassUtils.toURI(location.getName() + '/' + packageName + '/' + relativeName); + } + + @Override + public JavaFileObject getJavaFileForOutput(Location location, String qualifiedName, Kind kind, FileObject outputFile) + throws IOException { + JavaFileObject file = new JavaFileObjectImpl(qualifiedName, kind); + classLoader.add(qualifiedName, file); + return file; + } + + @Override + public ClassLoader getClassLoader(JavaFileManager.Location location) { + return classLoader; + } + + @Override + public String inferBinaryName(Location loc, JavaFileObject file) { + if (file instanceof JavaFileObjectImpl) { + return file.getName(); + } + return super.inferBinaryName(loc, file); + } + + @Override + public Iterable list(Location location, String packageName, Set kinds, boolean recurse) + throws IOException { + Iterable result = super.list(location, packageName, kinds, recurse); + + ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); + + ArrayList files = new ArrayList(); + + if (location == StandardLocation.CLASS_PATH && kinds.contains(JavaFileObject.Kind.CLASS)) { + for (JavaFileObject file : fileObjects.values()) { + if (file.getKind() == Kind.CLASS && file.getName().startsWith(packageName)) { + files.add(file); + } + } + + files.addAll(classLoader.files()); + } else if (location == StandardLocation.SOURCE_PATH && kinds.contains(JavaFileObject.Kind.SOURCE)) { + for (JavaFileObject file : fileObjects.values()) { + if (file.getKind() == Kind.SOURCE && file.getName().startsWith(packageName)) { + files.add(file); + } + } + } + + for (JavaFileObject file : result) { + files.add(file); + } + + return files; + } + } + + private static final class ClassLoaderImpl extends ClassLoader { + + private final Map classes = new HashMap(); + + ClassLoaderImpl(final ClassLoader parentClassLoader) { + super(parentClassLoader); + } + + Collection files() { + return Collections.unmodifiableCollection(classes.values()); + } + + @Override + protected Class findClass(final String qualifiedClassName) throws ClassNotFoundException { + JavaFileObject file = classes.get(qualifiedClassName); + if (file != null) { + byte[] bytes = ((JavaFileObjectImpl) file).getByteCode(); + return defineClass(qualifiedClassName, bytes, 0, bytes.length); + } + try { + return org.apache.dubbo.common.utils.ClassUtils.forNameWithCallerClassLoader(qualifiedClassName, getClass()); + } catch (ClassNotFoundException nf) { + return super.findClass(qualifiedClassName); + } + } + + void add(final String qualifiedClassName, final JavaFileObject javaFile) { + classes.put(qualifiedClassName, javaFile); + } + + @Override + protected synchronized Class loadClass(final String name, final boolean resolve) throws ClassNotFoundException { + return super.loadClass(name, resolve); + } + + @Override + public InputStream getResourceAsStream(final String name) { + if (name.endsWith(ClassUtils.CLASS_EXTENSION)) { + String qualifiedClassName = name.substring(0, name.length() - ClassUtils.CLASS_EXTENSION.length()).replace('/', '.'); + JavaFileObjectImpl file = (JavaFileObjectImpl) classes.get(qualifiedClassName); + if (file != null) { + return new ByteArrayInputStream(file.getByteCode()); + } + } + return super.getResourceAsStream(name); + } + } + + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java index 0c9178f359..a41d711b07 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java @@ -604,4 +604,4 @@ public class FileSystemDynamicConfiguration extends TreePathDynamicConfiguration new SynchronousQueue(), new NamedThreadFactory("dubbo-config-center-watch-events-loop", true)); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/Activate.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/Activate.java index 779350049a..5e1585b552 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/Activate.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/Activate.java @@ -1,94 +1,94 @@ -/* - * 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.common.extension; - -import org.apache.dubbo.common.URL; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Activate. This annotation is useful for automatically activate certain extensions with the given criteria, - * for examples: @Activate can be used to load certain Filter extension when there are - * multiple implementations. - *

    - *
  1. {@link Activate#group()} specifies group criteria. Framework SPI defines the valid group values. - *
  2. {@link Activate#value()} specifies parameter key in {@link URL} criteria. - *
- * SPI provider can call {@link ExtensionLoader#getActivateExtension(URL, String, String)} to find out all activated - * extensions with the given criteria. - * - * @see SPI - * @see URL - * @see ExtensionLoader - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE, ElementType.METHOD}) -public @interface Activate { - /** - * Activate the current extension when one of the groups matches. The group passed into - * {@link ExtensionLoader#getActivateExtension(URL, String, String)} will be used for matching. - * - * @return group names to match - * @see ExtensionLoader#getActivateExtension(URL, String, String) - */ - String[] group() default {}; - - /** - * Activate the current extension when the specified keys appear in the URL's parameters. - *

- * For example, given @Activate("cache, validation"), the current extension will be return only when - * there's either cache or validation key appeared in the URL's parameters. - *

- * - * @return URL parameter keys - * @see ExtensionLoader#getActivateExtension(URL, String) - * @see ExtensionLoader#getActivateExtension(URL, String, String) - */ - String[] value() default {}; - - /** - * Relative ordering info, optional - * Deprecated since 2.7.0 - * - * @return extension list which should be put before the current one - */ - @Deprecated - String[] before() default {}; - - /** - * Relative ordering info, optional - * Deprecated since 2.7.0 - * - * @return extension list which should be put after the current one - */ - @Deprecated - String[] after() default {}; - - /** - * Absolute ordering info, optional - * - * Ascending order, smaller values will be in the front o the list. - * - * @return absolute ordering info - */ - int order() default 0; -} \ No newline at end of file +/* + * 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.common.extension; + +import org.apache.dubbo.common.URL; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Activate. This annotation is useful for automatically activate certain extensions with the given criteria, + * for examples: @Activate can be used to load certain Filter extension when there are + * multiple implementations. + *
    + *
  1. {@link Activate#group()} specifies group criteria. Framework SPI defines the valid group values. + *
  2. {@link Activate#value()} specifies parameter key in {@link URL} criteria. + *
+ * SPI provider can call {@link ExtensionLoader#getActivateExtension(URL, String, String)} to find out all activated + * extensions with the given criteria. + * + * @see SPI + * @see URL + * @see ExtensionLoader + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE, ElementType.METHOD}) +public @interface Activate { + /** + * Activate the current extension when one of the groups matches. The group passed into + * {@link ExtensionLoader#getActivateExtension(URL, String, String)} will be used for matching. + * + * @return group names to match + * @see ExtensionLoader#getActivateExtension(URL, String, String) + */ + String[] group() default {}; + + /** + * Activate the current extension when the specified keys appear in the URL's parameters. + *

+ * For example, given @Activate("cache, validation"), the current extension will be return only when + * there's either cache or validation key appeared in the URL's parameters. + *

+ * + * @return URL parameter keys + * @see ExtensionLoader#getActivateExtension(URL, String) + * @see ExtensionLoader#getActivateExtension(URL, String, String) + */ + String[] value() default {}; + + /** + * Relative ordering info, optional + * Deprecated since 2.7.0 + * + * @return extension list which should be put before the current one + */ + @Deprecated + String[] before() default {}; + + /** + * Relative ordering info, optional + * Deprecated since 2.7.0 + * + * @return extension list which should be put after the current one + */ + @Deprecated + String[] after() default {}; + + /** + * Absolute ordering info, optional + * + * Ascending order, smaller values will be in the front o the list. + * + * @return absolute ordering info + */ + int order() default 0; +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/Adaptive.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/Adaptive.java index 0a9a0236fd..b209a2f93c 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/Adaptive.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/Adaptive.java @@ -57,4 +57,4 @@ public @interface Adaptive { */ String[] value() default {}; -} \ No newline at end of file +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionFactory.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionFactory.java index 35cee53399..32bb8465d9 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionFactory.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionFactory.java @@ -1,34 +1,34 @@ -/* - * 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.common.extension; - -/** - * ExtensionFactory - */ -@SPI -public interface ExtensionFactory { - - /** - * Get extension. - * - * @param type object type. - * @param name object name. - * @return object instance. - */ - T getExtension(Class type, String name); - -} +/* + * 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.common.extension; + +/** + * ExtensionFactory + */ +@SPI +public interface ExtensionFactory { + + /** + * Get extension. + * + * @param type object type. + * @param name object name. + * @return object instance. + */ + T getExtension(Class type, String name); + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/SPI.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/SPI.java index 94e6a965e9..70aa5b7f77 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/SPI.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/SPI.java @@ -1,64 +1,64 @@ -/* - * 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.common.extension; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Marker for extension interface - *

- * Changes on extension configuration file
- * Use Protocol as an example, its configuration file 'META-INF/dubbo/com.xxx.Protocol' is changed from:
- *

- *     com.foo.XxxProtocol
- *     com.foo.YyyProtocol
- * 
- *

- * to key-value pair
- *

- *     xxx=com.foo.XxxProtocol
- *     yyy=com.foo.YyyProtocol
- * 
- *
- * The reason for this change is: - *

- * If there's third party library referenced by static field or by method in extension implementation, its class will - * fail to initialize if the third party library doesn't exist. In this case, dubbo cannot figure out extension's id - * therefore cannot be able to map the exception information with the extension, if the previous format is used. - *

- * For example: - *

- * Fails to load Extension("mina"). When user configure to use mina, dubbo will complain the extension cannot be loaded, - * instead of reporting which extract extension implementation fails and the extract reason. - *

- */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) -public @interface SPI { - - /** - * default extension name - */ - String value() default ""; - -} \ No newline at end of file +/* + * 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.common.extension; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Marker for extension interface + *

+ * Changes on extension configuration file
+ * Use Protocol as an example, its configuration file 'META-INF/dubbo/com.xxx.Protocol' is changed from:
+ *

+ *     com.foo.XxxProtocol
+ *     com.foo.YyyProtocol
+ * 
+ *

+ * to key-value pair
+ *

+ *     xxx=com.foo.XxxProtocol
+ *     yyy=com.foo.YyyProtocol
+ * 
+ *
+ * The reason for this change is: + *

+ * If there's third party library referenced by static field or by method in extension implementation, its class will + * fail to initialize if the third party library doesn't exist. In this case, dubbo cannot figure out extension's id + * therefore cannot be able to map the exception information with the extension, if the previous format is used. + *

+ * For example: + *

+ * Fails to load Extension("mina"). When user configure to use mina, dubbo will complain the extension cannot be loaded, + * instead of reporting which extract extension implementation fails and the extract reason. + *

+ */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +public @interface SPI { + + /** + * default extension name + */ + String value() default ""; + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/factory/AdaptiveExtensionFactory.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/factory/AdaptiveExtensionFactory.java index 6ecd0467b6..d136ebc9a6 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/factory/AdaptiveExtensionFactory.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/factory/AdaptiveExtensionFactory.java @@ -1,55 +1,55 @@ -/* - * 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.common.extension.factory; - -import org.apache.dubbo.common.extension.Adaptive; -import org.apache.dubbo.common.extension.ExtensionFactory; -import org.apache.dubbo.common.extension.ExtensionLoader; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * AdaptiveExtensionFactory - */ -@Adaptive -public class AdaptiveExtensionFactory implements ExtensionFactory { - - private final List factories; - - public AdaptiveExtensionFactory() { - ExtensionLoader loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class); - List list = new ArrayList(); - for (String name : loader.getSupportedExtensions()) { - list.add(loader.getExtension(name)); - } - factories = Collections.unmodifiableList(list); - } - - @Override - public T getExtension(Class type, String name) { - for (ExtensionFactory factory : factories) { - T extension = factory.getExtension(type, name); - if (extension != null) { - return extension; - } - } - return null; - } - -} +/* + * 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.common.extension.factory; + +import org.apache.dubbo.common.extension.Adaptive; +import org.apache.dubbo.common.extension.ExtensionFactory; +import org.apache.dubbo.common.extension.ExtensionLoader; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * AdaptiveExtensionFactory + */ +@Adaptive +public class AdaptiveExtensionFactory implements ExtensionFactory { + + private final List factories; + + public AdaptiveExtensionFactory() { + ExtensionLoader loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class); + List list = new ArrayList(); + for (String name : loader.getSupportedExtensions()) { + list.add(loader.getExtension(name)); + } + factories = Collections.unmodifiableList(list); + } + + @Override + public T getExtension(Class type, String name) { + for (ExtensionFactory factory : factories) { + T extension = factory.getExtension(type, name); + if (extension != null) { + return extension; + } + } + return null; + } + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/factory/SpiExtensionFactory.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/factory/SpiExtensionFactory.java index 51c2b3c4b4..46cbe19f15 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/factory/SpiExtensionFactory.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/factory/SpiExtensionFactory.java @@ -1,39 +1,39 @@ -/* - * 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.common.extension.factory; - -import org.apache.dubbo.common.extension.ExtensionFactory; -import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.common.extension.SPI; - -/** - * SpiExtensionFactory - */ -public class SpiExtensionFactory implements ExtensionFactory { - - @Override - public T getExtension(Class type, String name) { - if (type.isInterface() && type.isAnnotationPresent(SPI.class)) { - ExtensionLoader loader = ExtensionLoader.getExtensionLoader(type); - if (!loader.getSupportedExtensions().isEmpty()) { - return loader.getAdaptiveExtension(); - } - } - return null; - } - -} +/* + * 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.common.extension.factory; + +import org.apache.dubbo.common.extension.ExtensionFactory; +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.common.extension.SPI; + +/** + * SpiExtensionFactory + */ +public class SpiExtensionFactory implements ExtensionFactory { + + @Override + public T getExtension(Class type, String name) { + if (type.isInterface() && type.isAnnotationPresent(SPI.class)) { + ExtensionLoader loader = ExtensionLoader.getExtensionLoader(type); + if (!loader.getSupportedExtensions().isEmpty()) { + return loader.getAdaptiveExtension(); + } + } + return null; + } + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/support/ActivateComparator.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/support/ActivateComparator.java index d5b9785d37..5db3b1f111 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/support/ActivateComparator.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/support/ActivateComparator.java @@ -1,146 +1,146 @@ -/* - * 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.common.extension.support; - -import org.apache.dubbo.common.extension.Activate; -import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.common.extension.SPI; -import org.apache.dubbo.common.utils.ArrayUtils; - -import java.util.Arrays; -import java.util.Comparator; - -/** - * OrderComparator - */ -public class ActivateComparator implements Comparator { - - public static final Comparator COMPARATOR = new ActivateComparator(); - - @Override - public int compare(Class o1, Class o2) { - if (o1 == null && o2 == null) { - return 0; - } - if (o1 == null) { - return -1; - } - if (o2 == null) { - return 1; - } - if (o1.equals(o2)) { - return 0; - } - - Class inf = findSpi(o1); - - ActivateInfo a1 = parseActivate(o1); - ActivateInfo a2 = parseActivate(o2); - - if ((a1.applicableToCompare() || a2.applicableToCompare()) && inf != null) { - ExtensionLoader extensionLoader = ExtensionLoader.getExtensionLoader(inf); - if (a1.applicableToCompare()) { - String n2 = extensionLoader.getExtensionName(o2); - if (a1.isLess(n2)) { - return -1; - } - - if (a1.isMore(n2)) { - return 1; - } - } - - if (a2.applicableToCompare()) { - String n1 = extensionLoader.getExtensionName(o1); - if (a2.isLess(n1)) { - return 1; - } - - if (a2.isMore(n1)) { - return -1; - } - } - - return a1.order > a2.order ? 1 : -1; - } - - // In order to avoid the problem of inconsistency between the loading order of two filters - // in different loading scenarios without specifying the order attribute of the filter, - // when the order is the same, compare its filterName - if (a1.order > a2.order) { - return 1; - } else if (a1.order == a2.order) { - return o1.getSimpleName().compareTo(o2.getSimpleName()) > 0 ? 1 : -1; - } else { - return -1; - } - } - - private Class findSpi(Class clazz) { - if (clazz.getInterfaces().length == 0) { - return null; - } - - for (Class intf : clazz.getInterfaces()) { - if (intf.isAnnotationPresent(SPI.class)) { - return intf; - } else { - Class result = findSpi(intf); - if (result != null) { - return result; - } - } - } - - return null; - } - - private ActivateInfo parseActivate(Class clazz) { - ActivateInfo info = new ActivateInfo(); - if (clazz.isAnnotationPresent(Activate.class)) { - Activate activate = clazz.getAnnotation(Activate.class); - info.before = activate.before(); - info.after = activate.after(); - info.order = activate.order(); - } else { - com.alibaba.dubbo.common.extension.Activate activate = clazz.getAnnotation( - com.alibaba.dubbo.common.extension.Activate.class); - info.before = activate.before(); - info.after = activate.after(); - info.order = activate.order(); - } - return info; - } - - private static class ActivateInfo { - private String[] before; - private String[] after; - private int order; - - private boolean applicableToCompare() { - return ArrayUtils.isNotEmpty(before) || ArrayUtils.isNotEmpty(after); - } - - private boolean isLess(String name) { - return Arrays.asList(before).contains(name); - } - - private boolean isMore(String name) { - return Arrays.asList(after).contains(name); - } - } -} +/* + * 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.common.extension.support; + +import org.apache.dubbo.common.extension.Activate; +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.common.extension.SPI; +import org.apache.dubbo.common.utils.ArrayUtils; + +import java.util.Arrays; +import java.util.Comparator; + +/** + * OrderComparator + */ +public class ActivateComparator implements Comparator { + + public static final Comparator COMPARATOR = new ActivateComparator(); + + @Override + public int compare(Class o1, Class o2) { + if (o1 == null && o2 == null) { + return 0; + } + if (o1 == null) { + return -1; + } + if (o2 == null) { + return 1; + } + if (o1.equals(o2)) { + return 0; + } + + Class inf = findSpi(o1); + + ActivateInfo a1 = parseActivate(o1); + ActivateInfo a2 = parseActivate(o2); + + if ((a1.applicableToCompare() || a2.applicableToCompare()) && inf != null) { + ExtensionLoader extensionLoader = ExtensionLoader.getExtensionLoader(inf); + if (a1.applicableToCompare()) { + String n2 = extensionLoader.getExtensionName(o2); + if (a1.isLess(n2)) { + return -1; + } + + if (a1.isMore(n2)) { + return 1; + } + } + + if (a2.applicableToCompare()) { + String n1 = extensionLoader.getExtensionName(o1); + if (a2.isLess(n1)) { + return 1; + } + + if (a2.isMore(n1)) { + return -1; + } + } + + return a1.order > a2.order ? 1 : -1; + } + + // In order to avoid the problem of inconsistency between the loading order of two filters + // in different loading scenarios without specifying the order attribute of the filter, + // when the order is the same, compare its filterName + if (a1.order > a2.order) { + return 1; + } else if (a1.order == a2.order) { + return o1.getSimpleName().compareTo(o2.getSimpleName()) > 0 ? 1 : -1; + } else { + return -1; + } + } + + private Class findSpi(Class clazz) { + if (clazz.getInterfaces().length == 0) { + return null; + } + + for (Class intf : clazz.getInterfaces()) { + if (intf.isAnnotationPresent(SPI.class)) { + return intf; + } else { + Class result = findSpi(intf); + if (result != null) { + return result; + } + } + } + + return null; + } + + private ActivateInfo parseActivate(Class clazz) { + ActivateInfo info = new ActivateInfo(); + if (clazz.isAnnotationPresent(Activate.class)) { + Activate activate = clazz.getAnnotation(Activate.class); + info.before = activate.before(); + info.after = activate.after(); + info.order = activate.order(); + } else { + com.alibaba.dubbo.common.extension.Activate activate = clazz.getAnnotation( + com.alibaba.dubbo.common.extension.Activate.class); + info.before = activate.before(); + info.after = activate.after(); + info.order = activate.order(); + } + return info; + } + + private static class ActivateInfo { + private String[] before; + private String[] after; + private int order; + + private boolean applicableToCompare() { + return ArrayUtils.isNotEmpty(before) || ArrayUtils.isNotEmpty(after); + } + + private boolean isLess(String name) { + return Arrays.asList(before).contains(name); + } + + private boolean isMore(String name) { + return Arrays.asList(after).contains(name); + } + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/support/WrapperComparator.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/support/WrapperComparator.java index ead4a4f6e4..e425dda30e 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/support/WrapperComparator.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/support/WrapperComparator.java @@ -92,4 +92,4 @@ public class WrapperComparator implements Comparator { private static class OrderInfo { private int order; } -} \ No newline at end of file +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/io/Bytes.java b/dubbo-common/src/main/java/org/apache/dubbo/common/io/Bytes.java index 236c4ba0a1..b7f4596147 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/io/Bytes.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/io/Bytes.java @@ -933,4 +933,4 @@ public class Bytes { } return ret; } -} \ No newline at end of file +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/io/UnsafeStringWriter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/io/UnsafeStringWriter.java index a27f77df3f..815123a5ec 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/io/UnsafeStringWriter.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/io/UnsafeStringWriter.java @@ -104,4 +104,4 @@ public class UnsafeStringWriter extends Writer { public String toString() { return mBuffer.toString(); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/json/J2oVisitor.java b/dubbo-common/src/main/java/org/apache/dubbo/common/json/J2oVisitor.java index bc6e4e39bb..6103f4aff7 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/json/J2oVisitor.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/json/J2oVisitor.java @@ -1,389 +1,389 @@ -/* - * 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.common.json; - -import org.apache.dubbo.common.bytecode.Wrapper; -import org.apache.dubbo.common.utils.Stack; -import org.apache.dubbo.common.utils.StringUtils; - -import java.io.IOException; -import java.lang.reflect.Array; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -/** - * JSON to Object visitor. - */ -@Deprecated -class J2oVisitor implements JSONVisitor { - public static final boolean[] EMPTY_BOOL_ARRAY = new boolean[0]; - - public static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; - - public static final char[] EMPTY_CHAR_ARRAY = new char[0]; - - public static final short[] EMPTY_SHORT_ARRAY = new short[0]; - - public static final int[] EMPTY_INT_ARRAY = new int[0]; - - public static final long[] EMPTY_LONG_ARRAY = new long[0]; - - public static final float[] EMPTY_FLOAT_ARRAY = new float[0]; - - public static final double[] EMPTY_DOUBLE_ARRAY = new double[0]; - - public static final String[] EMPTY_STRING_ARRAY = new String[0]; - - private Class[] mTypes; - - private Class mType = Object[].class; - - private Object mValue; - - private Wrapper mWrapper; - - private JSONConverter mConverter; - - private Stack mStack = new Stack(); - - J2oVisitor(Class type, JSONConverter jc) { - mType = type; - mConverter = jc; - } - - J2oVisitor(Class[] types, JSONConverter jc) { - mTypes = types; - mConverter = jc; - } - - private static Object toArray(Class c, Stack list, int len) throws ParseException { - if (c == String.class) { - if (len == 0) { - return EMPTY_STRING_ARRAY; - } else { - Object o; - String[] ss = new String[len]; - for (int i = len - 1; i >= 0; i--) { - o = list.pop(); - ss[i] = (o == null ? null : o.toString()); - } - return ss; - } - } - if (c == boolean.class) { - if (len == 0) { - return EMPTY_BOOL_ARRAY; - } - Object o; - boolean[] ret = new boolean[len]; - for (int i = len - 1; i >= 0; i--) { - o = list.pop(); - if (o instanceof Boolean) { - ret[i] = ((Boolean) o).booleanValue(); - } - } - return ret; - } - if (c == int.class) { - if (len == 0) { - return EMPTY_INT_ARRAY; - } - Object o; - int[] ret = new int[len]; - for (int i = len - 1; i >= 0; i--) { - o = list.pop(); - if (o instanceof Number) { - ret[i] = ((Number) o).intValue(); - } - } - return ret; - } - if (c == long.class) { - if (len == 0) { - return EMPTY_LONG_ARRAY; - } - Object o; - long[] ret = new long[len]; - for (int i = len - 1; i >= 0; i--) { - o = list.pop(); - if (o instanceof Number) { - ret[i] = ((Number) o).longValue(); - } - } - return ret; - } - if (c == float.class) { - if (len == 0) { - return EMPTY_FLOAT_ARRAY; - } - Object o; - float[] ret = new float[len]; - for (int i = len - 1; i >= 0; i--) { - o = list.pop(); - if (o instanceof Number) { - ret[i] = ((Number) o).floatValue(); - } - } - return ret; - } - if (c == double.class) { - if (len == 0) { - return EMPTY_DOUBLE_ARRAY; - } - Object o; - double[] ret = new double[len]; - for (int i = len - 1; i >= 0; i--) { - o = list.pop(); - if (o instanceof Number) { - ret[i] = ((Number) o).doubleValue(); - } - } - return ret; - } - if (c == byte.class) { - if (len == 0) { - return EMPTY_BYTE_ARRAY; - } - Object o; - byte[] ret = new byte[len]; - for (int i = len - 1; i >= 0; i--) { - o = list.pop(); - if (o instanceof Number) { - ret[i] = ((Number) o).byteValue(); - } - } - return ret; - } - if (c == char.class) { - if (len == 0) { - return EMPTY_CHAR_ARRAY; - } - Object o; - char[] ret = new char[len]; - for (int i = len - 1; i >= 0; i--) { - o = list.pop(); - if (o instanceof Character) { - ret[i] = ((Character) o).charValue(); - } - } - return ret; - } - if (c == short.class) { - if (len == 0) { - return EMPTY_SHORT_ARRAY; - } - Object o; - short[] ret = new short[len]; - for (int i = len - 1; i >= 0; i--) { - o = list.pop(); - if (o instanceof Number) { - ret[i] = ((Number) o).shortValue(); - } - } - return ret; - } - - Object ret = Array.newInstance(c, len); - for (int i = len - 1; i >= 0; i--) { - Array.set(ret, i, list.pop()); - } - return ret; - } - - private static String name(Class[] types) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < types.length; i++) { - if (i > 0) { - sb.append(", "); - } - sb.append(types[i].getName()); - } - return sb.toString(); - } - - @Override - public void begin() { - } - - @Override - public Object end(Object obj, boolean isValue) throws ParseException { - mStack.clear(); - try { - return mConverter.readValue(mType, obj); - } catch (IOException e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - - @Override - public void objectBegin() throws ParseException { - mStack.push(mValue); - mStack.push(mType); - mStack.push(mWrapper); - - if (mType == Object.class || Map.class.isAssignableFrom(mType)) { - if (!mType.isInterface() && mType != Object.class) { - try { - mValue = mType.newInstance(); - } catch (Exception e) { - throw new IllegalStateException(e.getMessage(), e); - } - } else if (mType == ConcurrentMap.class) { - mValue = new ConcurrentHashMap(); - } else { - mValue = new HashMap(); - } - mWrapper = null; - } else { - try { - mValue = mType.newInstance(); - mWrapper = Wrapper.getWrapper(mType); - } catch (IllegalAccessException | InstantiationException e) { - throw new ParseException(StringUtils.toString(e)); - } - } - } - - @Override - public Object objectEnd(int count) { - Object ret = mValue; - mWrapper = (Wrapper) mStack.pop(); - mType = (Class) mStack.pop(); - mValue = mStack.pop(); - return ret; - } - - @Override - public void objectItem(String name) { - mStack.push(name); // push name. - mType = (mWrapper == null ? Object.class : mWrapper.getPropertyType(name)); - } - - @Override - @SuppressWarnings("unchecked") - public void objectItemValue(Object obj, boolean isValue) throws ParseException { - String name = (String) mStack.pop(); // pop name. - if (mWrapper == null) { - ((Map) mValue).put(name, obj); - } else { - if (mType != null) { - if (isValue && obj != null) { - try { - obj = mConverter.readValue(mType, obj); - } catch (IOException e) { - throw new ParseException(StringUtils.toString(e)); - } - } - if (mValue instanceof Throwable && "message".equals(name)) { - try { - Field field = Throwable.class.getDeclaredField("detailMessage"); - if (!field.isAccessible()) { - field.setAccessible(true); - } - field.set(mValue, obj); - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new ParseException(StringUtils.toString(e)); - } - } else if (!CLASS_PROPERTY.equals(name)) { - mWrapper.setPropertyValue(mValue, name, obj); - } - } - } - } - - @Override - public void arrayBegin() throws ParseException { - mStack.push(mType); - - if (mType.isArray()) { - mType = mType.getComponentType(); - } else if (mType == Object.class || Collection.class.isAssignableFrom(mType)) { - mType = Object.class; - } else { - throw new ParseException("Convert error, can not load json array data into class [" + mType.getName() + "]."); - } - } - - @Override - @SuppressWarnings("unchecked") - public Object arrayEnd(int count) throws ParseException { - Object ret; - mType = (Class) mStack.get(-1 - count); - - if (mType.isArray()) { - ret = toArray(mType.getComponentType(), mStack, count); - } else { - Collection items; - if (mType == Object.class || Collection.class.isAssignableFrom(mType)) { - if (!mType.isInterface() && mType != Object.class) { - try { - items = (Collection) mType.newInstance(); - } catch (Exception e) { - throw new IllegalStateException(e.getMessage(), e); - } - } else if (mType.isAssignableFrom(ArrayList.class)) { // List - items = new ArrayList(count); - } else if (mType.isAssignableFrom(HashSet.class)) { // Set - items = new HashSet(count); - } else if (mType.isAssignableFrom(LinkedList.class)) { // Queue - items = new LinkedList(); - } else { // Other - items = new ArrayList(count); - } - } else { - throw new ParseException("Convert error, can not load json array data into class [" + mType.getName() + "]."); - } - for (int i = 0; i < count; i++) { - items.add(mStack.remove(i - count)); - } - ret = items; - } - mStack.pop(); - return ret; - } - - @Override - public void arrayItem(int index) throws ParseException { - if (mTypes != null && mStack.size() == index + 1) { - if (index < mTypes.length) { - mType = mTypes[index]; - } else { - throw new ParseException("Can not load json array data into [" + name(mTypes) + "]."); - } - } - } - - @Override - public void arrayItemValue(int index, Object obj, boolean isValue) throws ParseException { - if (isValue && obj != null) { - try { - obj = mConverter.readValue(mType, obj); - } catch (IOException e) { - throw new ParseException(e.getMessage()); - } - } - - mStack.push(obj); - } -} +/* + * 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.common.json; + +import org.apache.dubbo.common.bytecode.Wrapper; +import org.apache.dubbo.common.utils.Stack; +import org.apache.dubbo.common.utils.StringUtils; + +import java.io.IOException; +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + * JSON to Object visitor. + */ +@Deprecated +class J2oVisitor implements JSONVisitor { + public static final boolean[] EMPTY_BOOL_ARRAY = new boolean[0]; + + public static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; + + public static final char[] EMPTY_CHAR_ARRAY = new char[0]; + + public static final short[] EMPTY_SHORT_ARRAY = new short[0]; + + public static final int[] EMPTY_INT_ARRAY = new int[0]; + + public static final long[] EMPTY_LONG_ARRAY = new long[0]; + + public static final float[] EMPTY_FLOAT_ARRAY = new float[0]; + + public static final double[] EMPTY_DOUBLE_ARRAY = new double[0]; + + public static final String[] EMPTY_STRING_ARRAY = new String[0]; + + private Class[] mTypes; + + private Class mType = Object[].class; + + private Object mValue; + + private Wrapper mWrapper; + + private JSONConverter mConverter; + + private Stack mStack = new Stack(); + + J2oVisitor(Class type, JSONConverter jc) { + mType = type; + mConverter = jc; + } + + J2oVisitor(Class[] types, JSONConverter jc) { + mTypes = types; + mConverter = jc; + } + + private static Object toArray(Class c, Stack list, int len) throws ParseException { + if (c == String.class) { + if (len == 0) { + return EMPTY_STRING_ARRAY; + } else { + Object o; + String[] ss = new String[len]; + for (int i = len - 1; i >= 0; i--) { + o = list.pop(); + ss[i] = (o == null ? null : o.toString()); + } + return ss; + } + } + if (c == boolean.class) { + if (len == 0) { + return EMPTY_BOOL_ARRAY; + } + Object o; + boolean[] ret = new boolean[len]; + for (int i = len - 1; i >= 0; i--) { + o = list.pop(); + if (o instanceof Boolean) { + ret[i] = ((Boolean) o).booleanValue(); + } + } + return ret; + } + if (c == int.class) { + if (len == 0) { + return EMPTY_INT_ARRAY; + } + Object o; + int[] ret = new int[len]; + for (int i = len - 1; i >= 0; i--) { + o = list.pop(); + if (o instanceof Number) { + ret[i] = ((Number) o).intValue(); + } + } + return ret; + } + if (c == long.class) { + if (len == 0) { + return EMPTY_LONG_ARRAY; + } + Object o; + long[] ret = new long[len]; + for (int i = len - 1; i >= 0; i--) { + o = list.pop(); + if (o instanceof Number) { + ret[i] = ((Number) o).longValue(); + } + } + return ret; + } + if (c == float.class) { + if (len == 0) { + return EMPTY_FLOAT_ARRAY; + } + Object o; + float[] ret = new float[len]; + for (int i = len - 1; i >= 0; i--) { + o = list.pop(); + if (o instanceof Number) { + ret[i] = ((Number) o).floatValue(); + } + } + return ret; + } + if (c == double.class) { + if (len == 0) { + return EMPTY_DOUBLE_ARRAY; + } + Object o; + double[] ret = new double[len]; + for (int i = len - 1; i >= 0; i--) { + o = list.pop(); + if (o instanceof Number) { + ret[i] = ((Number) o).doubleValue(); + } + } + return ret; + } + if (c == byte.class) { + if (len == 0) { + return EMPTY_BYTE_ARRAY; + } + Object o; + byte[] ret = new byte[len]; + for (int i = len - 1; i >= 0; i--) { + o = list.pop(); + if (o instanceof Number) { + ret[i] = ((Number) o).byteValue(); + } + } + return ret; + } + if (c == char.class) { + if (len == 0) { + return EMPTY_CHAR_ARRAY; + } + Object o; + char[] ret = new char[len]; + for (int i = len - 1; i >= 0; i--) { + o = list.pop(); + if (o instanceof Character) { + ret[i] = ((Character) o).charValue(); + } + } + return ret; + } + if (c == short.class) { + if (len == 0) { + return EMPTY_SHORT_ARRAY; + } + Object o; + short[] ret = new short[len]; + for (int i = len - 1; i >= 0; i--) { + o = list.pop(); + if (o instanceof Number) { + ret[i] = ((Number) o).shortValue(); + } + } + return ret; + } + + Object ret = Array.newInstance(c, len); + for (int i = len - 1; i >= 0; i--) { + Array.set(ret, i, list.pop()); + } + return ret; + } + + private static String name(Class[] types) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < types.length; i++) { + if (i > 0) { + sb.append(", "); + } + sb.append(types[i].getName()); + } + return sb.toString(); + } + + @Override + public void begin() { + } + + @Override + public Object end(Object obj, boolean isValue) throws ParseException { + mStack.clear(); + try { + return mConverter.readValue(mType, obj); + } catch (IOException e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + @Override + public void objectBegin() throws ParseException { + mStack.push(mValue); + mStack.push(mType); + mStack.push(mWrapper); + + if (mType == Object.class || Map.class.isAssignableFrom(mType)) { + if (!mType.isInterface() && mType != Object.class) { + try { + mValue = mType.newInstance(); + } catch (Exception e) { + throw new IllegalStateException(e.getMessage(), e); + } + } else if (mType == ConcurrentMap.class) { + mValue = new ConcurrentHashMap(); + } else { + mValue = new HashMap(); + } + mWrapper = null; + } else { + try { + mValue = mType.newInstance(); + mWrapper = Wrapper.getWrapper(mType); + } catch (IllegalAccessException | InstantiationException e) { + throw new ParseException(StringUtils.toString(e)); + } + } + } + + @Override + public Object objectEnd(int count) { + Object ret = mValue; + mWrapper = (Wrapper) mStack.pop(); + mType = (Class) mStack.pop(); + mValue = mStack.pop(); + return ret; + } + + @Override + public void objectItem(String name) { + mStack.push(name); // push name. + mType = (mWrapper == null ? Object.class : mWrapper.getPropertyType(name)); + } + + @Override + @SuppressWarnings("unchecked") + public void objectItemValue(Object obj, boolean isValue) throws ParseException { + String name = (String) mStack.pop(); // pop name. + if (mWrapper == null) { + ((Map) mValue).put(name, obj); + } else { + if (mType != null) { + if (isValue && obj != null) { + try { + obj = mConverter.readValue(mType, obj); + } catch (IOException e) { + throw new ParseException(StringUtils.toString(e)); + } + } + if (mValue instanceof Throwable && "message".equals(name)) { + try { + Field field = Throwable.class.getDeclaredField("detailMessage"); + if (!field.isAccessible()) { + field.setAccessible(true); + } + field.set(mValue, obj); + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new ParseException(StringUtils.toString(e)); + } + } else if (!CLASS_PROPERTY.equals(name)) { + mWrapper.setPropertyValue(mValue, name, obj); + } + } + } + } + + @Override + public void arrayBegin() throws ParseException { + mStack.push(mType); + + if (mType.isArray()) { + mType = mType.getComponentType(); + } else if (mType == Object.class || Collection.class.isAssignableFrom(mType)) { + mType = Object.class; + } else { + throw new ParseException("Convert error, can not load json array data into class [" + mType.getName() + "]."); + } + } + + @Override + @SuppressWarnings("unchecked") + public Object arrayEnd(int count) throws ParseException { + Object ret; + mType = (Class) mStack.get(-1 - count); + + if (mType.isArray()) { + ret = toArray(mType.getComponentType(), mStack, count); + } else { + Collection items; + if (mType == Object.class || Collection.class.isAssignableFrom(mType)) { + if (!mType.isInterface() && mType != Object.class) { + try { + items = (Collection) mType.newInstance(); + } catch (Exception e) { + throw new IllegalStateException(e.getMessage(), e); + } + } else if (mType.isAssignableFrom(ArrayList.class)) { // List + items = new ArrayList(count); + } else if (mType.isAssignableFrom(HashSet.class)) { // Set + items = new HashSet(count); + } else if (mType.isAssignableFrom(LinkedList.class)) { // Queue + items = new LinkedList(); + } else { // Other + items = new ArrayList(count); + } + } else { + throw new ParseException("Convert error, can not load json array data into class [" + mType.getName() + "]."); + } + for (int i = 0; i < count; i++) { + items.add(mStack.remove(i - count)); + } + ret = items; + } + mStack.pop(); + return ret; + } + + @Override + public void arrayItem(int index) throws ParseException { + if (mTypes != null && mStack.size() == index + 1) { + if (index < mTypes.length) { + mType = mTypes[index]; + } else { + throw new ParseException("Can not load json array data into [" + name(mTypes) + "]."); + } + } + } + + @Override + public void arrayItemValue(int index, Object obj, boolean isValue) throws ParseException { + if (isValue && obj != null) { + try { + obj = mConverter.readValue(mType, obj); + } catch (IOException e) { + throw new ParseException(e.getMessage()); + } + } + + mStack.push(obj); + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSON.java b/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSON.java index 7c11dd3245..55dea2ca74 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSON.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSON.java @@ -1,711 +1,711 @@ -/* - * 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.common.json; - -import org.apache.dubbo.common.bytecode.Wrapper; -import org.apache.dubbo.common.utils.Stack; - -import java.io.IOException; -import java.io.Reader; -import java.io.StringReader; -import java.io.StringWriter; -import java.io.Writer; - -/** - * JSON. - */ -@Deprecated -public class JSON { - public static final char LBRACE = '{', RBRACE = '}'; - - public static final char LSQUARE = '[', RSQUARE = ']'; - - public static final char COMMA = ',', COLON = ':', QUOTE = '"'; - - public static final String NULL = "null"; - // state. - public static final byte END = 0, START = 1, OBJECT_ITEM = 2, OBJECT_VALUE = 3, ARRAY_ITEM = 4; - static final JSONConverter DEFAULT_CONVERTER = new GenericJSONConverter(); - - private JSON() { - } - - /** - * json string. - * - * @param obj object. - * @return json string. - * @throws IOException - */ - public static String json(Object obj) throws IOException { - if (obj == null) { - return NULL; - } - StringWriter sw = new StringWriter(); - try { - json(obj, sw); - return sw.getBuffer().toString(); - } finally { - sw.close(); - } - } - - /** - * write json. - * - * @param obj object. - * @param writer writer. - * @throws IOException - */ - public static void json(Object obj, Writer writer) throws IOException { - json(obj, writer, false); - } - - public static void json(Object obj, Writer writer, boolean writeClass) throws IOException { - if (obj == null) { - writer.write(NULL); - } else { - json(obj, new JSONWriter(writer), writeClass); - } - } - - /** - * json string. - * - * @param obj object. - * @param properties property name array. - * @return json string. - * @throws IOException - */ - public static String json(Object obj, String[] properties) throws IOException { - if (obj == null) { - return NULL; - } - StringWriter sw = new StringWriter(); - try { - json(obj, properties, sw); - return sw.getBuffer().toString(); - } finally { - sw.close(); - } - } - - public static void json(Object obj, final String[] properties, Writer writer) throws IOException { - json(obj, properties, writer, false); - } - - /** - * write json. - * - * @param obj object. - * @param properties property name array. - * @param writer writer. - * @throws IOException - */ - public static void json(Object obj, final String[] properties, Writer writer, boolean writeClass) throws IOException { - if (obj == null) { - writer.write(NULL); - } else { - json(obj, properties, new JSONWriter(writer), writeClass); - } - } - - private static void json(Object obj, JSONWriter jb, boolean writeClass) throws IOException { - if (obj == null) { - jb.valueNull(); - } else { - DEFAULT_CONVERTER.writeValue(obj, jb, writeClass); - } - } - - private static void json(Object obj, String[] properties, JSONWriter jb, boolean writeClass) throws IOException { - if (obj == null) { - jb.valueNull(); - } else { - Wrapper wrapper = Wrapper.getWrapper(obj.getClass()); - - Object value; - jb.objectBegin(); - for (String prop : properties) { - jb.objectItem(prop); - value = wrapper.getPropertyValue(obj, prop); - if (value == null) { - jb.valueNull(); - } else { - DEFAULT_CONVERTER.writeValue(value, jb, writeClass); - } - } - jb.objectEnd(); - } - } - - /** - * parse json. - * - * @param json json source. - * @return JSONObject or JSONArray or Boolean or Long or Double or String or null - * @throws ParseException - */ - public static Object parse(String json) throws ParseException { - StringReader reader = new StringReader(json); - try { - return parse(reader); - } catch (IOException e) { - throw new ParseException(e.getMessage()); - } finally { - reader.close(); - } - } - - /** - * parse json. - * - * @param reader reader. - * @return JSONObject or JSONArray or Boolean or Long or Double or String or null - * @throws IOException - * @throws ParseException - */ - public static Object parse(Reader reader) throws IOException, ParseException { - return parse(reader, JSONToken.ANY); - } - - /** - * parse json. - * - * @param json json string. - * @param type target type. - * @return result. - * @throws ParseException - */ - public static T parse(String json, Class type) throws ParseException { - StringReader reader = new StringReader(json); - try { - return parse(reader, type); - } catch (IOException e) { - throw new ParseException(e.getMessage()); - } finally { - reader.close(); - } - } - - /** - * parse json - * - * @param reader json source. - * @param type target type. - * @return result. - * @throws IOException - * @throws ParseException - */ - @SuppressWarnings("unchecked") - public static T parse(Reader reader, Class type) throws IOException, ParseException { - return (T) parse(reader, new J2oVisitor(type, DEFAULT_CONVERTER), JSONToken.ANY); - } - - /** - * parse json. - * - * @param json json string. - * @param types target type array. - * @return result. - * @throws ParseException - */ - public static Object[] parse(String json, Class[] types) throws ParseException { - StringReader reader = new StringReader(json); - try { - return (Object[]) parse(reader, types); - } catch (IOException e) { - throw new ParseException(e.getMessage()); - } finally { - reader.close(); - } - } - - /** - * parse json. - * - * @param reader json source. - * @param types target type array. - * @return result. - * @throws IOException - * @throws ParseException - */ - public static Object[] parse(Reader reader, Class[] types) throws IOException, ParseException { - return (Object[]) parse(reader, new J2oVisitor(types, DEFAULT_CONVERTER), JSONToken.LSQUARE); - } - - /** - * parse json. - * - * @param json json string. - * @param handler handler. - * @return result. - * @throws ParseException - */ - public static Object parse(String json, JSONVisitor handler) throws ParseException { - StringReader reader = new StringReader(json); - try { - return parse(reader, handler); - } catch (IOException e) { - throw new ParseException(e.getMessage()); - } finally { - reader.close(); - } - } - - /** - * parse json. - * - * @param reader json source. - * @param handler handler. - * @return result. - * @throws IOException - * @throws ParseException - */ - public static Object parse(Reader reader, JSONVisitor handler) throws IOException, ParseException { - return parse(reader, handler, JSONToken.ANY); - } - - private static Object parse(Reader reader, int expect) throws IOException, ParseException { - JSONReader jr = new JSONReader(reader); - JSONToken token = jr.nextToken(expect); - - byte state = START; - Object value = null, tmp; - Stack stack = new Stack(); - - do { - switch (state) { - case END: - throw new ParseException("JSON source format error."); - case START: { - switch (token.type) { - case JSONToken.NULL: - case JSONToken.BOOL: - case JSONToken.INT: - case JSONToken.FLOAT: - case JSONToken.STRING: { - state = END; - value = token.value; - break; - } - case JSONToken.LSQUARE: { - state = ARRAY_ITEM; - value = new JSONArray(); - break; - } - case JSONToken.LBRACE: { - state = OBJECT_ITEM; - value = new JSONObject(); - break; - } - default: - throw new ParseException("Unexcepted token expect [ VALUE or '[' or '{' ] get '" + JSONToken.token2string(token.type) + "'"); - } - break; - } - case ARRAY_ITEM: { - switch (token.type) { - case JSONToken.COMMA: - break; - case JSONToken.NULL: - case JSONToken.BOOL: - case JSONToken.INT: - case JSONToken.FLOAT: - case JSONToken.STRING: { - ((JSONArray) value).add(token.value); - break; - } - case JSONToken.RSQUARE: // end of array. - { - if (stack.isEmpty()) { - state = END; - } else { - Entry entry = stack.pop(); - state = entry.state; - value = entry.value; - } - break; - } - case JSONToken.LSQUARE: // array begin. - { - tmp = new JSONArray(); - ((JSONArray) value).add(tmp); - stack.push(new Entry(state, value)); - - state = ARRAY_ITEM; - value = tmp; - break; - } - case JSONToken.LBRACE: // object begin. - { - tmp = new JSONObject(); - ((JSONArray) value).add(tmp); - stack.push(new Entry(state, value)); - - state = OBJECT_ITEM; - value = tmp; - break; - } - default: - throw new ParseException("Unexcepted token expect [ VALUE or ',' or ']' or '[' or '{' ] get '" + JSONToken.token2string(token.type) + "'"); - } - break; - } - case OBJECT_ITEM: { - switch (token.type) { - case JSONToken.COMMA: - break; - case JSONToken.IDENT: // item name. - { - stack.push(new Entry(OBJECT_ITEM, (String) token.value)); - state = OBJECT_VALUE; - break; - } - case JSONToken.NULL: { - stack.push(new Entry(OBJECT_ITEM, "null")); - state = OBJECT_VALUE; - break; - } - case JSONToken.BOOL: - case JSONToken.INT: - case JSONToken.FLOAT: - case JSONToken.STRING: { - stack.push(new Entry(OBJECT_ITEM, token.value.toString())); - state = OBJECT_VALUE; - break; - } - case JSONToken.RBRACE: // end of object. - { - if (stack.isEmpty()) { - state = END; - } else { - Entry entry = stack.pop(); - state = entry.state; - value = entry.value; - } - break; - } - default: - throw new ParseException("Unexcepted token expect [ IDENT or VALUE or ',' or '}' ] get '" + JSONToken.token2string(token.type) + "'"); - } - break; - } - case OBJECT_VALUE: { - switch (token.type) { - case JSONToken.COLON: - break; - case JSONToken.NULL: - case JSONToken.BOOL: - case JSONToken.INT: - case JSONToken.FLOAT: - case JSONToken.STRING: { - ((JSONObject) value).put((String) stack.pop().value, token.value); - state = OBJECT_ITEM; - break; - } - case JSONToken.LSQUARE: // array begin. - { - tmp = new JSONArray(); - ((JSONObject) value).put((String) stack.pop().value, tmp); - stack.push(new Entry(OBJECT_ITEM, value)); - - state = ARRAY_ITEM; - value = tmp; - break; - } - case JSONToken.LBRACE: // object begin. - { - tmp = new JSONObject(); - ((JSONObject) value).put((String) stack.pop().value, tmp); - stack.push(new Entry(OBJECT_ITEM, value)); - - state = OBJECT_ITEM; - value = tmp; - break; - } - default: - throw new ParseException("Unexcepted token expect [ VALUE or '[' or '{' ] get '" + JSONToken.token2string(token.type) + "'"); - } - break; - } - default: - throw new ParseException("Unexcepted state."); - } - } - while ((token = jr.nextToken()) != null); - stack.clear(); - return value; - } - - private static Object parse(Reader reader, JSONVisitor handler, int expect) throws IOException, ParseException { - JSONReader jr = new JSONReader(reader); - JSONToken token = jr.nextToken(expect); - - Object value = null; - int state = START, index = 0; - Stack states = new Stack(); - boolean pv = false; - - handler.begin(); - do { - switch (state) { - case END: - throw new ParseException("JSON source format error."); - case START: { - switch (token.type) { - case JSONToken.NULL: { - value = token.value; - state = END; - pv = true; - break; - } - case JSONToken.BOOL: { - value = token.value; - state = END; - pv = true; - break; - } - case JSONToken.INT: { - value = token.value; - state = END; - pv = true; - break; - } - case JSONToken.FLOAT: { - value = token.value; - state = END; - pv = true; - break; - } - case JSONToken.STRING: { - value = token.value; - state = END; - pv = true; - break; - } - case JSONToken.LSQUARE: { - handler.arrayBegin(); - state = ARRAY_ITEM; - break; - } - case JSONToken.LBRACE: { - handler.objectBegin(); - state = OBJECT_ITEM; - break; - } - default: - throw new ParseException("Unexcepted token expect [ VALUE or '[' or '{' ] get '" + JSONToken.token2string(token.type) + "'"); - } - break; - } - case ARRAY_ITEM: { - switch (token.type) { - case JSONToken.COMMA: - break; - case JSONToken.NULL: { - handler.arrayItem(index++); - handler.arrayItemValue(index, token.value, true); - break; - } - case JSONToken.BOOL: { - handler.arrayItem(index++); - handler.arrayItemValue(index, token.value, true); - break; - } - case JSONToken.INT: { - handler.arrayItem(index++); - handler.arrayItemValue(index, token.value, true); - break; - } - case JSONToken.FLOAT: { - handler.arrayItem(index++); - handler.arrayItemValue(index, token.value, true); - break; - } - case JSONToken.STRING: { - handler.arrayItem(index++); - handler.arrayItemValue(index, token.value, true); - break; - } - case JSONToken.LSQUARE: { - handler.arrayItem(index++); - states.push(new int[]{state, index}); - - index = 0; - state = ARRAY_ITEM; - handler.arrayBegin(); - break; - } - case JSONToken.LBRACE: { - handler.arrayItem(index++); - states.push(new int[]{state, index}); - - index = 0; - state = OBJECT_ITEM; - handler.objectBegin(); - break; - } - case JSONToken.RSQUARE: { - if (states.isEmpty()) { - value = handler.arrayEnd(index); - state = END; - } else { - value = handler.arrayEnd(index); - int[] tmp = states.pop(); - state = tmp[0]; - index = tmp[1]; - - switch (state) { - case ARRAY_ITEM: { - handler.arrayItemValue(index, value, false); - break; - } - case OBJECT_ITEM: { - handler.objectItemValue(value, false); - break; - } - default: - } - } - break; - } - default: - throw new ParseException("Unexcepted token expect [ VALUE or ',' or ']' or '[' or '{' ] get '" + JSONToken.token2string(token.type) + "'"); - } - break; - } - case OBJECT_ITEM: { - switch (token.type) { - case JSONToken.COMMA: - break; - case JSONToken.IDENT: { - handler.objectItem((String) token.value); - state = OBJECT_VALUE; - break; - } - case JSONToken.NULL: { - handler.objectItem("null"); - state = OBJECT_VALUE; - break; - } - case JSONToken.BOOL: - case JSONToken.INT: - case JSONToken.FLOAT: - case JSONToken.STRING: { - handler.objectItem(token.value.toString()); - state = OBJECT_VALUE; - break; - } - case JSONToken.RBRACE: { - if (states.isEmpty()) { - value = handler.objectEnd(index); - state = END; - } else { - value = handler.objectEnd(index); - int[] tmp = states.pop(); - state = tmp[0]; - index = tmp[1]; - - switch (state) { - case ARRAY_ITEM: { - handler.arrayItemValue(index, value, false); - break; - } - case OBJECT_ITEM: { - handler.objectItemValue(value, false); - break; - } - default: - } - } - break; - } - default: - throw new ParseException("Unexcepted token expect [ IDENT or VALUE or ',' or '}' ] get '" + JSONToken.token2string(token.type) + "'"); - } - break; - } - case OBJECT_VALUE: { - switch (token.type) { - case JSONToken.COLON: - break; - case JSONToken.NULL: { - handler.objectItemValue(token.value, true); - state = OBJECT_ITEM; - break; - } - case JSONToken.BOOL: { - handler.objectItemValue(token.value, true); - state = OBJECT_ITEM; - break; - } - case JSONToken.INT: { - handler.objectItemValue(token.value, true); - state = OBJECT_ITEM; - break; - } - case JSONToken.FLOAT: { - handler.objectItemValue(token.value, true); - state = OBJECT_ITEM; - break; - } - case JSONToken.STRING: { - handler.objectItemValue(token.value, true); - state = OBJECT_ITEM; - break; - } - case JSONToken.LSQUARE: { - states.push(new int[]{OBJECT_ITEM, index}); - - index = 0; - state = ARRAY_ITEM; - handler.arrayBegin(); - break; - } - case JSONToken.LBRACE: { - states.push(new int[]{OBJECT_ITEM, index}); - - index = 0; - state = OBJECT_ITEM; - handler.objectBegin(); - break; - } - default: - throw new ParseException("Unexcepted token expect [ VALUE or '[' or '{' ] get '" + JSONToken.token2string(token.type) + "'"); - } - break; - } - default: - throw new ParseException("Unexcepted state."); - } - } - while ((token = jr.nextToken()) != null); - states.clear(); - return handler.end(value, pv); - } - - private static class Entry { - byte state; - Object value; - - Entry(byte s, Object v) { - state = s; - value = v; - } - } -} \ No newline at end of file +/* + * 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.common.json; + +import org.apache.dubbo.common.bytecode.Wrapper; +import org.apache.dubbo.common.utils.Stack; + +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; + +/** + * JSON. + */ +@Deprecated +public class JSON { + public static final char LBRACE = '{', RBRACE = '}'; + + public static final char LSQUARE = '[', RSQUARE = ']'; + + public static final char COMMA = ',', COLON = ':', QUOTE = '"'; + + public static final String NULL = "null"; + // state. + public static final byte END = 0, START = 1, OBJECT_ITEM = 2, OBJECT_VALUE = 3, ARRAY_ITEM = 4; + static final JSONConverter DEFAULT_CONVERTER = new GenericJSONConverter(); + + private JSON() { + } + + /** + * json string. + * + * @param obj object. + * @return json string. + * @throws IOException + */ + public static String json(Object obj) throws IOException { + if (obj == null) { + return NULL; + } + StringWriter sw = new StringWriter(); + try { + json(obj, sw); + return sw.getBuffer().toString(); + } finally { + sw.close(); + } + } + + /** + * write json. + * + * @param obj object. + * @param writer writer. + * @throws IOException + */ + public static void json(Object obj, Writer writer) throws IOException { + json(obj, writer, false); + } + + public static void json(Object obj, Writer writer, boolean writeClass) throws IOException { + if (obj == null) { + writer.write(NULL); + } else { + json(obj, new JSONWriter(writer), writeClass); + } + } + + /** + * json string. + * + * @param obj object. + * @param properties property name array. + * @return json string. + * @throws IOException + */ + public static String json(Object obj, String[] properties) throws IOException { + if (obj == null) { + return NULL; + } + StringWriter sw = new StringWriter(); + try { + json(obj, properties, sw); + return sw.getBuffer().toString(); + } finally { + sw.close(); + } + } + + public static void json(Object obj, final String[] properties, Writer writer) throws IOException { + json(obj, properties, writer, false); + } + + /** + * write json. + * + * @param obj object. + * @param properties property name array. + * @param writer writer. + * @throws IOException + */ + public static void json(Object obj, final String[] properties, Writer writer, boolean writeClass) throws IOException { + if (obj == null) { + writer.write(NULL); + } else { + json(obj, properties, new JSONWriter(writer), writeClass); + } + } + + private static void json(Object obj, JSONWriter jb, boolean writeClass) throws IOException { + if (obj == null) { + jb.valueNull(); + } else { + DEFAULT_CONVERTER.writeValue(obj, jb, writeClass); + } + } + + private static void json(Object obj, String[] properties, JSONWriter jb, boolean writeClass) throws IOException { + if (obj == null) { + jb.valueNull(); + } else { + Wrapper wrapper = Wrapper.getWrapper(obj.getClass()); + + Object value; + jb.objectBegin(); + for (String prop : properties) { + jb.objectItem(prop); + value = wrapper.getPropertyValue(obj, prop); + if (value == null) { + jb.valueNull(); + } else { + DEFAULT_CONVERTER.writeValue(value, jb, writeClass); + } + } + jb.objectEnd(); + } + } + + /** + * parse json. + * + * @param json json source. + * @return JSONObject or JSONArray or Boolean or Long or Double or String or null + * @throws ParseException + */ + public static Object parse(String json) throws ParseException { + StringReader reader = new StringReader(json); + try { + return parse(reader); + } catch (IOException e) { + throw new ParseException(e.getMessage()); + } finally { + reader.close(); + } + } + + /** + * parse json. + * + * @param reader reader. + * @return JSONObject or JSONArray or Boolean or Long or Double or String or null + * @throws IOException + * @throws ParseException + */ + public static Object parse(Reader reader) throws IOException, ParseException { + return parse(reader, JSONToken.ANY); + } + + /** + * parse json. + * + * @param json json string. + * @param type target type. + * @return result. + * @throws ParseException + */ + public static T parse(String json, Class type) throws ParseException { + StringReader reader = new StringReader(json); + try { + return parse(reader, type); + } catch (IOException e) { + throw new ParseException(e.getMessage()); + } finally { + reader.close(); + } + } + + /** + * parse json + * + * @param reader json source. + * @param type target type. + * @return result. + * @throws IOException + * @throws ParseException + */ + @SuppressWarnings("unchecked") + public static T parse(Reader reader, Class type) throws IOException, ParseException { + return (T) parse(reader, new J2oVisitor(type, DEFAULT_CONVERTER), JSONToken.ANY); + } + + /** + * parse json. + * + * @param json json string. + * @param types target type array. + * @return result. + * @throws ParseException + */ + public static Object[] parse(String json, Class[] types) throws ParseException { + StringReader reader = new StringReader(json); + try { + return (Object[]) parse(reader, types); + } catch (IOException e) { + throw new ParseException(e.getMessage()); + } finally { + reader.close(); + } + } + + /** + * parse json. + * + * @param reader json source. + * @param types target type array. + * @return result. + * @throws IOException + * @throws ParseException + */ + public static Object[] parse(Reader reader, Class[] types) throws IOException, ParseException { + return (Object[]) parse(reader, new J2oVisitor(types, DEFAULT_CONVERTER), JSONToken.LSQUARE); + } + + /** + * parse json. + * + * @param json json string. + * @param handler handler. + * @return result. + * @throws ParseException + */ + public static Object parse(String json, JSONVisitor handler) throws ParseException { + StringReader reader = new StringReader(json); + try { + return parse(reader, handler); + } catch (IOException e) { + throw new ParseException(e.getMessage()); + } finally { + reader.close(); + } + } + + /** + * parse json. + * + * @param reader json source. + * @param handler handler. + * @return result. + * @throws IOException + * @throws ParseException + */ + public static Object parse(Reader reader, JSONVisitor handler) throws IOException, ParseException { + return parse(reader, handler, JSONToken.ANY); + } + + private static Object parse(Reader reader, int expect) throws IOException, ParseException { + JSONReader jr = new JSONReader(reader); + JSONToken token = jr.nextToken(expect); + + byte state = START; + Object value = null, tmp; + Stack stack = new Stack(); + + do { + switch (state) { + case END: + throw new ParseException("JSON source format error."); + case START: { + switch (token.type) { + case JSONToken.NULL: + case JSONToken.BOOL: + case JSONToken.INT: + case JSONToken.FLOAT: + case JSONToken.STRING: { + state = END; + value = token.value; + break; + } + case JSONToken.LSQUARE: { + state = ARRAY_ITEM; + value = new JSONArray(); + break; + } + case JSONToken.LBRACE: { + state = OBJECT_ITEM; + value = new JSONObject(); + break; + } + default: + throw new ParseException("Unexcepted token expect [ VALUE or '[' or '{' ] get '" + JSONToken.token2string(token.type) + "'"); + } + break; + } + case ARRAY_ITEM: { + switch (token.type) { + case JSONToken.COMMA: + break; + case JSONToken.NULL: + case JSONToken.BOOL: + case JSONToken.INT: + case JSONToken.FLOAT: + case JSONToken.STRING: { + ((JSONArray) value).add(token.value); + break; + } + case JSONToken.RSQUARE: // end of array. + { + if (stack.isEmpty()) { + state = END; + } else { + Entry entry = stack.pop(); + state = entry.state; + value = entry.value; + } + break; + } + case JSONToken.LSQUARE: // array begin. + { + tmp = new JSONArray(); + ((JSONArray) value).add(tmp); + stack.push(new Entry(state, value)); + + state = ARRAY_ITEM; + value = tmp; + break; + } + case JSONToken.LBRACE: // object begin. + { + tmp = new JSONObject(); + ((JSONArray) value).add(tmp); + stack.push(new Entry(state, value)); + + state = OBJECT_ITEM; + value = tmp; + break; + } + default: + throw new ParseException("Unexcepted token expect [ VALUE or ',' or ']' or '[' or '{' ] get '" + JSONToken.token2string(token.type) + "'"); + } + break; + } + case OBJECT_ITEM: { + switch (token.type) { + case JSONToken.COMMA: + break; + case JSONToken.IDENT: // item name. + { + stack.push(new Entry(OBJECT_ITEM, (String) token.value)); + state = OBJECT_VALUE; + break; + } + case JSONToken.NULL: { + stack.push(new Entry(OBJECT_ITEM, "null")); + state = OBJECT_VALUE; + break; + } + case JSONToken.BOOL: + case JSONToken.INT: + case JSONToken.FLOAT: + case JSONToken.STRING: { + stack.push(new Entry(OBJECT_ITEM, token.value.toString())); + state = OBJECT_VALUE; + break; + } + case JSONToken.RBRACE: // end of object. + { + if (stack.isEmpty()) { + state = END; + } else { + Entry entry = stack.pop(); + state = entry.state; + value = entry.value; + } + break; + } + default: + throw new ParseException("Unexcepted token expect [ IDENT or VALUE or ',' or '}' ] get '" + JSONToken.token2string(token.type) + "'"); + } + break; + } + case OBJECT_VALUE: { + switch (token.type) { + case JSONToken.COLON: + break; + case JSONToken.NULL: + case JSONToken.BOOL: + case JSONToken.INT: + case JSONToken.FLOAT: + case JSONToken.STRING: { + ((JSONObject) value).put((String) stack.pop().value, token.value); + state = OBJECT_ITEM; + break; + } + case JSONToken.LSQUARE: // array begin. + { + tmp = new JSONArray(); + ((JSONObject) value).put((String) stack.pop().value, tmp); + stack.push(new Entry(OBJECT_ITEM, value)); + + state = ARRAY_ITEM; + value = tmp; + break; + } + case JSONToken.LBRACE: // object begin. + { + tmp = new JSONObject(); + ((JSONObject) value).put((String) stack.pop().value, tmp); + stack.push(new Entry(OBJECT_ITEM, value)); + + state = OBJECT_ITEM; + value = tmp; + break; + } + default: + throw new ParseException("Unexcepted token expect [ VALUE or '[' or '{' ] get '" + JSONToken.token2string(token.type) + "'"); + } + break; + } + default: + throw new ParseException("Unexcepted state."); + } + } + while ((token = jr.nextToken()) != null); + stack.clear(); + return value; + } + + private static Object parse(Reader reader, JSONVisitor handler, int expect) throws IOException, ParseException { + JSONReader jr = new JSONReader(reader); + JSONToken token = jr.nextToken(expect); + + Object value = null; + int state = START, index = 0; + Stack states = new Stack(); + boolean pv = false; + + handler.begin(); + do { + switch (state) { + case END: + throw new ParseException("JSON source format error."); + case START: { + switch (token.type) { + case JSONToken.NULL: { + value = token.value; + state = END; + pv = true; + break; + } + case JSONToken.BOOL: { + value = token.value; + state = END; + pv = true; + break; + } + case JSONToken.INT: { + value = token.value; + state = END; + pv = true; + break; + } + case JSONToken.FLOAT: { + value = token.value; + state = END; + pv = true; + break; + } + case JSONToken.STRING: { + value = token.value; + state = END; + pv = true; + break; + } + case JSONToken.LSQUARE: { + handler.arrayBegin(); + state = ARRAY_ITEM; + break; + } + case JSONToken.LBRACE: { + handler.objectBegin(); + state = OBJECT_ITEM; + break; + } + default: + throw new ParseException("Unexcepted token expect [ VALUE or '[' or '{' ] get '" + JSONToken.token2string(token.type) + "'"); + } + break; + } + case ARRAY_ITEM: { + switch (token.type) { + case JSONToken.COMMA: + break; + case JSONToken.NULL: { + handler.arrayItem(index++); + handler.arrayItemValue(index, token.value, true); + break; + } + case JSONToken.BOOL: { + handler.arrayItem(index++); + handler.arrayItemValue(index, token.value, true); + break; + } + case JSONToken.INT: { + handler.arrayItem(index++); + handler.arrayItemValue(index, token.value, true); + break; + } + case JSONToken.FLOAT: { + handler.arrayItem(index++); + handler.arrayItemValue(index, token.value, true); + break; + } + case JSONToken.STRING: { + handler.arrayItem(index++); + handler.arrayItemValue(index, token.value, true); + break; + } + case JSONToken.LSQUARE: { + handler.arrayItem(index++); + states.push(new int[]{state, index}); + + index = 0; + state = ARRAY_ITEM; + handler.arrayBegin(); + break; + } + case JSONToken.LBRACE: { + handler.arrayItem(index++); + states.push(new int[]{state, index}); + + index = 0; + state = OBJECT_ITEM; + handler.objectBegin(); + break; + } + case JSONToken.RSQUARE: { + if (states.isEmpty()) { + value = handler.arrayEnd(index); + state = END; + } else { + value = handler.arrayEnd(index); + int[] tmp = states.pop(); + state = tmp[0]; + index = tmp[1]; + + switch (state) { + case ARRAY_ITEM: { + handler.arrayItemValue(index, value, false); + break; + } + case OBJECT_ITEM: { + handler.objectItemValue(value, false); + break; + } + default: + } + } + break; + } + default: + throw new ParseException("Unexcepted token expect [ VALUE or ',' or ']' or '[' or '{' ] get '" + JSONToken.token2string(token.type) + "'"); + } + break; + } + case OBJECT_ITEM: { + switch (token.type) { + case JSONToken.COMMA: + break; + case JSONToken.IDENT: { + handler.objectItem((String) token.value); + state = OBJECT_VALUE; + break; + } + case JSONToken.NULL: { + handler.objectItem("null"); + state = OBJECT_VALUE; + break; + } + case JSONToken.BOOL: + case JSONToken.INT: + case JSONToken.FLOAT: + case JSONToken.STRING: { + handler.objectItem(token.value.toString()); + state = OBJECT_VALUE; + break; + } + case JSONToken.RBRACE: { + if (states.isEmpty()) { + value = handler.objectEnd(index); + state = END; + } else { + value = handler.objectEnd(index); + int[] tmp = states.pop(); + state = tmp[0]; + index = tmp[1]; + + switch (state) { + case ARRAY_ITEM: { + handler.arrayItemValue(index, value, false); + break; + } + case OBJECT_ITEM: { + handler.objectItemValue(value, false); + break; + } + default: + } + } + break; + } + default: + throw new ParseException("Unexcepted token expect [ IDENT or VALUE or ',' or '}' ] get '" + JSONToken.token2string(token.type) + "'"); + } + break; + } + case OBJECT_VALUE: { + switch (token.type) { + case JSONToken.COLON: + break; + case JSONToken.NULL: { + handler.objectItemValue(token.value, true); + state = OBJECT_ITEM; + break; + } + case JSONToken.BOOL: { + handler.objectItemValue(token.value, true); + state = OBJECT_ITEM; + break; + } + case JSONToken.INT: { + handler.objectItemValue(token.value, true); + state = OBJECT_ITEM; + break; + } + case JSONToken.FLOAT: { + handler.objectItemValue(token.value, true); + state = OBJECT_ITEM; + break; + } + case JSONToken.STRING: { + handler.objectItemValue(token.value, true); + state = OBJECT_ITEM; + break; + } + case JSONToken.LSQUARE: { + states.push(new int[]{OBJECT_ITEM, index}); + + index = 0; + state = ARRAY_ITEM; + handler.arrayBegin(); + break; + } + case JSONToken.LBRACE: { + states.push(new int[]{OBJECT_ITEM, index}); + + index = 0; + state = OBJECT_ITEM; + handler.objectBegin(); + break; + } + default: + throw new ParseException("Unexcepted token expect [ VALUE or '[' or '{' ] get '" + JSONToken.token2string(token.type) + "'"); + } + break; + } + default: + throw new ParseException("Unexcepted state."); + } + } + while ((token = jr.nextToken()) != null); + states.clear(); + return handler.end(value, pv); + } + + private static class Entry { + byte state; + Object value; + + Entry(byte s, Object v) { + state = s; + value = v; + } + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSONArray.java b/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSONArray.java index a75bedbdd4..d1947da02d 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSONArray.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSONArray.java @@ -1,184 +1,184 @@ -/* - * 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.common.json; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -/** - * JSONArray. - */ -@Deprecated -public class JSONArray implements JSONNode { - private List mArray = new ArrayList(); - - /** - * get. - * - * @param index index. - * @return boolean or long or double or String or JSONArray or JSONObject or null. - */ - public Object get(int index) { - return mArray.get(index); - } - - /** - * get boolean value. - * - * @param index index. - * @param def default value. - * @return value or default value. - */ - public boolean getBoolean(int index, boolean def) { - Object tmp = mArray.get(index); - return tmp instanceof Boolean ? ((Boolean) tmp).booleanValue() : def; - } - - /** - * get int value. - * - * @param index index. - * @param def default value. - * @return value or default value. - */ - public int getInt(int index, int def) { - Object tmp = mArray.get(index); - return tmp instanceof Number ? ((Number) tmp).intValue() : def; - } - - /** - * get long value. - * - * @param index index. - * @param def default value. - * @return value or default value. - */ - public long getLong(int index, long def) { - Object tmp = mArray.get(index); - return tmp instanceof Number ? ((Number) tmp).longValue() : def; - } - - /** - * get float value. - * - * @param index index. - * @param def default value. - * @return value or default value. - */ - public float getFloat(int index, float def) { - Object tmp = mArray.get(index); - return tmp instanceof Number ? ((Number) tmp).floatValue() : def; - } - - /** - * get double value. - * - * @param index index. - * @param def default value. - * @return value or default value. - */ - public double getDouble(int index, double def) { - Object tmp = mArray.get(index); - return tmp instanceof Number ? ((Number) tmp).doubleValue() : def; - } - - /** - * get string value. - * - * @param index index. - * @return value or default value. - */ - public String getString(int index) { - Object tmp = mArray.get(index); - return tmp == null ? null : tmp.toString(); - } - - /** - * get JSONArray value. - * - * @param index index. - * @return value or default value. - */ - public JSONArray getArray(int index) { - Object tmp = mArray.get(index); - return tmp == null ? null : tmp instanceof JSONArray ? (JSONArray) tmp : null; - } - - /** - * get JSONObject value. - * - * @param index index. - * @return value or default value. - */ - public JSONObject getObject(int index) { - Object tmp = mArray.get(index); - return tmp == null ? null : tmp instanceof JSONObject ? (JSONObject) tmp : null; - } - - /** - * get array length. - * - * @return length. - */ - public int length() { - return mArray.size(); - } - - /** - * add item. - */ - public void add(Object ele) { - mArray.add(ele); - } - - /** - * add items. - */ - public void addAll(Object[] eles) { - for (Object ele : eles) { - mArray.add(ele); - } - } - - /** - * add items. - */ - public void addAll(Collection c) { - mArray.addAll(c); - } - - /** - * write json. - * - * @param jc json converter - * @param jb json builder. - */ - @Override - public void writeJSON(JSONConverter jc, JSONWriter jb, boolean writeClass) throws IOException { - jb.arrayBegin(); - for (Object item : mArray) { - if (item == null) { - jb.valueNull(); - } else { - jc.writeValue(item, jb, writeClass); - } - } - jb.arrayEnd(); - } -} +/* + * 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.common.json; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * JSONArray. + */ +@Deprecated +public class JSONArray implements JSONNode { + private List mArray = new ArrayList(); + + /** + * get. + * + * @param index index. + * @return boolean or long or double or String or JSONArray or JSONObject or null. + */ + public Object get(int index) { + return mArray.get(index); + } + + /** + * get boolean value. + * + * @param index index. + * @param def default value. + * @return value or default value. + */ + public boolean getBoolean(int index, boolean def) { + Object tmp = mArray.get(index); + return tmp instanceof Boolean ? ((Boolean) tmp).booleanValue() : def; + } + + /** + * get int value. + * + * @param index index. + * @param def default value. + * @return value or default value. + */ + public int getInt(int index, int def) { + Object tmp = mArray.get(index); + return tmp instanceof Number ? ((Number) tmp).intValue() : def; + } + + /** + * get long value. + * + * @param index index. + * @param def default value. + * @return value or default value. + */ + public long getLong(int index, long def) { + Object tmp = mArray.get(index); + return tmp instanceof Number ? ((Number) tmp).longValue() : def; + } + + /** + * get float value. + * + * @param index index. + * @param def default value. + * @return value or default value. + */ + public float getFloat(int index, float def) { + Object tmp = mArray.get(index); + return tmp instanceof Number ? ((Number) tmp).floatValue() : def; + } + + /** + * get double value. + * + * @param index index. + * @param def default value. + * @return value or default value. + */ + public double getDouble(int index, double def) { + Object tmp = mArray.get(index); + return tmp instanceof Number ? ((Number) tmp).doubleValue() : def; + } + + /** + * get string value. + * + * @param index index. + * @return value or default value. + */ + public String getString(int index) { + Object tmp = mArray.get(index); + return tmp == null ? null : tmp.toString(); + } + + /** + * get JSONArray value. + * + * @param index index. + * @return value or default value. + */ + public JSONArray getArray(int index) { + Object tmp = mArray.get(index); + return tmp == null ? null : tmp instanceof JSONArray ? (JSONArray) tmp : null; + } + + /** + * get JSONObject value. + * + * @param index index. + * @return value or default value. + */ + public JSONObject getObject(int index) { + Object tmp = mArray.get(index); + return tmp == null ? null : tmp instanceof JSONObject ? (JSONObject) tmp : null; + } + + /** + * get array length. + * + * @return length. + */ + public int length() { + return mArray.size(); + } + + /** + * add item. + */ + public void add(Object ele) { + mArray.add(ele); + } + + /** + * add items. + */ + public void addAll(Object[] eles) { + for (Object ele : eles) { + mArray.add(ele); + } + } + + /** + * add items. + */ + public void addAll(Collection c) { + mArray.addAll(c); + } + + /** + * write json. + * + * @param jc json converter + * @param jb json builder. + */ + @Override + public void writeJSON(JSONConverter jc, JSONWriter jb, boolean writeClass) throws IOException { + jb.arrayBegin(); + for (Object item : mArray) { + if (item == null) { + jb.valueNull(); + } else { + jc.writeValue(item, jb, writeClass); + } + } + jb.arrayEnd(); + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSONConverter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSONConverter.java index e9fe94c03e..22260298ce 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSONConverter.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSONConverter.java @@ -41,4 +41,4 @@ public interface JSONConverter { * @throws IOException */ Object readValue(Class type, Object jv) throws IOException; -} \ No newline at end of file +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSONNode.java b/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSONNode.java index 0e7531b164..6d2fa2f756 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSONNode.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSONNode.java @@ -1,34 +1,34 @@ -/* - * 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.common.json; - -import java.io.IOException; - -/** - * JSONSerializable. - */ -@Deprecated -interface JSONNode { - /** - * write json string. - * - * @param jc json converter. - * @param jb json builder. - * @throws IOException - */ - void writeJSON(JSONConverter jc, JSONWriter jb, boolean writeClass) throws IOException; -} \ No newline at end of file +/* + * 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.common.json; + +import java.io.IOException; + +/** + * JSONSerializable. + */ +@Deprecated +interface JSONNode { + /** + * write json string. + * + * @param jc json converter. + * @param jb json builder. + * @throws IOException + */ + void writeJSON(JSONConverter jc, JSONWriter jb, boolean writeClass) throws IOException; +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSONObject.java b/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSONObject.java index c04d4e1405..d1634a8a59 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSONObject.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSONObject.java @@ -1,209 +1,209 @@ -/* - * 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.common.json; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -/** - * JSONObject. - */ -@Deprecated -public class JSONObject implements JSONNode { - private Map mMap = new HashMap(); - - /** - * get. - * - * @param key key. - * @return boolean or long or double or String or JSONArray or JSONObject or null. - */ - public Object get(String key) { - return mMap.get(key); - } - - /** - * get boolean value. - * - * @param key key. - * @param def default value. - * @return value or default value. - */ - public boolean getBoolean(String key, boolean def) { - Object tmp = mMap.get(key); - return tmp instanceof Boolean ? (Boolean) tmp : def; - } - - /** - * get int value. - * - * @param key key. - * @param def default value. - * @return value or default value. - */ - public int getInt(String key, int def) { - Object tmp = mMap.get(key); - return tmp instanceof Number ? ((Number) tmp).intValue() : def; - } - - /** - * get long value. - * - * @param key key. - * @param def default value. - * @return value or default value. - */ - public long getLong(String key, long def) { - Object tmp = mMap.get(key); - return tmp instanceof Number ? ((Number) tmp).longValue() : def; - } - - /** - * get float value. - * - * @param key key. - * @param def default value. - * @return value or default value. - */ - public float getFloat(String key, float def) { - Object tmp = mMap.get(key); - return tmp instanceof Number ? ((Number) tmp).floatValue() : def; - } - - /** - * get double value. - * - * @param key key. - * @param def default value. - * @return value or default value. - */ - public double getDouble(String key, double def) { - Object tmp = mMap.get(key); - return tmp instanceof Number ? ((Number) tmp).doubleValue() : def; - } - - /** - * get string value. - * - * @param key key. - * @return value or default value. - */ - public String getString(String key) { - Object tmp = mMap.get(key); - return tmp == null ? null : tmp.toString(); - } - - /** - * get JSONArray value. - * - * @param key key. - * @return value or default value. - */ - public JSONArray getArray(String key) { - Object tmp = mMap.get(key); - return tmp == null ? null : tmp instanceof JSONArray ? (JSONArray) tmp : null; - } - - /** - * get JSONObject value. - * - * @param key key. - * @return value or default value. - */ - public JSONObject getObject(String key) { - Object tmp = mMap.get(key); - return tmp == null ? null : tmp instanceof JSONObject ? (JSONObject) tmp : null; - } - - /** - * get key iterator. - * - * @return key iterator. - */ - public Iterator keys() { - return mMap.keySet().iterator(); - } - - /** - * contains key. - * - * @param key key. - * @return contains or not. - */ - public boolean contains(String key) { - return mMap.containsKey(key); - } - - /** - * put value. - * - * @param name name. - * @param value value. - */ - public void put(String name, Object value) { - mMap.put(name, value); - } - - /** - * put all. - * - * @param names name array. - * @param values value array. - */ - public void putAll(String[] names, Object[] values) { - for (int i = 0, len = Math.min(names.length, values.length); i < len; i++) { - mMap.put(names[i], values[i]); - } - } - - /** - * put all. - * - * @param map map. - */ - public void putAll(Map map) { - for (Map.Entry entry : map.entrySet()) { - mMap.put(entry.getKey(), entry.getValue()); - } - } - - /** - * write json. - * - * @param jc json converter. - * @param jb json builder. - */ - @Override - public void writeJSON(JSONConverter jc, JSONWriter jb, boolean writeClass) throws IOException { - String key; - Object value; - jb.objectBegin(); - for (Map.Entry entry : mMap.entrySet()) { - key = entry.getKey(); - jb.objectItem(key); - value = entry.getValue(); - if (value == null) { - jb.valueNull(); - } else { - jc.writeValue(value, jb, writeClass); - } - } - jb.objectEnd(); - } -} +/* + * 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.common.json; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * JSONObject. + */ +@Deprecated +public class JSONObject implements JSONNode { + private Map mMap = new HashMap(); + + /** + * get. + * + * @param key key. + * @return boolean or long or double or String or JSONArray or JSONObject or null. + */ + public Object get(String key) { + return mMap.get(key); + } + + /** + * get boolean value. + * + * @param key key. + * @param def default value. + * @return value or default value. + */ + public boolean getBoolean(String key, boolean def) { + Object tmp = mMap.get(key); + return tmp instanceof Boolean ? (Boolean) tmp : def; + } + + /** + * get int value. + * + * @param key key. + * @param def default value. + * @return value or default value. + */ + public int getInt(String key, int def) { + Object tmp = mMap.get(key); + return tmp instanceof Number ? ((Number) tmp).intValue() : def; + } + + /** + * get long value. + * + * @param key key. + * @param def default value. + * @return value or default value. + */ + public long getLong(String key, long def) { + Object tmp = mMap.get(key); + return tmp instanceof Number ? ((Number) tmp).longValue() : def; + } + + /** + * get float value. + * + * @param key key. + * @param def default value. + * @return value or default value. + */ + public float getFloat(String key, float def) { + Object tmp = mMap.get(key); + return tmp instanceof Number ? ((Number) tmp).floatValue() : def; + } + + /** + * get double value. + * + * @param key key. + * @param def default value. + * @return value or default value. + */ + public double getDouble(String key, double def) { + Object tmp = mMap.get(key); + return tmp instanceof Number ? ((Number) tmp).doubleValue() : def; + } + + /** + * get string value. + * + * @param key key. + * @return value or default value. + */ + public String getString(String key) { + Object tmp = mMap.get(key); + return tmp == null ? null : tmp.toString(); + } + + /** + * get JSONArray value. + * + * @param key key. + * @return value or default value. + */ + public JSONArray getArray(String key) { + Object tmp = mMap.get(key); + return tmp == null ? null : tmp instanceof JSONArray ? (JSONArray) tmp : null; + } + + /** + * get JSONObject value. + * + * @param key key. + * @return value or default value. + */ + public JSONObject getObject(String key) { + Object tmp = mMap.get(key); + return tmp == null ? null : tmp instanceof JSONObject ? (JSONObject) tmp : null; + } + + /** + * get key iterator. + * + * @return key iterator. + */ + public Iterator keys() { + return mMap.keySet().iterator(); + } + + /** + * contains key. + * + * @param key key. + * @return contains or not. + */ + public boolean contains(String key) { + return mMap.containsKey(key); + } + + /** + * put value. + * + * @param name name. + * @param value value. + */ + public void put(String name, Object value) { + mMap.put(name, value); + } + + /** + * put all. + * + * @param names name array. + * @param values value array. + */ + public void putAll(String[] names, Object[] values) { + for (int i = 0, len = Math.min(names.length, values.length); i < len; i++) { + mMap.put(names[i], values[i]); + } + } + + /** + * put all. + * + * @param map map. + */ + public void putAll(Map map) { + for (Map.Entry entry : map.entrySet()) { + mMap.put(entry.getKey(), entry.getValue()); + } + } + + /** + * write json. + * + * @param jc json converter. + * @param jb json builder. + */ + @Override + public void writeJSON(JSONConverter jc, JSONWriter jb, boolean writeClass) throws IOException { + String key; + Object value; + jb.objectBegin(); + for (Map.Entry entry : mMap.entrySet()) { + key = entry.getKey(); + jb.objectItem(key); + value = entry.getValue(); + if (value == null) { + jb.valueNull(); + } else { + jc.writeValue(value, jb, writeClass); + } + } + jb.objectEnd(); + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSONReader.java b/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSONReader.java index 616a15f597..47113fccf8 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSONReader.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSONReader.java @@ -65,4 +65,4 @@ public class JSONReader { } return ret; } -} \ No newline at end of file +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSONToken.java b/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSONToken.java index 7e363c9f20..4620f76c9c 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSONToken.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSONToken.java @@ -1,72 +1,72 @@ -/* - * 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.common.json; - -/** - * JSONToken. - */ -@Deprecated -public class JSONToken { - // token type - public static final int ANY = 0, IDENT = 0x01, LBRACE = 0x02, LSQUARE = 0x03, RBRACE = 0x04, RSQUARE = 0x05, COMMA = 0x06, COLON = 0x07; - - public static final int NULL = 0x10, BOOL = 0x11, INT = 0x12, FLOAT = 0x13, STRING = 0x14, ARRAY = 0x15, OBJECT = 0x16; - - public final int type; - - public final Object value; - - JSONToken(int t) { - this(t, null); - } - - JSONToken(int t, Object v) { - type = t; - value = v; - } - - static String token2string(int t) { - switch (t) { - case LBRACE: - return "{"; - case RBRACE: - return "}"; - case LSQUARE: - return "["; - case RSQUARE: - return "]"; - case COMMA: - return ","; - case COLON: - return ":"; - case IDENT: - return "IDENT"; - case NULL: - return "NULL"; - case BOOL: - return "BOOL VALUE"; - case INT: - return "INT VALUE"; - case FLOAT: - return "FLOAT VALUE"; - case STRING: - return "STRING VALUE"; - default: - return "ANY"; - } - } -} \ No newline at end of file +/* + * 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.common.json; + +/** + * JSONToken. + */ +@Deprecated +public class JSONToken { + // token type + public static final int ANY = 0, IDENT = 0x01, LBRACE = 0x02, LSQUARE = 0x03, RBRACE = 0x04, RSQUARE = 0x05, COMMA = 0x06, COLON = 0x07; + + public static final int NULL = 0x10, BOOL = 0x11, INT = 0x12, FLOAT = 0x13, STRING = 0x14, ARRAY = 0x15, OBJECT = 0x16; + + public final int type; + + public final Object value; + + JSONToken(int t) { + this(t, null); + } + + JSONToken(int t, Object v) { + type = t; + value = v; + } + + static String token2string(int t) { + switch (t) { + case LBRACE: + return "{"; + case RBRACE: + return "}"; + case LSQUARE: + return "["; + case RSQUARE: + return "]"; + case COMMA: + return ","; + case COLON: + return ":"; + case IDENT: + return "IDENT"; + case NULL: + return "NULL"; + case BOOL: + return "BOOL VALUE"; + case INT: + return "INT VALUE"; + case FLOAT: + return "FLOAT VALUE"; + case STRING: + return "STRING VALUE"; + default: + return "ANY"; + } + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSONVisitor.java b/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSONVisitor.java index 3847ef118d..c2547eede6 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSONVisitor.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSONVisitor.java @@ -1,107 +1,107 @@ -/* - * 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.common.json; - -/** - * JSONVisitor. - */ -@Deprecated -public interface JSONVisitor { - String CLASS_PROPERTY = "class"; - - /** - * parse begin . - */ - void begin(); - - /** - * parse end. - * - * @param obj root obj. - * @param isValue is json value. - * @return parse result. - * @throws ParseException - */ - Object end(Object obj, boolean isValue) throws ParseException; - - /** - * object begin. - * - * @throws ParseException - */ - void objectBegin() throws ParseException; - - /** - * object end, return object value. - * - * @param count property count. - * @return object value. - * @throws ParseException - */ - Object objectEnd(int count) throws ParseException; - - /** - * object property name. - * - * @param name name. - * @throws ParseException - */ - void objectItem(String name) throws ParseException; - - /** - * object property value. - * - * @param obj obj. - * @param isValue is json value. - * @throws ParseException - */ - void objectItemValue(Object obj, boolean isValue) throws ParseException; - - /** - * array begin. - * - * @throws ParseException - */ - void arrayBegin() throws ParseException; - - /** - * array end, return array value. - * - * @param count count. - * @return array value. - * @throws ParseException - */ - Object arrayEnd(int count) throws ParseException; - - /** - * array item. - * - * @param index index. - * @throws ParseException - */ - void arrayItem(int index) throws ParseException; - - /** - * array item. - * - * @param index index. - * @param obj item. - * @param isValue is json value. - * @throws ParseException - */ - void arrayItemValue(int index, Object obj, boolean isValue) throws ParseException; -} \ No newline at end of file +/* + * 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.common.json; + +/** + * JSONVisitor. + */ +@Deprecated +public interface JSONVisitor { + String CLASS_PROPERTY = "class"; + + /** + * parse begin . + */ + void begin(); + + /** + * parse end. + * + * @param obj root obj. + * @param isValue is json value. + * @return parse result. + * @throws ParseException + */ + Object end(Object obj, boolean isValue) throws ParseException; + + /** + * object begin. + * + * @throws ParseException + */ + void objectBegin() throws ParseException; + + /** + * object end, return object value. + * + * @param count property count. + * @return object value. + * @throws ParseException + */ + Object objectEnd(int count) throws ParseException; + + /** + * object property name. + * + * @param name name. + * @throws ParseException + */ + void objectItem(String name) throws ParseException; + + /** + * object property value. + * + * @param obj obj. + * @param isValue is json value. + * @throws ParseException + */ + void objectItemValue(Object obj, boolean isValue) throws ParseException; + + /** + * array begin. + * + * @throws ParseException + */ + void arrayBegin() throws ParseException; + + /** + * array end, return array value. + * + * @param count count. + * @return array value. + * @throws ParseException + */ + Object arrayEnd(int count) throws ParseException; + + /** + * array item. + * + * @param index index. + * @throws ParseException + */ + void arrayItem(int index) throws ParseException; + + /** + * array item. + * + * @param index index. + * @param obj item. + * @param isValue is json value. + * @throws ParseException + */ + void arrayItemValue(int index, Object obj, boolean isValue) throws ParseException; +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSONWriter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSONWriter.java index 6c6bf09c0f..35d4f5a502 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSONWriter.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSONWriter.java @@ -1,305 +1,305 @@ -/* - * 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.common.json; - -import org.apache.dubbo.common.utils.Stack; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.UnsupportedEncodingException; -import java.io.Writer; - -/** - * JSON Writer. - *

- * w.objectBegin().objectItem("name").valueString("qianlei").objectEnd() = {name:"qianlei"}. - */ -@Deprecated -public class JSONWriter { - private static final byte UNKNOWN = 0, ARRAY = 1, OBJECT = 2, OBJECT_VALUE = 3; - private static final String[] CONTROL_CHAR_MAP = new String[]{ - "\\u0000", "\\u0001", "\\u0002", "\\u0003", "\\u0004", "\\u0005", "\\u0006", "\\u0007", - "\\b", "\\t", "\\n", "\\u000b", "\\f", "\\r", "\\u000e", "\\u000f", - "\\u0010", "\\u0011", "\\u0012", "\\u0013", "\\u0014", "\\u0015", "\\u0016", "\\u0017", - "\\u0018", "\\u0019", "\\u001a", "\\u001b", "\\u001c", "\\u001d", "\\u001e", "\\u001f" - }; - private Writer mWriter; - - private State mState = new State(UNKNOWN); - - private Stack mStack = new Stack(); - - public JSONWriter(Writer writer) { - mWriter = writer; - } - - public JSONWriter(OutputStream is, String charset) throws UnsupportedEncodingException { - mWriter = new OutputStreamWriter(is, charset); - } - - private static String escape(String str) { - if (str == null) { - return str; - } - int len = str.length(); - if (len == 0) { - return str; - } - - char c; - StringBuilder sb = null; - for (int i = 0; i < len; i++) { - c = str.charAt(i); - if (c < ' ') // control char. - { - if (sb == null) { - sb = new StringBuilder(len << 1); - sb.append(str, 0, i); - } - sb.append(CONTROL_CHAR_MAP[c]); - } else { - switch (c) { - case '\\': - case '/': - case '"': - if (sb == null) { - sb = new StringBuilder(len << 1); - sb.append(str, 0, i); - } - sb.append('\\').append(c); - break; - default: - if (sb != null) { - sb.append(c); - } - } - } - } - return sb == null ? str : sb.toString(); - } - - /** - * object begin. - * - * @return this. - * @throws IOException - */ - public JSONWriter objectBegin() throws IOException { - beforeValue(); - - mWriter.write(JSON.LBRACE); - mStack.push(mState); - mState = new State(OBJECT); - return this; - } - - /** - * object end. - * - * @return this. - * @throws IOException - */ - public JSONWriter objectEnd() throws IOException { - mWriter.write(JSON.RBRACE); - mState = mStack.pop(); - return this; - } - - /** - * object item. - * - * @param name name. - * @return this. - * @throws IOException - */ - public JSONWriter objectItem(String name) throws IOException { - beforeObjectItem(); - - mWriter.write(JSON.QUOTE); - mWriter.write(escape(name)); - mWriter.write(JSON.QUOTE); - mWriter.write(JSON.COLON); - return this; - } - - /** - * array begin. - * - * @return this. - * @throws IOException - */ - public JSONWriter arrayBegin() throws IOException { - beforeValue(); - - mWriter.write(JSON.LSQUARE); - mStack.push(mState); - mState = new State(ARRAY); - return this; - } - - /** - * array end, return array value. - * - * @return this. - * @throws IOException - */ - public JSONWriter arrayEnd() throws IOException { - mWriter.write(JSON.RSQUARE); - mState = mStack.pop(); - return this; - } - - /** - * value. - * - * @return this. - * @throws IOException - */ - public JSONWriter valueNull() throws IOException { - beforeValue(); - - mWriter.write(JSON.NULL); - return this; - } - - /** - * value. - * - * @param value value. - * @return this. - * @throws IOException - */ - public JSONWriter valueString(String value) throws IOException { - beforeValue(); - - mWriter.write(JSON.QUOTE); - mWriter.write(escape(value)); - mWriter.write(JSON.QUOTE); - return this; - } - - /** - * value. - * - * @param value value. - * @return this. - * @throws IOException - */ - public JSONWriter valueBoolean(boolean value) throws IOException { - beforeValue(); - - mWriter.write(value ? "true" : "false"); - return this; - } - - /** - * value. - * - * @param value value. - * @return this. - * @throws IOException - */ - public JSONWriter valueInt(int value) throws IOException { - beforeValue(); - - mWriter.write(String.valueOf(value)); - return this; - } - - /** - * value. - * - * @param value value. - * @return this. - * @throws IOException - */ - public JSONWriter valueLong(long value) throws IOException { - beforeValue(); - - mWriter.write(String.valueOf(value)); - return this; - } - - /** - * value. - * - * @param value value. - * @return this. - * @throws IOException - */ - public JSONWriter valueFloat(float value) throws IOException { - beforeValue(); - - mWriter.write(String.valueOf(value)); - return this; - } - - /** - * value. - * - * @param value value. - * @return this. - * @throws IOException - */ - public JSONWriter valueDouble(double value) throws IOException { - beforeValue(); - - mWriter.write(String.valueOf(value)); - return this; - } - - private void beforeValue() throws IOException { - switch (mState.type) { - case ARRAY: - if (mState.itemCount++ > 0) { - mWriter.write(JSON.COMMA); - } - return; - case OBJECT: - throw new IOException("Must call objectItem first."); - case OBJECT_VALUE: - mState.type = OBJECT; - return; - default: - } - } - - private void beforeObjectItem() throws IOException { - switch (mState.type) { - case OBJECT_VALUE: - mWriter.write(JSON.NULL); - case OBJECT: - mState.type = OBJECT_VALUE; - if (mState.itemCount++ > 0) { - mWriter.write(JSON.COMMA); - } - return; - default: - throw new IOException("Must call objectBegin first."); - } - } - - private static class State { - private byte type; - private int itemCount = 0; - - State(byte t) { - type = t; - } - } -} \ No newline at end of file +/* + * 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.common.json; + +import org.apache.dubbo.common.utils.Stack; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.UnsupportedEncodingException; +import java.io.Writer; + +/** + * JSON Writer. + *

+ * w.objectBegin().objectItem("name").valueString("qianlei").objectEnd() = {name:"qianlei"}. + */ +@Deprecated +public class JSONWriter { + private static final byte UNKNOWN = 0, ARRAY = 1, OBJECT = 2, OBJECT_VALUE = 3; + private static final String[] CONTROL_CHAR_MAP = new String[]{ + "\\u0000", "\\u0001", "\\u0002", "\\u0003", "\\u0004", "\\u0005", "\\u0006", "\\u0007", + "\\b", "\\t", "\\n", "\\u000b", "\\f", "\\r", "\\u000e", "\\u000f", + "\\u0010", "\\u0011", "\\u0012", "\\u0013", "\\u0014", "\\u0015", "\\u0016", "\\u0017", + "\\u0018", "\\u0019", "\\u001a", "\\u001b", "\\u001c", "\\u001d", "\\u001e", "\\u001f" + }; + private Writer mWriter; + + private State mState = new State(UNKNOWN); + + private Stack mStack = new Stack(); + + public JSONWriter(Writer writer) { + mWriter = writer; + } + + public JSONWriter(OutputStream is, String charset) throws UnsupportedEncodingException { + mWriter = new OutputStreamWriter(is, charset); + } + + private static String escape(String str) { + if (str == null) { + return str; + } + int len = str.length(); + if (len == 0) { + return str; + } + + char c; + StringBuilder sb = null; + for (int i = 0; i < len; i++) { + c = str.charAt(i); + if (c < ' ') // control char. + { + if (sb == null) { + sb = new StringBuilder(len << 1); + sb.append(str, 0, i); + } + sb.append(CONTROL_CHAR_MAP[c]); + } else { + switch (c) { + case '\\': + case '/': + case '"': + if (sb == null) { + sb = new StringBuilder(len << 1); + sb.append(str, 0, i); + } + sb.append('\\').append(c); + break; + default: + if (sb != null) { + sb.append(c); + } + } + } + } + return sb == null ? str : sb.toString(); + } + + /** + * object begin. + * + * @return this. + * @throws IOException + */ + public JSONWriter objectBegin() throws IOException { + beforeValue(); + + mWriter.write(JSON.LBRACE); + mStack.push(mState); + mState = new State(OBJECT); + return this; + } + + /** + * object end. + * + * @return this. + * @throws IOException + */ + public JSONWriter objectEnd() throws IOException { + mWriter.write(JSON.RBRACE); + mState = mStack.pop(); + return this; + } + + /** + * object item. + * + * @param name name. + * @return this. + * @throws IOException + */ + public JSONWriter objectItem(String name) throws IOException { + beforeObjectItem(); + + mWriter.write(JSON.QUOTE); + mWriter.write(escape(name)); + mWriter.write(JSON.QUOTE); + mWriter.write(JSON.COLON); + return this; + } + + /** + * array begin. + * + * @return this. + * @throws IOException + */ + public JSONWriter arrayBegin() throws IOException { + beforeValue(); + + mWriter.write(JSON.LSQUARE); + mStack.push(mState); + mState = new State(ARRAY); + return this; + } + + /** + * array end, return array value. + * + * @return this. + * @throws IOException + */ + public JSONWriter arrayEnd() throws IOException { + mWriter.write(JSON.RSQUARE); + mState = mStack.pop(); + return this; + } + + /** + * value. + * + * @return this. + * @throws IOException + */ + public JSONWriter valueNull() throws IOException { + beforeValue(); + + mWriter.write(JSON.NULL); + return this; + } + + /** + * value. + * + * @param value value. + * @return this. + * @throws IOException + */ + public JSONWriter valueString(String value) throws IOException { + beforeValue(); + + mWriter.write(JSON.QUOTE); + mWriter.write(escape(value)); + mWriter.write(JSON.QUOTE); + return this; + } + + /** + * value. + * + * @param value value. + * @return this. + * @throws IOException + */ + public JSONWriter valueBoolean(boolean value) throws IOException { + beforeValue(); + + mWriter.write(value ? "true" : "false"); + return this; + } + + /** + * value. + * + * @param value value. + * @return this. + * @throws IOException + */ + public JSONWriter valueInt(int value) throws IOException { + beforeValue(); + + mWriter.write(String.valueOf(value)); + return this; + } + + /** + * value. + * + * @param value value. + * @return this. + * @throws IOException + */ + public JSONWriter valueLong(long value) throws IOException { + beforeValue(); + + mWriter.write(String.valueOf(value)); + return this; + } + + /** + * value. + * + * @param value value. + * @return this. + * @throws IOException + */ + public JSONWriter valueFloat(float value) throws IOException { + beforeValue(); + + mWriter.write(String.valueOf(value)); + return this; + } + + /** + * value. + * + * @param value value. + * @return this. + * @throws IOException + */ + public JSONWriter valueDouble(double value) throws IOException { + beforeValue(); + + mWriter.write(String.valueOf(value)); + return this; + } + + private void beforeValue() throws IOException { + switch (mState.type) { + case ARRAY: + if (mState.itemCount++ > 0) { + mWriter.write(JSON.COMMA); + } + return; + case OBJECT: + throw new IOException("Must call objectItem first."); + case OBJECT_VALUE: + mState.type = OBJECT; + return; + default: + } + } + + private void beforeObjectItem() throws IOException { + switch (mState.type) { + case OBJECT_VALUE: + mWriter.write(JSON.NULL); + case OBJECT: + mState.type = OBJECT_VALUE; + if (mState.itemCount++ > 0) { + mWriter.write(JSON.COMMA); + } + return; + default: + throw new IOException("Must call objectBegin first."); + } + } + + private static class State { + private byte type; + private int itemCount = 0; + + State(byte t) { + type = t; + } + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/json/ParseException.java b/dubbo-common/src/main/java/org/apache/dubbo/common/json/ParseException.java index 4994e44ce3..65c2c27772 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/json/ParseException.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/json/ParseException.java @@ -1,33 +1,33 @@ -/* - * 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.common.json; - -/** - * ParseException. - */ -@Deprecated -public class ParseException extends Exception { - private static final long serialVersionUID = 8611884051738966316L; - - public ParseException() { - super(); - } - - public ParseException(String message) { - super(message); - } -} \ No newline at end of file +/* + * 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.common.json; + +/** + * ParseException. + */ +@Deprecated +public class ParseException extends Exception { + private static final long serialVersionUID = 8611884051738966316L; + + public ParseException() { + super(); + } + + public ParseException(String message) { + super(message); + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/json/Yylex.java b/dubbo-common/src/main/java/org/apache/dubbo/common/json/Yylex.java index 32a73a7589..ca63280d33 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/json/Yylex.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/json/Yylex.java @@ -844,4 +844,4 @@ public class Yylex { } -} \ No newline at end of file +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/lang/ShutdownHookCallbacks.java b/dubbo-common/src/main/java/org/apache/dubbo/common/lang/ShutdownHookCallbacks.java index 385f7b22cf..e1d01a2119 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/lang/ShutdownHookCallbacks.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/lang/ShutdownHookCallbacks.java @@ -69,4 +69,4 @@ public class ShutdownHookCallbacks { public void callback() { getCallbacks().forEach(callback -> execute(callback::callback)); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/Level.java b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/Level.java index e4ef5391db..7e615de436 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/Level.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/Level.java @@ -1,59 +1,59 @@ -/* - * 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.common.logger; - -/** - * Level - */ -public enum Level { - - /** - * ALL - */ - ALL, - - /** - * TRACE - */ - TRACE, - - /** - * DEBUG - */ - DEBUG, - - /** - * INFO - */ - INFO, - - /** - * WARN - */ - WARN, - - /** - * ERROR - */ - ERROR, - - /** - * OFF - */ - OFF - -} \ No newline at end of file +/* + * 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.common.logger; + +/** + * Level + */ +public enum Level { + + /** + * ALL + */ + ALL, + + /** + * TRACE + */ + TRACE, + + /** + * DEBUG + */ + DEBUG, + + /** + * INFO + */ + INFO, + + /** + * WARN + */ + WARN, + + /** + * ERROR + */ + ERROR, + + /** + * OFF + */ + OFF + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/Logger.java b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/Logger.java index c505326d0c..511dd8a66d 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/Logger.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/Logger.java @@ -168,4 +168,4 @@ public interface Logger { */ boolean isErrorEnabled(); -} \ No newline at end of file +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/LoggerAdapter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/LoggerAdapter.java index 3300b3cb2f..1560c64f26 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/LoggerAdapter.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/LoggerAdapter.java @@ -69,4 +69,4 @@ public interface LoggerAdapter { * @param file logging file */ void setFile(File file); -} \ No newline at end of file +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/jcl/JclLogger.java b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/jcl/JclLogger.java index 59e30e24bb..7e23a681c6 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/jcl/JclLogger.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/jcl/JclLogger.java @@ -1,139 +1,139 @@ -/* - * 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.common.logger.jcl; - -import org.apache.dubbo.common.logger.Logger; - -import org.apache.commons.logging.Log; - -import java.io.Serializable; - -/** - * Adaptor to commons logging, depends on commons-logging.jar. For more information about commons logging, pls. refer to - * http://www.apache.org/ - */ -public class JclLogger implements Logger, Serializable { - - private static final long serialVersionUID = 1L; - - private final Log logger; - - public JclLogger(Log logger) { - this.logger = logger; - } - - @Override - public void trace(String msg) { - logger.trace(msg); - } - - @Override - public void trace(Throwable e) { - logger.trace(e); - } - - @Override - public void trace(String msg, Throwable e) { - logger.trace(msg, e); - } - - @Override - public void debug(String msg) { - logger.debug(msg); - } - - @Override - public void debug(Throwable e) { - logger.debug(e); - } - - @Override - public void debug(String msg, Throwable e) { - logger.debug(msg, e); - } - - @Override - public void info(String msg) { - logger.info(msg); - } - - @Override - public void info(Throwable e) { - logger.info(e); - } - - @Override - public void info(String msg, Throwable e) { - logger.info(msg, e); - } - - @Override - public void warn(String msg) { - logger.warn(msg); - } - - @Override - public void warn(Throwable e) { - logger.warn(e); - } - - @Override - public void warn(String msg, Throwable e) { - logger.warn(msg, e); - } - - @Override - public void error(String msg) { - logger.error(msg); - } - - @Override - public void error(Throwable e) { - logger.error(e); - } - - @Override - public void error(String msg, Throwable e) { - logger.error(msg, e); - } - - @Override - public boolean isTraceEnabled() { - return logger.isTraceEnabled(); - } - - @Override - public boolean isDebugEnabled() { - return logger.isDebugEnabled(); - } - - @Override - public boolean isInfoEnabled() { - return logger.isInfoEnabled(); - } - - @Override - public boolean isWarnEnabled() { - return logger.isWarnEnabled(); - } - - @Override - public boolean isErrorEnabled() { - return logger.isErrorEnabled(); - } - -} +/* + * 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.common.logger.jcl; + +import org.apache.dubbo.common.logger.Logger; + +import org.apache.commons.logging.Log; + +import java.io.Serializable; + +/** + * Adaptor to commons logging, depends on commons-logging.jar. For more information about commons logging, pls. refer to + * http://www.apache.org/ + */ +public class JclLogger implements Logger, Serializable { + + private static final long serialVersionUID = 1L; + + private final Log logger; + + public JclLogger(Log logger) { + this.logger = logger; + } + + @Override + public void trace(String msg) { + logger.trace(msg); + } + + @Override + public void trace(Throwable e) { + logger.trace(e); + } + + @Override + public void trace(String msg, Throwable e) { + logger.trace(msg, e); + } + + @Override + public void debug(String msg) { + logger.debug(msg); + } + + @Override + public void debug(Throwable e) { + logger.debug(e); + } + + @Override + public void debug(String msg, Throwable e) { + logger.debug(msg, e); + } + + @Override + public void info(String msg) { + logger.info(msg); + } + + @Override + public void info(Throwable e) { + logger.info(e); + } + + @Override + public void info(String msg, Throwable e) { + logger.info(msg, e); + } + + @Override + public void warn(String msg) { + logger.warn(msg); + } + + @Override + public void warn(Throwable e) { + logger.warn(e); + } + + @Override + public void warn(String msg, Throwable e) { + logger.warn(msg, e); + } + + @Override + public void error(String msg) { + logger.error(msg); + } + + @Override + public void error(Throwable e) { + logger.error(e); + } + + @Override + public void error(String msg, Throwable e) { + logger.error(msg, e); + } + + @Override + public boolean isTraceEnabled() { + return logger.isTraceEnabled(); + } + + @Override + public boolean isDebugEnabled() { + return logger.isDebugEnabled(); + } + + @Override + public boolean isInfoEnabled() { + return logger.isInfoEnabled(); + } + + @Override + public boolean isWarnEnabled() { + return logger.isWarnEnabled(); + } + + @Override + public boolean isErrorEnabled() { + return logger.isErrorEnabled(); + } + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/jcl/JclLoggerAdapter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/jcl/JclLoggerAdapter.java index 4ff23c66b9..959a5136df 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/jcl/JclLoggerAdapter.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/jcl/JclLoggerAdapter.java @@ -1,62 +1,62 @@ -/* - * 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.common.logger.jcl; - -import org.apache.dubbo.common.logger.Level; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerAdapter; - -import org.apache.commons.logging.LogFactory; - -import java.io.File; - -public class JclLoggerAdapter implements LoggerAdapter { - - private Level level; - private File file; - - @Override - public Logger getLogger(String key) { - return new JclLogger(LogFactory.getLog(key)); - } - - @Override - public Logger getLogger(Class key) { - return new JclLogger(LogFactory.getLog(key)); - } - - @Override - public Level getLevel() { - return level; - } - - @Override - public void setLevel(Level level) { - this.level = level; - } - - @Override - public File getFile() { - return file; - } - - @Override - public void setFile(File file) { - this.file = file; - } - -} +/* + * 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.common.logger.jcl; + +import org.apache.dubbo.common.logger.Level; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerAdapter; + +import org.apache.commons.logging.LogFactory; + +import java.io.File; + +public class JclLoggerAdapter implements LoggerAdapter { + + private Level level; + private File file; + + @Override + public Logger getLogger(String key) { + return new JclLogger(LogFactory.getLog(key)); + } + + @Override + public Logger getLogger(Class key) { + return new JclLogger(LogFactory.getLog(key)); + } + + @Override + public Level getLevel() { + return level; + } + + @Override + public void setLevel(Level level) { + this.level = level; + } + + @Override + public File getFile() { + return file; + } + + @Override + public void setFile(File file) { + this.file = file; + } + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/slf4j/Slf4jLogger.java b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/slf4j/Slf4jLogger.java index 20409d7fcb..f31c159e93 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/slf4j/Slf4jLogger.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/slf4j/Slf4jLogger.java @@ -1,205 +1,205 @@ -/* - * 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.common.logger.slf4j; - -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.support.FailsafeLogger; - -import org.slf4j.spi.LocationAwareLogger; - -import java.io.Serializable; - -public class Slf4jLogger implements Logger, Serializable { - - private static final long serialVersionUID = 1L; - - private static final String FQCN = FailsafeLogger.class.getName(); - - private final org.slf4j.Logger logger; - - private final LocationAwareLogger locationAwareLogger; - - public Slf4jLogger(org.slf4j.Logger logger) { - if (logger instanceof LocationAwareLogger) { - locationAwareLogger = (LocationAwareLogger) logger; - } else { - locationAwareLogger = null; - } - this.logger = logger; - } - - @Override - public void trace(String msg) { - if (locationAwareLogger != null) { - locationAwareLogger.log(null, FQCN, LocationAwareLogger.TRACE_INT, msg, null, null); - return; - } - logger.trace(msg); - } - - @Override - public void trace(Throwable e) { - if (locationAwareLogger != null) { - locationAwareLogger.log(null, FQCN, LocationAwareLogger.TRACE_INT, e.getMessage(), null, e); - return; - } - logger.trace(e.getMessage(), e); - } - - @Override - public void trace(String msg, Throwable e) { - if (locationAwareLogger != null) { - locationAwareLogger.log(null, FQCN, LocationAwareLogger.TRACE_INT, msg, null, e); - return; - } - logger.trace(msg, e); - } - - @Override - public void debug(String msg) { - if (locationAwareLogger != null) { - locationAwareLogger.log(null, FQCN, LocationAwareLogger.DEBUG_INT, msg, null, null); - return; - } - logger.debug(msg); - } - - @Override - public void debug(Throwable e) { - if (locationAwareLogger != null) { - locationAwareLogger.log(null, FQCN, LocationAwareLogger.DEBUG_INT, e.getMessage(), null, e); - return; - } - logger.debug(e.getMessage(), e); - } - - @Override - public void debug(String msg, Throwable e) { - if (locationAwareLogger != null) { - locationAwareLogger.log(null, FQCN, LocationAwareLogger.DEBUG_INT, msg, null, e); - return; - } - logger.debug(msg, e); - } - - @Override - public void info(String msg) { - if (locationAwareLogger != null) { - locationAwareLogger.log(null, FQCN, LocationAwareLogger.INFO_INT, msg, null, null); - return; - } - logger.info(msg); - } - - @Override - public void info(Throwable e) { - if (locationAwareLogger != null) { - locationAwareLogger.log(null, FQCN, LocationAwareLogger.INFO_INT, e.getMessage(), null, e); - return; - } - logger.info(e.getMessage(), e); - } - - @Override - public void info(String msg, Throwable e) { - if (locationAwareLogger != null) { - locationAwareLogger.log(null, FQCN, LocationAwareLogger.INFO_INT, msg, null, e); - return; - } - logger.info(msg, e); - } - - @Override - public void warn(String msg) { - if (locationAwareLogger != null) { - locationAwareLogger.log(null, FQCN, LocationAwareLogger.WARN_INT, msg, null, null); - return; - } - logger.warn(msg); - } - - @Override - public void warn(Throwable e) { - if (locationAwareLogger != null) { - locationAwareLogger.log(null, FQCN, LocationAwareLogger.WARN_INT, e.getMessage(), null, e); - return; - } - logger.warn(e.getMessage(), e); - } - - @Override - public void warn(String msg, Throwable e) { - if (locationAwareLogger != null) { - locationAwareLogger.log(null, FQCN, LocationAwareLogger.WARN_INT, msg, null, e); - return; - } - logger.warn(msg, e); - } - - @Override - public void error(String msg) { - if (locationAwareLogger != null) { - locationAwareLogger.log(null, FQCN, LocationAwareLogger.ERROR_INT, msg, null, null); - return; - } - logger.error(msg); - } - - @Override - public void error(Throwable e) { - if (locationAwareLogger != null) { - locationAwareLogger.log(null, FQCN, LocationAwareLogger.ERROR_INT, e.getMessage(), null, e); - return; - } - logger.error(e.getMessage(), e); - } - - @Override - public void error(String msg, Throwable e) { - if (locationAwareLogger != null) { - locationAwareLogger.log(null, FQCN, LocationAwareLogger.ERROR_INT, msg, null, e); - return; - } - logger.error(msg, e); - } - - @Override - public boolean isTraceEnabled() { - return logger.isTraceEnabled(); - } - - @Override - public boolean isDebugEnabled() { - return logger.isDebugEnabled(); - } - - @Override - public boolean isInfoEnabled() { - return logger.isInfoEnabled(); - } - - @Override - public boolean isWarnEnabled() { - return logger.isWarnEnabled(); - } - - @Override - public boolean isErrorEnabled() { - return logger.isErrorEnabled(); - } - -} +/* + * 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.common.logger.slf4j; + +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.support.FailsafeLogger; + +import org.slf4j.spi.LocationAwareLogger; + +import java.io.Serializable; + +public class Slf4jLogger implements Logger, Serializable { + + private static final long serialVersionUID = 1L; + + private static final String FQCN = FailsafeLogger.class.getName(); + + private final org.slf4j.Logger logger; + + private final LocationAwareLogger locationAwareLogger; + + public Slf4jLogger(org.slf4j.Logger logger) { + if (logger instanceof LocationAwareLogger) { + locationAwareLogger = (LocationAwareLogger) logger; + } else { + locationAwareLogger = null; + } + this.logger = logger; + } + + @Override + public void trace(String msg) { + if (locationAwareLogger != null) { + locationAwareLogger.log(null, FQCN, LocationAwareLogger.TRACE_INT, msg, null, null); + return; + } + logger.trace(msg); + } + + @Override + public void trace(Throwable e) { + if (locationAwareLogger != null) { + locationAwareLogger.log(null, FQCN, LocationAwareLogger.TRACE_INT, e.getMessage(), null, e); + return; + } + logger.trace(e.getMessage(), e); + } + + @Override + public void trace(String msg, Throwable e) { + if (locationAwareLogger != null) { + locationAwareLogger.log(null, FQCN, LocationAwareLogger.TRACE_INT, msg, null, e); + return; + } + logger.trace(msg, e); + } + + @Override + public void debug(String msg) { + if (locationAwareLogger != null) { + locationAwareLogger.log(null, FQCN, LocationAwareLogger.DEBUG_INT, msg, null, null); + return; + } + logger.debug(msg); + } + + @Override + public void debug(Throwable e) { + if (locationAwareLogger != null) { + locationAwareLogger.log(null, FQCN, LocationAwareLogger.DEBUG_INT, e.getMessage(), null, e); + return; + } + logger.debug(e.getMessage(), e); + } + + @Override + public void debug(String msg, Throwable e) { + if (locationAwareLogger != null) { + locationAwareLogger.log(null, FQCN, LocationAwareLogger.DEBUG_INT, msg, null, e); + return; + } + logger.debug(msg, e); + } + + @Override + public void info(String msg) { + if (locationAwareLogger != null) { + locationAwareLogger.log(null, FQCN, LocationAwareLogger.INFO_INT, msg, null, null); + return; + } + logger.info(msg); + } + + @Override + public void info(Throwable e) { + if (locationAwareLogger != null) { + locationAwareLogger.log(null, FQCN, LocationAwareLogger.INFO_INT, e.getMessage(), null, e); + return; + } + logger.info(e.getMessage(), e); + } + + @Override + public void info(String msg, Throwable e) { + if (locationAwareLogger != null) { + locationAwareLogger.log(null, FQCN, LocationAwareLogger.INFO_INT, msg, null, e); + return; + } + logger.info(msg, e); + } + + @Override + public void warn(String msg) { + if (locationAwareLogger != null) { + locationAwareLogger.log(null, FQCN, LocationAwareLogger.WARN_INT, msg, null, null); + return; + } + logger.warn(msg); + } + + @Override + public void warn(Throwable e) { + if (locationAwareLogger != null) { + locationAwareLogger.log(null, FQCN, LocationAwareLogger.WARN_INT, e.getMessage(), null, e); + return; + } + logger.warn(e.getMessage(), e); + } + + @Override + public void warn(String msg, Throwable e) { + if (locationAwareLogger != null) { + locationAwareLogger.log(null, FQCN, LocationAwareLogger.WARN_INT, msg, null, e); + return; + } + logger.warn(msg, e); + } + + @Override + public void error(String msg) { + if (locationAwareLogger != null) { + locationAwareLogger.log(null, FQCN, LocationAwareLogger.ERROR_INT, msg, null, null); + return; + } + logger.error(msg); + } + + @Override + public void error(Throwable e) { + if (locationAwareLogger != null) { + locationAwareLogger.log(null, FQCN, LocationAwareLogger.ERROR_INT, e.getMessage(), null, e); + return; + } + logger.error(e.getMessage(), e); + } + + @Override + public void error(String msg, Throwable e) { + if (locationAwareLogger != null) { + locationAwareLogger.log(null, FQCN, LocationAwareLogger.ERROR_INT, msg, null, e); + return; + } + logger.error(msg, e); + } + + @Override + public boolean isTraceEnabled() { + return logger.isTraceEnabled(); + } + + @Override + public boolean isDebugEnabled() { + return logger.isDebugEnabled(); + } + + @Override + public boolean isInfoEnabled() { + return logger.isInfoEnabled(); + } + + @Override + public boolean isWarnEnabled() { + return logger.isWarnEnabled(); + } + + @Override + public boolean isErrorEnabled() { + return logger.isErrorEnabled(); + } + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/slf4j/Slf4jLoggerAdapter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/slf4j/Slf4jLoggerAdapter.java index b23c461863..c28c8d8ef0 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/slf4j/Slf4jLoggerAdapter.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/slf4j/Slf4jLoggerAdapter.java @@ -1,60 +1,60 @@ -/* - * 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.common.logger.slf4j; - -import org.apache.dubbo.common.logger.Level; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerAdapter; - -import java.io.File; - -public class Slf4jLoggerAdapter implements LoggerAdapter { - - private Level level; - private File file; - - @Override - public Logger getLogger(String key) { - return new Slf4jLogger(org.slf4j.LoggerFactory.getLogger(key)); - } - - @Override - public Logger getLogger(Class key) { - return new Slf4jLogger(org.slf4j.LoggerFactory.getLogger(key)); - } - - @Override - public Level getLevel() { - return level; - } - - @Override - public void setLevel(Level level) { - this.level = level; - } - - @Override - public File getFile() { - return file; - } - - @Override - public void setFile(File file) { - this.file = file; - } - -} +/* + * 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.common.logger.slf4j; + +import org.apache.dubbo.common.logger.Level; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerAdapter; + +import java.io.File; + +public class Slf4jLoggerAdapter implements LoggerAdapter { + + private Level level; + private File file; + + @Override + public Logger getLogger(String key) { + return new Slf4jLogger(org.slf4j.LoggerFactory.getLogger(key)); + } + + @Override + public Logger getLogger(Class key) { + return new Slf4jLogger(org.slf4j.LoggerFactory.getLogger(key)); + } + + @Override + public Level getLevel() { + return level; + } + + @Override + public void setLevel(Level level) { + this.level = level; + } + + @Override + public File getFile() { + return file; + } + + @Override + public void setFile(File file) { + this.file = file; + } + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/status/Status.java b/dubbo-common/src/main/java/org/apache/dubbo/common/status/Status.java index db443b21c8..57ae3727e2 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/status/Status.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/status/Status.java @@ -1,79 +1,79 @@ -/* - * 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.common.status; - -/** - * Status - */ -public class Status { - - private final Level level; - private final String message; - private final String description; - - public Status(Level level) { - this(level, null, null); - } - - public Status(Level level, String message) { - this(level, message, null); - } - - public Status(Level level, String message, String description) { - this.level = level; - this.message = message; - this.description = description; - } - - public Level getLevel() { - return level; - } - - public String getMessage() { - return message; - } - - public String getDescription() { - return description; - } - - /** - * Level - */ - public enum Level { - /** - * OK - */ - OK, - - /** - * WARN - */ - WARN, - - /** - * ERROR - */ - ERROR, - - /** - * UNKNOWN - */ - UNKNOWN - } - -} \ No newline at end of file +/* + * 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.common.status; + +/** + * Status + */ +public class Status { + + private final Level level; + private final String message; + private final String description; + + public Status(Level level) { + this(level, null, null); + } + + public Status(Level level, String message) { + this(level, message, null); + } + + public Status(Level level, String message, String description) { + this.level = level; + this.message = message; + this.description = description; + } + + public Level getLevel() { + return level; + } + + public String getMessage() { + return message; + } + + public String getDescription() { + return description; + } + + /** + * Level + */ + public enum Level { + /** + * OK + */ + OK, + + /** + * WARN + */ + WARN, + + /** + * ERROR + */ + ERROR, + + /** + * UNKNOWN + */ + UNKNOWN + } + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/status/StatusChecker.java b/dubbo-common/src/main/java/org/apache/dubbo/common/status/StatusChecker.java index 368b85e78c..b5d7c41a6b 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/status/StatusChecker.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/status/StatusChecker.java @@ -1,34 +1,34 @@ -/* - * 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.common.status; - -import org.apache.dubbo.common.extension.SPI; - -/** - * StatusChecker - */ -@SPI -public interface StatusChecker { - - /** - * check status - * - * @return status - */ - Status check(); - -} \ No newline at end of file +/* + * 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.common.status; + +import org.apache.dubbo.common.extension.SPI; + +/** + * StatusChecker + */ +@SPI +public interface StatusChecker { + + /** + * check status + * + * @return status + */ + Status check(); + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/status/support/LoadStatusChecker.java b/dubbo-common/src/main/java/org/apache/dubbo/common/status/support/LoadStatusChecker.java index c5e2204a89..b2b4d180e9 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/status/support/LoadStatusChecker.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/status/support/LoadStatusChecker.java @@ -1,53 +1,53 @@ -/* - * 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.common.status.support; - -import org.apache.dubbo.common.extension.Activate; -import org.apache.dubbo.common.status.Status; -import org.apache.dubbo.common.status.StatusChecker; - -import java.lang.management.ManagementFactory; -import java.lang.management.OperatingSystemMXBean; -import java.lang.reflect.Method; - -/** - * Load Status - */ -@Activate -public class LoadStatusChecker implements StatusChecker { - - @Override - public Status check() { - OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean(); - double load; - try { - Method method = OperatingSystemMXBean.class.getMethod("getSystemLoadAverage", new Class[0]); - load = (Double) method.invoke(operatingSystemMXBean, new Object[0]); - if (load == -1) { - com.sun.management.OperatingSystemMXBean bean = - (com.sun.management.OperatingSystemMXBean) operatingSystemMXBean; - load = bean.getSystemCpuLoad(); - } - } catch (Throwable e) { - load = -1; - } - int cpu = operatingSystemMXBean.getAvailableProcessors(); - return new Status(load < 0 ? Status.Level.UNKNOWN : (load < cpu ? Status.Level.OK : Status.Level.WARN), - (load < 0 ? "" : "load:" + load + ",") + "cpu:" + cpu); - } - -} +/* + * 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.common.status.support; + +import org.apache.dubbo.common.extension.Activate; +import org.apache.dubbo.common.status.Status; +import org.apache.dubbo.common.status.StatusChecker; + +import java.lang.management.ManagementFactory; +import java.lang.management.OperatingSystemMXBean; +import java.lang.reflect.Method; + +/** + * Load Status + */ +@Activate +public class LoadStatusChecker implements StatusChecker { + + @Override + public Status check() { + OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean(); + double load; + try { + Method method = OperatingSystemMXBean.class.getMethod("getSystemLoadAverage", new Class[0]); + load = (Double) method.invoke(operatingSystemMXBean, new Object[0]); + if (load == -1) { + com.sun.management.OperatingSystemMXBean bean = + (com.sun.management.OperatingSystemMXBean) operatingSystemMXBean; + load = bean.getSystemCpuLoad(); + } + } catch (Throwable e) { + load = -1; + } + int cpu = operatingSystemMXBean.getAvailableProcessors(); + return new Status(load < 0 ? Status.Level.UNKNOWN : (load < cpu ? Status.Level.OK : Status.Level.WARN), + (load < 0 ? "" : "load:" + load + ",") + "cpu:" + cpu); + } + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/status/support/MemoryStatusChecker.java b/dubbo-common/src/main/java/org/apache/dubbo/common/status/support/MemoryStatusChecker.java index e81286dfcc..0f13000872 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/status/support/MemoryStatusChecker.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/status/support/MemoryStatusChecker.java @@ -1,41 +1,41 @@ -/* - * 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.common.status.support; - -import org.apache.dubbo.common.extension.Activate; -import org.apache.dubbo.common.status.Status; -import org.apache.dubbo.common.status.StatusChecker; - -/** - * MemoryStatus - */ -@Activate -public class MemoryStatusChecker implements StatusChecker { - - @Override - public Status check() { - Runtime runtime = Runtime.getRuntime(); - long freeMemory = runtime.freeMemory(); - long totalMemory = runtime.totalMemory(); - long maxMemory = runtime.maxMemory(); - boolean ok = (maxMemory - (totalMemory - freeMemory) > 2048); // Alarm when spare memory < 2M - String msg = "max:" + (maxMemory / 1024 / 1024) + "M,total:" - + (totalMemory / 1024 / 1024) + "M,used:" + ((totalMemory / 1024 / 1024) - (freeMemory / 1024 / 1024)) + "M,free:" + (freeMemory / 1024 / 1024) + "M"; - return new Status(ok ? Status.Level.OK : Status.Level.WARN, msg); - } - -} +/* + * 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.common.status.support; + +import org.apache.dubbo.common.extension.Activate; +import org.apache.dubbo.common.status.Status; +import org.apache.dubbo.common.status.StatusChecker; + +/** + * MemoryStatus + */ +@Activate +public class MemoryStatusChecker implements StatusChecker { + + @Override + public Status check() { + Runtime runtime = Runtime.getRuntime(); + long freeMemory = runtime.freeMemory(); + long totalMemory = runtime.totalMemory(); + long maxMemory = runtime.maxMemory(); + boolean ok = (maxMemory - (totalMemory - freeMemory) > 2048); // Alarm when spare memory < 2M + String msg = "max:" + (maxMemory / 1024 / 1024) + "M,total:" + + (totalMemory / 1024 / 1024) + "M,used:" + ((totalMemory / 1024 / 1024) - (freeMemory / 1024 / 1024)) + "M,free:" + (freeMemory / 1024 / 1024) + "M"; + return new Status(ok ? Status.Level.OK : Status.Level.WARN, msg); + } + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/status/support/StatusUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/status/support/StatusUtils.java index 21fb384113..15117cb6fc 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/status/support/StatusUtils.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/status/support/StatusUtils.java @@ -1,55 +1,55 @@ -/* - * 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.common.status.support; - -import org.apache.dubbo.common.status.Status; -import org.apache.dubbo.common.status.Status.Level; - -import java.util.Map; - -/** - * StatusManager - */ -public class StatusUtils { - - public static Status getSummaryStatus(Map statuses) { - Level level = Level.OK; - StringBuilder msg = new StringBuilder(); - for (Map.Entry entry : statuses.entrySet()) { - String key = entry.getKey(); - Status status = entry.getValue(); - Level l = status.getLevel(); - if (Level.ERROR.equals(l)) { - level = Level.ERROR; - if (msg.length() > 0) { - msg.append(","); - } - msg.append(key); - } else if (Level.WARN.equals(l)) { - if (!Level.ERROR.equals(level)) { - level = Level.WARN; - } - if (msg.length() > 0) { - msg.append(","); - } - msg.append(key); - } - } - return new Status(level, msg.toString()); - } - -} \ No newline at end of file +/* + * 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.common.status.support; + +import org.apache.dubbo.common.status.Status; +import org.apache.dubbo.common.status.Status.Level; + +import java.util.Map; + +/** + * StatusManager + */ +public class StatusUtils { + + public static Status getSummaryStatus(Map statuses) { + Level level = Level.OK; + StringBuilder msg = new StringBuilder(); + for (Map.Entry entry : statuses.entrySet()) { + String key = entry.getKey(); + Status status = entry.getValue(); + Level l = status.getLevel(); + if (Level.ERROR.equals(l)) { + level = Level.ERROR; + if (msg.length() > 0) { + msg.append(","); + } + msg.append(key); + } else if (Level.WARN.equals(l)) { + if (!Level.ERROR.equals(level)) { + level = Level.WARN; + } + if (msg.length() > 0) { + msg.append(","); + } + msg.append(key); + } + } + return new Status(level, msg.toString()); + } + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/AbortPolicyWithReport.java b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/AbortPolicyWithReport.java index a515175ba5..d00e6f1795 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/AbortPolicyWithReport.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/AbortPolicyWithReport.java @@ -1,170 +1,170 @@ -/* - * 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.common.threadpool.support; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.threadpool.event.ThreadPoolExhaustedEvent; -import org.apache.dubbo.common.threadpool.event.ThreadPoolExhaustedListener; -import org.apache.dubbo.common.utils.ConcurrentHashSet; -import org.apache.dubbo.common.utils.JVMUtil; -import org.apache.dubbo.common.utils.StringUtils; - -import java.io.File; -import java.io.FileOutputStream; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Set; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.Semaphore; -import java.util.concurrent.ThreadPoolExecutor; - -import static java.lang.String.format; -import static org.apache.dubbo.common.constants.CommonConstants.DUMP_DIRECTORY; - -/** - * Abort Policy. - * Log warn info when abort. - */ -public class AbortPolicyWithReport extends ThreadPoolExecutor.AbortPolicy { - - protected static final Logger logger = LoggerFactory.getLogger(AbortPolicyWithReport.class); - - private final String threadName; - - private final URL url; - - private static volatile long lastPrintTime = 0; - - private static final long TEN_MINUTES_MILLS = 10 * 60 * 1000; - - private static final String OS_WIN_PREFIX = "win"; - - private static final String OS_NAME_KEY = "os.name"; - - private static final String WIN_DATETIME_FORMAT = "yyyy-MM-dd_HH-mm-ss"; - - private static final String DEFAULT_DATETIME_FORMAT = "yyyy-MM-dd_HH:mm:ss"; - - private static Semaphore guard = new Semaphore(1); - - private static final String USER_HOME = System.getProperty("user.home"); - - private final Set listeners = new ConcurrentHashSet<>(); - - public AbortPolicyWithReport(String threadName, URL url) { - this.threadName = threadName; - this.url = url; - } - - @Override - public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { - String msg = String.format("Thread pool is EXHAUSTED!" + - " Thread Name: %s, Pool Size: %d (active: %d, core: %d, max: %d, largest: %d)," + - " Task: %d (completed: %d)," + - " Executor status:(isShutdown:%s, isTerminated:%s, isTerminating:%s), in %s://%s:%d!", - threadName, e.getPoolSize(), e.getActiveCount(), e.getCorePoolSize(), e.getMaximumPoolSize(), - e.getLargestPoolSize(), - e.getTaskCount(), e.getCompletedTaskCount(), e.isShutdown(), e.isTerminated(), e.isTerminating(), - url.getProtocol(), url.getIp(), url.getPort()); - logger.warn(msg); - dumpJStack(); - dispatchThreadPoolExhaustedEvent(msg); - throw new RejectedExecutionException(msg); - } - - public void addThreadPoolExhaustedEventListener(ThreadPoolExhaustedListener listener) { - listeners.add(listener); - } - - public void removeThreadPoolExhaustedEventListener(ThreadPoolExhaustedListener listener) { - listeners.remove(listener); - } - - /** - * dispatch ThreadPoolExhaustedEvent - * @param msg - */ - public void dispatchThreadPoolExhaustedEvent(String msg) { - listeners.forEach(listener -> listener.onEvent(new ThreadPoolExhaustedEvent(msg))); - } - - private void dumpJStack() { - long now = System.currentTimeMillis(); - - //dump every 10 minutes - if (now - lastPrintTime < TEN_MINUTES_MILLS) { - return; - } - - if (!guard.tryAcquire()) { - return; - } - - ExecutorService pool = Executors.newSingleThreadExecutor(); - pool.execute(() -> { - String dumpPath = getDumpPath(); - - SimpleDateFormat sdf; - - String os = System.getProperty(OS_NAME_KEY).toLowerCase(); - - // window system don't support ":" in file name - if (os.contains(OS_WIN_PREFIX)) { - sdf = new SimpleDateFormat(WIN_DATETIME_FORMAT); - } else { - sdf = new SimpleDateFormat(DEFAULT_DATETIME_FORMAT); - } - - String dateStr = sdf.format(new Date()); - //try-with-resources - try (FileOutputStream jStackStream = new FileOutputStream( - new File(dumpPath, "Dubbo_JStack.log" + "." + dateStr))) { - JVMUtil.jstack(jStackStream); - } catch (Throwable t) { - logger.error("dump jStack error", t); - } finally { - guard.release(); - } - lastPrintTime = System.currentTimeMillis(); - }); - //must shutdown thread pool ,if not will lead to OOM - pool.shutdown(); - - } - - private String getDumpPath() { - final String dumpPath = url.getParameter(DUMP_DIRECTORY); - if (StringUtils.isEmpty(dumpPath)) { - return USER_HOME; - } - final File dumpDirectory = new File(dumpPath); - if (!dumpDirectory.exists()) { - if (dumpDirectory.mkdirs()) { - logger.info(format("Dubbo dump directory[%s] created", dumpDirectory.getAbsolutePath())); - } else { - logger.warn(format("Dubbo dump directory[%s] can't be created, use the 'user.home'[%s]", - dumpDirectory.getAbsolutePath(), USER_HOME)); - return USER_HOME; - } - } - return dumpPath; - } -} +/* + * 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.common.threadpool.support; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.threadpool.event.ThreadPoolExhaustedEvent; +import org.apache.dubbo.common.threadpool.event.ThreadPoolExhaustedListener; +import org.apache.dubbo.common.utils.ConcurrentHashSet; +import org.apache.dubbo.common.utils.JVMUtil; +import org.apache.dubbo.common.utils.StringUtils; + +import java.io.File; +import java.io.FileOutputStream; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Set; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.Semaphore; +import java.util.concurrent.ThreadPoolExecutor; + +import static java.lang.String.format; +import static org.apache.dubbo.common.constants.CommonConstants.DUMP_DIRECTORY; + +/** + * Abort Policy. + * Log warn info when abort. + */ +public class AbortPolicyWithReport extends ThreadPoolExecutor.AbortPolicy { + + protected static final Logger logger = LoggerFactory.getLogger(AbortPolicyWithReport.class); + + private final String threadName; + + private final URL url; + + private static volatile long lastPrintTime = 0; + + private static final long TEN_MINUTES_MILLS = 10 * 60 * 1000; + + private static final String OS_WIN_PREFIX = "win"; + + private static final String OS_NAME_KEY = "os.name"; + + private static final String WIN_DATETIME_FORMAT = "yyyy-MM-dd_HH-mm-ss"; + + private static final String DEFAULT_DATETIME_FORMAT = "yyyy-MM-dd_HH:mm:ss"; + + private static Semaphore guard = new Semaphore(1); + + private static final String USER_HOME = System.getProperty("user.home"); + + private final Set listeners = new ConcurrentHashSet<>(); + + public AbortPolicyWithReport(String threadName, URL url) { + this.threadName = threadName; + this.url = url; + } + + @Override + public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { + String msg = String.format("Thread pool is EXHAUSTED!" + + " Thread Name: %s, Pool Size: %d (active: %d, core: %d, max: %d, largest: %d)," + + " Task: %d (completed: %d)," + + " Executor status:(isShutdown:%s, isTerminated:%s, isTerminating:%s), in %s://%s:%d!", + threadName, e.getPoolSize(), e.getActiveCount(), e.getCorePoolSize(), e.getMaximumPoolSize(), + e.getLargestPoolSize(), + e.getTaskCount(), e.getCompletedTaskCount(), e.isShutdown(), e.isTerminated(), e.isTerminating(), + url.getProtocol(), url.getIp(), url.getPort()); + logger.warn(msg); + dumpJStack(); + dispatchThreadPoolExhaustedEvent(msg); + throw new RejectedExecutionException(msg); + } + + public void addThreadPoolExhaustedEventListener(ThreadPoolExhaustedListener listener) { + listeners.add(listener); + } + + public void removeThreadPoolExhaustedEventListener(ThreadPoolExhaustedListener listener) { + listeners.remove(listener); + } + + /** + * dispatch ThreadPoolExhaustedEvent + * @param msg + */ + public void dispatchThreadPoolExhaustedEvent(String msg) { + listeners.forEach(listener -> listener.onEvent(new ThreadPoolExhaustedEvent(msg))); + } + + private void dumpJStack() { + long now = System.currentTimeMillis(); + + //dump every 10 minutes + if (now - lastPrintTime < TEN_MINUTES_MILLS) { + return; + } + + if (!guard.tryAcquire()) { + return; + } + + ExecutorService pool = Executors.newSingleThreadExecutor(); + pool.execute(() -> { + String dumpPath = getDumpPath(); + + SimpleDateFormat sdf; + + String os = System.getProperty(OS_NAME_KEY).toLowerCase(); + + // window system don't support ":" in file name + if (os.contains(OS_WIN_PREFIX)) { + sdf = new SimpleDateFormat(WIN_DATETIME_FORMAT); + } else { + sdf = new SimpleDateFormat(DEFAULT_DATETIME_FORMAT); + } + + String dateStr = sdf.format(new Date()); + //try-with-resources + try (FileOutputStream jStackStream = new FileOutputStream( + new File(dumpPath, "Dubbo_JStack.log" + "." + dateStr))) { + JVMUtil.jstack(jStackStream); + } catch (Throwable t) { + logger.error("dump jStack error", t); + } finally { + guard.release(); + } + lastPrintTime = System.currentTimeMillis(); + }); + //must shutdown thread pool ,if not will lead to OOM + pool.shutdown(); + + } + + private String getDumpPath() { + final String dumpPath = url.getParameter(DUMP_DIRECTORY); + if (StringUtils.isEmpty(dumpPath)) { + return USER_HOME; + } + final File dumpDirectory = new File(dumpPath); + if (!dumpDirectory.exists()) { + if (dumpDirectory.mkdirs()) { + logger.info(format("Dubbo dump directory[%s] created", dumpDirectory.getAbsolutePath())); + } else { + logger.warn(format("Dubbo dump directory[%s] can't be created, use the 'user.home'[%s]", + dumpDirectory.getAbsolutePath(), USER_HOME)); + return USER_HOME; + } + } + return dumpPath; + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/cached/CachedThreadPool.java b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/cached/CachedThreadPool.java index 6dbbced16f..02d3bb6f2d 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/cached/CachedThreadPool.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/cached/CachedThreadPool.java @@ -1,61 +1,61 @@ -/* - * 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.common.threadpool.support.cached; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.threadlocal.NamedInternalThreadFactory; -import org.apache.dubbo.common.threadpool.ThreadPool; -import org.apache.dubbo.common.threadpool.support.AbortPolicyWithReport; - -import java.util.concurrent.Executor; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.SynchronousQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -import static org.apache.dubbo.common.constants.CommonConstants.ALIVE_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.CORE_THREADS_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_ALIVE; -import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_CORE_THREADS; -import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_QUEUES; -import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_THREAD_NAME; -import static org.apache.dubbo.common.constants.CommonConstants.QUEUES_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.THREADS_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.THREAD_NAME_KEY; - -/** - * This thread pool is self-tuned. Thread will be recycled after idle for one minute, and new thread will be created for - * the upcoming request. - * - * @see java.util.concurrent.Executors#newCachedThreadPool() - */ -public class CachedThreadPool implements ThreadPool { - - @Override - public Executor getExecutor(URL url) { - String name = url.getParameter(THREAD_NAME_KEY, DEFAULT_THREAD_NAME); - int cores = url.getParameter(CORE_THREADS_KEY, DEFAULT_CORE_THREADS); - int threads = url.getParameter(THREADS_KEY, Integer.MAX_VALUE); - int queues = url.getParameter(QUEUES_KEY, DEFAULT_QUEUES); - int alive = url.getParameter(ALIVE_KEY, DEFAULT_ALIVE); - return new ThreadPoolExecutor(cores, threads, alive, TimeUnit.MILLISECONDS, - queues == 0 ? new SynchronousQueue() : - (queues < 0 ? new LinkedBlockingQueue() - : new LinkedBlockingQueue(queues)), - new NamedInternalThreadFactory(name, true), new AbortPolicyWithReport(name, url)); - } -} +/* + * 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.common.threadpool.support.cached; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.threadlocal.NamedInternalThreadFactory; +import org.apache.dubbo.common.threadpool.ThreadPool; +import org.apache.dubbo.common.threadpool.support.AbortPolicyWithReport; + +import java.util.concurrent.Executor; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import static org.apache.dubbo.common.constants.CommonConstants.ALIVE_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.CORE_THREADS_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_ALIVE; +import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_CORE_THREADS; +import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_QUEUES; +import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_THREAD_NAME; +import static org.apache.dubbo.common.constants.CommonConstants.QUEUES_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.THREADS_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.THREAD_NAME_KEY; + +/** + * This thread pool is self-tuned. Thread will be recycled after idle for one minute, and new thread will be created for + * the upcoming request. + * + * @see java.util.concurrent.Executors#newCachedThreadPool() + */ +public class CachedThreadPool implements ThreadPool { + + @Override + public Executor getExecutor(URL url) { + String name = url.getParameter(THREAD_NAME_KEY, DEFAULT_THREAD_NAME); + int cores = url.getParameter(CORE_THREADS_KEY, DEFAULT_CORE_THREADS); + int threads = url.getParameter(THREADS_KEY, Integer.MAX_VALUE); + int queues = url.getParameter(QUEUES_KEY, DEFAULT_QUEUES); + int alive = url.getParameter(ALIVE_KEY, DEFAULT_ALIVE); + return new ThreadPoolExecutor(cores, threads, alive, TimeUnit.MILLISECONDS, + queues == 0 ? new SynchronousQueue() : + (queues < 0 ? new LinkedBlockingQueue() + : new LinkedBlockingQueue(queues)), + new NamedInternalThreadFactory(name, true), new AbortPolicyWithReport(name, url)); + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/fixed/FixedThreadPool.java b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/fixed/FixedThreadPool.java index 606d7e1f91..bcf12f4917 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/fixed/FixedThreadPool.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/fixed/FixedThreadPool.java @@ -1,56 +1,56 @@ -/* - * 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.common.threadpool.support.fixed; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.threadlocal.NamedInternalThreadFactory; -import org.apache.dubbo.common.threadpool.ThreadPool; -import org.apache.dubbo.common.threadpool.support.AbortPolicyWithReport; - -import java.util.concurrent.Executor; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.SynchronousQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_QUEUES; -import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_THREADS; -import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_THREAD_NAME; -import static org.apache.dubbo.common.constants.CommonConstants.QUEUES_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.THREADS_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.THREAD_NAME_KEY; - -/** - * Creates a thread pool that reuses a fixed number of threads - * - * @see java.util.concurrent.Executors#newFixedThreadPool(int) - */ -public class FixedThreadPool implements ThreadPool { - - @Override - public Executor getExecutor(URL url) { - String name = url.getParameter(THREAD_NAME_KEY, DEFAULT_THREAD_NAME); - int threads = url.getParameter(THREADS_KEY, DEFAULT_THREADS); - int queues = url.getParameter(QUEUES_KEY, DEFAULT_QUEUES); - return new ThreadPoolExecutor(threads, threads, 0, TimeUnit.MILLISECONDS, - queues == 0 ? new SynchronousQueue() : - (queues < 0 ? new LinkedBlockingQueue() - : new LinkedBlockingQueue(queues)), - new NamedInternalThreadFactory(name, true), new AbortPolicyWithReport(name, url)); - } - -} +/* + * 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.common.threadpool.support.fixed; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.threadlocal.NamedInternalThreadFactory; +import org.apache.dubbo.common.threadpool.ThreadPool; +import org.apache.dubbo.common.threadpool.support.AbortPolicyWithReport; + +import java.util.concurrent.Executor; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_QUEUES; +import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_THREADS; +import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_THREAD_NAME; +import static org.apache.dubbo.common.constants.CommonConstants.QUEUES_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.THREADS_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.THREAD_NAME_KEY; + +/** + * Creates a thread pool that reuses a fixed number of threads + * + * @see java.util.concurrent.Executors#newFixedThreadPool(int) + */ +public class FixedThreadPool implements ThreadPool { + + @Override + public Executor getExecutor(URL url) { + String name = url.getParameter(THREAD_NAME_KEY, DEFAULT_THREAD_NAME); + int threads = url.getParameter(THREADS_KEY, DEFAULT_THREADS); + int queues = url.getParameter(QUEUES_KEY, DEFAULT_QUEUES); + return new ThreadPoolExecutor(threads, threads, 0, TimeUnit.MILLISECONDS, + queues == 0 ? new SynchronousQueue() : + (queues < 0 ? new LinkedBlockingQueue() + : new LinkedBlockingQueue(queues)), + new NamedInternalThreadFactory(name, true), new AbortPolicyWithReport(name, url)); + } + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/timer/HashedWheelTimer.java b/dubbo-common/src/main/java/org/apache/dubbo/common/timer/HashedWheelTimer.java index 487cc74ba5..9f95e1472d 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/timer/HashedWheelTimer.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/timer/HashedWheelTimer.java @@ -809,6 +809,6 @@ public class HashedWheelTimer implements Timer { private static final boolean IS_OS_WINDOWS = System.getProperty("os.name", "").toLowerCase(Locale.US).contains("win"); private boolean isWindows() { - return IS_OS_WINDOWS; + return IS_OS_WINDOWS; } } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/timer/Timeout.java b/dubbo-common/src/main/java/org/apache/dubbo/common/timer/Timeout.java index 3d4c2318f2..7fd056f768 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/timer/Timeout.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/timer/Timeout.java @@ -52,4 +52,4 @@ public interface Timeout { * @return True if the cancellation completed successfully, otherwise false */ boolean cancel(); -} \ No newline at end of file +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/timer/Timer.java b/dubbo-common/src/main/java/org/apache/dubbo/common/timer/Timer.java index 881fab95a5..44cace1d90 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/timer/Timer.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/timer/Timer.java @@ -52,4 +52,4 @@ public interface Timer { * @return true for stop */ boolean isStop(); -} \ No newline at end of file +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/timer/TimerTask.java b/dubbo-common/src/main/java/org/apache/dubbo/common/timer/TimerTask.java index ce818e1c6c..6448457671 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/timer/TimerTask.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/timer/TimerTask.java @@ -31,4 +31,4 @@ public interface TimerTask { * @param timeout a handle which is associated with this task */ void run(Timeout timeout) throws Exception; -} \ No newline at end of file +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/AtomicPositiveInteger.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/AtomicPositiveInteger.java index 63b9ab8d11..7aff6303aa 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/AtomicPositiveInteger.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/AtomicPositiveInteger.java @@ -1,154 +1,154 @@ -/* - * 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.common.utils; - -import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; - -public class AtomicPositiveInteger extends Number { - - private static final long serialVersionUID = -3038533876489105940L; - - private static final AtomicIntegerFieldUpdater INDEX_UPDATER = - AtomicIntegerFieldUpdater.newUpdater(AtomicPositiveInteger.class, "index"); - - @SuppressWarnings("unused") - private volatile int index = 0; - - public AtomicPositiveInteger() { - } - - public AtomicPositiveInteger(int initialValue) { - INDEX_UPDATER.set(this, initialValue); - } - - public final int getAndIncrement() { - return INDEX_UPDATER.getAndIncrement(this) & Integer.MAX_VALUE; - } - - public final int getAndDecrement() { - return INDEX_UPDATER.getAndDecrement(this) & Integer.MAX_VALUE; - } - - public final int incrementAndGet() { - return INDEX_UPDATER.incrementAndGet(this) & Integer.MAX_VALUE; - } - - public final int decrementAndGet() { - return INDEX_UPDATER.decrementAndGet(this) & Integer.MAX_VALUE; - } - - public final int get() { - return INDEX_UPDATER.get(this) & Integer.MAX_VALUE; - } - - public final void set(int newValue) { - if (newValue < 0) { - throw new IllegalArgumentException("new value " + newValue + " < 0"); - } - INDEX_UPDATER.set(this, newValue); - } - - public final int getAndSet(int newValue) { - if (newValue < 0) { - throw new IllegalArgumentException("new value " + newValue + " < 0"); - } - return INDEX_UPDATER.getAndSet(this, newValue) & Integer.MAX_VALUE; - } - - public final int getAndAdd(int delta) { - if (delta < 0) { - throw new IllegalArgumentException("delta " + delta + " < 0"); - } - return INDEX_UPDATER.getAndAdd(this, delta) & Integer.MAX_VALUE; - } - - public final int addAndGet(int delta) { - if (delta < 0) { - throw new IllegalArgumentException("delta " + delta + " < 0"); - } - return INDEX_UPDATER.addAndGet(this, delta) & Integer.MAX_VALUE; - } - - public final boolean compareAndSet(int expect, int update) { - if (update < 0) { - throw new IllegalArgumentException("update value " + update + " < 0"); - } - return INDEX_UPDATER.compareAndSet(this, expect, update); - } - - public final boolean weakCompareAndSet(int expect, int update) { - if (update < 0) { - throw new IllegalArgumentException("update value " + update + " < 0"); - } - return INDEX_UPDATER.weakCompareAndSet(this, expect, update); - } - - @Override - public byte byteValue() { - return (byte) get(); - } - - @Override - public short shortValue() { - return (short) get(); - } - - @Override - public int intValue() { - return get(); - } - - @Override - public long longValue() { - return (long) get(); - } - - @Override - public float floatValue() { - return (float) get(); - } - - @Override - public double doubleValue() { - return (double) get(); - } - - @Override - public String toString() { - return Integer.toString(get()); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + get(); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!(obj instanceof AtomicPositiveInteger)) { - return false; - } - AtomicPositiveInteger other = (AtomicPositiveInteger) obj; - return intValue() == other.intValue(); - } -} \ No newline at end of file +/* + * 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.common.utils; + +import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; + +public class AtomicPositiveInteger extends Number { + + private static final long serialVersionUID = -3038533876489105940L; + + private static final AtomicIntegerFieldUpdater INDEX_UPDATER = + AtomicIntegerFieldUpdater.newUpdater(AtomicPositiveInteger.class, "index"); + + @SuppressWarnings("unused") + private volatile int index = 0; + + public AtomicPositiveInteger() { + } + + public AtomicPositiveInteger(int initialValue) { + INDEX_UPDATER.set(this, initialValue); + } + + public final int getAndIncrement() { + return INDEX_UPDATER.getAndIncrement(this) & Integer.MAX_VALUE; + } + + public final int getAndDecrement() { + return INDEX_UPDATER.getAndDecrement(this) & Integer.MAX_VALUE; + } + + public final int incrementAndGet() { + return INDEX_UPDATER.incrementAndGet(this) & Integer.MAX_VALUE; + } + + public final int decrementAndGet() { + return INDEX_UPDATER.decrementAndGet(this) & Integer.MAX_VALUE; + } + + public final int get() { + return INDEX_UPDATER.get(this) & Integer.MAX_VALUE; + } + + public final void set(int newValue) { + if (newValue < 0) { + throw new IllegalArgumentException("new value " + newValue + " < 0"); + } + INDEX_UPDATER.set(this, newValue); + } + + public final int getAndSet(int newValue) { + if (newValue < 0) { + throw new IllegalArgumentException("new value " + newValue + " < 0"); + } + return INDEX_UPDATER.getAndSet(this, newValue) & Integer.MAX_VALUE; + } + + public final int getAndAdd(int delta) { + if (delta < 0) { + throw new IllegalArgumentException("delta " + delta + " < 0"); + } + return INDEX_UPDATER.getAndAdd(this, delta) & Integer.MAX_VALUE; + } + + public final int addAndGet(int delta) { + if (delta < 0) { + throw new IllegalArgumentException("delta " + delta + " < 0"); + } + return INDEX_UPDATER.addAndGet(this, delta) & Integer.MAX_VALUE; + } + + public final boolean compareAndSet(int expect, int update) { + if (update < 0) { + throw new IllegalArgumentException("update value " + update + " < 0"); + } + return INDEX_UPDATER.compareAndSet(this, expect, update); + } + + public final boolean weakCompareAndSet(int expect, int update) { + if (update < 0) { + throw new IllegalArgumentException("update value " + update + " < 0"); + } + return INDEX_UPDATER.weakCompareAndSet(this, expect, update); + } + + @Override + public byte byteValue() { + return (byte) get(); + } + + @Override + public short shortValue() { + return (short) get(); + } + + @Override + public int intValue() { + return get(); + } + + @Override + public long longValue() { + return (long) get(); + } + + @Override + public float floatValue() { + return (float) get(); + } + + @Override + public double doubleValue() { + return (double) get(); + } + + @Override + public String toString() { + return Integer.toString(get()); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + get(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof AtomicPositiveInteger)) { + return false; + } + AtomicPositiveInteger other = (AtomicPositiveInteger) obj; + return intValue() == other.intValue(); + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/CollectionUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/CollectionUtils.java index 13c55eb133..2a5cd21c84 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/CollectionUtils.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/CollectionUtils.java @@ -1,376 +1,376 @@ -/* - * 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.common.utils; - -import java.util.AbstractSet; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import static java.util.Collections.emptySet; -import static java.util.Collections.unmodifiableSet; - -/** - * Miscellaneous collection utility methods. - * Mainly for internal use within the framework. - * - * @author william.liangf - * @since 2.0.7 - */ -public class CollectionUtils { - - private static final Comparator SIMPLE_NAME_COMPARATOR = (s1, s2) -> { - if (s1 == null && s2 == null) { - return 0; - } - if (s1 == null) { - return -1; - } - if (s2 == null) { - return 1; - } - int i1 = s1.lastIndexOf('.'); - if (i1 >= 0) { - s1 = s1.substring(i1 + 1); - } - int i2 = s2.lastIndexOf('.'); - if (i2 >= 0) { - s2 = s2.substring(i2 + 1); - } - return s1.compareToIgnoreCase(s2); - }; - - private CollectionUtils() { - } - - @SuppressWarnings({"unchecked", "rawtypes"}) - public static List sort(List list) { - if (isNotEmpty(list)) { - Collections.sort((List) list); - } - return list; - } - - public static List sortSimpleName(List list) { - if (list != null && list.size() > 0) { - Collections.sort(list, SIMPLE_NAME_COMPARATOR); - } - return list; - } - - public static Map> splitAll(Map> list, String separator) { - if (list == null) { - return null; - } - Map> result = new HashMap<>(); - for (Map.Entry> entry : list.entrySet()) { - result.put(entry.getKey(), split(entry.getValue(), separator)); - } - return result; - } - - public static Map> joinAll(Map> map, String separator) { - if (map == null) { - return null; - } - Map> result = new HashMap<>(); - for (Map.Entry> entry : map.entrySet()) { - result.put(entry.getKey(), join(entry.getValue(), separator)); - } - return result; - } - - public static Map split(List list, String separator) { - if (list == null) { - return null; - } - Map map = new HashMap<>(); - if (list.isEmpty()) { - return map; - } - for (String item : list) { - int index = item.indexOf(separator); - if (index == -1) { - map.put(item, ""); - } else { - map.put(item.substring(0, index), item.substring(index + 1)); - } - } - return map; - } - - public static List join(Map map, String separator) { - if (map == null) { - return null; - } - List list = new ArrayList<>(); - if (map.size() == 0) { - return list; - } - for (Map.Entry entry : map.entrySet()) { - String key = entry.getKey(); - String value = entry.getValue(); - if (StringUtils.isEmpty(value)) { - list.add(key); - } else { - list.add(key + separator + value); - } - } - return list; - } - - public static String join(List list, String separator) { - StringBuilder sb = new StringBuilder(); - for (String ele : list) { - if (sb.length() > 0) { - sb.append(separator); - } - sb.append(ele); - } - return sb.toString(); - } - - public static boolean mapEquals(Map map1, Map map2) { - if (map1 == null && map2 == null) { - return true; - } - if (map1 == null || map2 == null) { - return false; - } - if (map1.size() != map2.size()) { - return false; - } - for (Map.Entry entry : map1.entrySet()) { - Object key = entry.getKey(); - Object value1 = entry.getValue(); - Object value2 = map2.get(key); - if (!objectEquals(value1, value2)) { - return false; - } - } - return true; - } - - private static boolean objectEquals(Object obj1, Object obj2) { - if (obj1 == null && obj2 == null) { - return true; - } - if (obj1 == null || obj2 == null) { - return false; - } - return obj1.equals(obj2); - } - - public static Map toStringMap(String... pairs) { - Map parameters = new HashMap<>(); - if (ArrayUtils.isEmpty(pairs)) { - return parameters; - } - - if (pairs.length > 0) { - if (pairs.length % 2 != 0) { - throw new IllegalArgumentException("pairs must be even."); - } - for (int i = 0; i < pairs.length; i = i + 2) { - parameters.put(pairs[i], pairs[i + 1]); - } - } - return parameters; - } - - @SuppressWarnings("unchecked") - public static Map toMap(Object... pairs) { - Map ret = new HashMap<>(); - if (pairs == null || pairs.length == 0) { - return ret; - } - - if (pairs.length % 2 != 0) { - throw new IllegalArgumentException("Map pairs can not be odd number."); - } - int len = pairs.length / 2; - for (int i = 0; i < len; i++) { - ret.put((K) pairs[2 * i], (V) pairs[2 * i + 1]); - } - return ret; - } - - /** - * Return {@code true} if the supplied Collection is {@code null} or empty. - * Otherwise, return {@code false}. - * - * @param collection the Collection to check - * @return whether the given Collection is empty - */ - public static boolean isEmpty(Collection collection) { - return collection == null || collection.isEmpty(); - } - - /** - * Return {@code true} if the supplied Collection is {@code not null} or not empty. - * Otherwise, return {@code false}. - * - * @param collection the Collection to check - * @return whether the given Collection is not empty - */ - public static boolean isNotEmpty(Collection collection) { - return !isEmpty(collection); - } - - /** - * Return {@code true} if the supplied Map is {@code null} or empty. - * Otherwise, return {@code false}. - * - * @param map the Map to check - * @return whether the given Map is empty - */ - public static boolean isEmptyMap(Map map) { - return map == null || map.size() == 0; - } - - /** - * Return {@code true} if the supplied Map is {@code not null} or not empty. - * Otherwise, return {@code false}. - * - * @param map the Map to check - * @return whether the given Map is not empty - */ - public static boolean isNotEmptyMap(Map map) { - return !isEmptyMap(map); - } - - /** - * Convert to multiple values to be {@link LinkedHashSet} - * - * @param values one or more values - * @param the type of values - * @return read-only {@link Set} - */ - public static Set ofSet(T... values) { - int size = values == null ? 0 : values.length; - if (size < 1) { - return emptySet(); - } - - float loadFactor = 1f / ((size + 1) * 1.0f); - - if (loadFactor > 0.75f) { - loadFactor = 0.75f; - } - - Set elements = new LinkedHashSet<>(size, loadFactor); - for (int i = 0; i < size; i++) { - elements.add(values[i]); - } - return unmodifiableSet(elements); - } - - /** - * Get the size of the specified {@link Collection} - * - * @param collection the specified {@link Collection} - * @return must be positive number - * @since 2.7.6 - */ - public static int size(Collection collection) { - return collection == null ? 0 : collection.size(); - } - - /** - * Compares the specified collection with another, the main implementation references - * {@link AbstractSet} - * - * @param one {@link Collection} - * @param another {@link Collection} - * @return if equals, return true, or false - * @since 2.7.6 - */ - public static boolean equals(Collection one, Collection another) { - - if (one == another) { - return true; - } - - if (isEmpty(one) && isEmpty(another)) { - return true; - } - - if (size(one) != size(another)) { - return false; - } - - try { - return one.containsAll(another); - } catch (ClassCastException | NullPointerException unused) { - return false; - } - } - - /** - * Add the multiple values into {@link Collection the specified collection} - * - * @param collection {@link Collection the specified collection} - * @param values the multiple values - * @param the type of values - * @return the effected count after added - * @since 2.7.6 - */ - public static int addAll(Collection collection, T... values) { - - int size = values == null ? 0 : values.length; - - if (collection == null || size < 1) { - return 0; - } - - int effectedCount = 0; - for (int i = 0; i < size; i++) { - if (collection.add(values[i])) { - effectedCount++; - } - } - - return effectedCount; - } - - /** - * Take the first element from the specified collection - * - * @param values the collection object - * @param the type of element of collection - * @return if found, return the first one, or null - * @since 2.7.6 - */ - public static T first(Collection values) { - if (isEmpty(values)) { - return null; - } - if (values instanceof List) { - List list = (List) values; - return list.get(0); - } else { - return values.iterator().next(); - } - } - -} +/* + * 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.common.utils; + +import java.util.AbstractSet; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static java.util.Collections.emptySet; +import static java.util.Collections.unmodifiableSet; + +/** + * Miscellaneous collection utility methods. + * Mainly for internal use within the framework. + * + * @author william.liangf + * @since 2.0.7 + */ +public class CollectionUtils { + + private static final Comparator SIMPLE_NAME_COMPARATOR = (s1, s2) -> { + if (s1 == null && s2 == null) { + return 0; + } + if (s1 == null) { + return -1; + } + if (s2 == null) { + return 1; + } + int i1 = s1.lastIndexOf('.'); + if (i1 >= 0) { + s1 = s1.substring(i1 + 1); + } + int i2 = s2.lastIndexOf('.'); + if (i2 >= 0) { + s2 = s2.substring(i2 + 1); + } + return s1.compareToIgnoreCase(s2); + }; + + private CollectionUtils() { + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + public static List sort(List list) { + if (isNotEmpty(list)) { + Collections.sort((List) list); + } + return list; + } + + public static List sortSimpleName(List list) { + if (list != null && list.size() > 0) { + Collections.sort(list, SIMPLE_NAME_COMPARATOR); + } + return list; + } + + public static Map> splitAll(Map> list, String separator) { + if (list == null) { + return null; + } + Map> result = new HashMap<>(); + for (Map.Entry> entry : list.entrySet()) { + result.put(entry.getKey(), split(entry.getValue(), separator)); + } + return result; + } + + public static Map> joinAll(Map> map, String separator) { + if (map == null) { + return null; + } + Map> result = new HashMap<>(); + for (Map.Entry> entry : map.entrySet()) { + result.put(entry.getKey(), join(entry.getValue(), separator)); + } + return result; + } + + public static Map split(List list, String separator) { + if (list == null) { + return null; + } + Map map = new HashMap<>(); + if (list.isEmpty()) { + return map; + } + for (String item : list) { + int index = item.indexOf(separator); + if (index == -1) { + map.put(item, ""); + } else { + map.put(item.substring(0, index), item.substring(index + 1)); + } + } + return map; + } + + public static List join(Map map, String separator) { + if (map == null) { + return null; + } + List list = new ArrayList<>(); + if (map.size() == 0) { + return list; + } + for (Map.Entry entry : map.entrySet()) { + String key = entry.getKey(); + String value = entry.getValue(); + if (StringUtils.isEmpty(value)) { + list.add(key); + } else { + list.add(key + separator + value); + } + } + return list; + } + + public static String join(List list, String separator) { + StringBuilder sb = new StringBuilder(); + for (String ele : list) { + if (sb.length() > 0) { + sb.append(separator); + } + sb.append(ele); + } + return sb.toString(); + } + + public static boolean mapEquals(Map map1, Map map2) { + if (map1 == null && map2 == null) { + return true; + } + if (map1 == null || map2 == null) { + return false; + } + if (map1.size() != map2.size()) { + return false; + } + for (Map.Entry entry : map1.entrySet()) { + Object key = entry.getKey(); + Object value1 = entry.getValue(); + Object value2 = map2.get(key); + if (!objectEquals(value1, value2)) { + return false; + } + } + return true; + } + + private static boolean objectEquals(Object obj1, Object obj2) { + if (obj1 == null && obj2 == null) { + return true; + } + if (obj1 == null || obj2 == null) { + return false; + } + return obj1.equals(obj2); + } + + public static Map toStringMap(String... pairs) { + Map parameters = new HashMap<>(); + if (ArrayUtils.isEmpty(pairs)) { + return parameters; + } + + if (pairs.length > 0) { + if (pairs.length % 2 != 0) { + throw new IllegalArgumentException("pairs must be even."); + } + for (int i = 0; i < pairs.length; i = i + 2) { + parameters.put(pairs[i], pairs[i + 1]); + } + } + return parameters; + } + + @SuppressWarnings("unchecked") + public static Map toMap(Object... pairs) { + Map ret = new HashMap<>(); + if (pairs == null || pairs.length == 0) { + return ret; + } + + if (pairs.length % 2 != 0) { + throw new IllegalArgumentException("Map pairs can not be odd number."); + } + int len = pairs.length / 2; + for (int i = 0; i < len; i++) { + ret.put((K) pairs[2 * i], (V) pairs[2 * i + 1]); + } + return ret; + } + + /** + * Return {@code true} if the supplied Collection is {@code null} or empty. + * Otherwise, return {@code false}. + * + * @param collection the Collection to check + * @return whether the given Collection is empty + */ + public static boolean isEmpty(Collection collection) { + return collection == null || collection.isEmpty(); + } + + /** + * Return {@code true} if the supplied Collection is {@code not null} or not empty. + * Otherwise, return {@code false}. + * + * @param collection the Collection to check + * @return whether the given Collection is not empty + */ + public static boolean isNotEmpty(Collection collection) { + return !isEmpty(collection); + } + + /** + * Return {@code true} if the supplied Map is {@code null} or empty. + * Otherwise, return {@code false}. + * + * @param map the Map to check + * @return whether the given Map is empty + */ + public static boolean isEmptyMap(Map map) { + return map == null || map.size() == 0; + } + + /** + * Return {@code true} if the supplied Map is {@code not null} or not empty. + * Otherwise, return {@code false}. + * + * @param map the Map to check + * @return whether the given Map is not empty + */ + public static boolean isNotEmptyMap(Map map) { + return !isEmptyMap(map); + } + + /** + * Convert to multiple values to be {@link LinkedHashSet} + * + * @param values one or more values + * @param the type of values + * @return read-only {@link Set} + */ + public static Set ofSet(T... values) { + int size = values == null ? 0 : values.length; + if (size < 1) { + return emptySet(); + } + + float loadFactor = 1f / ((size + 1) * 1.0f); + + if (loadFactor > 0.75f) { + loadFactor = 0.75f; + } + + Set elements = new LinkedHashSet<>(size, loadFactor); + for (int i = 0; i < size; i++) { + elements.add(values[i]); + } + return unmodifiableSet(elements); + } + + /** + * Get the size of the specified {@link Collection} + * + * @param collection the specified {@link Collection} + * @return must be positive number + * @since 2.7.6 + */ + public static int size(Collection collection) { + return collection == null ? 0 : collection.size(); + } + + /** + * Compares the specified collection with another, the main implementation references + * {@link AbstractSet} + * + * @param one {@link Collection} + * @param another {@link Collection} + * @return if equals, return true, or false + * @since 2.7.6 + */ + public static boolean equals(Collection one, Collection another) { + + if (one == another) { + return true; + } + + if (isEmpty(one) && isEmpty(another)) { + return true; + } + + if (size(one) != size(another)) { + return false; + } + + try { + return one.containsAll(another); + } catch (ClassCastException | NullPointerException unused) { + return false; + } + } + + /** + * Add the multiple values into {@link Collection the specified collection} + * + * @param collection {@link Collection the specified collection} + * @param values the multiple values + * @param the type of values + * @return the effected count after added + * @since 2.7.6 + */ + public static int addAll(Collection collection, T... values) { + + int size = values == null ? 0 : values.length; + + if (collection == null || size < 1) { + return 0; + } + + int effectedCount = 0; + for (int i = 0; i < size; i++) { + if (collection.add(values[i])) { + effectedCount++; + } + } + + return effectedCount; + } + + /** + * Take the first element from the specified collection + * + * @param values the collection object + * @param the type of element of collection + * @return if found, return the first one, or null + * @since 2.7.6 + */ + public static T first(Collection values) { + if (isEmpty(values)) { + return null; + } + if (values instanceof List) { + List list = (List) values; + return list.get(0); + } else { + return values.iterator().next(); + } + } + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/CompatibleTypeUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/CompatibleTypeUtils.java index fecec8b992..64437d56a6 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/CompatibleTypeUtils.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/CompatibleTypeUtils.java @@ -1,230 +1,230 @@ -/* - * 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.common.utils; - -import java.lang.reflect.Array; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -public class CompatibleTypeUtils { - - private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; - - private CompatibleTypeUtils() { - } - - /** - * Compatible type convert. Null value is allowed to pass in. If no conversion is needed, then the original value - * will be returned. - *

- * Supported compatible type conversions include (primary types and corresponding wrappers are not listed): - *

    - *
  • String -> char, enum, Date - *
  • byte, short, int, long -> byte, short, int, long - *
  • float, double -> float, double - *
- */ - @SuppressWarnings({"unchecked", "rawtypes"}) - public static Object compatibleTypeConvert(Object value, Class type) { - if (value == null || type == null || type.isAssignableFrom(value.getClass())) { - return value; - } - - if (value instanceof String) { - String string = (String) value; - if (char.class.equals(type) || Character.class.equals(type)) { - if (string.length() != 1) { - throw new IllegalArgumentException(String.format("CAN NOT convert String(%s) to char!" + - " when convert String to char, the String MUST only 1 char.", string)); - } - return string.charAt(0); - } - if (type.isEnum()) { - return Enum.valueOf((Class) type, string); - } - if (type == BigInteger.class) { - return new BigInteger(string); - } - if (type == BigDecimal.class) { - return new BigDecimal(string); - } - if (type == Short.class || type == short.class) { - return new Short(string); - } - if (type == Integer.class || type == int.class) { - return new Integer(string); - } - if (type == Long.class || type == long.class) { - return new Long(string); - } - if (type == Double.class || type == double.class) { - return new Double(string); - } - if (type == Float.class || type == float.class) { - return new Float(string); - } - if (type == Byte.class || type == byte.class) { - return new Byte(string); - } - if (type == Boolean.class || type == boolean.class) { - return Boolean.valueOf(string); - } - if (type == Date.class || type == java.sql.Date.class || type == java.sql.Timestamp.class - || type == java.sql.Time.class) { - try { - Date date = new SimpleDateFormat(DATE_FORMAT).parse(string); - if (type == java.sql.Date.class) { - return new java.sql.Date(date.getTime()); - } - if (type == java.sql.Timestamp.class) { - return new java.sql.Timestamp(date.getTime()); - } - if (type == java.sql.Time.class) { - return new java.sql.Time(date.getTime()); - } - return date; - } catch (ParseException e) { - throw new IllegalStateException("Failed to parse date " + value + " by format " - + DATE_FORMAT + ", cause: " + e.getMessage(), e); - } - } - if (type == java.time.LocalDateTime.class) { - if (StringUtils.isEmpty(string)) { - return null; - } - return LocalDateTime.parse(string); - } - if (type == java.time.LocalDate.class) { - if (StringUtils.isEmpty(string)) { - return null; - } - return LocalDate.parse(string); - } - if (type == java.time.LocalTime.class) { - if (StringUtils.isEmpty(string)) { - return null; - } - return LocalDateTime.parse(string).toLocalTime(); - } - if (type == Class.class) { - try { - return ReflectUtils.name2class(string); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e.getMessage(), e); - } - } - if (char[].class.equals(type)) { - // Process string to char array for generic invoke - // See - // - https://github.com/apache/dubbo/issues/2003 - int len = string.length(); - char[] chars = new char[len]; - string.getChars(0, len, chars, 0); - return chars; - } - } - if (value instanceof Number) { - Number number = (Number) value; - if (type == byte.class || type == Byte.class) { - return number.byteValue(); - } - if (type == short.class || type == Short.class) { - return number.shortValue(); - } - if (type == int.class || type == Integer.class) { - return number.intValue(); - } - if (type == long.class || type == Long.class) { - return number.longValue(); - } - if (type == float.class || type == Float.class) { - return number.floatValue(); - } - if (type == double.class || type == Double.class) { - return number.doubleValue(); - } - if (type == BigInteger.class) { - return BigInteger.valueOf(number.longValue()); - } - if (type == BigDecimal.class) { - return BigDecimal.valueOf(number.doubleValue()); - } - if (type == Date.class) { - return new Date(number.longValue()); - } - if (type == boolean.class || type == Boolean.class) { - return 0 != number.intValue(); - } - } - if (value instanceof Collection) { - Collection collection = (Collection) value; - if (type.isArray()) { - int length = collection.size(); - Object array = Array.newInstance(type.getComponentType(), length); - int i = 0; - for (Object item : collection) { - Array.set(array, i++, item); - } - return array; - } - if (!type.isInterface()) { - try { - Collection result = (Collection) type.newInstance(); - result.addAll(collection); - return result; - } catch (Throwable ignored) { - } - } - if (type == List.class) { - return new ArrayList(collection); - } - if (type == Set.class) { - return new HashSet(collection); - } - } - if (value.getClass().isArray() && Collection.class.isAssignableFrom(type)) { - int length = Array.getLength(value); - Collection collection; - if (!type.isInterface()) { - try { - collection = (Collection) type.newInstance(); - } catch (Throwable e) { - collection = new ArrayList(length); - } - } else if (type == Set.class) { - collection = new HashSet(Math.max((int) (length/.75f) + 1, 16)); - } else { - collection = new ArrayList(length); - } - for (int i = 0; i < length; i++) { - collection.add(Array.get(value, i)); - } - return collection; - } - return value; - } -} +/* + * 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.common.utils; + +import java.lang.reflect.Array; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class CompatibleTypeUtils { + + private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; + + private CompatibleTypeUtils() { + } + + /** + * Compatible type convert. Null value is allowed to pass in. If no conversion is needed, then the original value + * will be returned. + *

+ * Supported compatible type conversions include (primary types and corresponding wrappers are not listed): + *

    + *
  • String -> char, enum, Date + *
  • byte, short, int, long -> byte, short, int, long + *
  • float, double -> float, double + *
+ */ + @SuppressWarnings({"unchecked", "rawtypes"}) + public static Object compatibleTypeConvert(Object value, Class type) { + if (value == null || type == null || type.isAssignableFrom(value.getClass())) { + return value; + } + + if (value instanceof String) { + String string = (String) value; + if (char.class.equals(type) || Character.class.equals(type)) { + if (string.length() != 1) { + throw new IllegalArgumentException(String.format("CAN NOT convert String(%s) to char!" + + " when convert String to char, the String MUST only 1 char.", string)); + } + return string.charAt(0); + } + if (type.isEnum()) { + return Enum.valueOf((Class) type, string); + } + if (type == BigInteger.class) { + return new BigInteger(string); + } + if (type == BigDecimal.class) { + return new BigDecimal(string); + } + if (type == Short.class || type == short.class) { + return new Short(string); + } + if (type == Integer.class || type == int.class) { + return new Integer(string); + } + if (type == Long.class || type == long.class) { + return new Long(string); + } + if (type == Double.class || type == double.class) { + return new Double(string); + } + if (type == Float.class || type == float.class) { + return new Float(string); + } + if (type == Byte.class || type == byte.class) { + return new Byte(string); + } + if (type == Boolean.class || type == boolean.class) { + return Boolean.valueOf(string); + } + if (type == Date.class || type == java.sql.Date.class || type == java.sql.Timestamp.class + || type == java.sql.Time.class) { + try { + Date date = new SimpleDateFormat(DATE_FORMAT).parse(string); + if (type == java.sql.Date.class) { + return new java.sql.Date(date.getTime()); + } + if (type == java.sql.Timestamp.class) { + return new java.sql.Timestamp(date.getTime()); + } + if (type == java.sql.Time.class) { + return new java.sql.Time(date.getTime()); + } + return date; + } catch (ParseException e) { + throw new IllegalStateException("Failed to parse date " + value + " by format " + + DATE_FORMAT + ", cause: " + e.getMessage(), e); + } + } + if (type == java.time.LocalDateTime.class) { + if (StringUtils.isEmpty(string)) { + return null; + } + return LocalDateTime.parse(string); + } + if (type == java.time.LocalDate.class) { + if (StringUtils.isEmpty(string)) { + return null; + } + return LocalDate.parse(string); + } + if (type == java.time.LocalTime.class) { + if (StringUtils.isEmpty(string)) { + return null; + } + return LocalDateTime.parse(string).toLocalTime(); + } + if (type == Class.class) { + try { + return ReflectUtils.name2class(string); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + if (char[].class.equals(type)) { + // Process string to char array for generic invoke + // See + // - https://github.com/apache/dubbo/issues/2003 + int len = string.length(); + char[] chars = new char[len]; + string.getChars(0, len, chars, 0); + return chars; + } + } + if (value instanceof Number) { + Number number = (Number) value; + if (type == byte.class || type == Byte.class) { + return number.byteValue(); + } + if (type == short.class || type == Short.class) { + return number.shortValue(); + } + if (type == int.class || type == Integer.class) { + return number.intValue(); + } + if (type == long.class || type == Long.class) { + return number.longValue(); + } + if (type == float.class || type == Float.class) { + return number.floatValue(); + } + if (type == double.class || type == Double.class) { + return number.doubleValue(); + } + if (type == BigInteger.class) { + return BigInteger.valueOf(number.longValue()); + } + if (type == BigDecimal.class) { + return BigDecimal.valueOf(number.doubleValue()); + } + if (type == Date.class) { + return new Date(number.longValue()); + } + if (type == boolean.class || type == Boolean.class) { + return 0 != number.intValue(); + } + } + if (value instanceof Collection) { + Collection collection = (Collection) value; + if (type.isArray()) { + int length = collection.size(); + Object array = Array.newInstance(type.getComponentType(), length); + int i = 0; + for (Object item : collection) { + Array.set(array, i++, item); + } + return array; + } + if (!type.isInterface()) { + try { + Collection result = (Collection) type.newInstance(); + result.addAll(collection); + return result; + } catch (Throwable ignored) { + } + } + if (type == List.class) { + return new ArrayList(collection); + } + if (type == Set.class) { + return new HashSet(collection); + } + } + if (value.getClass().isArray() && Collection.class.isAssignableFrom(type)) { + int length = Array.getLength(value); + Collection collection; + if (!type.isInterface()) { + try { + collection = (Collection) type.newInstance(); + } catch (Throwable e) { + collection = new ArrayList(length); + } + } else if (type == Set.class) { + collection = new HashSet(Math.max((int) (length/.75f) + 1, 16)); + } else { + collection = new ArrayList(length); + } + for (int i = 0; i < length; i++) { + collection.add(Array.get(value, i)); + } + return collection; + } + return value; + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ConcurrentHashSet.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ConcurrentHashSet.java index a3ac9db8fd..5067a7aead 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ConcurrentHashSet.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ConcurrentHashSet.java @@ -1,130 +1,130 @@ -/* - * 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.common.utils; - -import java.util.AbstractSet; -import java.util.ConcurrentModificationException; -import java.util.Iterator; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -public class ConcurrentHashSet extends AbstractSet implements Set, java.io.Serializable { - - private static final long serialVersionUID = -8672117787651310382L; - - private static final Object PRESENT = new Object(); - - private final ConcurrentMap map; - - public ConcurrentHashSet() { - map = new ConcurrentHashMap(); - } - - public ConcurrentHashSet(int initialCapacity) { - map = new ConcurrentHashMap(initialCapacity); - } - - /** - * Returns an iterator over the elements in this set. The elements are - * returned in no particular order. - * - * @return an Iterator over the elements in this set - * @see ConcurrentModificationException - */ - @Override - public Iterator iterator() { - return map.keySet().iterator(); - } - - /** - * Returns the number of elements in this set (its cardinality). - * - * @return the number of elements in this set (its cardinality) - */ - @Override - public int size() { - return map.size(); - } - - /** - * Returns true if this set contains no elements. - * - * @return true if this set contains no elements - */ - @Override - public boolean isEmpty() { - return map.isEmpty(); - } - - /** - * Returns true if this set contains the specified element. More - * formally, returns true if and only if this set contains an - * element e such that - * (o==null ? e==null : o.equals(e)). - * - * @param o element whose presence in this set is to be tested - * @return true if this set contains the specified element - */ - @Override - public boolean contains(Object o) { - return map.containsKey(o); - } - - /** - * Adds the specified element to this set if it is not already present. More - * formally, adds the specified element e to this set if this set - * contains no element e2 such that - * (e==null ? e2==null : e.equals(e2)). If this - * set already contains the element, the call leaves the set unchanged and - * returns false. - * - * @param e element to be added to this set - * @return true if this set did not already contain the specified - * element - */ - @Override - public boolean add(E e) { - return map.put(e, PRESENT) == null; - } - - /** - * Removes the specified element from this set if it is present. More - * formally, removes an element e such that - * (o==null ? e==null : o.equals(e)), if this - * set contains such an element. Returns true if this set contained - * the element (or equivalently, if this set changed as a result of the - * call). (This set will not contain the element once the call returns.) - * - * @param o object to be removed from this set, if present - * @return true if the set contained the specified element - */ - @Override - public boolean remove(Object o) { - return map.remove(o) == PRESENT; - } - - /** - * Removes all of the elements from this set. The set will be empty after - * this call returns. - */ - @Override - public void clear() { - map.clear(); - } - -} +/* + * 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.common.utils; + +import java.util.AbstractSet; +import java.util.ConcurrentModificationException; +import java.util.Iterator; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +public class ConcurrentHashSet extends AbstractSet implements Set, java.io.Serializable { + + private static final long serialVersionUID = -8672117787651310382L; + + private static final Object PRESENT = new Object(); + + private final ConcurrentMap map; + + public ConcurrentHashSet() { + map = new ConcurrentHashMap(); + } + + public ConcurrentHashSet(int initialCapacity) { + map = new ConcurrentHashMap(initialCapacity); + } + + /** + * Returns an iterator over the elements in this set. The elements are + * returned in no particular order. + * + * @return an Iterator over the elements in this set + * @see ConcurrentModificationException + */ + @Override + public Iterator iterator() { + return map.keySet().iterator(); + } + + /** + * Returns the number of elements in this set (its cardinality). + * + * @return the number of elements in this set (its cardinality) + */ + @Override + public int size() { + return map.size(); + } + + /** + * Returns true if this set contains no elements. + * + * @return true if this set contains no elements + */ + @Override + public boolean isEmpty() { + return map.isEmpty(); + } + + /** + * Returns true if this set contains the specified element. More + * formally, returns true if and only if this set contains an + * element e such that + * (o==null ? e==null : o.equals(e)). + * + * @param o element whose presence in this set is to be tested + * @return true if this set contains the specified element + */ + @Override + public boolean contains(Object o) { + return map.containsKey(o); + } + + /** + * Adds the specified element to this set if it is not already present. More + * formally, adds the specified element e to this set if this set + * contains no element e2 such that + * (e==null ? e2==null : e.equals(e2)). If this + * set already contains the element, the call leaves the set unchanged and + * returns false. + * + * @param e element to be added to this set + * @return true if this set did not already contain the specified + * element + */ + @Override + public boolean add(E e) { + return map.put(e, PRESENT) == null; + } + + /** + * Removes the specified element from this set if it is present. More + * formally, removes an element e such that + * (o==null ? e==null : o.equals(e)), if this + * set contains such an element. Returns true if this set contained + * the element (or equivalently, if this set changed as a result of the + * call). (This set will not contain the element once the call returns.) + * + * @param o object to be removed from this set, if present + * @return true if the set contained the specified element + */ + @Override + public boolean remove(Object o) { + return map.remove(o) == PRESENT; + } + + /** + * Removes all of the elements from this set. The set will be empty after + * this call returns. + */ + @Override + public void clear() { + map.clear(); + } + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ConfigUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ConfigUtils.java index 9eabc4b37d..93d01ce22b 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ConfigUtils.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ConfigUtils.java @@ -1,395 +1,395 @@ -/* - * 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.common.utils; - -import org.apache.dubbo.common.config.Configuration; -import org.apache.dubbo.common.config.InmemoryConfiguration; -import org.apache.dubbo.common.constants.CommonConstants; -import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.lang.management.ManagementFactory; -import java.lang.management.RuntimeMXBean; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Enumeration; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN; -import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.REMOVE_VALUE_PREFIX; - -public class ConfigUtils { - - private static final Logger logger = LoggerFactory.getLogger(ConfigUtils.class); - private static Pattern VARIABLE_PATTERN = Pattern.compile( - "\\$\\s*\\{?\\s*([\\._0-9a-zA-Z]+)\\s*\\}?"); - private static volatile Properties PROPERTIES; - private static int PID = -1; - - private ConfigUtils() { - } - - public static boolean isNotEmpty(String value) { - return !isEmpty(value); - } - - public static boolean isEmpty(String value) { - return StringUtils.isEmpty(value) - || "false".equalsIgnoreCase(value) - || "0".equalsIgnoreCase(value) - || "null".equalsIgnoreCase(value) - || "N/A".equalsIgnoreCase(value); - } - - public static boolean isDefault(String value) { - return "true".equalsIgnoreCase(value) - || "default".equalsIgnoreCase(value); - } - - /** - * Insert default extension into extension list. - *

- * Extension list support

    - *
  • Special value default, means the location for default extensions. - *
  • Special symbol-, means remove. -foo1 will remove default extension 'foo'; -default will remove all default extensions. - *
- * - * @param type Extension type - * @param cfg Extension name list - * @param def Default extension list - * @return result extension list - */ - public static List mergeValues(Class type, String cfg, List def) { - List defaults = new ArrayList(); - if (def != null) { - for (String name : def) { - if (ExtensionLoader.getExtensionLoader(type).hasExtension(name)) { - defaults.add(name); - } - } - } - - List names = new ArrayList(); - - // add initial values - String[] configs = (cfg == null || cfg.trim().length() == 0) ? new String[0] : COMMA_SPLIT_PATTERN.split(cfg); - for (String config : configs) { - if (config != null && config.trim().length() > 0) { - names.add(config); - } - } - - // -default is not included - if (!names.contains(REMOVE_VALUE_PREFIX + DEFAULT_KEY)) { - // add default extension - int i = names.indexOf(DEFAULT_KEY); - if (i > 0) { - names.addAll(i, defaults); - } else { - names.addAll(0, defaults); - } - names.remove(DEFAULT_KEY); - } else { - names.remove(DEFAULT_KEY); - } - - // merge - configuration - for (String name : new ArrayList(names)) { - if (name.startsWith(REMOVE_VALUE_PREFIX)) { - names.remove(name); - names.remove(name.substring(1)); - } - } - return names; - } - - public static String replaceProperty(String expression, Map params) { - return replaceProperty(expression, new InmemoryConfiguration(params)); - } - - public static String replaceProperty(String expression, Configuration configuration) { - if (expression == null || expression.length() == 0 || expression.indexOf('$') < 0) { - return expression; - } - Matcher matcher = VARIABLE_PATTERN.matcher(expression); - StringBuffer sb = new StringBuffer(); - while (matcher.find()) { - String key = matcher.group(1); - String value = System.getProperty(key); - if (value == null && configuration != null) { - Object val = configuration.getProperty(key); - value = (val != null) ? val.toString() : null; - } - if (value == null) { - // maybe not placeholders, use origin express - value = matcher.group(); - } - matcher.appendReplacement(sb, Matcher.quoteReplacement(value)); - } - matcher.appendTail(sb); - return sb.toString(); - } - - /** - * Get dubbo properties. - * It is not recommended to use this method to modify dubbo properties. - * @return - */ - public static Properties getProperties() { - //TODO remove global instance PROPERTIES from ConfigUtils - if (PROPERTIES == null) { - synchronized (ConfigUtils.class) { - if (PROPERTIES == null) { - String path = System.getProperty(CommonConstants.DUBBO_PROPERTIES_KEY); - if (path == null || path.length() == 0) { - path = System.getenv(CommonConstants.DUBBO_PROPERTIES_KEY); - if (path == null || path.length() == 0) { - path = CommonConstants.DEFAULT_DUBBO_PROPERTIES; - } - } - PROPERTIES = ConfigUtils.loadProperties(path, false, true); - } - } - } - return PROPERTIES; - } - - /** - * This method should be called before Dubbo starting. - * It is not recommended to use this method to modify dubbo properties. - */ - public static void setProperties(Properties properties) { - PROPERTIES = properties; - } - - /** - * This method should be called before Dubbo starting. - * It is not recommended to use this method to modify dubbo properties. - */ - public static void addProperties(Properties properties) { - if (properties != null) { - getProperties().putAll(properties); - } - } - - public static String getProperty(String key) { - return getProperty(key, null); - } - - @SuppressWarnings({"unchecked", "rawtypes"}) - public static String getProperty(String key, String defaultValue) { - String value = System.getProperty(key); - if (value != null && value.length() > 0) { - return value; - } - return getProperty(getProperties(), key, defaultValue); - } - - public static String getProperty(Properties properties, String key, String defaultValue) { - return replaceProperty(properties.getProperty(key, defaultValue), (Map) properties); - } - - /** - * System environment -> System properties - * - * @param key key - * @return value - */ - public static String getSystemProperty(String key) { - String value = System.getenv(key); - if (StringUtils.isEmpty(value)) { - value = System.getProperty(key); - } - return value; - } - - public static Properties loadProperties(String fileName) { - return loadProperties(fileName, false, false); - } - - public static Properties loadProperties(String fileName, boolean allowMultiFile) { - return loadProperties(fileName, allowMultiFile, false); - } - - /** - * Load properties file to {@link Properties} from class path. - * - * @param fileName properties file name. for example: dubbo.properties, METE-INF/conf/foo.properties - * @param allowMultiFile if false, throw {@link IllegalStateException} when found multi file on the class path. - * @param optional is optional. if false, log warn when properties config file not found!s - * @return loaded {@link Properties} content.
    - *
  • return empty Properties if no file found. - *
  • merge multi properties file if found multi file - *
- * @throws IllegalStateException not allow multi-file, but multi-file exist on class path. - */ - public static Properties loadProperties(String fileName, boolean allowMultiFile, boolean optional) { - Properties properties = new Properties(); - // add scene judgement in windows environment Fix 2557 - if (checkFileNameExist(fileName)) { - try { - FileInputStream input = new FileInputStream(fileName); - try { - properties.load(input); - } finally { - input.close(); - } - } catch (Throwable e) { - logger.warn("Failed to load " + fileName + " file from " + fileName + "(ignore this file): " + e.getMessage(), e); - } - return properties; - } - - List list = new ArrayList(); - try { - Enumeration urls = ClassUtils.getClassLoader().getResources(fileName); - list = new ArrayList(); - while (urls.hasMoreElements()) { - list.add(urls.nextElement()); - } - } catch (Throwable t) { - logger.warn("Fail to load " + fileName + " file: " + t.getMessage(), t); - } - - if (list.isEmpty()) { - if (!optional) { - logger.warn("No " + fileName + " found on the class path."); - } - return properties; - } - - if (!allowMultiFile) { - if (list.size() > 1) { - String errMsg = String.format("only 1 %s file is expected, but %d dubbo.properties files found on class path: %s", - fileName, list.size(), list.toString()); - logger.warn(errMsg); - } - - // fall back to use method getResourceAsStream - try { - properties.load(ClassUtils.getClassLoader().getResourceAsStream(fileName)); - } catch (Throwable e) { - logger.warn("Failed to load " + fileName + " file from " + fileName + "(ignore this file): " + e.getMessage(), e); - } - return properties; - } - - logger.info("load " + fileName + " properties file from " + list); - - for (java.net.URL url : list) { - try { - Properties p = new Properties(); - InputStream input = url.openStream(); - if (input != null) { - try { - p.load(input); - properties.putAll(p); - } finally { - try { - input.close(); - } catch (Throwable t) { - } - } - } - } catch (Throwable e) { - logger.warn("Fail to load " + fileName + " file from " + url + "(ignore this file): " + e.getMessage(), e); - } - } - - return properties; - } - - public static String loadMigrationRule(String fileName) { - String rawRule = ""; - if (checkFileNameExist(fileName)) { - try { - try (FileInputStream input = new FileInputStream(fileName)) { - rawRule = readString(input); - } - } catch (Throwable e) { - logger.warn("Failed to load " + fileName + " file from " + fileName + "(ignore this file): " + e.getMessage(), e); - } - return rawRule; - } - - try { - InputStream is = ClassUtils.getClassLoader().getResourceAsStream(fileName); - if (is != null) { - rawRule = readString(is); - } - } catch (Throwable e) { - logger.warn("Failed to load " + fileName + " file from " + fileName + "(ignore this file): " + e.getMessage(), e); - } - return rawRule; - } - - private static String readString(InputStream is) { - StringBuilder stringBuilder = new StringBuilder(); - char[] buffer = new char[10]; - try (BufferedReader reader = new BufferedReader(new InputStreamReader(is))){ - int n; - while ((n = reader.read(buffer)) != -1) { - if (n < 10) { - buffer = Arrays.copyOf(buffer, n); - } - stringBuilder.append(String.valueOf(buffer)); - buffer = new char[10]; - } - } catch (IOException e) { - logger.error("Read migration file error.", e); - } - - return stringBuilder.toString(); - } - - /** - * check if the fileName can be found in filesystem - * - * @param fileName - * @return - */ - private static boolean checkFileNameExist(String fileName) { - File file = new File(fileName); - return file.exists(); - } - - - public static int getPid() { - if (PID < 0) { - try { - RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean(); - String name = runtime.getName(); // format: "pid@hostname" - PID = Integer.parseInt(name.substring(0, name.indexOf('@'))); - } catch (Throwable e) { - PID = 0; - } - } - return PID; - } -} +/* + * 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.common.utils; + +import org.apache.dubbo.common.config.Configuration; +import org.apache.dubbo.common.config.InmemoryConfiguration; +import org.apache.dubbo.common.constants.CommonConstants; +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.management.ManagementFactory; +import java.lang.management.RuntimeMXBean; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Enumeration; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN; +import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.REMOVE_VALUE_PREFIX; + +public class ConfigUtils { + + private static final Logger logger = LoggerFactory.getLogger(ConfigUtils.class); + private static Pattern VARIABLE_PATTERN = Pattern.compile( + "\\$\\s*\\{?\\s*([\\._0-9a-zA-Z]+)\\s*\\}?"); + private static volatile Properties PROPERTIES; + private static int PID = -1; + + private ConfigUtils() { + } + + public static boolean isNotEmpty(String value) { + return !isEmpty(value); + } + + public static boolean isEmpty(String value) { + return StringUtils.isEmpty(value) + || "false".equalsIgnoreCase(value) + || "0".equalsIgnoreCase(value) + || "null".equalsIgnoreCase(value) + || "N/A".equalsIgnoreCase(value); + } + + public static boolean isDefault(String value) { + return "true".equalsIgnoreCase(value) + || "default".equalsIgnoreCase(value); + } + + /** + * Insert default extension into extension list. + *

+ * Extension list support

    + *
  • Special value default, means the location for default extensions. + *
  • Special symbol-, means remove. -foo1 will remove default extension 'foo'; -default will remove all default extensions. + *
+ * + * @param type Extension type + * @param cfg Extension name list + * @param def Default extension list + * @return result extension list + */ + public static List mergeValues(Class type, String cfg, List def) { + List defaults = new ArrayList(); + if (def != null) { + for (String name : def) { + if (ExtensionLoader.getExtensionLoader(type).hasExtension(name)) { + defaults.add(name); + } + } + } + + List names = new ArrayList(); + + // add initial values + String[] configs = (cfg == null || cfg.trim().length() == 0) ? new String[0] : COMMA_SPLIT_PATTERN.split(cfg); + for (String config : configs) { + if (config != null && config.trim().length() > 0) { + names.add(config); + } + } + + // -default is not included + if (!names.contains(REMOVE_VALUE_PREFIX + DEFAULT_KEY)) { + // add default extension + int i = names.indexOf(DEFAULT_KEY); + if (i > 0) { + names.addAll(i, defaults); + } else { + names.addAll(0, defaults); + } + names.remove(DEFAULT_KEY); + } else { + names.remove(DEFAULT_KEY); + } + + // merge - configuration + for (String name : new ArrayList(names)) { + if (name.startsWith(REMOVE_VALUE_PREFIX)) { + names.remove(name); + names.remove(name.substring(1)); + } + } + return names; + } + + public static String replaceProperty(String expression, Map params) { + return replaceProperty(expression, new InmemoryConfiguration(params)); + } + + public static String replaceProperty(String expression, Configuration configuration) { + if (expression == null || expression.length() == 0 || expression.indexOf('$') < 0) { + return expression; + } + Matcher matcher = VARIABLE_PATTERN.matcher(expression); + StringBuffer sb = new StringBuffer(); + while (matcher.find()) { + String key = matcher.group(1); + String value = System.getProperty(key); + if (value == null && configuration != null) { + Object val = configuration.getProperty(key); + value = (val != null) ? val.toString() : null; + } + if (value == null) { + // maybe not placeholders, use origin express + value = matcher.group(); + } + matcher.appendReplacement(sb, Matcher.quoteReplacement(value)); + } + matcher.appendTail(sb); + return sb.toString(); + } + + /** + * Get dubbo properties. + * It is not recommended to use this method to modify dubbo properties. + * @return + */ + public static Properties getProperties() { + //TODO remove global instance PROPERTIES from ConfigUtils + if (PROPERTIES == null) { + synchronized (ConfigUtils.class) { + if (PROPERTIES == null) { + String path = System.getProperty(CommonConstants.DUBBO_PROPERTIES_KEY); + if (path == null || path.length() == 0) { + path = System.getenv(CommonConstants.DUBBO_PROPERTIES_KEY); + if (path == null || path.length() == 0) { + path = CommonConstants.DEFAULT_DUBBO_PROPERTIES; + } + } + PROPERTIES = ConfigUtils.loadProperties(path, false, true); + } + } + } + return PROPERTIES; + } + + /** + * This method should be called before Dubbo starting. + * It is not recommended to use this method to modify dubbo properties. + */ + public static void setProperties(Properties properties) { + PROPERTIES = properties; + } + + /** + * This method should be called before Dubbo starting. + * It is not recommended to use this method to modify dubbo properties. + */ + public static void addProperties(Properties properties) { + if (properties != null) { + getProperties().putAll(properties); + } + } + + public static String getProperty(String key) { + return getProperty(key, null); + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + public static String getProperty(String key, String defaultValue) { + String value = System.getProperty(key); + if (value != null && value.length() > 0) { + return value; + } + return getProperty(getProperties(), key, defaultValue); + } + + public static String getProperty(Properties properties, String key, String defaultValue) { + return replaceProperty(properties.getProperty(key, defaultValue), (Map) properties); + } + + /** + * System environment -> System properties + * + * @param key key + * @return value + */ + public static String getSystemProperty(String key) { + String value = System.getenv(key); + if (StringUtils.isEmpty(value)) { + value = System.getProperty(key); + } + return value; + } + + public static Properties loadProperties(String fileName) { + return loadProperties(fileName, false, false); + } + + public static Properties loadProperties(String fileName, boolean allowMultiFile) { + return loadProperties(fileName, allowMultiFile, false); + } + + /** + * Load properties file to {@link Properties} from class path. + * + * @param fileName properties file name. for example: dubbo.properties, METE-INF/conf/foo.properties + * @param allowMultiFile if false, throw {@link IllegalStateException} when found multi file on the class path. + * @param optional is optional. if false, log warn when properties config file not found!s + * @return loaded {@link Properties} content.
    + *
  • return empty Properties if no file found. + *
  • merge multi properties file if found multi file + *
+ * @throws IllegalStateException not allow multi-file, but multi-file exist on class path. + */ + public static Properties loadProperties(String fileName, boolean allowMultiFile, boolean optional) { + Properties properties = new Properties(); + // add scene judgement in windows environment Fix 2557 + if (checkFileNameExist(fileName)) { + try { + FileInputStream input = new FileInputStream(fileName); + try { + properties.load(input); + } finally { + input.close(); + } + } catch (Throwable e) { + logger.warn("Failed to load " + fileName + " file from " + fileName + "(ignore this file): " + e.getMessage(), e); + } + return properties; + } + + List list = new ArrayList(); + try { + Enumeration urls = ClassUtils.getClassLoader().getResources(fileName); + list = new ArrayList(); + while (urls.hasMoreElements()) { + list.add(urls.nextElement()); + } + } catch (Throwable t) { + logger.warn("Fail to load " + fileName + " file: " + t.getMessage(), t); + } + + if (list.isEmpty()) { + if (!optional) { + logger.warn("No " + fileName + " found on the class path."); + } + return properties; + } + + if (!allowMultiFile) { + if (list.size() > 1) { + String errMsg = String.format("only 1 %s file is expected, but %d dubbo.properties files found on class path: %s", + fileName, list.size(), list.toString()); + logger.warn(errMsg); + } + + // fall back to use method getResourceAsStream + try { + properties.load(ClassUtils.getClassLoader().getResourceAsStream(fileName)); + } catch (Throwable e) { + logger.warn("Failed to load " + fileName + " file from " + fileName + "(ignore this file): " + e.getMessage(), e); + } + return properties; + } + + logger.info("load " + fileName + " properties file from " + list); + + for (java.net.URL url : list) { + try { + Properties p = new Properties(); + InputStream input = url.openStream(); + if (input != null) { + try { + p.load(input); + properties.putAll(p); + } finally { + try { + input.close(); + } catch (Throwable t) { + } + } + } + } catch (Throwable e) { + logger.warn("Fail to load " + fileName + " file from " + url + "(ignore this file): " + e.getMessage(), e); + } + } + + return properties; + } + + public static String loadMigrationRule(String fileName) { + String rawRule = ""; + if (checkFileNameExist(fileName)) { + try { + try (FileInputStream input = new FileInputStream(fileName)) { + rawRule = readString(input); + } + } catch (Throwable e) { + logger.warn("Failed to load " + fileName + " file from " + fileName + "(ignore this file): " + e.getMessage(), e); + } + return rawRule; + } + + try { + InputStream is = ClassUtils.getClassLoader().getResourceAsStream(fileName); + if (is != null) { + rawRule = readString(is); + } + } catch (Throwable e) { + logger.warn("Failed to load " + fileName + " file from " + fileName + "(ignore this file): " + e.getMessage(), e); + } + return rawRule; + } + + private static String readString(InputStream is) { + StringBuilder stringBuilder = new StringBuilder(); + char[] buffer = new char[10]; + try (BufferedReader reader = new BufferedReader(new InputStreamReader(is))){ + int n; + while ((n = reader.read(buffer)) != -1) { + if (n < 10) { + buffer = Arrays.copyOf(buffer, n); + } + stringBuilder.append(String.valueOf(buffer)); + buffer = new char[10]; + } + } catch (IOException e) { + logger.error("Read migration file error.", e); + } + + return stringBuilder.toString(); + } + + /** + * check if the fileName can be found in filesystem + * + * @param fileName + * @return + */ + private static boolean checkFileNameExist(String fileName) { + File file = new File(fileName); + return file.exists(); + } + + + public static int getPid() { + if (PID < 0) { + try { + RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean(); + String name = runtime.getName(); // format: "pid@hostname" + PID = Integer.parseInt(name.substring(0, name.indexOf('@'))); + } catch (Throwable e) { + PID = 0; + } + } + return PID; + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/DubboAppender.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/DubboAppender.java index e2b1940a7e..4f9d72b4ed 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/DubboAppender.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/DubboAppender.java @@ -1,68 +1,68 @@ -/* - * 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.common.utils; - -import org.apache.log4j.FileAppender; -import org.apache.log4j.spi.LoggingEvent; - -import java.util.ArrayList; -import java.util.List; - -public class DubboAppender extends FileAppender { - - private static final String DEFAULT_FILE_NAME = "dubbo.log"; - - public DubboAppender() { - super(); - setFile(DEFAULT_FILE_NAME); - } - - public static boolean available = false; - - public static List logList = new ArrayList<>(); - - public static void doStart() { - available = true; - } - - public static void doStop() { - available = false; - } - - public static void clear() { - logList.clear(); - } - - @Override - public void append(LoggingEvent event) { - super.append(event); - if (available) { - Log temp = parseLog(event); - logList.add(temp); - } - } - - private Log parseLog(LoggingEvent event) { - Log log = new Log(); - log.setLogName(event.getLogger().getName()); - log.setLogLevel(event.getLevel()); - log.setLogThread(event.getThreadName()); - log.setLogMessage(event.getMessage().toString()); - return log; - } - -} +/* + * 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.common.utils; + +import org.apache.log4j.FileAppender; +import org.apache.log4j.spi.LoggingEvent; + +import java.util.ArrayList; +import java.util.List; + +public class DubboAppender extends FileAppender { + + private static final String DEFAULT_FILE_NAME = "dubbo.log"; + + public DubboAppender() { + super(); + setFile(DEFAULT_FILE_NAME); + } + + public static boolean available = false; + + public static List logList = new ArrayList<>(); + + public static void doStart() { + available = true; + } + + public static void doStop() { + available = false; + } + + public static void clear() { + logList.clear(); + } + + @Override + public void append(LoggingEvent event) { + super.append(event); + if (available) { + Log temp = parseLog(event); + logList.add(temp); + } + } + + private Log parseLog(LoggingEvent event) { + Log log = new Log(); + log.setLogName(event.getLogger().getName()); + log.setLogLevel(event.getLevel()); + log.setLogThread(event.getThreadName()); + log.setLogMessage(event.getMessage().toString()); + return log; + } + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/Holder.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/Holder.java index 145ab8eba1..07c3e32ca4 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/Holder.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/Holder.java @@ -31,4 +31,4 @@ public class Holder { return value; } -} \ No newline at end of file +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/IOUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/IOUtils.java index b7e26169cc..0923f1dbec 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/IOUtils.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/IOUtils.java @@ -1,270 +1,270 @@ -/* - * 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.common.utils; - -import org.apache.dubbo.common.constants.CommonConstants; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.io.Reader; -import java.io.StringReader; -import java.io.StringWriter; -import java.io.Writer; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; -import java.util.List; - -/** - * Miscellaneous io utility methods. - * Mainly for internal use within the framework. - * - * @author william.liangf - * @since 2.0.7 - */ -public class IOUtils { - private static final int BUFFER_SIZE = 1024 * 8; - public static final int EOF = -1; - - private IOUtils() { - } - - /** - * write. - * - * @param is InputStream instance. - * @param os OutputStream instance. - * @return count. - * @throws IOException If an I/O error occurs - */ - public static long write(InputStream is, OutputStream os) throws IOException { - return write(is, os, BUFFER_SIZE); - } - - /** - * write. - * - * @param is InputStream instance. - * @param os OutputStream instance. - * @param bufferSize buffer size. - * @return count. - * @throws IOException If an I/O error occurs - */ - public static long write(InputStream is, OutputStream os, int bufferSize) throws IOException { - byte[] buff = new byte[bufferSize]; - return write(is, os, buff); - } - - /** - * write. - * - * @param input InputStream instance. - * @param output OutputStream instance. - * @param buffer buffer byte array - * @return count. - * @throws IOException If an I/O error occurs - */ - public static long write(final InputStream input, final OutputStream output, final byte[] buffer) throws IOException { - long count = 0; - int n; - while (EOF != (n = input.read(buffer))) { - output.write(buffer, 0, n); - count += n; - } - return count; - } - - /** - * read string. - * - * @param reader Reader instance. - * @return String. - * @throws IOException If an I/O error occurs - */ - public static String read(Reader reader) throws IOException { - try (StringWriter writer = new StringWriter()) { - write(reader, writer); - return writer.getBuffer().toString(); - } - } - - /** - * write string. - * - * @param writer Writer instance. - * @param string String. - * @throws IOException If an I/O error occurs - */ - public static long write(Writer writer, String string) throws IOException { - try (Reader reader = new StringReader(string)) { - return write(reader, writer); - } - } - - /** - * write. - * - * @param reader Reader. - * @param writer Writer. - * @return count. - * @throws IOException If an I/O error occurs - */ - public static long write(Reader reader, Writer writer) throws IOException { - return write(reader, writer, BUFFER_SIZE); - } - - /** - * write. - * - * @param reader Reader. - * @param writer Writer. - * @param bufferSize buffer size. - * @return count. - * @throws IOException If an I/O error occurs - */ - public static long write(Reader reader, Writer writer, int bufferSize) throws IOException { - int read; - long total = 0; - char[] buf = new char[bufferSize]; - while ((read = reader.read(buf)) != -1) { - writer.write(buf, 0, read); - total += read; - } - return total; - } - - /** - * read lines. - * - * @param file file. - * @return lines. - * @throws IOException If an I/O error occurs - */ - public static String[] readLines(File file) throws IOException { - if (file == null || !file.exists() || !file.canRead()) { - return new String[0]; - } - - return readLines(new FileInputStream(file)); - } - - /** - * read lines. - * - * @param is input stream. - * @return lines. - * @throws IOException If an I/O error occurs - */ - public static String[] readLines(InputStream is) throws IOException { - List lines = new ArrayList(); - try (BufferedReader reader = new BufferedReader(new InputStreamReader(is))) { - String line; - while ((line = reader.readLine()) != null) { - lines.add(line); - } - return lines.toArray(new String[0]); - } - } - - /** - * write lines. - * - * @param os output stream. - * @param lines lines. - * @throws IOException If an I/O error occurs - */ - public static void writeLines(OutputStream os, String[] lines) throws IOException { - try (PrintWriter writer = new PrintWriter(new OutputStreamWriter(os))) { - for (String line : lines) { - writer.println(line); - } - writer.flush(); - } - } - - /** - * write lines. - * - * @param file file. - * @param lines lines. - * @throws IOException If an I/O error occurs - */ - public static void writeLines(File file, String[] lines) throws IOException { - if (file == null) { - throw new IOException("File is null."); - } - writeLines(new FileOutputStream(file), lines); - } - - /** - * append lines. - * - * @param file file. - * @param lines lines. - * @throws IOException If an I/O error occurs - */ - public static void appendLines(File file, String[] lines) throws IOException { - if (file == null) { - throw new IOException("File is null."); - } - writeLines(new FileOutputStream(file, true), lines); - } - - - /** - * use like spring code - * @param resourceLocation - * @return - */ - public static URL getURL(String resourceLocation) throws FileNotFoundException { - Assert.notNull(resourceLocation, "Resource location must not be null"); - if (resourceLocation.startsWith(CommonConstants.CLASSPATH_URL_PREFIX)) { - String path = resourceLocation.substring(CommonConstants.CLASSPATH_URL_PREFIX.length()); - ClassLoader cl = ClassUtils.getClassLoader(); - URL url = (cl != null ? cl.getResource(path) : ClassLoader.getSystemResource(path)); - if (url == null) { - String description = "class path resource [" + path + "]"; - throw new FileNotFoundException(description + - " cannot be resolved to URL because it does not exist"); - } - return url; - } - try { - // try URL - return new URL(resourceLocation); - } - catch (MalformedURLException ex) { - // no URL -> treat as file path - try { - return new File(resourceLocation).toURI().toURL(); - } - catch (MalformedURLException ex2) { - throw new FileNotFoundException("Resource location [" + resourceLocation + - "] is neither a URL not a well-formed file path"); - } - } - } -} \ No newline at end of file +/* + * 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.common.utils; + +import org.apache.dubbo.common.constants.CommonConstants; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +/** + * Miscellaneous io utility methods. + * Mainly for internal use within the framework. + * + * @author william.liangf + * @since 2.0.7 + */ +public class IOUtils { + private static final int BUFFER_SIZE = 1024 * 8; + public static final int EOF = -1; + + private IOUtils() { + } + + /** + * write. + * + * @param is InputStream instance. + * @param os OutputStream instance. + * @return count. + * @throws IOException If an I/O error occurs + */ + public static long write(InputStream is, OutputStream os) throws IOException { + return write(is, os, BUFFER_SIZE); + } + + /** + * write. + * + * @param is InputStream instance. + * @param os OutputStream instance. + * @param bufferSize buffer size. + * @return count. + * @throws IOException If an I/O error occurs + */ + public static long write(InputStream is, OutputStream os, int bufferSize) throws IOException { + byte[] buff = new byte[bufferSize]; + return write(is, os, buff); + } + + /** + * write. + * + * @param input InputStream instance. + * @param output OutputStream instance. + * @param buffer buffer byte array + * @return count. + * @throws IOException If an I/O error occurs + */ + public static long write(final InputStream input, final OutputStream output, final byte[] buffer) throws IOException { + long count = 0; + int n; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } + + /** + * read string. + * + * @param reader Reader instance. + * @return String. + * @throws IOException If an I/O error occurs + */ + public static String read(Reader reader) throws IOException { + try (StringWriter writer = new StringWriter()) { + write(reader, writer); + return writer.getBuffer().toString(); + } + } + + /** + * write string. + * + * @param writer Writer instance. + * @param string String. + * @throws IOException If an I/O error occurs + */ + public static long write(Writer writer, String string) throws IOException { + try (Reader reader = new StringReader(string)) { + return write(reader, writer); + } + } + + /** + * write. + * + * @param reader Reader. + * @param writer Writer. + * @return count. + * @throws IOException If an I/O error occurs + */ + public static long write(Reader reader, Writer writer) throws IOException { + return write(reader, writer, BUFFER_SIZE); + } + + /** + * write. + * + * @param reader Reader. + * @param writer Writer. + * @param bufferSize buffer size. + * @return count. + * @throws IOException If an I/O error occurs + */ + public static long write(Reader reader, Writer writer, int bufferSize) throws IOException { + int read; + long total = 0; + char[] buf = new char[bufferSize]; + while ((read = reader.read(buf)) != -1) { + writer.write(buf, 0, read); + total += read; + } + return total; + } + + /** + * read lines. + * + * @param file file. + * @return lines. + * @throws IOException If an I/O error occurs + */ + public static String[] readLines(File file) throws IOException { + if (file == null || !file.exists() || !file.canRead()) { + return new String[0]; + } + + return readLines(new FileInputStream(file)); + } + + /** + * read lines. + * + * @param is input stream. + * @return lines. + * @throws IOException If an I/O error occurs + */ + public static String[] readLines(InputStream is) throws IOException { + List lines = new ArrayList(); + try (BufferedReader reader = new BufferedReader(new InputStreamReader(is))) { + String line; + while ((line = reader.readLine()) != null) { + lines.add(line); + } + return lines.toArray(new String[0]); + } + } + + /** + * write lines. + * + * @param os output stream. + * @param lines lines. + * @throws IOException If an I/O error occurs + */ + public static void writeLines(OutputStream os, String[] lines) throws IOException { + try (PrintWriter writer = new PrintWriter(new OutputStreamWriter(os))) { + for (String line : lines) { + writer.println(line); + } + writer.flush(); + } + } + + /** + * write lines. + * + * @param file file. + * @param lines lines. + * @throws IOException If an I/O error occurs + */ + public static void writeLines(File file, String[] lines) throws IOException { + if (file == null) { + throw new IOException("File is null."); + } + writeLines(new FileOutputStream(file), lines); + } + + /** + * append lines. + * + * @param file file. + * @param lines lines. + * @throws IOException If an I/O error occurs + */ + public static void appendLines(File file, String[] lines) throws IOException { + if (file == null) { + throw new IOException("File is null."); + } + writeLines(new FileOutputStream(file, true), lines); + } + + + /** + * use like spring code + * @param resourceLocation + * @return + */ + public static URL getURL(String resourceLocation) throws FileNotFoundException { + Assert.notNull(resourceLocation, "Resource location must not be null"); + if (resourceLocation.startsWith(CommonConstants.CLASSPATH_URL_PREFIX)) { + String path = resourceLocation.substring(CommonConstants.CLASSPATH_URL_PREFIX.length()); + ClassLoader cl = ClassUtils.getClassLoader(); + URL url = (cl != null ? cl.getResource(path) : ClassLoader.getSystemResource(path)); + if (url == null) { + String description = "class path resource [" + path + "]"; + throw new FileNotFoundException(description + + " cannot be resolved to URL because it does not exist"); + } + return url; + } + try { + // try URL + return new URL(resourceLocation); + } + catch (MalformedURLException ex) { + // no URL -> treat as file path + try { + return new File(resourceLocation).toURI().toURL(); + } + catch (MalformedURLException ex2) { + throw new FileNotFoundException("Resource location [" + resourceLocation + + "] is neither a URL not a well-formed file path"); + } + } + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/LFUCache.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/LFUCache.java index 8230bd6886..ddcf2e62ea 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/LFUCache.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/LFUCache.java @@ -283,4 +283,4 @@ public class LFUCache { } -} \ No newline at end of file +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/LRUCache.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/LRUCache.java index 1072766407..6b398909c3 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/LRUCache.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/LRUCache.java @@ -156,4 +156,4 @@ public class LRUCache extends LinkedHashMap { } } -} \ No newline at end of file +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/Log.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/Log.java index 974058ffb1..7a3d028e7f 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/Log.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/Log.java @@ -1,116 +1,116 @@ -/* - * 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.common.utils; - -import org.apache.log4j.Level; - -import java.io.Serializable; - -public class Log implements Serializable { - private static final long serialVersionUID = -534113138054377073L; - private String logName; - private Level logLevel; - private String logMessage; - private String logThread; - - public String getLogName() { - return logName; - } - - public void setLogName(String logName) { - this.logName = logName; - } - - public Level getLogLevel() { - return logLevel; - } - - public void setLogLevel(Level logLevel) { - this.logLevel = logLevel; - } - - public String getLogMessage() { - return logMessage; - } - - public void setLogMessage(String logMessage) { - this.logMessage = logMessage; - } - - public String getLogThread() { - return logThread; - } - - public void setLogThread(String logThread) { - this.logThread = logThread; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((logLevel == null) ? 0 : logLevel.hashCode()); - result = prime * result + ((logMessage == null) ? 0 : logMessage.hashCode()); - result = prime * result + ((logName == null) ? 0 : logName.hashCode()); - result = prime * result + ((logThread == null) ? 0 : logThread.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - Log other = (Log) obj; - if (logLevel == null) { - if (other.logLevel != null) { - return false; - } - } else if (!logLevel.equals(other.logLevel)) { - return false; - } - if (logMessage == null) { - if (other.logMessage != null) { - return false; - } - } else if (!logMessage.equals(other.logMessage)) { - return false; - } - if (logName == null) { - if (other.logName != null) { - return false; - } - } else if (!logName.equals(other.logName)) { - return false; - } - if (logThread == null) { - if (other.logThread != null) { - return false; - } - } else if (!logThread.equals(other.logThread)) { - return false; - } - return true; - } - -} \ No newline at end of file +/* + * 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.common.utils; + +import org.apache.log4j.Level; + +import java.io.Serializable; + +public class Log implements Serializable { + private static final long serialVersionUID = -534113138054377073L; + private String logName; + private Level logLevel; + private String logMessage; + private String logThread; + + public String getLogName() { + return logName; + } + + public void setLogName(String logName) { + this.logName = logName; + } + + public Level getLogLevel() { + return logLevel; + } + + public void setLogLevel(Level logLevel) { + this.logLevel = logLevel; + } + + public String getLogMessage() { + return logMessage; + } + + public void setLogMessage(String logMessage) { + this.logMessage = logMessage; + } + + public String getLogThread() { + return logThread; + } + + public void setLogThread(String logThread) { + this.logThread = logThread; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((logLevel == null) ? 0 : logLevel.hashCode()); + result = prime * result + ((logMessage == null) ? 0 : logMessage.hashCode()); + result = prime * result + ((logName == null) ? 0 : logName.hashCode()); + result = prime * result + ((logThread == null) ? 0 : logThread.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Log other = (Log) obj; + if (logLevel == null) { + if (other.logLevel != null) { + return false; + } + } else if (!logLevel.equals(other.logLevel)) { + return false; + } + if (logMessage == null) { + if (other.logMessage != null) { + return false; + } + } else if (!logMessage.equals(other.logMessage)) { + return false; + } + if (logName == null) { + if (other.logName != null) { + return false; + } + } else if (!logName.equals(other.logName)) { + return false; + } + if (logThread == null) { + if (other.logThread != null) { + return false; + } + } else if (!logThread.equals(other.logThread)) { + return false; + } + return true; + } + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/LogUtil.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/LogUtil.java index 6b5eff58c2..46d535215a 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/LogUtil.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/LogUtil.java @@ -1,131 +1,131 @@ -/* - * 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.common.utils; - -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; - -import org.apache.log4j.Level; - -import java.util.Iterator; -import java.util.List; - -public class LogUtil { - - private static Logger Log = LoggerFactory.getLogger(LogUtil.class); - - public static void start() { - DubboAppender.doStart(); - } - - public static void stop() { - DubboAppender.doStop(); - } - - public static boolean checkNoError() { - if (findLevel(Level.ERROR) == 0) { - return true; - } else { - return false; - } - - } - - public static int findName(String expectedLogName) { - int count = 0; - List logList = DubboAppender.logList; - for (int i = 0; i < logList.size(); i++) { - String logName = logList.get(i).getLogName(); - if (logName.contains(expectedLogName)) { - count++; - } - } - return count; - } - - public static int findLevel(Level expectedLevel) { - int count = 0; - List logList = DubboAppender.logList; - for (int i = 0; i < logList.size(); i++) { - Level logLevel = logList.get(i).getLogLevel(); - if (logLevel.equals(expectedLevel)) { - count++; - } - } - return count; - } - - public static int findLevelWithThreadName(Level expectedLevel, String threadName) { - int count = 0; - List logList = DubboAppender.logList; - for (int i = 0; i < logList.size(); i++) { - Log log = logList.get(i); - if (log.getLogLevel().equals(expectedLevel) && log.getLogThread().equals(threadName)) { - count++; - } - } - return count; - } - - public static int findThread(String expectedThread) { - int count = 0; - List logList = DubboAppender.logList; - for (int i = 0; i < logList.size(); i++) { - String logThread = logList.get(i).getLogThread(); - if (logThread.contains(expectedThread)) { - count++; - } - } - return count; - } - - public static int findMessage(String expectedMessage) { - int count = 0; - List logList = DubboAppender.logList; - for (int i = 0; i < logList.size(); i++) { - String logMessage = logList.get(i).getLogMessage(); - if (logMessage.contains(expectedMessage)) { - count++; - } - } - return count; - } - - public static int findMessage(Level expectedLevel, String expectedMessage) { - int count = 0; - List logList = DubboAppender.logList; - for (int i = 0; i < logList.size(); i++) { - Level logLevel = logList.get(i).getLogLevel(); - if (logLevel.equals(expectedLevel)) { - String logMessage = logList.get(i).getLogMessage(); - if (logMessage.contains(expectedMessage)) { - count++; - } - } - } - return count; - } - - public static void printList(List list) { - Log.info("PrintList:"); - Iterator it = list.iterator(); - while (it.hasNext()) { - Log.info(it.next().toString()); - } - - } -} \ No newline at end of file +/* + * 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.common.utils; + +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; + +import org.apache.log4j.Level; + +import java.util.Iterator; +import java.util.List; + +public class LogUtil { + + private static Logger Log = LoggerFactory.getLogger(LogUtil.class); + + public static void start() { + DubboAppender.doStart(); + } + + public static void stop() { + DubboAppender.doStop(); + } + + public static boolean checkNoError() { + if (findLevel(Level.ERROR) == 0) { + return true; + } else { + return false; + } + + } + + public static int findName(String expectedLogName) { + int count = 0; + List logList = DubboAppender.logList; + for (int i = 0; i < logList.size(); i++) { + String logName = logList.get(i).getLogName(); + if (logName.contains(expectedLogName)) { + count++; + } + } + return count; + } + + public static int findLevel(Level expectedLevel) { + int count = 0; + List logList = DubboAppender.logList; + for (int i = 0; i < logList.size(); i++) { + Level logLevel = logList.get(i).getLogLevel(); + if (logLevel.equals(expectedLevel)) { + count++; + } + } + return count; + } + + public static int findLevelWithThreadName(Level expectedLevel, String threadName) { + int count = 0; + List logList = DubboAppender.logList; + for (int i = 0; i < logList.size(); i++) { + Log log = logList.get(i); + if (log.getLogLevel().equals(expectedLevel) && log.getLogThread().equals(threadName)) { + count++; + } + } + return count; + } + + public static int findThread(String expectedThread) { + int count = 0; + List logList = DubboAppender.logList; + for (int i = 0; i < logList.size(); i++) { + String logThread = logList.get(i).getLogThread(); + if (logThread.contains(expectedThread)) { + count++; + } + } + return count; + } + + public static int findMessage(String expectedMessage) { + int count = 0; + List logList = DubboAppender.logList; + for (int i = 0; i < logList.size(); i++) { + String logMessage = logList.get(i).getLogMessage(); + if (logMessage.contains(expectedMessage)) { + count++; + } + } + return count; + } + + public static int findMessage(Level expectedLevel, String expectedMessage) { + int count = 0; + List logList = DubboAppender.logList; + for (int i = 0; i < logList.size(); i++) { + Level logLevel = logList.get(i).getLogLevel(); + if (logLevel.equals(expectedLevel)) { + String logMessage = logList.get(i).getLogMessage(); + if (logMessage.contains(expectedMessage)) { + count++; + } + } + } + return count; + } + + public static void printList(List list) { + Log.info("PrintList:"); + Iterator it = list.iterator(); + while (it.hasNext()) { + Log.info(it.next().toString()); + } + + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/MemberUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/MemberUtils.java index f7aa6ff990..daf9273020 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/MemberUtils.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/MemberUtils.java @@ -59,4 +59,4 @@ public interface MemberUtils { return member != null && Modifier.isPublic(member.getModifiers()); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/NamedThreadFactory.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/NamedThreadFactory.java index a0c4620d35..7d887fda34 100755 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/NamedThreadFactory.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/NamedThreadFactory.java @@ -1,63 +1,63 @@ -/* - * 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.common.utils; - -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * InternalThreadFactory. - */ -public class NamedThreadFactory implements ThreadFactory { - - protected static final AtomicInteger POOL_SEQ = new AtomicInteger(1); - - protected final AtomicInteger mThreadNum = new AtomicInteger(1); - - protected final String mPrefix; - - protected final boolean mDaemon; - - protected final ThreadGroup mGroup; - - public NamedThreadFactory() { - this("pool-" + POOL_SEQ.getAndIncrement(), false); - } - - public NamedThreadFactory(String prefix) { - this(prefix, false); - } - - public NamedThreadFactory(String prefix, boolean daemon) { - mPrefix = prefix + "-thread-"; - mDaemon = daemon; - SecurityManager s = System.getSecurityManager(); - mGroup = (s == null) ? Thread.currentThread().getThreadGroup() : s.getThreadGroup(); - } - - @Override - public Thread newThread(Runnable runnable) { - String name = mPrefix + mThreadNum.getAndIncrement(); - Thread ret = new Thread(mGroup, runnable, name, 0); - ret.setDaemon(mDaemon); - return ret; - } - - public ThreadGroup getThreadGroup() { - return mGroup; - } -} +/* + * 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.common.utils; + +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * InternalThreadFactory. + */ +public class NamedThreadFactory implements ThreadFactory { + + protected static final AtomicInteger POOL_SEQ = new AtomicInteger(1); + + protected final AtomicInteger mThreadNum = new AtomicInteger(1); + + protected final String mPrefix; + + protected final boolean mDaemon; + + protected final ThreadGroup mGroup; + + public NamedThreadFactory() { + this("pool-" + POOL_SEQ.getAndIncrement(), false); + } + + public NamedThreadFactory(String prefix) { + this(prefix, false); + } + + public NamedThreadFactory(String prefix, boolean daemon) { + mPrefix = prefix + "-thread-"; + mDaemon = daemon; + SecurityManager s = System.getSecurityManager(); + mGroup = (s == null) ? Thread.currentThread().getThreadGroup() : s.getThreadGroup(); + } + + @Override + public Thread newThread(Runnable runnable) { + String name = mPrefix + mThreadNum.getAndIncrement(); + Thread ret = new Thread(mGroup, runnable, name, 0); + ret.setDaemon(mDaemon); + return ret; + } + + public ThreadGroup getThreadGroup() { + return mGroup; + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/NetUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/NetUtils.java index 01855f4b5f..af08299cff 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/NetUtils.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/NetUtils.java @@ -1,653 +1,653 @@ -/* - * 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.common.utils; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.config.ConfigurationUtils; -import org.apache.dubbo.common.constants.CommonConstants; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.logger.support.FailsafeLogger; - -import java.io.IOException; -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.MulticastSocket; -import java.net.NetworkInterface; -import java.net.ServerSocket; -import java.net.SocketException; -import java.net.UnknownHostException; -import java.util.Enumeration; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.concurrent.ThreadLocalRandom; -import java.util.regex.Pattern; - -import static java.util.Collections.emptyList; -import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_VALUE; -import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_IP_TO_BIND; -import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_PREFERRED_NETWORK_INTERFACE; -import static org.apache.dubbo.common.constants.CommonConstants.LOCALHOST_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.LOCALHOST_VALUE; -import static org.apache.dubbo.common.utils.CollectionUtils.first; - -/** - * IP and Port Helper for RPC - */ -public class NetUtils { - - private static Logger logger; - - static { - logger = LoggerFactory.getLogger(NetUtils.class); - if (logger instanceof FailsafeLogger) { - logger = ((FailsafeLogger) logger).getLogger(); - } - } - - // returned port range is [30000, 39999] - private static final int RND_PORT_START = 30000; - private static final int RND_PORT_RANGE = 10000; - - // valid port range is (0, 65535] - private static final int MIN_PORT = 0; - private static final int MAX_PORT = 65535; - - private static final Pattern ADDRESS_PATTERN = Pattern.compile("^\\d{1,3}(\\.\\d{1,3}){3}\\:\\d{1,5}$"); - private static final Pattern LOCAL_IP_PATTERN = Pattern.compile("127(\\.\\d{1,3}){3}$"); - private static final Pattern IP_PATTERN = Pattern.compile("\\d{1,3}(\\.\\d{1,3}){3,5}$"); - - private static final Map HOST_NAME_CACHE = new LRUCache<>(1000); - private static volatile InetAddress LOCAL_ADDRESS = null; - - private static final String SPLIT_IPV4_CHARACTER = "\\."; - private static final String SPLIT_IPV6_CHARACTER = ":"; - - public static int getRandomPort() { - return RND_PORT_START + ThreadLocalRandom.current().nextInt(RND_PORT_RANGE); - } - - public static int getAvailablePort() { - try (ServerSocket ss = new ServerSocket()) { - ss.bind(null); - return ss.getLocalPort(); - } catch (IOException e) { - return getRandomPort(); - } - } - - public static int getAvailablePort(int port) { - if (port <= 0) { - return getAvailablePort(); - } - for (int i = port; i < MAX_PORT; i++) { - try (ServerSocket ignored = new ServerSocket(i)) { - return i; - } catch (IOException e) { - // continue - } - } - return port; - } - - public static boolean isInvalidPort(int port) { - return port <= MIN_PORT || port > MAX_PORT; - } - - public static boolean isValidAddress(String address) { - return ADDRESS_PATTERN.matcher(address).matches(); - } - - public static boolean isLocalHost(String host) { - return host != null - && (LOCAL_IP_PATTERN.matcher(host).matches() - || host.equalsIgnoreCase(LOCALHOST_KEY)); - } - - public static boolean isAnyHost(String host) { - return ANYHOST_VALUE.equals(host); - } - - public static boolean isInvalidLocalHost(String host) { - return host == null - || host.length() == 0 - || host.equalsIgnoreCase(LOCALHOST_KEY) - || host.equals(ANYHOST_VALUE) - || host.startsWith("127."); - } - - public static boolean isValidLocalHost(String host) { - return !isInvalidLocalHost(host); - } - - public static InetSocketAddress getLocalSocketAddress(String host, int port) { - return isInvalidLocalHost(host) ? - new InetSocketAddress(port) : new InetSocketAddress(host, port); - } - - static boolean isValidV4Address(InetAddress address) { - if (address == null || address.isLoopbackAddress()) { - return false; - } - - String name = address.getHostAddress(); - return (name != null - && IP_PATTERN.matcher(name).matches() - && !ANYHOST_VALUE.equals(name) - && !LOCALHOST_VALUE.equals(name)); - } - - /** - * Check if an ipv6 address - * - * @return true if it is reachable - */ - static boolean isPreferIPV6Address() { - return Boolean.getBoolean("java.net.preferIPv6Addresses"); - } - - /** - * normalize the ipv6 Address, convert scope name to scope id. - * e.g. - * convert - * fe80:0:0:0:894:aeec:f37d:23e1%en0 - * to - * fe80:0:0:0:894:aeec:f37d:23e1%5 - *

- * The %5 after ipv6 address is called scope id. - * see java doc of {@link Inet6Address} for more details. - * - * @param address the input address - * @return the normalized address, with scope id converted to int - */ - static InetAddress normalizeV6Address(Inet6Address address) { - String addr = address.getHostAddress(); - int i = addr.lastIndexOf('%'); - if (i > 0) { - try { - return InetAddress.getByName(addr.substring(0, i) + '%' + address.getScopeId()); - } catch (UnknownHostException e) { - // ignore - logger.debug("Unknown IPV6 address: ", e); - } - } - return address; - } - - private static volatile String HOST_ADDRESS; - - public static String getLocalHost() { - if (HOST_ADDRESS != null) { - return HOST_ADDRESS; - } - - InetAddress address = getLocalAddress(); - if (address != null) { - return HOST_ADDRESS = address.getHostAddress(); - } - return LOCALHOST_VALUE; - } - - public static String filterLocalHost(String host) { - if (host == null || host.length() == 0) { - return host; - } - if (host.contains("://")) { - URL u = URL.valueOf(host); - if (NetUtils.isInvalidLocalHost(u.getHost())) { - return u.setHost(NetUtils.getLocalHost()).toFullString(); - } - } else if (host.contains(":")) { - int i = host.lastIndexOf(':'); - if (NetUtils.isInvalidLocalHost(host.substring(0, i))) { - return NetUtils.getLocalHost() + host.substring(i); - } - } else { - if (NetUtils.isInvalidLocalHost(host)) { - return NetUtils.getLocalHost(); - } - } - return host; - } - - public static String getIpByConfig() { - String configIp = ConfigurationUtils.getProperty(DUBBO_IP_TO_BIND); - if (configIp != null) { - return configIp; - } - - InetAddress localAddress = getLocalAddress(); - String hostName = localAddress == null ? LOCALHOST_VALUE : localAddress.getHostName(); - return getIpByHost(hostName); - } - - /** - * Find first valid IP from local network card - * - * @return first valid local IP - */ - public static InetAddress getLocalAddress() { - if (LOCAL_ADDRESS != null) { - return LOCAL_ADDRESS; - } - InetAddress localAddress = getLocalAddress0(); - LOCAL_ADDRESS = localAddress; - return localAddress; - } - - private static Optional toValidAddress(InetAddress address) { - if (address instanceof Inet6Address) { - Inet6Address v6Address = (Inet6Address) address; - if (isPreferIPV6Address()) { - return Optional.ofNullable(normalizeV6Address(v6Address)); - } - } - if (isValidV4Address(address)) { - return Optional.of(address); - } - return Optional.empty(); - } - - private static InetAddress getLocalAddress0() { - InetAddress localAddress = null; - - // @since 2.7.6, choose the {@link NetworkInterface} first - try { - NetworkInterface networkInterface = findNetworkInterface(); - Enumeration addresses = networkInterface.getInetAddresses(); - while (addresses.hasMoreElements()) { - Optional addressOp = toValidAddress(addresses.nextElement()); - if (addressOp.isPresent()) { - try { - if (addressOp.get().isReachable(100)) { - return addressOp.get(); - } - } catch (IOException e) { - // ignore - } - } - } - } catch (Throwable e) { - logger.warn(e); - } - - try { - localAddress = InetAddress.getLocalHost(); - Optional addressOp = toValidAddress(localAddress); - if (addressOp.isPresent()) { - return addressOp.get(); - } - } catch (Throwable e) { - logger.warn(e); - } - - - return localAddress; - } - - /** - * @param networkInterface {@link NetworkInterface} - * @return if the specified {@link NetworkInterface} should be ignored, return true - * @throws SocketException SocketException if an I/O error occurs. - * @since 2.7.6 - */ - private static boolean ignoreNetworkInterface(NetworkInterface networkInterface) throws SocketException { - return networkInterface == null - || networkInterface.isLoopback() - || networkInterface.isVirtual() - || !networkInterface.isUp(); - } - - /** - * Get the valid {@link NetworkInterface network interfaces} - * - * @return non-null - * @throws SocketException SocketException if an I/O error occurs. - * @since 2.7.6 - */ - private static List getValidNetworkInterfaces() throws SocketException { - List validNetworkInterfaces = new LinkedList<>(); - Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); - while (interfaces.hasMoreElements()) { - NetworkInterface networkInterface = interfaces.nextElement(); - if (ignoreNetworkInterface(networkInterface)) { // ignore - continue; - } - validNetworkInterfaces.add(networkInterface); - } - return validNetworkInterfaces; - } - - /** - * Is preferred {@link NetworkInterface} or not - * - * @param networkInterface {@link NetworkInterface} - * @return if the name of the specified {@link NetworkInterface} matches - * the property value from {@link CommonConstants#DUBBO_PREFERRED_NETWORK_INTERFACE}, return true, - * or false - */ - public static boolean isPreferredNetworkInterface(NetworkInterface networkInterface) { - String preferredNetworkInterface = System.getProperty(DUBBO_PREFERRED_NETWORK_INTERFACE); - return Objects.equals(networkInterface.getDisplayName(), preferredNetworkInterface); - } - - /** - * Get the suitable {@link NetworkInterface} - * - * @return If no {@link NetworkInterface} is available , return null - * @since 2.7.6 - */ - public static NetworkInterface findNetworkInterface() { - - List validNetworkInterfaces = emptyList(); - try { - validNetworkInterfaces = getValidNetworkInterfaces(); - } catch (Throwable e) { - logger.warn(e); - } - - NetworkInterface result = null; - - // Try to find the preferred one - for (NetworkInterface networkInterface : validNetworkInterfaces) { - if (isPreferredNetworkInterface(networkInterface)) { - result = networkInterface; - break; - } - } - - if (result == null) { // If not found, try to get the first one - for (NetworkInterface networkInterface : validNetworkInterfaces) { - Enumeration addresses = networkInterface.getInetAddresses(); - while (addresses.hasMoreElements()) { - Optional addressOp = toValidAddress(addresses.nextElement()); - if (addressOp.isPresent()) { - try { - if (addressOp.get().isReachable(100)) { - result = networkInterface; - break; - } - } catch (IOException e) { - // ignore - } - } - } - } - } - - if (result == null) { - result = first(validNetworkInterfaces); - } - - return result; - } - - public static String getHostName(String address) { - try { - int i = address.indexOf(':'); - if (i > -1) { - address = address.substring(0, i); - } - String hostname = HOST_NAME_CACHE.get(address); - if (hostname != null && hostname.length() > 0) { - return hostname; - } - InetAddress inetAddress = InetAddress.getByName(address); - if (inetAddress != null) { - hostname = inetAddress.getHostName(); - HOST_NAME_CACHE.put(address, hostname); - return hostname; - } - } catch (Throwable e) { - // ignore - } - return address; - } - - /** - * @param hostName - * @return ip address or hostName if UnknownHostException - */ - public static String getIpByHost(String hostName) { - try { - return InetAddress.getByName(hostName).getHostAddress(); - } catch (UnknownHostException e) { - return hostName; - } - } - - public static String toAddressString(InetSocketAddress address) { - return address.getAddress().getHostAddress() + ":" + address.getPort(); - } - - public static InetSocketAddress toAddress(String address) { - int i = address.indexOf(':'); - String host; - int port; - if (i > -1) { - host = address.substring(0, i); - port = Integer.parseInt(address.substring(i + 1)); - } else { - host = address; - port = 0; - } - return new InetSocketAddress(host, port); - } - - public static String toURL(String protocol, String host, int port, String path) { - StringBuilder sb = new StringBuilder(); - sb.append(protocol).append("://"); - sb.append(host).append(':').append(port); - if (path.charAt(0) != '/') { - sb.append('/'); - } - sb.append(path); - return sb.toString(); - } - - public static void joinMulticastGroup(MulticastSocket multicastSocket, InetAddress multicastAddress) throws - IOException { - setInterface(multicastSocket, multicastAddress instanceof Inet6Address); - multicastSocket.setLoopbackMode(false); - multicastSocket.joinGroup(multicastAddress); - } - - public static void setInterface(MulticastSocket multicastSocket, boolean preferIpv6) throws IOException { - boolean interfaceSet = false; - for (NetworkInterface networkInterface : getValidNetworkInterfaces()) { - Enumeration addresses = networkInterface.getInetAddresses(); - while (addresses.hasMoreElements()) { - InetAddress address = (InetAddress) addresses.nextElement(); - if (preferIpv6 && address instanceof Inet6Address) { - try { - if (address.isReachable(100)) { - multicastSocket.setInterface(address); - interfaceSet = true; - break; - } - } catch (IOException e) { - // ignore - } - } else if (!preferIpv6 && address instanceof Inet4Address) { - try { - if (address.isReachable(100)) { - multicastSocket.setInterface(address); - interfaceSet = true; - break; - } - } catch (IOException e) { - // ignore - } - } - } - if (interfaceSet) { - break; - } - } - } - - public static boolean matchIpExpression(String pattern, String host, int port) throws UnknownHostException { - - // if the pattern is subnet format, it will not be allowed to config port param in pattern. - if (pattern.contains("/")) { - CIDRUtils utils = new CIDRUtils(pattern); - return utils.isInRange(host); - } - - - return matchIpRange(pattern, host, port); - } - - /** - * @param pattern - * @param host - * @param port - * @return - * @throws UnknownHostException - */ - public static boolean matchIpRange(String pattern, String host, int port) throws UnknownHostException { - if (pattern == null || host == null) { - throw new IllegalArgumentException("Illegal Argument pattern or hostName. Pattern:" + pattern + ", Host:" + host); - } - pattern = pattern.trim(); - if ("*.*.*.*".equals(pattern) || "*".equals(pattern)) { - return true; - } - - InetAddress inetAddress = InetAddress.getByName(host); - boolean isIpv4 = isValidV4Address(inetAddress); - String[] hostAndPort = getPatternHostAndPort(pattern, isIpv4); - if (hostAndPort[1] != null && !hostAndPort[1].equals(String.valueOf(port))) { - return false; - } - pattern = hostAndPort[0]; - - String splitCharacter = SPLIT_IPV4_CHARACTER; - if (!isIpv4) { - splitCharacter = SPLIT_IPV6_CHARACTER; - } - String[] mask = pattern.split(splitCharacter); - //check format of pattern - checkHostPattern(pattern, mask, isIpv4); - - host = inetAddress.getHostAddress(); - if (pattern.equals(host)) { - return true; - } - - // short name condition - if (!ipPatternContainExpression(pattern)) { - InetAddress patternAddress = InetAddress.getByName(pattern); - return patternAddress.getHostAddress().equals(host); - } - - String[] ipAddress = host.split(splitCharacter); - for (int i = 0; i < mask.length; i++) { - if ("*".equals(mask[i]) || mask[i].equals(ipAddress[i])) { - continue; - } else if (mask[i].contains("-")) { - String[] rangeNumStrs = StringUtils.split(mask[i], '-'); - if (rangeNumStrs.length != 2) { - throw new IllegalArgumentException("There is wrong format of ip Address: " + mask[i]); - } - Integer min = getNumOfIpSegment(rangeNumStrs[0], isIpv4); - Integer max = getNumOfIpSegment(rangeNumStrs[1], isIpv4); - Integer ip = getNumOfIpSegment(ipAddress[i], isIpv4); - if (ip < min || ip > max) { - return false; - } - } else if ("0".equals(ipAddress[i]) && ("0".equals(mask[i]) || "00".equals(mask[i]) || "000".equals(mask[i]) || "0000".equals(mask[i]))) { - continue; - } else if (!mask[i].equals(ipAddress[i])) { - return false; - } - } - return true; - } - - /** - * is multicast address or not - * - * @param host ipv4 address - * @return {@code true} if is multicast address - */ - public static boolean isMulticastAddress(String host) { - int i = host.indexOf('.'); - if (i > 0) { - String prefix = host.substring(0, i); - if (StringUtils.isInteger(prefix)) { - int p = Integer.parseInt(prefix); - return p >= 224 && p <= 239; - } - } - return false; - } - - private static boolean ipPatternContainExpression(String pattern) { - return pattern.contains("*") || pattern.contains("-"); - } - - private static void checkHostPattern(String pattern, String[] mask, boolean isIpv4) { - if (!isIpv4) { - if (mask.length != 8 && ipPatternContainExpression(pattern)) { - throw new IllegalArgumentException("If you config ip expression that contains '*' or '-', please fill qualified ip pattern like 234e:0:4567:0:0:0:3d:*. "); - } - if (mask.length != 8 && !pattern.contains("::")) { - throw new IllegalArgumentException("The host is ipv6, but the pattern is not ipv6 pattern : " + pattern); - } - } else { - if (mask.length != 4) { - throw new IllegalArgumentException("The host is ipv4, but the pattern is not ipv4 pattern : " + pattern); - } - } - } - - private static String[] getPatternHostAndPort(String pattern, boolean isIpv4) { - String[] result = new String[2]; - if (pattern.startsWith("[") && pattern.contains("]:")) { - int end = pattern.indexOf("]:"); - result[0] = pattern.substring(1, end); - result[1] = pattern.substring(end + 2); - return result; - } else if (pattern.startsWith("[") && pattern.endsWith("]")) { - result[0] = pattern.substring(1, pattern.length() - 1); - result[1] = null; - return result; - } else if (isIpv4 && pattern.contains(":")) { - int end = pattern.indexOf(":"); - result[0] = pattern.substring(0, end); - result[1] = pattern.substring(end + 1); - return result; - } else { - result[0] = pattern; - return result; - } - } - - private static Integer getNumOfIpSegment(String ipSegment, boolean isIpv4) { - if (isIpv4) { - return Integer.parseInt(ipSegment); - } - return Integer.parseInt(ipSegment, 16); - } - -} +/* + * 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.common.utils; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.config.ConfigurationUtils; +import org.apache.dubbo.common.constants.CommonConstants; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.logger.support.FailsafeLogger; + +import java.io.IOException; +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.MulticastSocket; +import java.net.NetworkInterface; +import java.net.ServerSocket; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.util.Enumeration; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.concurrent.ThreadLocalRandom; +import java.util.regex.Pattern; + +import static java.util.Collections.emptyList; +import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_VALUE; +import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_IP_TO_BIND; +import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_PREFERRED_NETWORK_INTERFACE; +import static org.apache.dubbo.common.constants.CommonConstants.LOCALHOST_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.LOCALHOST_VALUE; +import static org.apache.dubbo.common.utils.CollectionUtils.first; + +/** + * IP and Port Helper for RPC + */ +public class NetUtils { + + private static Logger logger; + + static { + logger = LoggerFactory.getLogger(NetUtils.class); + if (logger instanceof FailsafeLogger) { + logger = ((FailsafeLogger) logger).getLogger(); + } + } + + // returned port range is [30000, 39999] + private static final int RND_PORT_START = 30000; + private static final int RND_PORT_RANGE = 10000; + + // valid port range is (0, 65535] + private static final int MIN_PORT = 0; + private static final int MAX_PORT = 65535; + + private static final Pattern ADDRESS_PATTERN = Pattern.compile("^\\d{1,3}(\\.\\d{1,3}){3}\\:\\d{1,5}$"); + private static final Pattern LOCAL_IP_PATTERN = Pattern.compile("127(\\.\\d{1,3}){3}$"); + private static final Pattern IP_PATTERN = Pattern.compile("\\d{1,3}(\\.\\d{1,3}){3,5}$"); + + private static final Map HOST_NAME_CACHE = new LRUCache<>(1000); + private static volatile InetAddress LOCAL_ADDRESS = null; + + private static final String SPLIT_IPV4_CHARACTER = "\\."; + private static final String SPLIT_IPV6_CHARACTER = ":"; + + public static int getRandomPort() { + return RND_PORT_START + ThreadLocalRandom.current().nextInt(RND_PORT_RANGE); + } + + public static int getAvailablePort() { + try (ServerSocket ss = new ServerSocket()) { + ss.bind(null); + return ss.getLocalPort(); + } catch (IOException e) { + return getRandomPort(); + } + } + + public static int getAvailablePort(int port) { + if (port <= 0) { + return getAvailablePort(); + } + for (int i = port; i < MAX_PORT; i++) { + try (ServerSocket ignored = new ServerSocket(i)) { + return i; + } catch (IOException e) { + // continue + } + } + return port; + } + + public static boolean isInvalidPort(int port) { + return port <= MIN_PORT || port > MAX_PORT; + } + + public static boolean isValidAddress(String address) { + return ADDRESS_PATTERN.matcher(address).matches(); + } + + public static boolean isLocalHost(String host) { + return host != null + && (LOCAL_IP_PATTERN.matcher(host).matches() + || host.equalsIgnoreCase(LOCALHOST_KEY)); + } + + public static boolean isAnyHost(String host) { + return ANYHOST_VALUE.equals(host); + } + + public static boolean isInvalidLocalHost(String host) { + return host == null + || host.length() == 0 + || host.equalsIgnoreCase(LOCALHOST_KEY) + || host.equals(ANYHOST_VALUE) + || host.startsWith("127."); + } + + public static boolean isValidLocalHost(String host) { + return !isInvalidLocalHost(host); + } + + public static InetSocketAddress getLocalSocketAddress(String host, int port) { + return isInvalidLocalHost(host) ? + new InetSocketAddress(port) : new InetSocketAddress(host, port); + } + + static boolean isValidV4Address(InetAddress address) { + if (address == null || address.isLoopbackAddress()) { + return false; + } + + String name = address.getHostAddress(); + return (name != null + && IP_PATTERN.matcher(name).matches() + && !ANYHOST_VALUE.equals(name) + && !LOCALHOST_VALUE.equals(name)); + } + + /** + * Check if an ipv6 address + * + * @return true if it is reachable + */ + static boolean isPreferIPV6Address() { + return Boolean.getBoolean("java.net.preferIPv6Addresses"); + } + + /** + * normalize the ipv6 Address, convert scope name to scope id. + * e.g. + * convert + * fe80:0:0:0:894:aeec:f37d:23e1%en0 + * to + * fe80:0:0:0:894:aeec:f37d:23e1%5 + *

+ * The %5 after ipv6 address is called scope id. + * see java doc of {@link Inet6Address} for more details. + * + * @param address the input address + * @return the normalized address, with scope id converted to int + */ + static InetAddress normalizeV6Address(Inet6Address address) { + String addr = address.getHostAddress(); + int i = addr.lastIndexOf('%'); + if (i > 0) { + try { + return InetAddress.getByName(addr.substring(0, i) + '%' + address.getScopeId()); + } catch (UnknownHostException e) { + // ignore + logger.debug("Unknown IPV6 address: ", e); + } + } + return address; + } + + private static volatile String HOST_ADDRESS; + + public static String getLocalHost() { + if (HOST_ADDRESS != null) { + return HOST_ADDRESS; + } + + InetAddress address = getLocalAddress(); + if (address != null) { + return HOST_ADDRESS = address.getHostAddress(); + } + return LOCALHOST_VALUE; + } + + public static String filterLocalHost(String host) { + if (host == null || host.length() == 0) { + return host; + } + if (host.contains("://")) { + URL u = URL.valueOf(host); + if (NetUtils.isInvalidLocalHost(u.getHost())) { + return u.setHost(NetUtils.getLocalHost()).toFullString(); + } + } else if (host.contains(":")) { + int i = host.lastIndexOf(':'); + if (NetUtils.isInvalidLocalHost(host.substring(0, i))) { + return NetUtils.getLocalHost() + host.substring(i); + } + } else { + if (NetUtils.isInvalidLocalHost(host)) { + return NetUtils.getLocalHost(); + } + } + return host; + } + + public static String getIpByConfig() { + String configIp = ConfigurationUtils.getProperty(DUBBO_IP_TO_BIND); + if (configIp != null) { + return configIp; + } + + InetAddress localAddress = getLocalAddress(); + String hostName = localAddress == null ? LOCALHOST_VALUE : localAddress.getHostName(); + return getIpByHost(hostName); + } + + /** + * Find first valid IP from local network card + * + * @return first valid local IP + */ + public static InetAddress getLocalAddress() { + if (LOCAL_ADDRESS != null) { + return LOCAL_ADDRESS; + } + InetAddress localAddress = getLocalAddress0(); + LOCAL_ADDRESS = localAddress; + return localAddress; + } + + private static Optional toValidAddress(InetAddress address) { + if (address instanceof Inet6Address) { + Inet6Address v6Address = (Inet6Address) address; + if (isPreferIPV6Address()) { + return Optional.ofNullable(normalizeV6Address(v6Address)); + } + } + if (isValidV4Address(address)) { + return Optional.of(address); + } + return Optional.empty(); + } + + private static InetAddress getLocalAddress0() { + InetAddress localAddress = null; + + // @since 2.7.6, choose the {@link NetworkInterface} first + try { + NetworkInterface networkInterface = findNetworkInterface(); + Enumeration addresses = networkInterface.getInetAddresses(); + while (addresses.hasMoreElements()) { + Optional addressOp = toValidAddress(addresses.nextElement()); + if (addressOp.isPresent()) { + try { + if (addressOp.get().isReachable(100)) { + return addressOp.get(); + } + } catch (IOException e) { + // ignore + } + } + } + } catch (Throwable e) { + logger.warn(e); + } + + try { + localAddress = InetAddress.getLocalHost(); + Optional addressOp = toValidAddress(localAddress); + if (addressOp.isPresent()) { + return addressOp.get(); + } + } catch (Throwable e) { + logger.warn(e); + } + + + return localAddress; + } + + /** + * @param networkInterface {@link NetworkInterface} + * @return if the specified {@link NetworkInterface} should be ignored, return true + * @throws SocketException SocketException if an I/O error occurs. + * @since 2.7.6 + */ + private static boolean ignoreNetworkInterface(NetworkInterface networkInterface) throws SocketException { + return networkInterface == null + || networkInterface.isLoopback() + || networkInterface.isVirtual() + || !networkInterface.isUp(); + } + + /** + * Get the valid {@link NetworkInterface network interfaces} + * + * @return non-null + * @throws SocketException SocketException if an I/O error occurs. + * @since 2.7.6 + */ + private static List getValidNetworkInterfaces() throws SocketException { + List validNetworkInterfaces = new LinkedList<>(); + Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); + while (interfaces.hasMoreElements()) { + NetworkInterface networkInterface = interfaces.nextElement(); + if (ignoreNetworkInterface(networkInterface)) { // ignore + continue; + } + validNetworkInterfaces.add(networkInterface); + } + return validNetworkInterfaces; + } + + /** + * Is preferred {@link NetworkInterface} or not + * + * @param networkInterface {@link NetworkInterface} + * @return if the name of the specified {@link NetworkInterface} matches + * the property value from {@link CommonConstants#DUBBO_PREFERRED_NETWORK_INTERFACE}, return true, + * or false + */ + public static boolean isPreferredNetworkInterface(NetworkInterface networkInterface) { + String preferredNetworkInterface = System.getProperty(DUBBO_PREFERRED_NETWORK_INTERFACE); + return Objects.equals(networkInterface.getDisplayName(), preferredNetworkInterface); + } + + /** + * Get the suitable {@link NetworkInterface} + * + * @return If no {@link NetworkInterface} is available , return null + * @since 2.7.6 + */ + public static NetworkInterface findNetworkInterface() { + + List validNetworkInterfaces = emptyList(); + try { + validNetworkInterfaces = getValidNetworkInterfaces(); + } catch (Throwable e) { + logger.warn(e); + } + + NetworkInterface result = null; + + // Try to find the preferred one + for (NetworkInterface networkInterface : validNetworkInterfaces) { + if (isPreferredNetworkInterface(networkInterface)) { + result = networkInterface; + break; + } + } + + if (result == null) { // If not found, try to get the first one + for (NetworkInterface networkInterface : validNetworkInterfaces) { + Enumeration addresses = networkInterface.getInetAddresses(); + while (addresses.hasMoreElements()) { + Optional addressOp = toValidAddress(addresses.nextElement()); + if (addressOp.isPresent()) { + try { + if (addressOp.get().isReachable(100)) { + result = networkInterface; + break; + } + } catch (IOException e) { + // ignore + } + } + } + } + } + + if (result == null) { + result = first(validNetworkInterfaces); + } + + return result; + } + + public static String getHostName(String address) { + try { + int i = address.indexOf(':'); + if (i > -1) { + address = address.substring(0, i); + } + String hostname = HOST_NAME_CACHE.get(address); + if (hostname != null && hostname.length() > 0) { + return hostname; + } + InetAddress inetAddress = InetAddress.getByName(address); + if (inetAddress != null) { + hostname = inetAddress.getHostName(); + HOST_NAME_CACHE.put(address, hostname); + return hostname; + } + } catch (Throwable e) { + // ignore + } + return address; + } + + /** + * @param hostName + * @return ip address or hostName if UnknownHostException + */ + public static String getIpByHost(String hostName) { + try { + return InetAddress.getByName(hostName).getHostAddress(); + } catch (UnknownHostException e) { + return hostName; + } + } + + public static String toAddressString(InetSocketAddress address) { + return address.getAddress().getHostAddress() + ":" + address.getPort(); + } + + public static InetSocketAddress toAddress(String address) { + int i = address.indexOf(':'); + String host; + int port; + if (i > -1) { + host = address.substring(0, i); + port = Integer.parseInt(address.substring(i + 1)); + } else { + host = address; + port = 0; + } + return new InetSocketAddress(host, port); + } + + public static String toURL(String protocol, String host, int port, String path) { + StringBuilder sb = new StringBuilder(); + sb.append(protocol).append("://"); + sb.append(host).append(':').append(port); + if (path.charAt(0) != '/') { + sb.append('/'); + } + sb.append(path); + return sb.toString(); + } + + public static void joinMulticastGroup(MulticastSocket multicastSocket, InetAddress multicastAddress) throws + IOException { + setInterface(multicastSocket, multicastAddress instanceof Inet6Address); + multicastSocket.setLoopbackMode(false); + multicastSocket.joinGroup(multicastAddress); + } + + public static void setInterface(MulticastSocket multicastSocket, boolean preferIpv6) throws IOException { + boolean interfaceSet = false; + for (NetworkInterface networkInterface : getValidNetworkInterfaces()) { + Enumeration addresses = networkInterface.getInetAddresses(); + while (addresses.hasMoreElements()) { + InetAddress address = (InetAddress) addresses.nextElement(); + if (preferIpv6 && address instanceof Inet6Address) { + try { + if (address.isReachable(100)) { + multicastSocket.setInterface(address); + interfaceSet = true; + break; + } + } catch (IOException e) { + // ignore + } + } else if (!preferIpv6 && address instanceof Inet4Address) { + try { + if (address.isReachable(100)) { + multicastSocket.setInterface(address); + interfaceSet = true; + break; + } + } catch (IOException e) { + // ignore + } + } + } + if (interfaceSet) { + break; + } + } + } + + public static boolean matchIpExpression(String pattern, String host, int port) throws UnknownHostException { + + // if the pattern is subnet format, it will not be allowed to config port param in pattern. + if (pattern.contains("/")) { + CIDRUtils utils = new CIDRUtils(pattern); + return utils.isInRange(host); + } + + + return matchIpRange(pattern, host, port); + } + + /** + * @param pattern + * @param host + * @param port + * @return + * @throws UnknownHostException + */ + public static boolean matchIpRange(String pattern, String host, int port) throws UnknownHostException { + if (pattern == null || host == null) { + throw new IllegalArgumentException("Illegal Argument pattern or hostName. Pattern:" + pattern + ", Host:" + host); + } + pattern = pattern.trim(); + if ("*.*.*.*".equals(pattern) || "*".equals(pattern)) { + return true; + } + + InetAddress inetAddress = InetAddress.getByName(host); + boolean isIpv4 = isValidV4Address(inetAddress); + String[] hostAndPort = getPatternHostAndPort(pattern, isIpv4); + if (hostAndPort[1] != null && !hostAndPort[1].equals(String.valueOf(port))) { + return false; + } + pattern = hostAndPort[0]; + + String splitCharacter = SPLIT_IPV4_CHARACTER; + if (!isIpv4) { + splitCharacter = SPLIT_IPV6_CHARACTER; + } + String[] mask = pattern.split(splitCharacter); + //check format of pattern + checkHostPattern(pattern, mask, isIpv4); + + host = inetAddress.getHostAddress(); + if (pattern.equals(host)) { + return true; + } + + // short name condition + if (!ipPatternContainExpression(pattern)) { + InetAddress patternAddress = InetAddress.getByName(pattern); + return patternAddress.getHostAddress().equals(host); + } + + String[] ipAddress = host.split(splitCharacter); + for (int i = 0; i < mask.length; i++) { + if ("*".equals(mask[i]) || mask[i].equals(ipAddress[i])) { + continue; + } else if (mask[i].contains("-")) { + String[] rangeNumStrs = StringUtils.split(mask[i], '-'); + if (rangeNumStrs.length != 2) { + throw new IllegalArgumentException("There is wrong format of ip Address: " + mask[i]); + } + Integer min = getNumOfIpSegment(rangeNumStrs[0], isIpv4); + Integer max = getNumOfIpSegment(rangeNumStrs[1], isIpv4); + Integer ip = getNumOfIpSegment(ipAddress[i], isIpv4); + if (ip < min || ip > max) { + return false; + } + } else if ("0".equals(ipAddress[i]) && ("0".equals(mask[i]) || "00".equals(mask[i]) || "000".equals(mask[i]) || "0000".equals(mask[i]))) { + continue; + } else if (!mask[i].equals(ipAddress[i])) { + return false; + } + } + return true; + } + + /** + * is multicast address or not + * + * @param host ipv4 address + * @return {@code true} if is multicast address + */ + public static boolean isMulticastAddress(String host) { + int i = host.indexOf('.'); + if (i > 0) { + String prefix = host.substring(0, i); + if (StringUtils.isInteger(prefix)) { + int p = Integer.parseInt(prefix); + return p >= 224 && p <= 239; + } + } + return false; + } + + private static boolean ipPatternContainExpression(String pattern) { + return pattern.contains("*") || pattern.contains("-"); + } + + private static void checkHostPattern(String pattern, String[] mask, boolean isIpv4) { + if (!isIpv4) { + if (mask.length != 8 && ipPatternContainExpression(pattern)) { + throw new IllegalArgumentException("If you config ip expression that contains '*' or '-', please fill qualified ip pattern like 234e:0:4567:0:0:0:3d:*. "); + } + if (mask.length != 8 && !pattern.contains("::")) { + throw new IllegalArgumentException("The host is ipv6, but the pattern is not ipv6 pattern : " + pattern); + } + } else { + if (mask.length != 4) { + throw new IllegalArgumentException("The host is ipv4, but the pattern is not ipv4 pattern : " + pattern); + } + } + } + + private static String[] getPatternHostAndPort(String pattern, boolean isIpv4) { + String[] result = new String[2]; + if (pattern.startsWith("[") && pattern.contains("]:")) { + int end = pattern.indexOf("]:"); + result[0] = pattern.substring(1, end); + result[1] = pattern.substring(end + 2); + return result; + } else if (pattern.startsWith("[") && pattern.endsWith("]")) { + result[0] = pattern.substring(1, pattern.length() - 1); + result[1] = null; + return result; + } else if (isIpv4 && pattern.contains(":")) { + int end = pattern.indexOf(":"); + result[0] = pattern.substring(0, end); + result[1] = pattern.substring(end + 1); + return result; + } else { + result[0] = pattern; + return result; + } + } + + private static Integer getNumOfIpSegment(String ipSegment, boolean isIpv4) { + if (isIpv4) { + return Integer.parseInt(ipSegment); + } + return Integer.parseInt(ipSegment, 16); + } + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PojoUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PojoUtils.java index b940d047d8..53238dd335 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PojoUtils.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PojoUtils.java @@ -1,685 +1,685 @@ -/* - * 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.common.utils; - -import org.apache.dubbo.common.constants.CommonConstants; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; - -import java.lang.reflect.Array; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Proxy; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Hashtable; -import java.util.IdentityHashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.TreeMap; -import java.util.WeakHashMap; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.ConcurrentSkipListMap; -import java.util.function.Consumer; -import java.util.function.Supplier; - -/** - * PojoUtils. Travel object deeply, and convert complex type to simple type. - *

- * Simple type below will be remained: - *

    - *
  • Primitive Type, also include String, Number(Integer, Long), Date - *
  • Array of Primitive Type - *
  • Collection, eg: List, Map, Set etc. - *
- *

- * Other type will be covert to a map which contains the attributes and value pair of object. - */ -public class PojoUtils { - - private static final Logger logger = LoggerFactory.getLogger(PojoUtils.class); - private static final ConcurrentMap NAME_METHODS_CACHE = new ConcurrentHashMap(); - private static final ConcurrentMap, ConcurrentMap> CLASS_FIELD_CACHE = new ConcurrentHashMap, ConcurrentMap>(); - private static final boolean GENERIC_WITH_CLZ = Boolean.parseBoolean(ConfigUtils.getProperty(CommonConstants.GENERIC_WITH_CLZ_KEY, "true")); - - public static Object[] generalize(Object[] objs) { - Object[] dests = new Object[objs.length]; - for (int i = 0; i < objs.length; i++) { - dests[i] = generalize(objs[i]); - } - return dests; - } - - public static Object[] realize(Object[] objs, Class[] types) { - if (objs.length != types.length) { - throw new IllegalArgumentException("args.length != types.length"); - } - - Object[] dests = new Object[objs.length]; - for (int i = 0; i < objs.length; i++) { - dests[i] = realize(objs[i], types[i]); - } - - return dests; - } - - public static Object[] realize(Object[] objs, Class[] types, Type[] gtypes) { - if (objs.length != types.length || objs.length != gtypes.length) { - throw new IllegalArgumentException("args.length != types.length"); - } - Object[] dests = new Object[objs.length]; - for (int i = 0; i < objs.length; i++) { - dests[i] = realize(objs[i], types[i], gtypes[i]); - } - return dests; - } - - public static Object generalize(Object pojo) { - return generalize(pojo, new IdentityHashMap()); - } - - @SuppressWarnings("unchecked") - private static Object generalize(Object pojo, Map history) { - if (pojo == null) { - return null; - } - - if (pojo instanceof Enum) { - return ((Enum) pojo).name(); - } - if (pojo.getClass().isArray() && Enum.class.isAssignableFrom(pojo.getClass().getComponentType())) { - int len = Array.getLength(pojo); - String[] values = new String[len]; - for (int i = 0; i < len; i++) { - values[i] = ((Enum) Array.get(pojo, i)).name(); - } - return values; - } - - if (ReflectUtils.isPrimitives(pojo.getClass())) { - return pojo; - } - - if (pojo instanceof Class) { - return ((Class) pojo).getName(); - } - - Object o = history.get(pojo); - if (o != null) { - return o; - } - history.put(pojo, pojo); - - if (pojo.getClass().isArray()) { - int len = Array.getLength(pojo); - Object[] dest = new Object[len]; - history.put(pojo, dest); - for (int i = 0; i < len; i++) { - Object obj = Array.get(pojo, i); - dest[i] = generalize(obj, history); - } - return dest; - } - if (pojo instanceof Collection) { - Collection src = (Collection) pojo; - int len = src.size(); - Collection dest = (pojo instanceof List) ? new ArrayList(len) : new HashSet(len); - history.put(pojo, dest); - for (Object obj : src) { - dest.add(generalize(obj, history)); - } - return dest; - } - if (pojo instanceof Map) { - Map src = (Map) pojo; - Map dest = createMap(src); - history.put(pojo, dest); - for (Map.Entry obj : src.entrySet()) { - dest.put(generalize(obj.getKey(), history), generalize(obj.getValue(), history)); - } - return dest; - } - Map map = new HashMap(); - history.put(pojo, map); - if (GENERIC_WITH_CLZ) { - map.put("class", pojo.getClass().getName()); - } - for (Method method : pojo.getClass().getMethods()) { - if (ReflectUtils.isBeanPropertyReadMethod(method)) { - ReflectUtils.makeAccessible(method); - try { - map.put(ReflectUtils.getPropertyNameFromBeanReadMethod(method), generalize(method.invoke(pojo), history)); - } catch (Exception e) { - throw new RuntimeException(e.getMessage(), e); - } - } - } - // public field - for (Field field : pojo.getClass().getFields()) { - if (ReflectUtils.isPublicInstanceField(field)) { - try { - Object fieldValue = field.get(pojo); - if (history.containsKey(pojo)) { - Object pojoGeneralizedValue = history.get(pojo); - if (pojoGeneralizedValue instanceof Map - && ((Map) pojoGeneralizedValue).containsKey(field.getName())) { - continue; - } - } - if (fieldValue != null) { - map.put(field.getName(), generalize(fieldValue, history)); - } - } catch (Exception e) { - throw new RuntimeException(e.getMessage(), e); - } - } - } - return map; - } - - public static Object realize(Object pojo, Class type) { - return realize0(pojo, type, null, new IdentityHashMap()); - } - - public static Object realize(Object pojo, Class type, Type genericType) { - return realize0(pojo, type, genericType, new IdentityHashMap()); - } - - private static class PojoInvocationHandler implements InvocationHandler { - - private Map map; - - public PojoInvocationHandler(Map map) { - this.map = map; - } - - @Override - @SuppressWarnings("unchecked") - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - if (method.getDeclaringClass() == Object.class) { - return method.invoke(map, args); - } - String methodName = method.getName(); - Object value = null; - if (methodName.length() > 3 && methodName.startsWith("get")) { - value = map.get(methodName.substring(3, 4).toLowerCase() + methodName.substring(4)); - } else if (methodName.length() > 2 && methodName.startsWith("is")) { - value = map.get(methodName.substring(2, 3).toLowerCase() + methodName.substring(3)); - } else { - value = map.get(methodName.substring(0, 1).toLowerCase() + methodName.substring(1)); - } - if (value instanceof Map && !Map.class.isAssignableFrom(method.getReturnType())) { - value = realize0((Map) value, method.getReturnType(), null, new IdentityHashMap()); - } - return value; - } - } - - @SuppressWarnings("unchecked") - private static Collection createCollection(Class type, int len) { - if (type.isAssignableFrom(ArrayList.class)) { - return new ArrayList(len); - } - if (type.isAssignableFrom(HashSet.class)) { - return new HashSet(len); - } - if (!type.isInterface() && !Modifier.isAbstract(type.getModifiers())) { - try { - return (Collection) type.newInstance(); - } catch (Exception e) { - // ignore - } - } - return new ArrayList(); - } - - private static Map createMap(Map src) { - Class cl = src.getClass(); - Map result = null; - if (HashMap.class == cl) { - result = new HashMap(); - } else if (Hashtable.class == cl) { - result = new Hashtable(); - } else if (IdentityHashMap.class == cl) { - result = new IdentityHashMap(); - } else if (LinkedHashMap.class == cl) { - result = new LinkedHashMap(); - } else if (Properties.class == cl) { - result = new Properties(); - } else if (TreeMap.class == cl) { - result = new TreeMap(); - } else if (WeakHashMap.class == cl) { - return new WeakHashMap(); - } else if (ConcurrentHashMap.class == cl) { - result = new ConcurrentHashMap(); - } else if (ConcurrentSkipListMap.class == cl) { - result = new ConcurrentSkipListMap(); - } else { - try { - result = cl.newInstance(); - } catch (Exception e) { /* ignore */ } - - if (result == null) { - try { - Constructor constructor = cl.getConstructor(Map.class); - result = (Map) constructor.newInstance(Collections.EMPTY_MAP); - } catch (Exception e) { /* ignore */ } - } - } - - if (result == null) { - result = new HashMap(); - } - - return result; - } - - @SuppressWarnings({"unchecked", "rawtypes"}) - private static Object realize0(Object pojo, Class type, Type genericType, final Map history) { - if (pojo == null) { - return null; - } - - if (type != null && type.isEnum() && pojo.getClass() == String.class) { - return Enum.valueOf((Class) type, (String) pojo); - } - - if (ReflectUtils.isPrimitives(pojo.getClass()) - && !(type != null && type.isArray() - && type.getComponentType().isEnum() - && pojo.getClass() == String[].class)) { - return CompatibleTypeUtils.compatibleTypeConvert(pojo, type); - } - - Object o = history.get(pojo); - - if (o != null) { - return o; - } - - history.put(pojo, pojo); - - if (pojo.getClass().isArray()) { - if (Collection.class.isAssignableFrom(type)) { - Class ctype = pojo.getClass().getComponentType(); - int len = Array.getLength(pojo); - Collection dest = createCollection(type, len); - history.put(pojo, dest); - for (int i = 0; i < len; i++) { - Object obj = Array.get(pojo, i); - Object value = realize0(obj, ctype, null, history); - dest.add(value); - } - return dest; - } else { - Class ctype = (type != null && type.isArray() ? type.getComponentType() : pojo.getClass().getComponentType()); - int len = Array.getLength(pojo); - Object dest = Array.newInstance(ctype, len); - history.put(pojo, dest); - for (int i = 0; i < len; i++) { - Object obj = Array.get(pojo, i); - Object value = realize0(obj, ctype, null, history); - Array.set(dest, i, value); - } - return dest; - } - } - - if (pojo instanceof Collection) { - if (type.isArray()) { - Class ctype = type.getComponentType(); - Collection src = (Collection) pojo; - int len = src.size(); - Object dest = Array.newInstance(ctype, len); - history.put(pojo, dest); - int i = 0; - for (Object obj : src) { - Object value = realize0(obj, ctype, null, history); - Array.set(dest, i, value); - i++; - } - return dest; - } else { - Collection src = (Collection) pojo; - int len = src.size(); - Collection dest = createCollection(type, len); - history.put(pojo, dest); - for (Object obj : src) { - Type keyType = getGenericClassByIndex(genericType, 0); - Class keyClazz = obj == null ? null : obj.getClass(); - if (keyType instanceof Class) { - keyClazz = (Class) keyType; - } - Object value = realize0(obj, keyClazz, keyType, history); - dest.add(value); - } - return dest; - } - } - - if (pojo instanceof Map && type != null) { - Object className = ((Map) pojo).get("class"); - if (className instanceof String) { - SerializeClassChecker.getInstance().validateClass((String) className); - try { - type = ClassUtils.forName((String) className); - } catch (ClassNotFoundException e) { - // ignore - } - } - - // special logic for enum - if (type.isEnum()) { - Object name = ((Map) pojo).get("name"); - if (name != null) { - return Enum.valueOf((Class) type, name.toString()); - } - } - Map map; - // when return type is not the subclass of return type from the signature and not an interface - if (!type.isInterface() && !type.isAssignableFrom(pojo.getClass())) { - try { - map = (Map) type.newInstance(); - Map mapPojo = (Map) pojo; - map.putAll(mapPojo); - if (GENERIC_WITH_CLZ) { - map.remove("class"); - } - } catch (Exception e) { - //ignore error - map = (Map) pojo; - } - } else { - map = (Map) pojo; - } - - if (Map.class.isAssignableFrom(type) || type == Object.class) { - final Map result; - // fix issue#5939 - Type mapKeyType = getKeyTypeForMap(map.getClass()); - Type typeKeyType = getGenericClassByIndex(genericType, 0); - boolean typeMismatch = mapKeyType instanceof Class - && typeKeyType instanceof Class - && !typeKeyType.getTypeName().equals(mapKeyType.getTypeName()); - if (typeMismatch) { - result = createMap(new HashMap(0)); - } else { - result = createMap(map); - } - - history.put(pojo, result); - for (Map.Entry entry : map.entrySet()) { - Type keyType = getGenericClassByIndex(genericType, 0); - Type valueType = getGenericClassByIndex(genericType, 1); - Class keyClazz; - if (keyType instanceof Class) { - keyClazz = (Class) keyType; - } else if (keyType instanceof ParameterizedType) { - keyClazz = (Class) ((ParameterizedType) keyType).getRawType(); - } else { - keyClazz = entry.getKey() == null ? null : entry.getKey().getClass(); - } - Class valueClazz; - if (valueType instanceof Class) { - valueClazz = (Class) valueType; - } else if (valueType instanceof ParameterizedType) { - valueClazz = (Class) ((ParameterizedType) valueType).getRawType(); - } else { - valueClazz = entry.getValue() == null ? null : entry.getValue().getClass(); - } - - Object key = keyClazz == null ? entry.getKey() : realize0(entry.getKey(), keyClazz, keyType, history); - Object value = valueClazz == null ? entry.getValue() : realize0(entry.getValue(), valueClazz, valueType, history); - result.put(key, value); - } - return result; - } else if (type.isInterface()) { - Object dest = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[]{type}, new PojoInvocationHandler(map)); - history.put(pojo, dest); - return dest; - } else { - Object dest = newInstance(type); - history.put(pojo, dest); - for (Map.Entry entry : map.entrySet()) { - Object key = entry.getKey(); - if (key instanceof String) { - String name = (String) key; - Object value = entry.getValue(); - if (value != null) { - Method method = getSetterMethod(dest.getClass(), name, value.getClass()); - Field field = getField(dest.getClass(), name); - if (method != null) { - if (!method.isAccessible()) { - method.setAccessible(true); - } - Type ptype = method.getGenericParameterTypes()[0]; - value = realize0(value, method.getParameterTypes()[0], ptype, history); - try { - method.invoke(dest, value); - } catch (Exception e) { - String exceptionDescription = "Failed to set pojo " + dest.getClass().getSimpleName() + " property " + name - + " value " + value + "(" + value.getClass() + "), cause: " + e.getMessage(); - logger.error(exceptionDescription, e); - throw new RuntimeException(exceptionDescription, e); - } - } else if (field != null) { - value = realize0(value, field.getType(), field.getGenericType(), history); - try { - field.set(dest, value); - } catch (IllegalAccessException e) { - throw new RuntimeException("Failed to set field " + name + " of pojo " + dest.getClass().getName() + " : " + e.getMessage(), e); - } - } - } - } - } - if (dest instanceof Throwable) { - Object message = map.get("message"); - if (message instanceof String) { - try { - Field field = Throwable.class.getDeclaredField("detailMessage"); - if (!field.isAccessible()) { - field.setAccessible(true); - } - field.set(dest, message); - } catch (Exception e) { - } - } - } - return dest; - } - } - return pojo; - } - - /** - * Get key type for {@link Map} directly implemented by {@code clazz}. - * If {@code clazz} does not implement {@link Map} directly, return {@code null}. - * - * @param clazz {@link Class} - * @return Return String.class for {@link com.alibaba.fastjson.JSONObject} - */ - private static Type getKeyTypeForMap(Class clazz) { - Type[] interfaces = clazz.getGenericInterfaces(); - if (!ArrayUtils.isEmpty(interfaces)) { - for (Type type : interfaces) { - if (type instanceof ParameterizedType) { - ParameterizedType t = (ParameterizedType) type; - if ("java.util.Map".equals(t.getRawType().getTypeName())) { - return t.getActualTypeArguments()[0]; - } - } - } - } - return null; - } - - /** - * Get parameterized type - * - * @param genericType generic type - * @param index index of the target parameterized type - * @return Return Person.class for List, return Person.class for Map when index=0 - */ - private static Type getGenericClassByIndex(Type genericType, int index) { - Type clazz = null; - // find parameterized type - if (genericType instanceof ParameterizedType) { - ParameterizedType t = (ParameterizedType) genericType; - Type[] types = t.getActualTypeArguments(); - clazz = types[index]; - } - return clazz; - } - - private static Object newInstance(Class cls) { - try { - return cls.newInstance(); - } catch (Throwable t) { - try { - Constructor[] constructors = cls.getDeclaredConstructors(); - /** - * From Javadoc java.lang.Class#getDeclaredConstructors - * This method returns an array of Constructor objects reflecting all the constructors - * declared by the class represented by this Class object. - * This method returns an array of length 0, - * if this Class object represents an interface, a primitive type, an array class, or void. - */ - if (constructors.length == 0) { - throw new RuntimeException("Illegal constructor: " + cls.getName()); - } - Constructor constructor = constructors[0]; - if (constructor.getParameterTypes().length > 0) { - for (Constructor c : constructors) { - if (c.getParameterTypes().length < constructor.getParameterTypes().length) { - constructor = c; - if (constructor.getParameterTypes().length == 0) { - break; - } - } - } - } - constructor.setAccessible(true); - Object[] parameters = Arrays.stream(constructor.getParameterTypes()).map(PojoUtils::getDefaultValue).toArray(); - return constructor.newInstance(parameters); - } catch (InstantiationException | InvocationTargetException | IllegalAccessException e) { - throw new RuntimeException(e.getMessage(), e); - } - } - } - - /** - * return init value - * - * @param parameterType - * @return - */ - private static Object getDefaultValue(Class parameterType) { - if ("char".equals(parameterType.getName())) { - return Character.MIN_VALUE; - } - if ("boolean".equals(parameterType.getName())) { - return false; - } - if ("byte".equals(parameterType.getName())) { - return (byte) 0; - } - if ("short".equals(parameterType.getName())) { - return (short) 0; - } - return parameterType.isPrimitive() ? 0 : null; - } - - private static Method getSetterMethod(Class cls, String property, Class valueCls) { - String name = "set" + property.substring(0, 1).toUpperCase() + property.substring(1); - Method method = NAME_METHODS_CACHE.get(cls.getName() + "." + name + "(" + valueCls.getName() + ")"); - if (method == null) { - try { - method = cls.getMethod(name, valueCls); - } catch (NoSuchMethodException e) { - for (Method m : cls.getMethods()) { - if (ReflectUtils.isBeanPropertyWriteMethod(m) && m.getName().equals(name)) { - method = m; - break; - } - } - } - if (method != null) { - NAME_METHODS_CACHE.put(cls.getName() + "." + name + "(" + valueCls.getName() + ")", method); - } - } - return method; - } - - private static Field getField(Class cls, String fieldName) { - Field result = null; - if (CLASS_FIELD_CACHE.containsKey(cls) && CLASS_FIELD_CACHE.get(cls).containsKey(fieldName)) { - return CLASS_FIELD_CACHE.get(cls).get(fieldName); - } - try { - result = cls.getDeclaredField(fieldName); - result.setAccessible(true); - } catch (NoSuchFieldException e) { - for (Field field : cls.getFields()) { - if (fieldName.equals(field.getName()) && ReflectUtils.isPublicInstanceField(field)) { - result = field; - break; - } - } - } - if (result != null) { - ConcurrentMap fields = CLASS_FIELD_CACHE.computeIfAbsent(cls, k -> new ConcurrentHashMap<>()); - fields.putIfAbsent(fieldName, result); - } - return result; - } - - public static boolean isPojo(Class cls) { - return !ReflectUtils.isPrimitives(cls) - && !Collection.class.isAssignableFrom(cls) - && !Map.class.isAssignableFrom(cls); - } - - /** - * Update the property if absent - * - * @param getterMethod the getter method - * @param setterMethod the setter method - * @param newValue the new value - * @param the value type - * @since 2.7.8 - */ - public static void updatePropertyIfAbsent(Supplier getterMethod, Consumer setterMethod, T newValue) { - if (newValue != null && getterMethod.get() == null) { - setterMethod.accept(newValue); - } - } - -} +/* + * 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.common.utils; + +import org.apache.dubbo.common.constants.CommonConstants; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; + +import java.lang.reflect.Array; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Proxy; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.IdentityHashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.TreeMap; +import java.util.WeakHashMap; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ConcurrentSkipListMap; +import java.util.function.Consumer; +import java.util.function.Supplier; + +/** + * PojoUtils. Travel object deeply, and convert complex type to simple type. + *

+ * Simple type below will be remained: + *

    + *
  • Primitive Type, also include String, Number(Integer, Long), Date + *
  • Array of Primitive Type + *
  • Collection, eg: List, Map, Set etc. + *
+ *

+ * Other type will be covert to a map which contains the attributes and value pair of object. + */ +public class PojoUtils { + + private static final Logger logger = LoggerFactory.getLogger(PojoUtils.class); + private static final ConcurrentMap NAME_METHODS_CACHE = new ConcurrentHashMap(); + private static final ConcurrentMap, ConcurrentMap> CLASS_FIELD_CACHE = new ConcurrentHashMap, ConcurrentMap>(); + private static final boolean GENERIC_WITH_CLZ = Boolean.parseBoolean(ConfigUtils.getProperty(CommonConstants.GENERIC_WITH_CLZ_KEY, "true")); + + public static Object[] generalize(Object[] objs) { + Object[] dests = new Object[objs.length]; + for (int i = 0; i < objs.length; i++) { + dests[i] = generalize(objs[i]); + } + return dests; + } + + public static Object[] realize(Object[] objs, Class[] types) { + if (objs.length != types.length) { + throw new IllegalArgumentException("args.length != types.length"); + } + + Object[] dests = new Object[objs.length]; + for (int i = 0; i < objs.length; i++) { + dests[i] = realize(objs[i], types[i]); + } + + return dests; + } + + public static Object[] realize(Object[] objs, Class[] types, Type[] gtypes) { + if (objs.length != types.length || objs.length != gtypes.length) { + throw new IllegalArgumentException("args.length != types.length"); + } + Object[] dests = new Object[objs.length]; + for (int i = 0; i < objs.length; i++) { + dests[i] = realize(objs[i], types[i], gtypes[i]); + } + return dests; + } + + public static Object generalize(Object pojo) { + return generalize(pojo, new IdentityHashMap()); + } + + @SuppressWarnings("unchecked") + private static Object generalize(Object pojo, Map history) { + if (pojo == null) { + return null; + } + + if (pojo instanceof Enum) { + return ((Enum) pojo).name(); + } + if (pojo.getClass().isArray() && Enum.class.isAssignableFrom(pojo.getClass().getComponentType())) { + int len = Array.getLength(pojo); + String[] values = new String[len]; + for (int i = 0; i < len; i++) { + values[i] = ((Enum) Array.get(pojo, i)).name(); + } + return values; + } + + if (ReflectUtils.isPrimitives(pojo.getClass())) { + return pojo; + } + + if (pojo instanceof Class) { + return ((Class) pojo).getName(); + } + + Object o = history.get(pojo); + if (o != null) { + return o; + } + history.put(pojo, pojo); + + if (pojo.getClass().isArray()) { + int len = Array.getLength(pojo); + Object[] dest = new Object[len]; + history.put(pojo, dest); + for (int i = 0; i < len; i++) { + Object obj = Array.get(pojo, i); + dest[i] = generalize(obj, history); + } + return dest; + } + if (pojo instanceof Collection) { + Collection src = (Collection) pojo; + int len = src.size(); + Collection dest = (pojo instanceof List) ? new ArrayList(len) : new HashSet(len); + history.put(pojo, dest); + for (Object obj : src) { + dest.add(generalize(obj, history)); + } + return dest; + } + if (pojo instanceof Map) { + Map src = (Map) pojo; + Map dest = createMap(src); + history.put(pojo, dest); + for (Map.Entry obj : src.entrySet()) { + dest.put(generalize(obj.getKey(), history), generalize(obj.getValue(), history)); + } + return dest; + } + Map map = new HashMap(); + history.put(pojo, map); + if (GENERIC_WITH_CLZ) { + map.put("class", pojo.getClass().getName()); + } + for (Method method : pojo.getClass().getMethods()) { + if (ReflectUtils.isBeanPropertyReadMethod(method)) { + ReflectUtils.makeAccessible(method); + try { + map.put(ReflectUtils.getPropertyNameFromBeanReadMethod(method), generalize(method.invoke(pojo), history)); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } + } + // public field + for (Field field : pojo.getClass().getFields()) { + if (ReflectUtils.isPublicInstanceField(field)) { + try { + Object fieldValue = field.get(pojo); + if (history.containsKey(pojo)) { + Object pojoGeneralizedValue = history.get(pojo); + if (pojoGeneralizedValue instanceof Map + && ((Map) pojoGeneralizedValue).containsKey(field.getName())) { + continue; + } + } + if (fieldValue != null) { + map.put(field.getName(), generalize(fieldValue, history)); + } + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } + } + return map; + } + + public static Object realize(Object pojo, Class type) { + return realize0(pojo, type, null, new IdentityHashMap()); + } + + public static Object realize(Object pojo, Class type, Type genericType) { + return realize0(pojo, type, genericType, new IdentityHashMap()); + } + + private static class PojoInvocationHandler implements InvocationHandler { + + private Map map; + + public PojoInvocationHandler(Map map) { + this.map = map; + } + + @Override + @SuppressWarnings("unchecked") + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + if (method.getDeclaringClass() == Object.class) { + return method.invoke(map, args); + } + String methodName = method.getName(); + Object value = null; + if (methodName.length() > 3 && methodName.startsWith("get")) { + value = map.get(methodName.substring(3, 4).toLowerCase() + methodName.substring(4)); + } else if (methodName.length() > 2 && methodName.startsWith("is")) { + value = map.get(methodName.substring(2, 3).toLowerCase() + methodName.substring(3)); + } else { + value = map.get(methodName.substring(0, 1).toLowerCase() + methodName.substring(1)); + } + if (value instanceof Map && !Map.class.isAssignableFrom(method.getReturnType())) { + value = realize0((Map) value, method.getReturnType(), null, new IdentityHashMap()); + } + return value; + } + } + + @SuppressWarnings("unchecked") + private static Collection createCollection(Class type, int len) { + if (type.isAssignableFrom(ArrayList.class)) { + return new ArrayList(len); + } + if (type.isAssignableFrom(HashSet.class)) { + return new HashSet(len); + } + if (!type.isInterface() && !Modifier.isAbstract(type.getModifiers())) { + try { + return (Collection) type.newInstance(); + } catch (Exception e) { + // ignore + } + } + return new ArrayList(); + } + + private static Map createMap(Map src) { + Class cl = src.getClass(); + Map result = null; + if (HashMap.class == cl) { + result = new HashMap(); + } else if (Hashtable.class == cl) { + result = new Hashtable(); + } else if (IdentityHashMap.class == cl) { + result = new IdentityHashMap(); + } else if (LinkedHashMap.class == cl) { + result = new LinkedHashMap(); + } else if (Properties.class == cl) { + result = new Properties(); + } else if (TreeMap.class == cl) { + result = new TreeMap(); + } else if (WeakHashMap.class == cl) { + return new WeakHashMap(); + } else if (ConcurrentHashMap.class == cl) { + result = new ConcurrentHashMap(); + } else if (ConcurrentSkipListMap.class == cl) { + result = new ConcurrentSkipListMap(); + } else { + try { + result = cl.newInstance(); + } catch (Exception e) { /* ignore */ } + + if (result == null) { + try { + Constructor constructor = cl.getConstructor(Map.class); + result = (Map) constructor.newInstance(Collections.EMPTY_MAP); + } catch (Exception e) { /* ignore */ } + } + } + + if (result == null) { + result = new HashMap(); + } + + return result; + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + private static Object realize0(Object pojo, Class type, Type genericType, final Map history) { + if (pojo == null) { + return null; + } + + if (type != null && type.isEnum() && pojo.getClass() == String.class) { + return Enum.valueOf((Class) type, (String) pojo); + } + + if (ReflectUtils.isPrimitives(pojo.getClass()) + && !(type != null && type.isArray() + && type.getComponentType().isEnum() + && pojo.getClass() == String[].class)) { + return CompatibleTypeUtils.compatibleTypeConvert(pojo, type); + } + + Object o = history.get(pojo); + + if (o != null) { + return o; + } + + history.put(pojo, pojo); + + if (pojo.getClass().isArray()) { + if (Collection.class.isAssignableFrom(type)) { + Class ctype = pojo.getClass().getComponentType(); + int len = Array.getLength(pojo); + Collection dest = createCollection(type, len); + history.put(pojo, dest); + for (int i = 0; i < len; i++) { + Object obj = Array.get(pojo, i); + Object value = realize0(obj, ctype, null, history); + dest.add(value); + } + return dest; + } else { + Class ctype = (type != null && type.isArray() ? type.getComponentType() : pojo.getClass().getComponentType()); + int len = Array.getLength(pojo); + Object dest = Array.newInstance(ctype, len); + history.put(pojo, dest); + for (int i = 0; i < len; i++) { + Object obj = Array.get(pojo, i); + Object value = realize0(obj, ctype, null, history); + Array.set(dest, i, value); + } + return dest; + } + } + + if (pojo instanceof Collection) { + if (type.isArray()) { + Class ctype = type.getComponentType(); + Collection src = (Collection) pojo; + int len = src.size(); + Object dest = Array.newInstance(ctype, len); + history.put(pojo, dest); + int i = 0; + for (Object obj : src) { + Object value = realize0(obj, ctype, null, history); + Array.set(dest, i, value); + i++; + } + return dest; + } else { + Collection src = (Collection) pojo; + int len = src.size(); + Collection dest = createCollection(type, len); + history.put(pojo, dest); + for (Object obj : src) { + Type keyType = getGenericClassByIndex(genericType, 0); + Class keyClazz = obj == null ? null : obj.getClass(); + if (keyType instanceof Class) { + keyClazz = (Class) keyType; + } + Object value = realize0(obj, keyClazz, keyType, history); + dest.add(value); + } + return dest; + } + } + + if (pojo instanceof Map && type != null) { + Object className = ((Map) pojo).get("class"); + if (className instanceof String) { + SerializeClassChecker.getInstance().validateClass((String) className); + try { + type = ClassUtils.forName((String) className); + } catch (ClassNotFoundException e) { + // ignore + } + } + + // special logic for enum + if (type.isEnum()) { + Object name = ((Map) pojo).get("name"); + if (name != null) { + return Enum.valueOf((Class) type, name.toString()); + } + } + Map map; + // when return type is not the subclass of return type from the signature and not an interface + if (!type.isInterface() && !type.isAssignableFrom(pojo.getClass())) { + try { + map = (Map) type.newInstance(); + Map mapPojo = (Map) pojo; + map.putAll(mapPojo); + if (GENERIC_WITH_CLZ) { + map.remove("class"); + } + } catch (Exception e) { + //ignore error + map = (Map) pojo; + } + } else { + map = (Map) pojo; + } + + if (Map.class.isAssignableFrom(type) || type == Object.class) { + final Map result; + // fix issue#5939 + Type mapKeyType = getKeyTypeForMap(map.getClass()); + Type typeKeyType = getGenericClassByIndex(genericType, 0); + boolean typeMismatch = mapKeyType instanceof Class + && typeKeyType instanceof Class + && !typeKeyType.getTypeName().equals(mapKeyType.getTypeName()); + if (typeMismatch) { + result = createMap(new HashMap(0)); + } else { + result = createMap(map); + } + + history.put(pojo, result); + for (Map.Entry entry : map.entrySet()) { + Type keyType = getGenericClassByIndex(genericType, 0); + Type valueType = getGenericClassByIndex(genericType, 1); + Class keyClazz; + if (keyType instanceof Class) { + keyClazz = (Class) keyType; + } else if (keyType instanceof ParameterizedType) { + keyClazz = (Class) ((ParameterizedType) keyType).getRawType(); + } else { + keyClazz = entry.getKey() == null ? null : entry.getKey().getClass(); + } + Class valueClazz; + if (valueType instanceof Class) { + valueClazz = (Class) valueType; + } else if (valueType instanceof ParameterizedType) { + valueClazz = (Class) ((ParameterizedType) valueType).getRawType(); + } else { + valueClazz = entry.getValue() == null ? null : entry.getValue().getClass(); + } + + Object key = keyClazz == null ? entry.getKey() : realize0(entry.getKey(), keyClazz, keyType, history); + Object value = valueClazz == null ? entry.getValue() : realize0(entry.getValue(), valueClazz, valueType, history); + result.put(key, value); + } + return result; + } else if (type.isInterface()) { + Object dest = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[]{type}, new PojoInvocationHandler(map)); + history.put(pojo, dest); + return dest; + } else { + Object dest = newInstance(type); + history.put(pojo, dest); + for (Map.Entry entry : map.entrySet()) { + Object key = entry.getKey(); + if (key instanceof String) { + String name = (String) key; + Object value = entry.getValue(); + if (value != null) { + Method method = getSetterMethod(dest.getClass(), name, value.getClass()); + Field field = getField(dest.getClass(), name); + if (method != null) { + if (!method.isAccessible()) { + method.setAccessible(true); + } + Type ptype = method.getGenericParameterTypes()[0]; + value = realize0(value, method.getParameterTypes()[0], ptype, history); + try { + method.invoke(dest, value); + } catch (Exception e) { + String exceptionDescription = "Failed to set pojo " + dest.getClass().getSimpleName() + " property " + name + + " value " + value + "(" + value.getClass() + "), cause: " + e.getMessage(); + logger.error(exceptionDescription, e); + throw new RuntimeException(exceptionDescription, e); + } + } else if (field != null) { + value = realize0(value, field.getType(), field.getGenericType(), history); + try { + field.set(dest, value); + } catch (IllegalAccessException e) { + throw new RuntimeException("Failed to set field " + name + " of pojo " + dest.getClass().getName() + " : " + e.getMessage(), e); + } + } + } + } + } + if (dest instanceof Throwable) { + Object message = map.get("message"); + if (message instanceof String) { + try { + Field field = Throwable.class.getDeclaredField("detailMessage"); + if (!field.isAccessible()) { + field.setAccessible(true); + } + field.set(dest, message); + } catch (Exception e) { + } + } + } + return dest; + } + } + return pojo; + } + + /** + * Get key type for {@link Map} directly implemented by {@code clazz}. + * If {@code clazz} does not implement {@link Map} directly, return {@code null}. + * + * @param clazz {@link Class} + * @return Return String.class for {@link com.alibaba.fastjson.JSONObject} + */ + private static Type getKeyTypeForMap(Class clazz) { + Type[] interfaces = clazz.getGenericInterfaces(); + if (!ArrayUtils.isEmpty(interfaces)) { + for (Type type : interfaces) { + if (type instanceof ParameterizedType) { + ParameterizedType t = (ParameterizedType) type; + if ("java.util.Map".equals(t.getRawType().getTypeName())) { + return t.getActualTypeArguments()[0]; + } + } + } + } + return null; + } + + /** + * Get parameterized type + * + * @param genericType generic type + * @param index index of the target parameterized type + * @return Return Person.class for List, return Person.class for Map when index=0 + */ + private static Type getGenericClassByIndex(Type genericType, int index) { + Type clazz = null; + // find parameterized type + if (genericType instanceof ParameterizedType) { + ParameterizedType t = (ParameterizedType) genericType; + Type[] types = t.getActualTypeArguments(); + clazz = types[index]; + } + return clazz; + } + + private static Object newInstance(Class cls) { + try { + return cls.newInstance(); + } catch (Throwable t) { + try { + Constructor[] constructors = cls.getDeclaredConstructors(); + /** + * From Javadoc java.lang.Class#getDeclaredConstructors + * This method returns an array of Constructor objects reflecting all the constructors + * declared by the class represented by this Class object. + * This method returns an array of length 0, + * if this Class object represents an interface, a primitive type, an array class, or void. + */ + if (constructors.length == 0) { + throw new RuntimeException("Illegal constructor: " + cls.getName()); + } + Constructor constructor = constructors[0]; + if (constructor.getParameterTypes().length > 0) { + for (Constructor c : constructors) { + if (c.getParameterTypes().length < constructor.getParameterTypes().length) { + constructor = c; + if (constructor.getParameterTypes().length == 0) { + break; + } + } + } + } + constructor.setAccessible(true); + Object[] parameters = Arrays.stream(constructor.getParameterTypes()).map(PojoUtils::getDefaultValue).toArray(); + return constructor.newInstance(parameters); + } catch (InstantiationException | InvocationTargetException | IllegalAccessException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + } + + /** + * return init value + * + * @param parameterType + * @return + */ + private static Object getDefaultValue(Class parameterType) { + if ("char".equals(parameterType.getName())) { + return Character.MIN_VALUE; + } + if ("boolean".equals(parameterType.getName())) { + return false; + } + if ("byte".equals(parameterType.getName())) { + return (byte) 0; + } + if ("short".equals(parameterType.getName())) { + return (short) 0; + } + return parameterType.isPrimitive() ? 0 : null; + } + + private static Method getSetterMethod(Class cls, String property, Class valueCls) { + String name = "set" + property.substring(0, 1).toUpperCase() + property.substring(1); + Method method = NAME_METHODS_CACHE.get(cls.getName() + "." + name + "(" + valueCls.getName() + ")"); + if (method == null) { + try { + method = cls.getMethod(name, valueCls); + } catch (NoSuchMethodException e) { + for (Method m : cls.getMethods()) { + if (ReflectUtils.isBeanPropertyWriteMethod(m) && m.getName().equals(name)) { + method = m; + break; + } + } + } + if (method != null) { + NAME_METHODS_CACHE.put(cls.getName() + "." + name + "(" + valueCls.getName() + ")", method); + } + } + return method; + } + + private static Field getField(Class cls, String fieldName) { + Field result = null; + if (CLASS_FIELD_CACHE.containsKey(cls) && CLASS_FIELD_CACHE.get(cls).containsKey(fieldName)) { + return CLASS_FIELD_CACHE.get(cls).get(fieldName); + } + try { + result = cls.getDeclaredField(fieldName); + result.setAccessible(true); + } catch (NoSuchFieldException e) { + for (Field field : cls.getFields()) { + if (fieldName.equals(field.getName()) && ReflectUtils.isPublicInstanceField(field)) { + result = field; + break; + } + } + } + if (result != null) { + ConcurrentMap fields = CLASS_FIELD_CACHE.computeIfAbsent(cls, k -> new ConcurrentHashMap<>()); + fields.putIfAbsent(fieldName, result); + } + return result; + } + + public static boolean isPojo(Class cls) { + return !ReflectUtils.isPrimitives(cls) + && !Collection.class.isAssignableFrom(cls) + && !Map.class.isAssignableFrom(cls); + } + + /** + * Update the property if absent + * + * @param getterMethod the getter method + * @param setterMethod the setter method + * @param newValue the new value + * @param the value type + * @since 2.7.8 + */ + public static void updatePropertyIfAbsent(Supplier getterMethod, Consumer setterMethod, T newValue) { + if (newValue != null && getterMethod.get() == null) { + setterMethod.accept(newValue); + } + } + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/Stack.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/Stack.java index b7ec70c279..0d737cd7b1 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/Stack.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/Stack.java @@ -140,4 +140,4 @@ public class Stack { mSize = 0; mElements.clear(); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/StringUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/StringUtils.java index d60ea13720..a46b5c8a62 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/StringUtils.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/StringUtils.java @@ -1,1227 +1,1227 @@ -/* - * 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.common.utils; - -import org.apache.dubbo.common.io.UnsafeStringWriter; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; - -import com.alibaba.fastjson.JSON; - -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import static java.lang.String.valueOf; -import static java.util.Collections.emptySet; -import static java.util.Collections.unmodifiableSet; -import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SEPARATOR; -import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN; -import static org.apache.dubbo.common.constants.CommonConstants.DOT_REGEX; -import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.HIDE_KEY_PREFIX; -import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.SEPARATOR_REGEX; -import static org.apache.dubbo.common.constants.CommonConstants.UNDERLINE_SEPARATOR; -import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY; - -/** - * StringUtils - */ - -public final class StringUtils { - - public static final String EMPTY_STRING = ""; - public static final int INDEX_NOT_FOUND = -1; - public static final String[] EMPTY_STRING_ARRAY = new String[0]; - - private static final Logger logger = LoggerFactory.getLogger(StringUtils.class); - private static final Pattern KVP_PATTERN = Pattern.compile("([_.a-zA-Z0-9][-_.a-zA-Z0-9]*)[=](.*)"); //key value pair pattern. - private static final Pattern INT_PATTERN = Pattern.compile("^\\d+$"); - private static final Pattern PARAMETERS_PATTERN = Pattern.compile("^\\[((\\s*\\{\\s*[\\w_\\-\\.]+\\s*:\\s*.+?\\s*\\}\\s*,?\\s*)+)\\s*\\]$"); - private static final Pattern PAIR_PARAMETERS_PATTERN = Pattern.compile("^\\{\\s*([\\w-_\\.]+)\\s*:\\s*(.+)\\s*\\}$"); - private static final int PAD_LIMIT = 8192; - private static final byte[] HEX2B; - - - /** - * @since 2.7.5 - */ - public static final char EQUAL_CHAR = '='; - - public static final String EQUAL = valueOf(EQUAL_CHAR); - - public static final char AND_CHAR = '&'; - - public static final String AND = valueOf(AND_CHAR); - - public static final char SEMICOLON_CHAR = ';'; - - public static final String SEMICOLON = valueOf(SEMICOLON_CHAR); - - public static final char QUESTION_MASK_CHAR = '?'; - - public static final String QUESTION_MASK = valueOf(QUESTION_MASK_CHAR); - - public static final char SLASH_CHAR = '/'; - - public static final String SLASH = valueOf(SLASH_CHAR); - - public static final char HYPHEN_CHAR = '-'; - - public static final String HYPHEN = valueOf(HYPHEN_CHAR); - - static { - HEX2B = new byte[128]; - Arrays.fill(HEX2B, (byte) -1); - HEX2B['0'] = (byte) 0; - HEX2B['1'] = (byte) 1; - HEX2B['2'] = (byte) 2; - HEX2B['3'] = (byte) 3; - HEX2B['4'] = (byte) 4; - HEX2B['5'] = (byte) 5; - HEX2B['6'] = (byte) 6; - HEX2B['7'] = (byte) 7; - HEX2B['8'] = (byte) 8; - HEX2B['9'] = (byte) 9; - HEX2B['A'] = (byte) 10; - HEX2B['B'] = (byte) 11; - HEX2B['C'] = (byte) 12; - HEX2B['D'] = (byte) 13; - HEX2B['E'] = (byte) 14; - HEX2B['F'] = (byte) 15; - HEX2B['a'] = (byte) 10; - HEX2B['b'] = (byte) 11; - HEX2B['c'] = (byte) 12; - HEX2B['d'] = (byte) 13; - HEX2B['e'] = (byte) 14; - HEX2B['f'] = (byte) 15; - } - - private StringUtils() { - } - - /** - * Gets a CharSequence length or {@code 0} if the CharSequence is - * {@code null}. - * - * @param cs a CharSequence or {@code null} - * @return CharSequence length or {@code 0} if the CharSequence is - * {@code null}. - */ - public static int length(final CharSequence cs) { - return cs == null ? 0 : cs.length(); - } - - /** - *

Repeat a String {@code repeat} times to form a - * new String.

- * - *
-     * StringUtils.repeat(null, 2) = null
-     * StringUtils.repeat("", 0)   = ""
-     * StringUtils.repeat("", 2)   = ""
-     * StringUtils.repeat("a", 3)  = "aaa"
-     * StringUtils.repeat("ab", 2) = "abab"
-     * StringUtils.repeat("a", -2) = ""
-     * 
- * - * @param str the String to repeat, may be null - * @param repeat number of times to repeat str, negative treated as zero - * @return a new String consisting of the original String repeated, - * {@code null} if null String input - */ - public static String repeat(final String str, final int repeat) { - // Performance tuned for 2.0 (JDK1.4) - - if (str == null) { - return null; - } - if (repeat <= 0) { - return EMPTY_STRING; - } - final int inputLength = str.length(); - if (repeat == 1 || inputLength == 0) { - return str; - } - if (inputLength == 1 && repeat <= PAD_LIMIT) { - return repeat(str.charAt(0), repeat); - } - - final int outputLength = inputLength * repeat; - switch (inputLength) { - case 1: - return repeat(str.charAt(0), repeat); - case 2: - final char ch0 = str.charAt(0); - final char ch1 = str.charAt(1); - final char[] output2 = new char[outputLength]; - for (int i = repeat * 2 - 2; i >= 0; i--, i--) { - output2[i] = ch0; - output2[i + 1] = ch1; - } - return new String(output2); - default: - final StringBuilder buf = new StringBuilder(outputLength); - for (int i = 0; i < repeat; i++) { - buf.append(str); - } - return buf.toString(); - } - } - - /** - *

Repeat a String {@code repeat} times to form a - * new String, with a String separator injected each time.

- * - *
-     * StringUtils.repeat(null, null, 2) = null
-     * StringUtils.repeat(null, "x", 2)  = null
-     * StringUtils.repeat("", null, 0)   = ""
-     * StringUtils.repeat("", "", 2)     = ""
-     * StringUtils.repeat("", "x", 3)    = "xxx"
-     * StringUtils.repeat("?", ", ", 3)  = "?, ?, ?"
-     * 
- * - * @param str the String to repeat, may be null - * @param separator the String to inject, may be null - * @param repeat number of times to repeat str, negative treated as zero - * @return a new String consisting of the original String repeated, - * {@code null} if null String input - * @since 2.5 - */ - public static String repeat(final String str, final String separator, final int repeat) { - if (str == null || separator == null) { - return repeat(str, repeat); - } - // given that repeat(String, int) is quite optimized, better to rely on it than try and splice this into it - final String result = repeat(str + separator, repeat); - return removeEnd(result, separator); - } - - /** - *

Removes a substring only if it is at the end of a source string, - * otherwise returns the source string.

- * - *

A {@code null} source string will return {@code null}. - * An empty ("") source string will return the empty string. - * A {@code null} search string will return the source string.

- * - *
-     * StringUtils.removeEnd(null, *)      = null
-     * StringUtils.removeEnd("", *)        = ""
-     * StringUtils.removeEnd(*, null)      = *
-     * StringUtils.removeEnd("www.domain.com", ".com.")  = "www.domain.com"
-     * StringUtils.removeEnd("www.domain.com", ".com")   = "www.domain"
-     * StringUtils.removeEnd("www.domain.com", "domain") = "www.domain.com"
-     * StringUtils.removeEnd("abc", "")    = "abc"
-     * 
- * - * @param str the source String to search, may be null - * @param remove the String to search for and remove, may be null - * @return the substring with the string removed if found, - * {@code null} if null String input - */ - public static String removeEnd(final String str, final String remove) { - if (isAnyEmpty(str, remove)) { - return str; - } - if (str.endsWith(remove)) { - return str.substring(0, str.length() - remove.length()); - } - return str; - } - - /** - *

Returns padding using the specified delimiter repeated - * to a given length.

- * - *
-     * StringUtils.repeat('e', 0)  = ""
-     * StringUtils.repeat('e', 3)  = "eee"
-     * StringUtils.repeat('e', -2) = ""
-     * 
- * - *

Note: this method doesn't not support padding with - * Unicode Supplementary Characters - * as they require a pair of {@code char}s to be represented. - * If you are needing to support full I18N of your applications - * consider using {@link #repeat(String, int)} instead. - *

- * - * @param ch character to repeat - * @param repeat number of times to repeat char, negative treated as zero - * @return String with repeated character - * @see #repeat(String, int) - */ - public static String repeat(final char ch, final int repeat) { - final char[] buf = new char[repeat]; - for (int i = repeat - 1; i >= 0; i--) { - buf[i] = ch; - } - return new String(buf); - } - - /** - *

Strips any of a set of characters from the end of a String.

- * - *

A {@code null} input String returns {@code null}. - * An empty string ("") input returns the empty string.

- * - *

If the stripChars String is {@code null}, whitespace is - * stripped as defined by {@link Character#isWhitespace(char)}.

- * - *
-     * StringUtils.stripEnd(null, *)          = null
-     * StringUtils.stripEnd("", *)            = ""
-     * StringUtils.stripEnd("abc", "")        = "abc"
-     * StringUtils.stripEnd("abc", null)      = "abc"
-     * StringUtils.stripEnd("  abc", null)    = "  abc"
-     * StringUtils.stripEnd("abc  ", null)    = "abc"
-     * StringUtils.stripEnd(" abc ", null)    = " abc"
-     * StringUtils.stripEnd("  abcyx", "xyz") = "  abc"
-     * StringUtils.stripEnd("120.00", ".0")   = "12"
-     * 
- * - * @param str the String to remove characters from, may be null - * @param stripChars the set of characters to remove, null treated as whitespace - * @return the stripped String, {@code null} if null String input - */ - public static String stripEnd(final String str, final String stripChars) { - int end; - if (str == null || (end = str.length()) == 0) { - return str; - } - - if (stripChars == null) { - while (end != 0 && Character.isWhitespace(str.charAt(end - 1))) { - end--; - } - } else if (stripChars.isEmpty()) { - return str; - } else { - while (end != 0 && stripChars.indexOf(str.charAt(end - 1)) != INDEX_NOT_FOUND) { - end--; - } - } - return str.substring(0, end); - } - - /** - *

Replaces all occurrences of a String within another String.

- * - *

A {@code null} reference passed to this method is a no-op.

- * - *
-     * StringUtils.replace(null, *, *)        = null
-     * StringUtils.replace("", *, *)          = ""
-     * StringUtils.replace("any", null, *)    = "any"
-     * StringUtils.replace("any", *, null)    = "any"
-     * StringUtils.replace("any", "", *)      = "any"
-     * StringUtils.replace("aba", "a", null)  = "aba"
-     * StringUtils.replace("aba", "a", "")    = "b"
-     * StringUtils.replace("aba", "a", "z")   = "zbz"
-     * 
- * - * @param text text to search and replace in, may be null - * @param searchString the String to search for, may be null - * @param replacement the String to replace it with, may be null - * @return the text with any replacements processed, - * {@code null} if null String input - * @see #replace(String text, String searchString, String replacement, int max) - */ - public static String replace(final String text, final String searchString, final String replacement) { - return replace(text, searchString, replacement, -1); - } - - /** - *

Replaces a String with another String inside a larger String, - * for the first {@code max} values of the search String.

- * - *

A {@code null} reference passed to this method is a no-op.

- * - *
-     * StringUtils.replace(null, *, *, *)         = null
-     * StringUtils.replace("", *, *, *)           = ""
-     * StringUtils.replace("any", null, *, *)     = "any"
-     * StringUtils.replace("any", *, null, *)     = "any"
-     * StringUtils.replace("any", "", *, *)       = "any"
-     * StringUtils.replace("any", *, *, 0)        = "any"
-     * StringUtils.replace("abaa", "a", null, -1) = "abaa"
-     * StringUtils.replace("abaa", "a", "", -1)   = "b"
-     * StringUtils.replace("abaa", "a", "z", 0)   = "abaa"
-     * StringUtils.replace("abaa", "a", "z", 1)   = "zbaa"
-     * StringUtils.replace("abaa", "a", "z", 2)   = "zbza"
-     * StringUtils.replace("abaa", "a", "z", -1)  = "zbzz"
-     * 
- * - * @param text text to search and replace in, may be null - * @param searchString the String to search for, may be null - * @param replacement the String to replace it with, may be null - * @param max maximum number of values to replace, or {@code -1} if no maximum - * @return the text with any replacements processed, - * {@code null} if null String input - */ - public static String replace(final String text, final String searchString, final String replacement, int max) { - if (isAnyEmpty(text, searchString) || replacement == null || max == 0) { - return text; - } - int start = 0; - int end = text.indexOf(searchString, start); - if (end == INDEX_NOT_FOUND) { - return text; - } - final int replLength = searchString.length(); - int increase = replacement.length() - replLength; - increase = increase < 0 ? 0 : increase; - increase *= max < 0 ? 16 : max > 64 ? 64 : max; - final StringBuilder buf = new StringBuilder(text.length() + increase); - while (end != INDEX_NOT_FOUND) { - buf.append(text, start, end).append(replacement); - start = end + replLength; - if (--max == 0) { - break; - } - end = text.indexOf(searchString, start); - } - buf.append(text.substring(start)); - return buf.toString(); - } - - public static boolean isBlank(CharSequence cs) { - int strLen; - if (cs == null || (strLen = cs.length()) == 0) { - return true; - } - for (int i = 0; i < strLen; i++) { - if (!Character.isWhitespace(cs.charAt(i))) { - return false; - } - } - return true; - } - - /** - * Check the cs String whether contains non whitespace characters. - * @param cs - * @return - */ - public static boolean hasText(CharSequence cs) { - return !isBlank(cs); - } - - /** - * is empty string. - * - * @param str source string. - * @return is empty. - */ - public static boolean isEmpty(String str) { - return str == null || str.isEmpty(); - } - - /** - *

Checks if the strings contain empty or null elements.

- * - *

-     * StringUtils.isNoneEmpty(null)            = false
-     * StringUtils.isNoneEmpty("")              = false
-     * StringUtils.isNoneEmpty(" ")             = true
-     * StringUtils.isNoneEmpty("abc")           = true
-     * StringUtils.isNoneEmpty("abc", "def")    = true
-     * StringUtils.isNoneEmpty("abc", null)     = false
-     * StringUtils.isNoneEmpty("abc", "")       = false
-     * StringUtils.isNoneEmpty("abc", " ")      = true
-     * 
- * - * @param ss the strings to check - * @return {@code true} if all strings are not empty or null - */ - public static boolean isNoneEmpty(final String... ss) { - if (ArrayUtils.isEmpty(ss)) { - return false; - } - for (final String s : ss) { - if (isEmpty(s)) { - return false; - } - } - return true; - } - - /** - *

Checks if the strings contain at least on empty or null element.

- * - *

-     * StringUtils.isAnyEmpty(null)            = true
-     * StringUtils.isAnyEmpty("")              = true
-     * StringUtils.isAnyEmpty(" ")             = false
-     * StringUtils.isAnyEmpty("abc")           = false
-     * StringUtils.isAnyEmpty("abc", "def")    = false
-     * StringUtils.isAnyEmpty("abc", null)     = true
-     * StringUtils.isAnyEmpty("abc", "")       = true
-     * StringUtils.isAnyEmpty("abc", " ")      = false
-     * 
- * - * @param ss the strings to check - * @return {@code true} if at least one in the strings is empty or null - */ - public static boolean isAnyEmpty(final String... ss) { - return !isNoneEmpty(ss); - } - - /** - * is not empty string. - * - * @param str source string. - * @return is not empty. - */ - public static boolean isNotEmpty(String str) { - return !isEmpty(str); - } - - /** - * @param s1 - * @param s2 - * @return equals - */ - public static boolean isEquals(String s1, String s2) { - if (s1 == null && s2 == null) { - return true; - } - if (s1 == null || s2 == null) { - return false; - } - return s1.equals(s2); - } - - /** - * is integer string. - * - * @param str - * @return is integer - */ - public static boolean isInteger(String str) { - return isNotEmpty(str) && INT_PATTERN.matcher(str).matches(); - } - - public static int parseInteger(String str) { - return isInteger(str) ? Integer.parseInt(str) : 0; - } - - /** - * Returns true if s is a legal Java identifier.

- * more info. - */ - public static boolean isJavaIdentifier(String s) { - if (isEmpty(s) || !Character.isJavaIdentifierStart(s.charAt(0))) { - return false; - } - for (int i = 1; i < s.length(); i++) { - if (!Character.isJavaIdentifierPart(s.charAt(i))) { - return false; - } - } - return true; - } - - public static boolean isContains(String values, String value) { - return isNotEmpty(values) && isContains(COMMA_SPLIT_PATTERN.split(values), value); - } - - public static boolean isContains(String str, char ch) { - return isNotEmpty(str) && str.indexOf(ch) >= 0; - } - - public static boolean isNotContains(String str, char ch) { - return !isContains(str, ch); - } - - /** - * @param values - * @param value - * @return contains - */ - public static boolean isContains(String[] values, String value) { - if (isNotEmpty(value) && ArrayUtils.isNotEmpty(values)) { - for (String v : values) { - if (value.equals(v)) { - return true; - } - } - } - return false; - } - - public static boolean isNumeric(String str, boolean allowDot) { - if (str == null || str.isEmpty()) { - return false; - } - boolean hasDot = false; - int sz = str.length(); - for (int i = 0; i < sz; i++) { - if (str.charAt(i) == '.') { - if (hasDot || !allowDot) { - return false; - } - hasDot = true; - continue; - } - if (!Character.isDigit(str.charAt(i))) { - return false; - } - } - return true; - } - - - /** - * @param e - * @return string - */ - public static String toString(Throwable e) { - UnsafeStringWriter w = new UnsafeStringWriter(); - PrintWriter p = new PrintWriter(w); - p.print(e.getClass().getName()); - if (e.getMessage() != null) { - p.print(": " + e.getMessage()); - } - p.println(); - try { - e.printStackTrace(p); - return w.toString(); - } finally { - p.close(); - } - } - - /** - * @param msg - * @param e - * @return string - */ - public static String toString(String msg, Throwable e) { - UnsafeStringWriter w = new UnsafeStringWriter(); - w.write(msg + "\n"); - PrintWriter p = new PrintWriter(w); - try { - e.printStackTrace(p); - return w.toString(); - } finally { - p.close(); - } - } - - /** - * translate. - * - * @param src source string. - * @param from src char table. - * @param to target char table. - * @return String. - */ - public static String translate(String src, String from, String to) { - if (isEmpty(src)) { - return src; - } - StringBuilder sb = null; - int ix; - char c; - for (int i = 0, len = src.length(); i < len; i++) { - c = src.charAt(i); - ix = from.indexOf(c); - if (ix == -1) { - if (sb != null) { - sb.append(c); - } - } else { - if (sb == null) { - sb = new StringBuilder(len); - sb.append(src, 0, i); - } - if (ix < to.length()) { - sb.append(to.charAt(ix)); - } - } - } - return sb == null ? src : sb.toString(); - } - - /** - * split. - * - * @param ch char. - * @return string array. - */ - public static String[] split(String str, char ch) { - if (isEmpty(str)) { - return EMPTY_STRING_ARRAY; - } - return splitToList0(str, ch).toArray(EMPTY_STRING_ARRAY); - } - - private static List splitToList0(String str, char ch) { - List result = new ArrayList<>(); - int ix = 0, len = str.length(); - for (int i = 0; i < len; i++) { - if (str.charAt(i) == ch) { - result.add(str.substring(ix, i)); - ix = i + 1; - } - } - - if (ix >= 0) { - result.add(str.substring(ix)); - } - return result; - } - - /** - * Splits String around matches of the given character. - *

- * Note: Compare with {@link StringUtils#split(String, char)}, this method reduce memory copy. - */ - public static List splitToList(String str, char ch) { - if (isEmpty(str)) { - return Collections.emptyList(); - } - return splitToList0(str, ch); - } - - /** - * Split the specified value to be a {@link Set} - * - * @param value the content to be split - * @param separatorChar a char to separate - * @return non-null read-only {@link Set} - * @since 2.7.8 - */ - public static Set splitToSet(String value, char separatorChar) { - return splitToSet(value, separatorChar, false); - } - - /** - * Split the specified value to be a {@link Set} - * - * @param value the content to be split - * @param separatorChar a char to separate - * @param trimElements require to trim the elements or not - * @return non-null read-only {@link Set} - * @since 2.7.8 - */ - public static Set splitToSet(String value, char separatorChar, boolean trimElements) { - List values = splitToList(value, separatorChar); - int size = values.size(); - - if (size < 1) { // empty condition - return emptySet(); - } - - if (!trimElements) { // Do not require to trim the elements - return new LinkedHashSet(values); - } - - return unmodifiableSet(values - .stream() - .map(String::trim) - .collect(LinkedHashSet::new, Set::add, Set::addAll)); - } - - /** - * join string. - * - * @param array String array. - * @return String. - */ - public static String join(String[] array) { - if (ArrayUtils.isEmpty(array)) { - return EMPTY_STRING; - } - StringBuilder sb = new StringBuilder(); - for (String s : array) { - sb.append(s); - } - return sb.toString(); - } - - /** - * join string like javascript. - * - * @param array String array. - * @param split split - * @return String. - */ - public static String join(String[] array, char split) { - if (ArrayUtils.isEmpty(array)) { - return EMPTY_STRING; - } - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < array.length; i++) { - if (i > 0) { - sb.append(split); - } - sb.append(array[i]); - } - return sb.toString(); - } - - /** - * join string like javascript. - * - * @param array String array. - * @param split split - * @return String. - */ - public static String join(String[] array, String split) { - if (ArrayUtils.isEmpty(array)) { - return EMPTY_STRING; - } - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < array.length; i++) { - if (i > 0) { - sb.append(split); - } - sb.append(array[i]); - } - return sb.toString(); - } - - public static String join(Collection coll, String split) { - if (CollectionUtils.isEmpty(coll)) { - return EMPTY_STRING; - } - - StringBuilder sb = new StringBuilder(); - boolean isFirst = true; - for (String s : coll) { - if (isFirst) { - isFirst = false; - } else { - sb.append(split); - } - sb.append(s); - } - return sb.toString(); - } - - /** - * parse key-value pair. - * - * @param str string. - * @param itemSeparator item separator. - * @return key-value map; - */ - private static Map parseKeyValuePair(String str, String itemSeparator) { - String[] tmp = str.split(itemSeparator); - Map map = new HashMap(tmp.length); - for (int i = 0; i < tmp.length; i++) { - Matcher matcher = KVP_PATTERN.matcher(tmp[i]); - if (!matcher.matches()) { - continue; - } - map.put(matcher.group(1), matcher.group(2)); - } - return map; - } - - public static String getQueryStringValue(String qs, String key) { - Map map = parseQueryString(qs); - return map.get(key); - } - - /** - * parse query string to Parameters. - * - * @param qs query string. - * @return Parameters instance. - */ - public static Map parseQueryString(String qs) { - if (isEmpty(qs)) { - return new HashMap(); - } - return parseKeyValuePair(qs, "\\&"); - } - - public static String getServiceKey(Map ps) { - StringBuilder buf = new StringBuilder(); - String group = ps.get(GROUP_KEY); - if (isNotEmpty(group)) { - buf.append(group).append("/"); - } - buf.append(ps.get(INTERFACE_KEY)); - String version = ps.get(VERSION_KEY); - if (isNotEmpty(group)) { - buf.append(":").append(version); - } - return buf.toString(); - } - - public static String toQueryString(Map ps) { - StringBuilder buf = new StringBuilder(); - if (ps != null && ps.size() > 0) { - for (Map.Entry entry : new TreeMap(ps).entrySet()) { - String key = entry.getKey(); - String value = entry.getValue(); - if (isNoneEmpty(key, value)) { - if (buf.length() > 0) { - buf.append("&"); - } - buf.append(key); - buf.append("="); - buf.append(value); - } - } - } - return buf.toString(); - } - - public static String camelToSplitName(String camelName, String split) { - if (isEmpty(camelName)) { - return camelName; - } - if (!isWord(camelName)) { - // convert Ab-Cd-Ef to ab-cd-ef - if (isSplitCase(camelName, split.charAt(0))) { - return camelName.toLowerCase(); - } - // not camel case - return camelName; - } - - StringBuilder buf = null; - for (int i = 0; i < camelName.length(); i++) { - char ch = camelName.charAt(i); - if (ch >= 'A' && ch <= 'Z') { - if (buf == null) { - buf = new StringBuilder(); - if (i > 0) { - buf.append(camelName, 0, i); - } - } - if (i > 0) { - buf.append(split); - } - buf.append(Character.toLowerCase(ch)); - } else if (buf != null) { - buf.append(ch); - } - } - return buf == null ? camelName.toLowerCase() : buf.toString().toLowerCase(); - } - - private static boolean isSplitCase(String str, char separator) { - if (str == null) { - return false; - } - return str.chars().allMatch(ch -> (ch == separator) || isWord((char)ch) ); - } - - private static boolean isWord(String str) { - if (str == null) { - return false; - } - return str.chars().allMatch(ch -> isWord((char)ch)); - } - - private static boolean isWord(char ch) { - if ((ch >= 'A' && ch <= 'Z') || - (ch >= 'a' && ch <= 'z') || - (ch >= '0' && ch <= '9')) { - return true; - } - return false; - } - - /** - * Convert snake_case or SNAKE_CASE to kebab-case. - *

- * NOTE: Return itself if it's not a snake case. - * @param snakeName - * @param split - * @return - */ - public static String snakeToSplitName(String snakeName, String split) { - String lowerCase = snakeName.toLowerCase(); - if (isSnakeCase(snakeName)) { - return replace(lowerCase, "_", split); - } - return snakeName; - } - - protected static boolean isSnakeCase(String str) { - return str.contains("_") || str.equals(str.toLowerCase()) || str.equals(str.toUpperCase()); - } - - /** - * Convert camelCase or snake_case/SNAKE_CASE to kebab-case - * @param str - * @param split - * @return - */ - public static String convertToSplitName(String str, String split) { - if (isSnakeCase(str)) { - return snakeToSplitName(str, split); - } else { - return camelToSplitName(str, split); - } - } - - public static String toArgumentString(Object[] args) { - StringBuilder buf = new StringBuilder(); - for (Object arg : args) { - if (buf.length() > 0) { - buf.append(COMMA_SEPARATOR); - } - if (arg == null || ReflectUtils.isPrimitives(arg.getClass())) { - buf.append(arg); - } else { - try { - buf.append(JSON.toJSONString(arg)); - } catch (Exception e) { - logger.warn(e.getMessage(), e); - buf.append(arg); - } - } - } - return buf.toString(); - } - - public static String trim(String str) { - return str == null ? null : str.trim(); - } - - public static String toURLKey(String key) { - return key.toLowerCase().replaceAll(SEPARATOR_REGEX, HIDE_KEY_PREFIX); - } - - public static String toOSStyleKey(String key) { - key = key.toUpperCase().replaceAll(DOT_REGEX, UNDERLINE_SEPARATOR); - if (!key.startsWith("DUBBO_")) { - key = "DUBBO_" + key; - } - return key; - } - - public static boolean isAllUpperCase(String str) { - if (str != null && !isEmpty(str)) { - int sz = str.length(); - - for (int i = 0; i < sz; ++i) { - if (!Character.isUpperCase(str.charAt(i))) { - return false; - } - } - - return true; - } else { - return false; - } - } - - public static String[] delimitedListToStringArray(String str, String delimiter) { - return delimitedListToStringArray(str, delimiter, (String) null); - } - - public static String[] delimitedListToStringArray(String str, String delimiter, String charsToDelete) { - if (str == null) { - return new String[0]; - } else if (delimiter == null) { - return new String[]{str}; - } else { - List result = new ArrayList(); - int pos; - if ("".equals(delimiter)) { - for (pos = 0; pos < str.length(); ++pos) { - result.add(deleteAny(str.substring(pos, pos + 1), charsToDelete)); - } - } else { - int delPos; - for (pos = 0; (delPos = str.indexOf(delimiter, pos)) != -1; pos = delPos + delimiter.length()) { - result.add(deleteAny(str.substring(pos, delPos), charsToDelete)); - } - - if (str.length() > 0 && pos <= str.length()) { - result.add(deleteAny(str.substring(pos), charsToDelete)); - } - } - - return toStringArray((Collection) result); - } - } - - public static String arrayToDelimitedString(Object[] arr, String delim) { - if (ArrayUtils.isEmpty(arr)) { - return ""; - } else if (arr.length == 1) { - return nullSafeToString(arr[0]); - } else { - StringBuilder sb = new StringBuilder(); - - for (int i = 0; i < arr.length; ++i) { - if (i > 0) { - sb.append(delim); - } - - sb.append(arr[i]); - } - - return sb.toString(); - } - } - - public static String deleteAny(String inString, String charsToDelete) { - if (isNotEmpty(inString) && isNotEmpty(charsToDelete)) { - StringBuilder sb = new StringBuilder(inString.length()); - - for (int i = 0; i < inString.length(); ++i) { - char c = inString.charAt(i); - if (charsToDelete.indexOf(c) == -1) { - sb.append(c); - } - } - - return sb.toString(); - } else { - return inString; - } - } - - public static String[] toStringArray(Collection collection) { - return (String[]) collection.toArray(new String[0]); - } - - public static String nullSafeToString(Object obj) { - if (obj == null) { - return "null"; - } else if (obj instanceof String) { - return (String) obj; - } else { - String str = obj.toString(); - return str != null ? str : ""; - } - } - - /** - * Decode parameters string to map - * @param rawParameters format like '[{a:b},{c:d}]' - * @return - */ - public static Map parseParameters(String rawParameters) { - if (StringUtils.isBlank(rawParameters)) { - return Collections.emptyMap(); - } - Matcher matcher = PARAMETERS_PATTERN.matcher(rawParameters); - if (!matcher.matches()) { - return Collections.emptyMap(); - } - - String pairs = matcher.group(1); - String[] pairArr = pairs.split("\\s*,\\s*"); - - Map parameters = new HashMap<>(); - for (String pair : pairArr) { - Matcher pairMatcher = PAIR_PARAMETERS_PATTERN.matcher(pair); - if (pairMatcher.matches()) { - parameters.put(pairMatcher.group(1), pairMatcher.group(2)); - } - } - return parameters; - } - - /** - * Encode parameters map to string, like '[{a:b},{c:d}]' - * @param params - * @return - */ - public static String encodeParameters(Map params) { - if (params == null || params.isEmpty()) { - return null; - } - - StringBuilder sb = new StringBuilder(); - sb.append("["); - params.forEach((key,value) -> { - // {key:value}, - if (hasText(value)) { - sb.append("{").append(key).append(":").append(value).append("},"); - } - }); - // delete last separator ',' - if (sb.charAt(sb.length() - 1) == ',') { - sb.deleteCharAt(sb.length()-1); - } - sb.append("]"); - return sb.toString(); - } - - public static int decodeHexNibble(final char c) { - // Character.digit() is not used here, as it addresses a larger - // set of characters (both ASCII and full-width latin letters). - byte[] hex2b = HEX2B; - return c < hex2b.length ? hex2b[c] : -1; - } - - /** - * Decode a 2-digit hex byte from within a string. - */ - public static byte decodeHexByte(CharSequence s, int pos) { - int hi = decodeHexNibble(s.charAt(pos)); - int lo = decodeHexNibble(s.charAt(pos + 1)); - if (hi == -1 || lo == -1) { - throw new IllegalArgumentException(String.format( - "invalid hex byte '%s' at index %d of '%s'", s.subSequence(pos, pos + 2), pos, s)); - } - return (byte) ((hi << 4) + lo); - } - - /** - * Create the common-delimited {@link String} by one or more {@link String} members - * - * @param one one {@link String} - * @param others others {@link String} - * @return null if one or others is null - * @since 2.7.8 - */ - public static String toCommaDelimitedString(String one, String... others) { - String another = arrayToDelimitedString(others, COMMA_SEPARATOR); - return isEmpty(another) ? one : one + COMMA_SEPARATOR + another; - } - - /** - * Test str whether starts with the prefix ignore case. - * @param str - * @param prefix - * @return - */ - public static boolean startsWithIgnoreCase(String str, String prefix) { - if (str == null || prefix == null || str.length() < prefix.length()) { - return false; - } - // return str.substring(0, prefix.length()).equalsIgnoreCase(prefix); - return str.regionMatches(true, 0, prefix, 0, prefix.length()); - } -} +/* + * 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.common.utils; + +import org.apache.dubbo.common.io.UnsafeStringWriter; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; + +import com.alibaba.fastjson.JSON; + +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static java.lang.String.valueOf; +import static java.util.Collections.emptySet; +import static java.util.Collections.unmodifiableSet; +import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SEPARATOR; +import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN; +import static org.apache.dubbo.common.constants.CommonConstants.DOT_REGEX; +import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.HIDE_KEY_PREFIX; +import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.SEPARATOR_REGEX; +import static org.apache.dubbo.common.constants.CommonConstants.UNDERLINE_SEPARATOR; +import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY; + +/** + * StringUtils + */ + +public final class StringUtils { + + public static final String EMPTY_STRING = ""; + public static final int INDEX_NOT_FOUND = -1; + public static final String[] EMPTY_STRING_ARRAY = new String[0]; + + private static final Logger logger = LoggerFactory.getLogger(StringUtils.class); + private static final Pattern KVP_PATTERN = Pattern.compile("([_.a-zA-Z0-9][-_.a-zA-Z0-9]*)[=](.*)"); //key value pair pattern. + private static final Pattern INT_PATTERN = Pattern.compile("^\\d+$"); + private static final Pattern PARAMETERS_PATTERN = Pattern.compile("^\\[((\\s*\\{\\s*[\\w_\\-\\.]+\\s*:\\s*.+?\\s*\\}\\s*,?\\s*)+)\\s*\\]$"); + private static final Pattern PAIR_PARAMETERS_PATTERN = Pattern.compile("^\\{\\s*([\\w-_\\.]+)\\s*:\\s*(.+)\\s*\\}$"); + private static final int PAD_LIMIT = 8192; + private static final byte[] HEX2B; + + + /** + * @since 2.7.5 + */ + public static final char EQUAL_CHAR = '='; + + public static final String EQUAL = valueOf(EQUAL_CHAR); + + public static final char AND_CHAR = '&'; + + public static final String AND = valueOf(AND_CHAR); + + public static final char SEMICOLON_CHAR = ';'; + + public static final String SEMICOLON = valueOf(SEMICOLON_CHAR); + + public static final char QUESTION_MASK_CHAR = '?'; + + public static final String QUESTION_MASK = valueOf(QUESTION_MASK_CHAR); + + public static final char SLASH_CHAR = '/'; + + public static final String SLASH = valueOf(SLASH_CHAR); + + public static final char HYPHEN_CHAR = '-'; + + public static final String HYPHEN = valueOf(HYPHEN_CHAR); + + static { + HEX2B = new byte[128]; + Arrays.fill(HEX2B, (byte) -1); + HEX2B['0'] = (byte) 0; + HEX2B['1'] = (byte) 1; + HEX2B['2'] = (byte) 2; + HEX2B['3'] = (byte) 3; + HEX2B['4'] = (byte) 4; + HEX2B['5'] = (byte) 5; + HEX2B['6'] = (byte) 6; + HEX2B['7'] = (byte) 7; + HEX2B['8'] = (byte) 8; + HEX2B['9'] = (byte) 9; + HEX2B['A'] = (byte) 10; + HEX2B['B'] = (byte) 11; + HEX2B['C'] = (byte) 12; + HEX2B['D'] = (byte) 13; + HEX2B['E'] = (byte) 14; + HEX2B['F'] = (byte) 15; + HEX2B['a'] = (byte) 10; + HEX2B['b'] = (byte) 11; + HEX2B['c'] = (byte) 12; + HEX2B['d'] = (byte) 13; + HEX2B['e'] = (byte) 14; + HEX2B['f'] = (byte) 15; + } + + private StringUtils() { + } + + /** + * Gets a CharSequence length or {@code 0} if the CharSequence is + * {@code null}. + * + * @param cs a CharSequence or {@code null} + * @return CharSequence length or {@code 0} if the CharSequence is + * {@code null}. + */ + public static int length(final CharSequence cs) { + return cs == null ? 0 : cs.length(); + } + + /** + *

Repeat a String {@code repeat} times to form a + * new String.

+ * + *
+     * StringUtils.repeat(null, 2) = null
+     * StringUtils.repeat("", 0)   = ""
+     * StringUtils.repeat("", 2)   = ""
+     * StringUtils.repeat("a", 3)  = "aaa"
+     * StringUtils.repeat("ab", 2) = "abab"
+     * StringUtils.repeat("a", -2) = ""
+     * 
+ * + * @param str the String to repeat, may be null + * @param repeat number of times to repeat str, negative treated as zero + * @return a new String consisting of the original String repeated, + * {@code null} if null String input + */ + public static String repeat(final String str, final int repeat) { + // Performance tuned for 2.0 (JDK1.4) + + if (str == null) { + return null; + } + if (repeat <= 0) { + return EMPTY_STRING; + } + final int inputLength = str.length(); + if (repeat == 1 || inputLength == 0) { + return str; + } + if (inputLength == 1 && repeat <= PAD_LIMIT) { + return repeat(str.charAt(0), repeat); + } + + final int outputLength = inputLength * repeat; + switch (inputLength) { + case 1: + return repeat(str.charAt(0), repeat); + case 2: + final char ch0 = str.charAt(0); + final char ch1 = str.charAt(1); + final char[] output2 = new char[outputLength]; + for (int i = repeat * 2 - 2; i >= 0; i--, i--) { + output2[i] = ch0; + output2[i + 1] = ch1; + } + return new String(output2); + default: + final StringBuilder buf = new StringBuilder(outputLength); + for (int i = 0; i < repeat; i++) { + buf.append(str); + } + return buf.toString(); + } + } + + /** + *

Repeat a String {@code repeat} times to form a + * new String, with a String separator injected each time.

+ * + *
+     * StringUtils.repeat(null, null, 2) = null
+     * StringUtils.repeat(null, "x", 2)  = null
+     * StringUtils.repeat("", null, 0)   = ""
+     * StringUtils.repeat("", "", 2)     = ""
+     * StringUtils.repeat("", "x", 3)    = "xxx"
+     * StringUtils.repeat("?", ", ", 3)  = "?, ?, ?"
+     * 
+ * + * @param str the String to repeat, may be null + * @param separator the String to inject, may be null + * @param repeat number of times to repeat str, negative treated as zero + * @return a new String consisting of the original String repeated, + * {@code null} if null String input + * @since 2.5 + */ + public static String repeat(final String str, final String separator, final int repeat) { + if (str == null || separator == null) { + return repeat(str, repeat); + } + // given that repeat(String, int) is quite optimized, better to rely on it than try and splice this into it + final String result = repeat(str + separator, repeat); + return removeEnd(result, separator); + } + + /** + *

Removes a substring only if it is at the end of a source string, + * otherwise returns the source string.

+ * + *

A {@code null} source string will return {@code null}. + * An empty ("") source string will return the empty string. + * A {@code null} search string will return the source string.

+ * + *
+     * StringUtils.removeEnd(null, *)      = null
+     * StringUtils.removeEnd("", *)        = ""
+     * StringUtils.removeEnd(*, null)      = *
+     * StringUtils.removeEnd("www.domain.com", ".com.")  = "www.domain.com"
+     * StringUtils.removeEnd("www.domain.com", ".com")   = "www.domain"
+     * StringUtils.removeEnd("www.domain.com", "domain") = "www.domain.com"
+     * StringUtils.removeEnd("abc", "")    = "abc"
+     * 
+ * + * @param str the source String to search, may be null + * @param remove the String to search for and remove, may be null + * @return the substring with the string removed if found, + * {@code null} if null String input + */ + public static String removeEnd(final String str, final String remove) { + if (isAnyEmpty(str, remove)) { + return str; + } + if (str.endsWith(remove)) { + return str.substring(0, str.length() - remove.length()); + } + return str; + } + + /** + *

Returns padding using the specified delimiter repeated + * to a given length.

+ * + *
+     * StringUtils.repeat('e', 0)  = ""
+     * StringUtils.repeat('e', 3)  = "eee"
+     * StringUtils.repeat('e', -2) = ""
+     * 
+ * + *

Note: this method doesn't not support padding with + * Unicode Supplementary Characters + * as they require a pair of {@code char}s to be represented. + * If you are needing to support full I18N of your applications + * consider using {@link #repeat(String, int)} instead. + *

+ * + * @param ch character to repeat + * @param repeat number of times to repeat char, negative treated as zero + * @return String with repeated character + * @see #repeat(String, int) + */ + public static String repeat(final char ch, final int repeat) { + final char[] buf = new char[repeat]; + for (int i = repeat - 1; i >= 0; i--) { + buf[i] = ch; + } + return new String(buf); + } + + /** + *

Strips any of a set of characters from the end of a String.

+ * + *

A {@code null} input String returns {@code null}. + * An empty string ("") input returns the empty string.

+ * + *

If the stripChars String is {@code null}, whitespace is + * stripped as defined by {@link Character#isWhitespace(char)}.

+ * + *
+     * StringUtils.stripEnd(null, *)          = null
+     * StringUtils.stripEnd("", *)            = ""
+     * StringUtils.stripEnd("abc", "")        = "abc"
+     * StringUtils.stripEnd("abc", null)      = "abc"
+     * StringUtils.stripEnd("  abc", null)    = "  abc"
+     * StringUtils.stripEnd("abc  ", null)    = "abc"
+     * StringUtils.stripEnd(" abc ", null)    = " abc"
+     * StringUtils.stripEnd("  abcyx", "xyz") = "  abc"
+     * StringUtils.stripEnd("120.00", ".0")   = "12"
+     * 
+ * + * @param str the String to remove characters from, may be null + * @param stripChars the set of characters to remove, null treated as whitespace + * @return the stripped String, {@code null} if null String input + */ + public static String stripEnd(final String str, final String stripChars) { + int end; + if (str == null || (end = str.length()) == 0) { + return str; + } + + if (stripChars == null) { + while (end != 0 && Character.isWhitespace(str.charAt(end - 1))) { + end--; + } + } else if (stripChars.isEmpty()) { + return str; + } else { + while (end != 0 && stripChars.indexOf(str.charAt(end - 1)) != INDEX_NOT_FOUND) { + end--; + } + } + return str.substring(0, end); + } + + /** + *

Replaces all occurrences of a String within another String.

+ * + *

A {@code null} reference passed to this method is a no-op.

+ * + *
+     * StringUtils.replace(null, *, *)        = null
+     * StringUtils.replace("", *, *)          = ""
+     * StringUtils.replace("any", null, *)    = "any"
+     * StringUtils.replace("any", *, null)    = "any"
+     * StringUtils.replace("any", "", *)      = "any"
+     * StringUtils.replace("aba", "a", null)  = "aba"
+     * StringUtils.replace("aba", "a", "")    = "b"
+     * StringUtils.replace("aba", "a", "z")   = "zbz"
+     * 
+ * + * @param text text to search and replace in, may be null + * @param searchString the String to search for, may be null + * @param replacement the String to replace it with, may be null + * @return the text with any replacements processed, + * {@code null} if null String input + * @see #replace(String text, String searchString, String replacement, int max) + */ + public static String replace(final String text, final String searchString, final String replacement) { + return replace(text, searchString, replacement, -1); + } + + /** + *

Replaces a String with another String inside a larger String, + * for the first {@code max} values of the search String.

+ * + *

A {@code null} reference passed to this method is a no-op.

+ * + *
+     * StringUtils.replace(null, *, *, *)         = null
+     * StringUtils.replace("", *, *, *)           = ""
+     * StringUtils.replace("any", null, *, *)     = "any"
+     * StringUtils.replace("any", *, null, *)     = "any"
+     * StringUtils.replace("any", "", *, *)       = "any"
+     * StringUtils.replace("any", *, *, 0)        = "any"
+     * StringUtils.replace("abaa", "a", null, -1) = "abaa"
+     * StringUtils.replace("abaa", "a", "", -1)   = "b"
+     * StringUtils.replace("abaa", "a", "z", 0)   = "abaa"
+     * StringUtils.replace("abaa", "a", "z", 1)   = "zbaa"
+     * StringUtils.replace("abaa", "a", "z", 2)   = "zbza"
+     * StringUtils.replace("abaa", "a", "z", -1)  = "zbzz"
+     * 
+ * + * @param text text to search and replace in, may be null + * @param searchString the String to search for, may be null + * @param replacement the String to replace it with, may be null + * @param max maximum number of values to replace, or {@code -1} if no maximum + * @return the text with any replacements processed, + * {@code null} if null String input + */ + public static String replace(final String text, final String searchString, final String replacement, int max) { + if (isAnyEmpty(text, searchString) || replacement == null || max == 0) { + return text; + } + int start = 0; + int end = text.indexOf(searchString, start); + if (end == INDEX_NOT_FOUND) { + return text; + } + final int replLength = searchString.length(); + int increase = replacement.length() - replLength; + increase = increase < 0 ? 0 : increase; + increase *= max < 0 ? 16 : max > 64 ? 64 : max; + final StringBuilder buf = new StringBuilder(text.length() + increase); + while (end != INDEX_NOT_FOUND) { + buf.append(text, start, end).append(replacement); + start = end + replLength; + if (--max == 0) { + break; + } + end = text.indexOf(searchString, start); + } + buf.append(text.substring(start)); + return buf.toString(); + } + + public static boolean isBlank(CharSequence cs) { + int strLen; + if (cs == null || (strLen = cs.length()) == 0) { + return true; + } + for (int i = 0; i < strLen; i++) { + if (!Character.isWhitespace(cs.charAt(i))) { + return false; + } + } + return true; + } + + /** + * Check the cs String whether contains non whitespace characters. + * @param cs + * @return + */ + public static boolean hasText(CharSequence cs) { + return !isBlank(cs); + } + + /** + * is empty string. + * + * @param str source string. + * @return is empty. + */ + public static boolean isEmpty(String str) { + return str == null || str.isEmpty(); + } + + /** + *

Checks if the strings contain empty or null elements.

+ * + *

+     * StringUtils.isNoneEmpty(null)            = false
+     * StringUtils.isNoneEmpty("")              = false
+     * StringUtils.isNoneEmpty(" ")             = true
+     * StringUtils.isNoneEmpty("abc")           = true
+     * StringUtils.isNoneEmpty("abc", "def")    = true
+     * StringUtils.isNoneEmpty("abc", null)     = false
+     * StringUtils.isNoneEmpty("abc", "")       = false
+     * StringUtils.isNoneEmpty("abc", " ")      = true
+     * 
+ * + * @param ss the strings to check + * @return {@code true} if all strings are not empty or null + */ + public static boolean isNoneEmpty(final String... ss) { + if (ArrayUtils.isEmpty(ss)) { + return false; + } + for (final String s : ss) { + if (isEmpty(s)) { + return false; + } + } + return true; + } + + /** + *

Checks if the strings contain at least on empty or null element.

+ * + *

+     * StringUtils.isAnyEmpty(null)            = true
+     * StringUtils.isAnyEmpty("")              = true
+     * StringUtils.isAnyEmpty(" ")             = false
+     * StringUtils.isAnyEmpty("abc")           = false
+     * StringUtils.isAnyEmpty("abc", "def")    = false
+     * StringUtils.isAnyEmpty("abc", null)     = true
+     * StringUtils.isAnyEmpty("abc", "")       = true
+     * StringUtils.isAnyEmpty("abc", " ")      = false
+     * 
+ * + * @param ss the strings to check + * @return {@code true} if at least one in the strings is empty or null + */ + public static boolean isAnyEmpty(final String... ss) { + return !isNoneEmpty(ss); + } + + /** + * is not empty string. + * + * @param str source string. + * @return is not empty. + */ + public static boolean isNotEmpty(String str) { + return !isEmpty(str); + } + + /** + * @param s1 + * @param s2 + * @return equals + */ + public static boolean isEquals(String s1, String s2) { + if (s1 == null && s2 == null) { + return true; + } + if (s1 == null || s2 == null) { + return false; + } + return s1.equals(s2); + } + + /** + * is integer string. + * + * @param str + * @return is integer + */ + public static boolean isInteger(String str) { + return isNotEmpty(str) && INT_PATTERN.matcher(str).matches(); + } + + public static int parseInteger(String str) { + return isInteger(str) ? Integer.parseInt(str) : 0; + } + + /** + * Returns true if s is a legal Java identifier.

+ * more info. + */ + public static boolean isJavaIdentifier(String s) { + if (isEmpty(s) || !Character.isJavaIdentifierStart(s.charAt(0))) { + return false; + } + for (int i = 1; i < s.length(); i++) { + if (!Character.isJavaIdentifierPart(s.charAt(i))) { + return false; + } + } + return true; + } + + public static boolean isContains(String values, String value) { + return isNotEmpty(values) && isContains(COMMA_SPLIT_PATTERN.split(values), value); + } + + public static boolean isContains(String str, char ch) { + return isNotEmpty(str) && str.indexOf(ch) >= 0; + } + + public static boolean isNotContains(String str, char ch) { + return !isContains(str, ch); + } + + /** + * @param values + * @param value + * @return contains + */ + public static boolean isContains(String[] values, String value) { + if (isNotEmpty(value) && ArrayUtils.isNotEmpty(values)) { + for (String v : values) { + if (value.equals(v)) { + return true; + } + } + } + return false; + } + + public static boolean isNumeric(String str, boolean allowDot) { + if (str == null || str.isEmpty()) { + return false; + } + boolean hasDot = false; + int sz = str.length(); + for (int i = 0; i < sz; i++) { + if (str.charAt(i) == '.') { + if (hasDot || !allowDot) { + return false; + } + hasDot = true; + continue; + } + if (!Character.isDigit(str.charAt(i))) { + return false; + } + } + return true; + } + + + /** + * @param e + * @return string + */ + public static String toString(Throwable e) { + UnsafeStringWriter w = new UnsafeStringWriter(); + PrintWriter p = new PrintWriter(w); + p.print(e.getClass().getName()); + if (e.getMessage() != null) { + p.print(": " + e.getMessage()); + } + p.println(); + try { + e.printStackTrace(p); + return w.toString(); + } finally { + p.close(); + } + } + + /** + * @param msg + * @param e + * @return string + */ + public static String toString(String msg, Throwable e) { + UnsafeStringWriter w = new UnsafeStringWriter(); + w.write(msg + "\n"); + PrintWriter p = new PrintWriter(w); + try { + e.printStackTrace(p); + return w.toString(); + } finally { + p.close(); + } + } + + /** + * translate. + * + * @param src source string. + * @param from src char table. + * @param to target char table. + * @return String. + */ + public static String translate(String src, String from, String to) { + if (isEmpty(src)) { + return src; + } + StringBuilder sb = null; + int ix; + char c; + for (int i = 0, len = src.length(); i < len; i++) { + c = src.charAt(i); + ix = from.indexOf(c); + if (ix == -1) { + if (sb != null) { + sb.append(c); + } + } else { + if (sb == null) { + sb = new StringBuilder(len); + sb.append(src, 0, i); + } + if (ix < to.length()) { + sb.append(to.charAt(ix)); + } + } + } + return sb == null ? src : sb.toString(); + } + + /** + * split. + * + * @param ch char. + * @return string array. + */ + public static String[] split(String str, char ch) { + if (isEmpty(str)) { + return EMPTY_STRING_ARRAY; + } + return splitToList0(str, ch).toArray(EMPTY_STRING_ARRAY); + } + + private static List splitToList0(String str, char ch) { + List result = new ArrayList<>(); + int ix = 0, len = str.length(); + for (int i = 0; i < len; i++) { + if (str.charAt(i) == ch) { + result.add(str.substring(ix, i)); + ix = i + 1; + } + } + + if (ix >= 0) { + result.add(str.substring(ix)); + } + return result; + } + + /** + * Splits String around matches of the given character. + *

+ * Note: Compare with {@link StringUtils#split(String, char)}, this method reduce memory copy. + */ + public static List splitToList(String str, char ch) { + if (isEmpty(str)) { + return Collections.emptyList(); + } + return splitToList0(str, ch); + } + + /** + * Split the specified value to be a {@link Set} + * + * @param value the content to be split + * @param separatorChar a char to separate + * @return non-null read-only {@link Set} + * @since 2.7.8 + */ + public static Set splitToSet(String value, char separatorChar) { + return splitToSet(value, separatorChar, false); + } + + /** + * Split the specified value to be a {@link Set} + * + * @param value the content to be split + * @param separatorChar a char to separate + * @param trimElements require to trim the elements or not + * @return non-null read-only {@link Set} + * @since 2.7.8 + */ + public static Set splitToSet(String value, char separatorChar, boolean trimElements) { + List values = splitToList(value, separatorChar); + int size = values.size(); + + if (size < 1) { // empty condition + return emptySet(); + } + + if (!trimElements) { // Do not require to trim the elements + return new LinkedHashSet(values); + } + + return unmodifiableSet(values + .stream() + .map(String::trim) + .collect(LinkedHashSet::new, Set::add, Set::addAll)); + } + + /** + * join string. + * + * @param array String array. + * @return String. + */ + public static String join(String[] array) { + if (ArrayUtils.isEmpty(array)) { + return EMPTY_STRING; + } + StringBuilder sb = new StringBuilder(); + for (String s : array) { + sb.append(s); + } + return sb.toString(); + } + + /** + * join string like javascript. + * + * @param array String array. + * @param split split + * @return String. + */ + public static String join(String[] array, char split) { + if (ArrayUtils.isEmpty(array)) { + return EMPTY_STRING; + } + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < array.length; i++) { + if (i > 0) { + sb.append(split); + } + sb.append(array[i]); + } + return sb.toString(); + } + + /** + * join string like javascript. + * + * @param array String array. + * @param split split + * @return String. + */ + public static String join(String[] array, String split) { + if (ArrayUtils.isEmpty(array)) { + return EMPTY_STRING; + } + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < array.length; i++) { + if (i > 0) { + sb.append(split); + } + sb.append(array[i]); + } + return sb.toString(); + } + + public static String join(Collection coll, String split) { + if (CollectionUtils.isEmpty(coll)) { + return EMPTY_STRING; + } + + StringBuilder sb = new StringBuilder(); + boolean isFirst = true; + for (String s : coll) { + if (isFirst) { + isFirst = false; + } else { + sb.append(split); + } + sb.append(s); + } + return sb.toString(); + } + + /** + * parse key-value pair. + * + * @param str string. + * @param itemSeparator item separator. + * @return key-value map; + */ + private static Map parseKeyValuePair(String str, String itemSeparator) { + String[] tmp = str.split(itemSeparator); + Map map = new HashMap(tmp.length); + for (int i = 0; i < tmp.length; i++) { + Matcher matcher = KVP_PATTERN.matcher(tmp[i]); + if (!matcher.matches()) { + continue; + } + map.put(matcher.group(1), matcher.group(2)); + } + return map; + } + + public static String getQueryStringValue(String qs, String key) { + Map map = parseQueryString(qs); + return map.get(key); + } + + /** + * parse query string to Parameters. + * + * @param qs query string. + * @return Parameters instance. + */ + public static Map parseQueryString(String qs) { + if (isEmpty(qs)) { + return new HashMap(); + } + return parseKeyValuePair(qs, "\\&"); + } + + public static String getServiceKey(Map ps) { + StringBuilder buf = new StringBuilder(); + String group = ps.get(GROUP_KEY); + if (isNotEmpty(group)) { + buf.append(group).append("/"); + } + buf.append(ps.get(INTERFACE_KEY)); + String version = ps.get(VERSION_KEY); + if (isNotEmpty(group)) { + buf.append(":").append(version); + } + return buf.toString(); + } + + public static String toQueryString(Map ps) { + StringBuilder buf = new StringBuilder(); + if (ps != null && ps.size() > 0) { + for (Map.Entry entry : new TreeMap(ps).entrySet()) { + String key = entry.getKey(); + String value = entry.getValue(); + if (isNoneEmpty(key, value)) { + if (buf.length() > 0) { + buf.append("&"); + } + buf.append(key); + buf.append("="); + buf.append(value); + } + } + } + return buf.toString(); + } + + public static String camelToSplitName(String camelName, String split) { + if (isEmpty(camelName)) { + return camelName; + } + if (!isWord(camelName)) { + // convert Ab-Cd-Ef to ab-cd-ef + if (isSplitCase(camelName, split.charAt(0))) { + return camelName.toLowerCase(); + } + // not camel case + return camelName; + } + + StringBuilder buf = null; + for (int i = 0; i < camelName.length(); i++) { + char ch = camelName.charAt(i); + if (ch >= 'A' && ch <= 'Z') { + if (buf == null) { + buf = new StringBuilder(); + if (i > 0) { + buf.append(camelName, 0, i); + } + } + if (i > 0) { + buf.append(split); + } + buf.append(Character.toLowerCase(ch)); + } else if (buf != null) { + buf.append(ch); + } + } + return buf == null ? camelName.toLowerCase() : buf.toString().toLowerCase(); + } + + private static boolean isSplitCase(String str, char separator) { + if (str == null) { + return false; + } + return str.chars().allMatch(ch -> (ch == separator) || isWord((char)ch) ); + } + + private static boolean isWord(String str) { + if (str == null) { + return false; + } + return str.chars().allMatch(ch -> isWord((char)ch)); + } + + private static boolean isWord(char ch) { + if ((ch >= 'A' && ch <= 'Z') || + (ch >= 'a' && ch <= 'z') || + (ch >= '0' && ch <= '9')) { + return true; + } + return false; + } + + /** + * Convert snake_case or SNAKE_CASE to kebab-case. + *

+ * NOTE: Return itself if it's not a snake case. + * @param snakeName + * @param split + * @return + */ + public static String snakeToSplitName(String snakeName, String split) { + String lowerCase = snakeName.toLowerCase(); + if (isSnakeCase(snakeName)) { + return replace(lowerCase, "_", split); + } + return snakeName; + } + + protected static boolean isSnakeCase(String str) { + return str.contains("_") || str.equals(str.toLowerCase()) || str.equals(str.toUpperCase()); + } + + /** + * Convert camelCase or snake_case/SNAKE_CASE to kebab-case + * @param str + * @param split + * @return + */ + public static String convertToSplitName(String str, String split) { + if (isSnakeCase(str)) { + return snakeToSplitName(str, split); + } else { + return camelToSplitName(str, split); + } + } + + public static String toArgumentString(Object[] args) { + StringBuilder buf = new StringBuilder(); + for (Object arg : args) { + if (buf.length() > 0) { + buf.append(COMMA_SEPARATOR); + } + if (arg == null || ReflectUtils.isPrimitives(arg.getClass())) { + buf.append(arg); + } else { + try { + buf.append(JSON.toJSONString(arg)); + } catch (Exception e) { + logger.warn(e.getMessage(), e); + buf.append(arg); + } + } + } + return buf.toString(); + } + + public static String trim(String str) { + return str == null ? null : str.trim(); + } + + public static String toURLKey(String key) { + return key.toLowerCase().replaceAll(SEPARATOR_REGEX, HIDE_KEY_PREFIX); + } + + public static String toOSStyleKey(String key) { + key = key.toUpperCase().replaceAll(DOT_REGEX, UNDERLINE_SEPARATOR); + if (!key.startsWith("DUBBO_")) { + key = "DUBBO_" + key; + } + return key; + } + + public static boolean isAllUpperCase(String str) { + if (str != null && !isEmpty(str)) { + int sz = str.length(); + + for (int i = 0; i < sz; ++i) { + if (!Character.isUpperCase(str.charAt(i))) { + return false; + } + } + + return true; + } else { + return false; + } + } + + public static String[] delimitedListToStringArray(String str, String delimiter) { + return delimitedListToStringArray(str, delimiter, (String) null); + } + + public static String[] delimitedListToStringArray(String str, String delimiter, String charsToDelete) { + if (str == null) { + return new String[0]; + } else if (delimiter == null) { + return new String[]{str}; + } else { + List result = new ArrayList(); + int pos; + if ("".equals(delimiter)) { + for (pos = 0; pos < str.length(); ++pos) { + result.add(deleteAny(str.substring(pos, pos + 1), charsToDelete)); + } + } else { + int delPos; + for (pos = 0; (delPos = str.indexOf(delimiter, pos)) != -1; pos = delPos + delimiter.length()) { + result.add(deleteAny(str.substring(pos, delPos), charsToDelete)); + } + + if (str.length() > 0 && pos <= str.length()) { + result.add(deleteAny(str.substring(pos), charsToDelete)); + } + } + + return toStringArray((Collection) result); + } + } + + public static String arrayToDelimitedString(Object[] arr, String delim) { + if (ArrayUtils.isEmpty(arr)) { + return ""; + } else if (arr.length == 1) { + return nullSafeToString(arr[0]); + } else { + StringBuilder sb = new StringBuilder(); + + for (int i = 0; i < arr.length; ++i) { + if (i > 0) { + sb.append(delim); + } + + sb.append(arr[i]); + } + + return sb.toString(); + } + } + + public static String deleteAny(String inString, String charsToDelete) { + if (isNotEmpty(inString) && isNotEmpty(charsToDelete)) { + StringBuilder sb = new StringBuilder(inString.length()); + + for (int i = 0; i < inString.length(); ++i) { + char c = inString.charAt(i); + if (charsToDelete.indexOf(c) == -1) { + sb.append(c); + } + } + + return sb.toString(); + } else { + return inString; + } + } + + public static String[] toStringArray(Collection collection) { + return (String[]) collection.toArray(new String[0]); + } + + public static String nullSafeToString(Object obj) { + if (obj == null) { + return "null"; + } else if (obj instanceof String) { + return (String) obj; + } else { + String str = obj.toString(); + return str != null ? str : ""; + } + } + + /** + * Decode parameters string to map + * @param rawParameters format like '[{a:b},{c:d}]' + * @return + */ + public static Map parseParameters(String rawParameters) { + if (StringUtils.isBlank(rawParameters)) { + return Collections.emptyMap(); + } + Matcher matcher = PARAMETERS_PATTERN.matcher(rawParameters); + if (!matcher.matches()) { + return Collections.emptyMap(); + } + + String pairs = matcher.group(1); + String[] pairArr = pairs.split("\\s*,\\s*"); + + Map parameters = new HashMap<>(); + for (String pair : pairArr) { + Matcher pairMatcher = PAIR_PARAMETERS_PATTERN.matcher(pair); + if (pairMatcher.matches()) { + parameters.put(pairMatcher.group(1), pairMatcher.group(2)); + } + } + return parameters; + } + + /** + * Encode parameters map to string, like '[{a:b},{c:d}]' + * @param params + * @return + */ + public static String encodeParameters(Map params) { + if (params == null || params.isEmpty()) { + return null; + } + + StringBuilder sb = new StringBuilder(); + sb.append("["); + params.forEach((key,value) -> { + // {key:value}, + if (hasText(value)) { + sb.append("{").append(key).append(":").append(value).append("},"); + } + }); + // delete last separator ',' + if (sb.charAt(sb.length() - 1) == ',') { + sb.deleteCharAt(sb.length()-1); + } + sb.append("]"); + return sb.toString(); + } + + public static int decodeHexNibble(final char c) { + // Character.digit() is not used here, as it addresses a larger + // set of characters (both ASCII and full-width latin letters). + byte[] hex2b = HEX2B; + return c < hex2b.length ? hex2b[c] : -1; + } + + /** + * Decode a 2-digit hex byte from within a string. + */ + public static byte decodeHexByte(CharSequence s, int pos) { + int hi = decodeHexNibble(s.charAt(pos)); + int lo = decodeHexNibble(s.charAt(pos + 1)); + if (hi == -1 || lo == -1) { + throw new IllegalArgumentException(String.format( + "invalid hex byte '%s' at index %d of '%s'", s.subSequence(pos, pos + 2), pos, s)); + } + return (byte) ((hi << 4) + lo); + } + + /** + * Create the common-delimited {@link String} by one or more {@link String} members + * + * @param one one {@link String} + * @param others others {@link String} + * @return null if one or others is null + * @since 2.7.8 + */ + public static String toCommaDelimitedString(String one, String... others) { + String another = arrayToDelimitedString(others, COMMA_SEPARATOR); + return isEmpty(another) ? one : one + COMMA_SEPARATOR + another; + } + + /** + * Test str whether starts with the prefix ignore case. + * @param str + * @param prefix + * @return + */ + public static boolean startsWithIgnoreCase(String str, String prefix) { + if (str == null || prefix == null || str.length() < prefix.length()) { + return false; + } + // return str.substring(0, prefix.length()).equalsIgnoreCase(prefix); + return str.regionMatches(true, 0, prefix, 0, prefix.length()); + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/UrlUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/UrlUtils.java index 3f21374737..e437d9975c 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/UrlUtils.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/UrlUtils.java @@ -1,658 +1,658 @@ -/* - * 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.common.utils; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.URLStrParser; -import org.apache.dubbo.common.constants.RemotingConstants; -import org.apache.dubbo.common.url.component.ServiceConfigURL; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -import static java.util.Collections.emptyMap; -import static org.apache.dubbo.common.constants.CommonConstants.ANY_VALUE; -import static org.apache.dubbo.common.constants.CommonConstants.CLASSIFIER_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN; -import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY_PREFIX; -import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_PROTOCOL; -import static org.apache.dubbo.common.constants.CommonConstants.ENABLED_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.HOST_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.PASSWORD_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.PORT_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.REGISTRY_SPLIT_PATTERN; -import static org.apache.dubbo.common.constants.CommonConstants.REMOVE_VALUE_PREFIX; -import static org.apache.dubbo.common.constants.CommonConstants.USERNAME_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY; -import static org.apache.dubbo.common.constants.RegistryConstants.CATEGORY_KEY; -import static org.apache.dubbo.common.constants.RegistryConstants.CONFIGURATORS_CATEGORY; -import static org.apache.dubbo.common.constants.RegistryConstants.DEFAULT_CATEGORY; -import static org.apache.dubbo.common.constants.RegistryConstants.EMPTY_PROTOCOL; -import static org.apache.dubbo.common.constants.RegistryConstants.OVERRIDE_PROTOCOL; -import static org.apache.dubbo.common.constants.RegistryConstants.PROVIDERS_CATEGORY; -import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_PROTOCOL; -import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_TYPE_KEY; -import static org.apache.dubbo.common.constants.RegistryConstants.ROUTERS_CATEGORY; -import static org.apache.dubbo.common.constants.RegistryConstants.ROUTE_PROTOCOL; -import static org.apache.dubbo.common.constants.RegistryConstants.SERVICE_REGISTRY_PROTOCOL; -import static org.apache.dubbo.common.constants.RegistryConstants.SERVICE_REGISTRY_TYPE; - -public class UrlUtils { - - /** - * in the url string,mark the param begin - */ - private final static String URL_PARAM_STARTING_SYMBOL = "?"; - - public static URL parseURL(String address, Map defaults) { - if (address == null || address.length() == 0) { - return null; - } - String url; - if (address.contains("://") || address.contains(URL_PARAM_STARTING_SYMBOL)) { - url = address; - } else { - String[] addresses = COMMA_SPLIT_PATTERN.split(address); - url = addresses[0]; - if (addresses.length > 1) { - StringBuilder backup = new StringBuilder(); - for (int i = 1; i < addresses.length; i++) { - if (i > 1) { - backup.append(','); - } - backup.append(addresses[i]); - } - url += URL_PARAM_STARTING_SYMBOL + RemotingConstants.BACKUP_KEY + "=" + backup.toString(); - } - } - String defaultProtocol = defaults == null ? null : defaults.get(PROTOCOL_KEY); - if (defaultProtocol == null || defaultProtocol.length() == 0) { - defaultProtocol = DUBBO_PROTOCOL; - } - String defaultUsername = defaults == null ? null : defaults.get(USERNAME_KEY); - String defaultPassword = defaults == null ? null : defaults.get(PASSWORD_KEY); - int defaultPort = StringUtils.parseInteger(defaults == null ? null : defaults.get(PORT_KEY)); - String defaultPath = defaults == null ? null : defaults.get(PATH_KEY); - Map defaultParameters = defaults == null ? null : new HashMap<>(defaults); - if (defaultParameters != null) { - defaultParameters.remove(PROTOCOL_KEY); - defaultParameters.remove(USERNAME_KEY); - defaultParameters.remove(PASSWORD_KEY); - defaultParameters.remove(HOST_KEY); - defaultParameters.remove(PORT_KEY); - defaultParameters.remove(PATH_KEY); - } - URL u = URL.cacheableValueOf(url); - boolean changed = false; - String protocol = u.getProtocol(); - String username = u.getUsername(); - String password = u.getPassword(); - String host = u.getHost(); - int port = u.getPort(); - String path = u.getPath(); - Map parameters = new HashMap<>(u.getParameters()); - if (protocol == null || protocol.length() == 0) { - changed = true; - protocol = defaultProtocol; - } - if ((username == null || username.length() == 0) && defaultUsername != null && defaultUsername.length() > 0) { - changed = true; - username = defaultUsername; - } - if ((password == null || password.length() == 0) && defaultPassword != null && defaultPassword.length() > 0) { - changed = true; - password = defaultPassword; - } - /*if (u.isAnyHost() || u.isLocalHost()) { - changed = true; - host = NetUtils.getLocalHost(); - }*/ - if (port <= 0) { - if (defaultPort > 0) { - changed = true; - port = defaultPort; - } else { - changed = true; - port = 9090; - } - } - if (path == null || path.length() == 0) { - if (defaultPath != null && defaultPath.length() > 0) { - changed = true; - path = defaultPath; - } - } - if (defaultParameters != null && defaultParameters.size() > 0) { - for (Map.Entry entry : defaultParameters.entrySet()) { - String key = entry.getKey(); - String defaultValue = entry.getValue(); - if (defaultValue != null && defaultValue.length() > 0) { - String value = parameters.get(key); - if (StringUtils.isEmpty(value)) { - changed = true; - parameters.put(key, defaultValue); - } - } - } - } - if (changed) { - u = new ServiceConfigURL(protocol, username, password, host, port, path, parameters); - } - return u; - } - - public static List parseURLs(String address, Map defaults) { - if (address == null || address.length() == 0) { - return null; - } - String[] addresses = REGISTRY_SPLIT_PATTERN.split(address); - if (addresses == null || addresses.length == 0) { - return null; //here won't be empty - } - List registries = new ArrayList(); - for (String addr : addresses) { - registries.add(parseURL(addr, defaults)); - } - return registries; - } - - public static Map> convertRegister(Map> register) { - Map> newRegister = new HashMap>(); - for (Map.Entry> entry : register.entrySet()) { - String serviceName = entry.getKey(); - Map serviceUrls = entry.getValue(); - if (StringUtils.isNotContains(serviceName, ':') && StringUtils.isNotContains(serviceName, '/')) { - for (Map.Entry entry2 : serviceUrls.entrySet()) { - String serviceUrl = entry2.getKey(); - String serviceQuery = entry2.getValue(); - Map params = StringUtils.parseQueryString(serviceQuery); - String group = params.get("group"); - String version = params.get("version"); - //params.remove("group"); - //params.remove("version"); - String name = serviceName; - if (group != null && group.length() > 0) { - name = group + "/" + name; - } - if (version != null && version.length() > 0) { - name = name + ":" + version; - } - Map newUrls = newRegister.computeIfAbsent(name, k -> new HashMap<>()); - newUrls.put(serviceUrl, StringUtils.toQueryString(params)); - } - } else { - newRegister.put(serviceName, serviceUrls); - } - } - return newRegister; - } - - public static Map convertSubscribe(Map subscribe) { - Map newSubscribe = new HashMap(); - for (Map.Entry entry : subscribe.entrySet()) { - String serviceName = entry.getKey(); - String serviceQuery = entry.getValue(); - if (StringUtils.isNotContains(serviceName, ':') && StringUtils.isNotContains(serviceName, '/')) { - Map params = StringUtils.parseQueryString(serviceQuery); - String group = params.get("group"); - String version = params.get("version"); - //params.remove("group"); - //params.remove("version"); - String name = serviceName; - if (group != null && group.length() > 0) { - name = group + "/" + name; - } - if (version != null && version.length() > 0) { - name = name + ":" + version; - } - newSubscribe.put(name, StringUtils.toQueryString(params)); - } else { - newSubscribe.put(serviceName, serviceQuery); - } - } - return newSubscribe; - } - - public static Map> revertRegister(Map> register) { - Map> newRegister = new HashMap>(); - for (Map.Entry> entry : register.entrySet()) { - String serviceName = entry.getKey(); - Map serviceUrls = entry.getValue(); - if (StringUtils.isContains(serviceName, ':') && StringUtils.isContains(serviceName, '/')) { - for (Map.Entry entry2 : serviceUrls.entrySet()) { - String serviceUrl = entry2.getKey(); - String serviceQuery = entry2.getValue(); - Map params = StringUtils.parseQueryString(serviceQuery); - String name = serviceName; - int i = name.indexOf('/'); - if (i >= 0) { - params.put("group", name.substring(0, i)); - name = name.substring(i + 1); - } - i = name.lastIndexOf(':'); - if (i >= 0) { - params.put("version", name.substring(i + 1)); - name = name.substring(0, i); - } - Map newUrls = newRegister.computeIfAbsent(name, k -> new HashMap()); - newUrls.put(serviceUrl, StringUtils.toQueryString(params)); - } - } else { - newRegister.put(serviceName, serviceUrls); - } - } - return newRegister; - } - - public static Map revertSubscribe(Map subscribe) { - Map newSubscribe = new HashMap(); - for (Map.Entry entry : subscribe.entrySet()) { - String serviceName = entry.getKey(); - String serviceQuery = entry.getValue(); - if (StringUtils.isContains(serviceName, ':') && StringUtils.isContains(serviceName, '/')) { - Map params = StringUtils.parseQueryString(serviceQuery); - String name = serviceName; - int i = name.indexOf('/'); - if (i >= 0) { - params.put("group", name.substring(0, i)); - name = name.substring(i + 1); - } - i = name.lastIndexOf(':'); - if (i >= 0) { - params.put("version", name.substring(i + 1)); - name = name.substring(0, i); - } - newSubscribe.put(name, StringUtils.toQueryString(params)); - } else { - newSubscribe.put(serviceName, serviceQuery); - } - } - return newSubscribe; - } - - public static Map> revertNotify(Map> notify) { - if (notify != null && notify.size() > 0) { - Map> newNotify = new HashMap>(); - for (Map.Entry> entry : notify.entrySet()) { - String serviceName = entry.getKey(); - Map serviceUrls = entry.getValue(); - if (StringUtils.isNotContains(serviceName, ':') && StringUtils.isNotContains(serviceName, '/')) { - if (serviceUrls != null && serviceUrls.size() > 0) { - for (Map.Entry entry2 : serviceUrls.entrySet()) { - String url = entry2.getKey(); - String query = entry2.getValue(); - Map params = StringUtils.parseQueryString(query); - String group = params.get("group"); - String version = params.get("version"); - // params.remove("group"); - // params.remove("version"); - String name = serviceName; - if (group != null && group.length() > 0) { - name = group + "/" + name; - } - if (version != null && version.length() > 0) { - name = name + ":" + version; - } - Map newUrls = newNotify.computeIfAbsent(name, k -> new HashMap()); - newUrls.put(url, StringUtils.toQueryString(params)); - } - } - } else { - newNotify.put(serviceName, serviceUrls); - } - } - return newNotify; - } - return notify; - } - - //compatible for dubbo-2.0.0 - public static List revertForbid(List forbid, Set subscribed) { - if (CollectionUtils.isNotEmpty(forbid)) { - List newForbid = new ArrayList(); - for (String serviceName : forbid) { - if (StringUtils.isNotContains(serviceName, ':') && StringUtils.isNotContains(serviceName, '/')) { - for (URL url : subscribed) { - if (serviceName.equals(url.getServiceInterface())) { - newForbid.add(url.getServiceKey()); - break; - } - } - } else { - newForbid.add(serviceName); - } - } - return newForbid; - } - return forbid; - } - - public static URL getEmptyUrl(String service, String category) { - String group = null; - String version = null; - int i = service.indexOf('/'); - if (i > 0) { - group = service.substring(0, i); - service = service.substring(i + 1); - } - i = service.lastIndexOf(':'); - if (i > 0) { - version = service.substring(i + 1); - service = service.substring(0, i); - } - return URL.valueOf(EMPTY_PROTOCOL + "://0.0.0.0/" + service + URL_PARAM_STARTING_SYMBOL - + CATEGORY_KEY + "=" + category - + (group == null ? "" : "&" + GROUP_KEY + "=" + group) - + (version == null ? "" : "&" + VERSION_KEY + "=" + version)); - } - - public static boolean isMatchCategory(String category, String categories) { - if (categories == null || categories.length() == 0) { - return DEFAULT_CATEGORY.equals(category); - } else if (categories.contains(ANY_VALUE)) { - return true; - } else if (categories.contains(REMOVE_VALUE_PREFIX)) { - return !categories.contains(REMOVE_VALUE_PREFIX + category); - } else { - return categories.contains(category); - } - } - - public static boolean isMatch(URL consumerUrl, URL providerUrl) { - String consumerInterface = consumerUrl.getServiceInterface(); - String providerInterface = providerUrl.getServiceInterface(); - //FIXME accept providerUrl with '*' as interface name, after carefully thought about all possible scenarios I think it's ok to add this condition. - if (!(ANY_VALUE.equals(consumerInterface) - || ANY_VALUE.equals(providerInterface) - || StringUtils.isEquals(consumerInterface, providerInterface))) { - return false; - } - - if (!isMatchCategory(providerUrl.getCategory(DEFAULT_CATEGORY), - consumerUrl.getCategory(DEFAULT_CATEGORY))) { - return false; - } - if (!providerUrl.getParameter(ENABLED_KEY, true) - && !ANY_VALUE.equals(consumerUrl.getParameter(ENABLED_KEY))) { - return false; - } - - String consumerGroup = consumerUrl.getGroup(); - String consumerVersion = consumerUrl.getVersion(); - String consumerClassifier = consumerUrl.getParameter(CLASSIFIER_KEY, ANY_VALUE); - - String providerGroup = providerUrl.getGroup(); - String providerVersion = providerUrl.getVersion(); - String providerClassifier = providerUrl.getParameter(CLASSIFIER_KEY, ANY_VALUE); - return (ANY_VALUE.equals(consumerGroup) || StringUtils.isEquals(consumerGroup, providerGroup) || StringUtils.isContains(consumerGroup, providerGroup)) - && (ANY_VALUE.equals(consumerVersion) || StringUtils.isEquals(consumerVersion, providerVersion)) - && (consumerClassifier == null || ANY_VALUE.equals(consumerClassifier) || StringUtils.isEquals(consumerClassifier, providerClassifier)); - } - - public static boolean isMatchGlobPattern(String pattern, String value, URL param) { - if (param != null && pattern.startsWith("$")) { - pattern = param.getRawParameter(pattern.substring(1)); - } - return isMatchGlobPattern(pattern, value); - } - - public static boolean isMatchGlobPattern(String pattern, String value) { - if ("*".equals(pattern)) { - return true; - } - if (StringUtils.isEmpty(pattern) && StringUtils.isEmpty(value)) { - return true; - } - if (StringUtils.isEmpty(pattern) || StringUtils.isEmpty(value)) { - return false; - } - - int i = pattern.lastIndexOf('*'); - // doesn't find "*" - if (i == -1) { - return value.equals(pattern); - } - // "*" is at the end - else if (i == pattern.length() - 1) { - return value.startsWith(pattern.substring(0, i)); - } - // "*" is at the beginning - else if (i == 0) { - return value.endsWith(pattern.substring(i + 1)); - } - // "*" is in the middle - else { - String prefix = pattern.substring(0, i); - String suffix = pattern.substring(i + 1); - return value.startsWith(prefix) && value.endsWith(suffix); - } - } - - public static boolean isServiceKeyMatch(URL pattern, URL value) { - return pattern.getParameter(INTERFACE_KEY).equals( - value.getParameter(INTERFACE_KEY)) - && isItemMatch(pattern.getGroup(), - value.getGroup()) - && isItemMatch(pattern.getVersion(), - value.getVersion()); - } - - public static List classifyUrls(List urls, Predicate predicate) { - return urls.stream().filter(predicate).collect(Collectors.toList()); - } - - public static boolean isConfigurator(URL url) { - return OVERRIDE_PROTOCOL.equals(url.getProtocol()) || - CONFIGURATORS_CATEGORY.equals(url.getCategory(DEFAULT_CATEGORY)); - } - - public static boolean isRoute(URL url) { - return ROUTE_PROTOCOL.equals(url.getProtocol()) || - ROUTERS_CATEGORY.equals(url.getCategory(DEFAULT_CATEGORY)); - } - - public static boolean isProvider(URL url) { - return !OVERRIDE_PROTOCOL.equals(url.getProtocol()) && - !ROUTE_PROTOCOL.equals(url.getProtocol()) && - PROVIDERS_CATEGORY.equals(url.getCategory(PROVIDERS_CATEGORY)); - } - - public static boolean isRegistry(URL url) { - return REGISTRY_PROTOCOL.equals(url.getProtocol()) - || SERVICE_REGISTRY_PROTOCOL.equalsIgnoreCase(url.getProtocol()) - || (url.getProtocol() != null && url.getProtocol().endsWith("-registry-protocol")); - } - - /** - * The specified {@link URL} is service discovery registry type or not - * - * @param url the {@link URL} connects to the registry - * @return If it is, return true, or false - * @since 2.7.5 - */ - public static boolean hasServiceDiscoveryRegistryTypeKey(URL url) { - return hasServiceDiscoveryRegistryTypeKey(url == null ? emptyMap() : url.getParameters()); - } - - public static boolean hasServiceDiscoveryRegistryProtocol(URL url) { - return SERVICE_REGISTRY_PROTOCOL.equalsIgnoreCase(url.getProtocol()); - } - - public static boolean isServiceDiscoveryURL(URL url) { - return hasServiceDiscoveryRegistryProtocol(url) || hasServiceDiscoveryRegistryTypeKey(url); - } - - /** - * The specified parameters of {@link URL} is service discovery registry type or not - * - * @param parameters the parameters of {@link URL} that connects to the registry - * @return If it is, return true, or false - * @since 2.7.5 - */ - public static boolean hasServiceDiscoveryRegistryTypeKey(Map parameters) { - if (parameters == null || parameters.isEmpty()) { - return false; - } - return SERVICE_REGISTRY_TYPE.equals(parameters.get(REGISTRY_TYPE_KEY)); - } - - /** - * Check if the given value matches the given pattern. The pattern supports wildcard "*". - * - * @param pattern pattern - * @param value value - * @return true if match otherwise false - */ - static boolean isItemMatch(String pattern, String value) { - if (pattern == null) { - return value == null; - } else { - return "*".equals(pattern) || pattern.equals(value); - } - } - - /** - * @param serviceKey, {group}/{interfaceName}:{version} - * @return [group, interfaceName, version] - */ - public static String[] parseServiceKey(String serviceKey) { - String[] arr = new String[3]; - int i = serviceKey.indexOf('/'); - if (i > 0) { - arr[0] = serviceKey.substring(0, i); - serviceKey = serviceKey.substring(i + 1); - } - - int j = serviceKey.indexOf(':'); - if (j > 0) { - arr[2] = serviceKey.substring(j + 1); - serviceKey = serviceKey.substring(0, j); - } - arr[1] = serviceKey; - return arr; - } - - /** - * NOTICE: This method allocate too much objects, we can use {@link URLStrParser#parseDecodedStr(String)} instead. - *

- * Parse url string - * - * @param url URL string - * @return URL instance - * @see URL - */ - public static URL valueOf(String url) { - if (url == null || (url = url.trim()).length() == 0) { - throw new IllegalArgumentException("url == null"); - } - String protocol = null; - String username = null; - String password = null; - String host = null; - int port = 0; - String path = null; - Map parameters = null; - int i = url.indexOf('?'); // separator between body and parameters - if (i >= 0) { - String[] parts = url.substring(i + 1).split("&"); - parameters = new HashMap<>(); - for (String part : parts) { - part = part.trim(); - if (part.length() > 0) { - int j = part.indexOf('='); - if (j >= 0) { - String key = part.substring(0, j); - String value = part.substring(j + 1); - parameters.put(key, value); - // compatible with lower versions registering "default." keys - if (key.startsWith(DEFAULT_KEY_PREFIX)) { - parameters.putIfAbsent(key.substring(DEFAULT_KEY_PREFIX.length()), value); - } - } else { - parameters.put(part, part); - } - } - } - url = url.substring(0, i); - } - i = url.indexOf("://"); - if (i >= 0) { - if (i == 0) { - throw new IllegalStateException("url missing protocol: \"" + url + "\""); - } - protocol = url.substring(0, i); - url = url.substring(i + 3); - } else { - // case: file:/path/to/file.txt - i = url.indexOf(":/"); - if (i >= 0) { - if (i == 0) { - throw new IllegalStateException("url missing protocol: \"" + url + "\""); - } - protocol = url.substring(0, i); - url = url.substring(i + 1); - } - } - - i = url.indexOf('/'); - if (i >= 0) { - path = url.substring(i + 1); - url = url.substring(0, i); - } - i = url.lastIndexOf('@'); - if (i >= 0) { - username = url.substring(0, i); - int j = username.indexOf(':'); - if (j >= 0) { - password = username.substring(j + 1); - username = username.substring(0, j); - } - url = url.substring(i + 1); - } - i = url.lastIndexOf(':'); - if (i >= 0 && i < url.length() - 1) { - if (url.lastIndexOf('%') > i) { - // ipv6 address with scope id - // e.g. fe80:0:0:0:894:aeec:f37d:23e1%en0 - // see https://howdoesinternetwork.com/2013/ipv6-zone-id - // ignore - } else { - port = Integer.parseInt(url.substring(i + 1)); - url = url.substring(0, i); - } - } - if (url.length() > 0) { - host = url; - } - - return new ServiceConfigURL(protocol, username, password, host, port, path, parameters); - } - - public static boolean isConsumer(URL url) { - return url.getProtocol().equalsIgnoreCase("consumer") || url.getPort() == 0; - } - -} +/* + * 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.common.utils; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.URLStrParser; +import org.apache.dubbo.common.constants.RemotingConstants; +import org.apache.dubbo.common.url.component.ServiceConfigURL; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import static java.util.Collections.emptyMap; +import static org.apache.dubbo.common.constants.CommonConstants.ANY_VALUE; +import static org.apache.dubbo.common.constants.CommonConstants.CLASSIFIER_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN; +import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY_PREFIX; +import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_PROTOCOL; +import static org.apache.dubbo.common.constants.CommonConstants.ENABLED_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.HOST_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.PASSWORD_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.PORT_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.REGISTRY_SPLIT_PATTERN; +import static org.apache.dubbo.common.constants.CommonConstants.REMOVE_VALUE_PREFIX; +import static org.apache.dubbo.common.constants.CommonConstants.USERNAME_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY; +import static org.apache.dubbo.common.constants.RegistryConstants.CATEGORY_KEY; +import static org.apache.dubbo.common.constants.RegistryConstants.CONFIGURATORS_CATEGORY; +import static org.apache.dubbo.common.constants.RegistryConstants.DEFAULT_CATEGORY; +import static org.apache.dubbo.common.constants.RegistryConstants.EMPTY_PROTOCOL; +import static org.apache.dubbo.common.constants.RegistryConstants.OVERRIDE_PROTOCOL; +import static org.apache.dubbo.common.constants.RegistryConstants.PROVIDERS_CATEGORY; +import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_PROTOCOL; +import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_TYPE_KEY; +import static org.apache.dubbo.common.constants.RegistryConstants.ROUTERS_CATEGORY; +import static org.apache.dubbo.common.constants.RegistryConstants.ROUTE_PROTOCOL; +import static org.apache.dubbo.common.constants.RegistryConstants.SERVICE_REGISTRY_PROTOCOL; +import static org.apache.dubbo.common.constants.RegistryConstants.SERVICE_REGISTRY_TYPE; + +public class UrlUtils { + + /** + * in the url string,mark the param begin + */ + private final static String URL_PARAM_STARTING_SYMBOL = "?"; + + public static URL parseURL(String address, Map defaults) { + if (address == null || address.length() == 0) { + return null; + } + String url; + if (address.contains("://") || address.contains(URL_PARAM_STARTING_SYMBOL)) { + url = address; + } else { + String[] addresses = COMMA_SPLIT_PATTERN.split(address); + url = addresses[0]; + if (addresses.length > 1) { + StringBuilder backup = new StringBuilder(); + for (int i = 1; i < addresses.length; i++) { + if (i > 1) { + backup.append(','); + } + backup.append(addresses[i]); + } + url += URL_PARAM_STARTING_SYMBOL + RemotingConstants.BACKUP_KEY + "=" + backup.toString(); + } + } + String defaultProtocol = defaults == null ? null : defaults.get(PROTOCOL_KEY); + if (defaultProtocol == null || defaultProtocol.length() == 0) { + defaultProtocol = DUBBO_PROTOCOL; + } + String defaultUsername = defaults == null ? null : defaults.get(USERNAME_KEY); + String defaultPassword = defaults == null ? null : defaults.get(PASSWORD_KEY); + int defaultPort = StringUtils.parseInteger(defaults == null ? null : defaults.get(PORT_KEY)); + String defaultPath = defaults == null ? null : defaults.get(PATH_KEY); + Map defaultParameters = defaults == null ? null : new HashMap<>(defaults); + if (defaultParameters != null) { + defaultParameters.remove(PROTOCOL_KEY); + defaultParameters.remove(USERNAME_KEY); + defaultParameters.remove(PASSWORD_KEY); + defaultParameters.remove(HOST_KEY); + defaultParameters.remove(PORT_KEY); + defaultParameters.remove(PATH_KEY); + } + URL u = URL.cacheableValueOf(url); + boolean changed = false; + String protocol = u.getProtocol(); + String username = u.getUsername(); + String password = u.getPassword(); + String host = u.getHost(); + int port = u.getPort(); + String path = u.getPath(); + Map parameters = new HashMap<>(u.getParameters()); + if (protocol == null || protocol.length() == 0) { + changed = true; + protocol = defaultProtocol; + } + if ((username == null || username.length() == 0) && defaultUsername != null && defaultUsername.length() > 0) { + changed = true; + username = defaultUsername; + } + if ((password == null || password.length() == 0) && defaultPassword != null && defaultPassword.length() > 0) { + changed = true; + password = defaultPassword; + } + /*if (u.isAnyHost() || u.isLocalHost()) { + changed = true; + host = NetUtils.getLocalHost(); + }*/ + if (port <= 0) { + if (defaultPort > 0) { + changed = true; + port = defaultPort; + } else { + changed = true; + port = 9090; + } + } + if (path == null || path.length() == 0) { + if (defaultPath != null && defaultPath.length() > 0) { + changed = true; + path = defaultPath; + } + } + if (defaultParameters != null && defaultParameters.size() > 0) { + for (Map.Entry entry : defaultParameters.entrySet()) { + String key = entry.getKey(); + String defaultValue = entry.getValue(); + if (defaultValue != null && defaultValue.length() > 0) { + String value = parameters.get(key); + if (StringUtils.isEmpty(value)) { + changed = true; + parameters.put(key, defaultValue); + } + } + } + } + if (changed) { + u = new ServiceConfigURL(protocol, username, password, host, port, path, parameters); + } + return u; + } + + public static List parseURLs(String address, Map defaults) { + if (address == null || address.length() == 0) { + return null; + } + String[] addresses = REGISTRY_SPLIT_PATTERN.split(address); + if (addresses == null || addresses.length == 0) { + return null; //here won't be empty + } + List registries = new ArrayList(); + for (String addr : addresses) { + registries.add(parseURL(addr, defaults)); + } + return registries; + } + + public static Map> convertRegister(Map> register) { + Map> newRegister = new HashMap>(); + for (Map.Entry> entry : register.entrySet()) { + String serviceName = entry.getKey(); + Map serviceUrls = entry.getValue(); + if (StringUtils.isNotContains(serviceName, ':') && StringUtils.isNotContains(serviceName, '/')) { + for (Map.Entry entry2 : serviceUrls.entrySet()) { + String serviceUrl = entry2.getKey(); + String serviceQuery = entry2.getValue(); + Map params = StringUtils.parseQueryString(serviceQuery); + String group = params.get("group"); + String version = params.get("version"); + //params.remove("group"); + //params.remove("version"); + String name = serviceName; + if (group != null && group.length() > 0) { + name = group + "/" + name; + } + if (version != null && version.length() > 0) { + name = name + ":" + version; + } + Map newUrls = newRegister.computeIfAbsent(name, k -> new HashMap<>()); + newUrls.put(serviceUrl, StringUtils.toQueryString(params)); + } + } else { + newRegister.put(serviceName, serviceUrls); + } + } + return newRegister; + } + + public static Map convertSubscribe(Map subscribe) { + Map newSubscribe = new HashMap(); + for (Map.Entry entry : subscribe.entrySet()) { + String serviceName = entry.getKey(); + String serviceQuery = entry.getValue(); + if (StringUtils.isNotContains(serviceName, ':') && StringUtils.isNotContains(serviceName, '/')) { + Map params = StringUtils.parseQueryString(serviceQuery); + String group = params.get("group"); + String version = params.get("version"); + //params.remove("group"); + //params.remove("version"); + String name = serviceName; + if (group != null && group.length() > 0) { + name = group + "/" + name; + } + if (version != null && version.length() > 0) { + name = name + ":" + version; + } + newSubscribe.put(name, StringUtils.toQueryString(params)); + } else { + newSubscribe.put(serviceName, serviceQuery); + } + } + return newSubscribe; + } + + public static Map> revertRegister(Map> register) { + Map> newRegister = new HashMap>(); + for (Map.Entry> entry : register.entrySet()) { + String serviceName = entry.getKey(); + Map serviceUrls = entry.getValue(); + if (StringUtils.isContains(serviceName, ':') && StringUtils.isContains(serviceName, '/')) { + for (Map.Entry entry2 : serviceUrls.entrySet()) { + String serviceUrl = entry2.getKey(); + String serviceQuery = entry2.getValue(); + Map params = StringUtils.parseQueryString(serviceQuery); + String name = serviceName; + int i = name.indexOf('/'); + if (i >= 0) { + params.put("group", name.substring(0, i)); + name = name.substring(i + 1); + } + i = name.lastIndexOf(':'); + if (i >= 0) { + params.put("version", name.substring(i + 1)); + name = name.substring(0, i); + } + Map newUrls = newRegister.computeIfAbsent(name, k -> new HashMap()); + newUrls.put(serviceUrl, StringUtils.toQueryString(params)); + } + } else { + newRegister.put(serviceName, serviceUrls); + } + } + return newRegister; + } + + public static Map revertSubscribe(Map subscribe) { + Map newSubscribe = new HashMap(); + for (Map.Entry entry : subscribe.entrySet()) { + String serviceName = entry.getKey(); + String serviceQuery = entry.getValue(); + if (StringUtils.isContains(serviceName, ':') && StringUtils.isContains(serviceName, '/')) { + Map params = StringUtils.parseQueryString(serviceQuery); + String name = serviceName; + int i = name.indexOf('/'); + if (i >= 0) { + params.put("group", name.substring(0, i)); + name = name.substring(i + 1); + } + i = name.lastIndexOf(':'); + if (i >= 0) { + params.put("version", name.substring(i + 1)); + name = name.substring(0, i); + } + newSubscribe.put(name, StringUtils.toQueryString(params)); + } else { + newSubscribe.put(serviceName, serviceQuery); + } + } + return newSubscribe; + } + + public static Map> revertNotify(Map> notify) { + if (notify != null && notify.size() > 0) { + Map> newNotify = new HashMap>(); + for (Map.Entry> entry : notify.entrySet()) { + String serviceName = entry.getKey(); + Map serviceUrls = entry.getValue(); + if (StringUtils.isNotContains(serviceName, ':') && StringUtils.isNotContains(serviceName, '/')) { + if (serviceUrls != null && serviceUrls.size() > 0) { + for (Map.Entry entry2 : serviceUrls.entrySet()) { + String url = entry2.getKey(); + String query = entry2.getValue(); + Map params = StringUtils.parseQueryString(query); + String group = params.get("group"); + String version = params.get("version"); + // params.remove("group"); + // params.remove("version"); + String name = serviceName; + if (group != null && group.length() > 0) { + name = group + "/" + name; + } + if (version != null && version.length() > 0) { + name = name + ":" + version; + } + Map newUrls = newNotify.computeIfAbsent(name, k -> new HashMap()); + newUrls.put(url, StringUtils.toQueryString(params)); + } + } + } else { + newNotify.put(serviceName, serviceUrls); + } + } + return newNotify; + } + return notify; + } + + //compatible for dubbo-2.0.0 + public static List revertForbid(List forbid, Set subscribed) { + if (CollectionUtils.isNotEmpty(forbid)) { + List newForbid = new ArrayList(); + for (String serviceName : forbid) { + if (StringUtils.isNotContains(serviceName, ':') && StringUtils.isNotContains(serviceName, '/')) { + for (URL url : subscribed) { + if (serviceName.equals(url.getServiceInterface())) { + newForbid.add(url.getServiceKey()); + break; + } + } + } else { + newForbid.add(serviceName); + } + } + return newForbid; + } + return forbid; + } + + public static URL getEmptyUrl(String service, String category) { + String group = null; + String version = null; + int i = service.indexOf('/'); + if (i > 0) { + group = service.substring(0, i); + service = service.substring(i + 1); + } + i = service.lastIndexOf(':'); + if (i > 0) { + version = service.substring(i + 1); + service = service.substring(0, i); + } + return URL.valueOf(EMPTY_PROTOCOL + "://0.0.0.0/" + service + URL_PARAM_STARTING_SYMBOL + + CATEGORY_KEY + "=" + category + + (group == null ? "" : "&" + GROUP_KEY + "=" + group) + + (version == null ? "" : "&" + VERSION_KEY + "=" + version)); + } + + public static boolean isMatchCategory(String category, String categories) { + if (categories == null || categories.length() == 0) { + return DEFAULT_CATEGORY.equals(category); + } else if (categories.contains(ANY_VALUE)) { + return true; + } else if (categories.contains(REMOVE_VALUE_PREFIX)) { + return !categories.contains(REMOVE_VALUE_PREFIX + category); + } else { + return categories.contains(category); + } + } + + public static boolean isMatch(URL consumerUrl, URL providerUrl) { + String consumerInterface = consumerUrl.getServiceInterface(); + String providerInterface = providerUrl.getServiceInterface(); + //FIXME accept providerUrl with '*' as interface name, after carefully thought about all possible scenarios I think it's ok to add this condition. + if (!(ANY_VALUE.equals(consumerInterface) + || ANY_VALUE.equals(providerInterface) + || StringUtils.isEquals(consumerInterface, providerInterface))) { + return false; + } + + if (!isMatchCategory(providerUrl.getCategory(DEFAULT_CATEGORY), + consumerUrl.getCategory(DEFAULT_CATEGORY))) { + return false; + } + if (!providerUrl.getParameter(ENABLED_KEY, true) + && !ANY_VALUE.equals(consumerUrl.getParameter(ENABLED_KEY))) { + return false; + } + + String consumerGroup = consumerUrl.getGroup(); + String consumerVersion = consumerUrl.getVersion(); + String consumerClassifier = consumerUrl.getParameter(CLASSIFIER_KEY, ANY_VALUE); + + String providerGroup = providerUrl.getGroup(); + String providerVersion = providerUrl.getVersion(); + String providerClassifier = providerUrl.getParameter(CLASSIFIER_KEY, ANY_VALUE); + return (ANY_VALUE.equals(consumerGroup) || StringUtils.isEquals(consumerGroup, providerGroup) || StringUtils.isContains(consumerGroup, providerGroup)) + && (ANY_VALUE.equals(consumerVersion) || StringUtils.isEquals(consumerVersion, providerVersion)) + && (consumerClassifier == null || ANY_VALUE.equals(consumerClassifier) || StringUtils.isEquals(consumerClassifier, providerClassifier)); + } + + public static boolean isMatchGlobPattern(String pattern, String value, URL param) { + if (param != null && pattern.startsWith("$")) { + pattern = param.getRawParameter(pattern.substring(1)); + } + return isMatchGlobPattern(pattern, value); + } + + public static boolean isMatchGlobPattern(String pattern, String value) { + if ("*".equals(pattern)) { + return true; + } + if (StringUtils.isEmpty(pattern) && StringUtils.isEmpty(value)) { + return true; + } + if (StringUtils.isEmpty(pattern) || StringUtils.isEmpty(value)) { + return false; + } + + int i = pattern.lastIndexOf('*'); + // doesn't find "*" + if (i == -1) { + return value.equals(pattern); + } + // "*" is at the end + else if (i == pattern.length() - 1) { + return value.startsWith(pattern.substring(0, i)); + } + // "*" is at the beginning + else if (i == 0) { + return value.endsWith(pattern.substring(i + 1)); + } + // "*" is in the middle + else { + String prefix = pattern.substring(0, i); + String suffix = pattern.substring(i + 1); + return value.startsWith(prefix) && value.endsWith(suffix); + } + } + + public static boolean isServiceKeyMatch(URL pattern, URL value) { + return pattern.getParameter(INTERFACE_KEY).equals( + value.getParameter(INTERFACE_KEY)) + && isItemMatch(pattern.getGroup(), + value.getGroup()) + && isItemMatch(pattern.getVersion(), + value.getVersion()); + } + + public static List classifyUrls(List urls, Predicate predicate) { + return urls.stream().filter(predicate).collect(Collectors.toList()); + } + + public static boolean isConfigurator(URL url) { + return OVERRIDE_PROTOCOL.equals(url.getProtocol()) || + CONFIGURATORS_CATEGORY.equals(url.getCategory(DEFAULT_CATEGORY)); + } + + public static boolean isRoute(URL url) { + return ROUTE_PROTOCOL.equals(url.getProtocol()) || + ROUTERS_CATEGORY.equals(url.getCategory(DEFAULT_CATEGORY)); + } + + public static boolean isProvider(URL url) { + return !OVERRIDE_PROTOCOL.equals(url.getProtocol()) && + !ROUTE_PROTOCOL.equals(url.getProtocol()) && + PROVIDERS_CATEGORY.equals(url.getCategory(PROVIDERS_CATEGORY)); + } + + public static boolean isRegistry(URL url) { + return REGISTRY_PROTOCOL.equals(url.getProtocol()) + || SERVICE_REGISTRY_PROTOCOL.equalsIgnoreCase(url.getProtocol()) + || (url.getProtocol() != null && url.getProtocol().endsWith("-registry-protocol")); + } + + /** + * The specified {@link URL} is service discovery registry type or not + * + * @param url the {@link URL} connects to the registry + * @return If it is, return true, or false + * @since 2.7.5 + */ + public static boolean hasServiceDiscoveryRegistryTypeKey(URL url) { + return hasServiceDiscoveryRegistryTypeKey(url == null ? emptyMap() : url.getParameters()); + } + + public static boolean hasServiceDiscoveryRegistryProtocol(URL url) { + return SERVICE_REGISTRY_PROTOCOL.equalsIgnoreCase(url.getProtocol()); + } + + public static boolean isServiceDiscoveryURL(URL url) { + return hasServiceDiscoveryRegistryProtocol(url) || hasServiceDiscoveryRegistryTypeKey(url); + } + + /** + * The specified parameters of {@link URL} is service discovery registry type or not + * + * @param parameters the parameters of {@link URL} that connects to the registry + * @return If it is, return true, or false + * @since 2.7.5 + */ + public static boolean hasServiceDiscoveryRegistryTypeKey(Map parameters) { + if (parameters == null || parameters.isEmpty()) { + return false; + } + return SERVICE_REGISTRY_TYPE.equals(parameters.get(REGISTRY_TYPE_KEY)); + } + + /** + * Check if the given value matches the given pattern. The pattern supports wildcard "*". + * + * @param pattern pattern + * @param value value + * @return true if match otherwise false + */ + static boolean isItemMatch(String pattern, String value) { + if (pattern == null) { + return value == null; + } else { + return "*".equals(pattern) || pattern.equals(value); + } + } + + /** + * @param serviceKey, {group}/{interfaceName}:{version} + * @return [group, interfaceName, version] + */ + public static String[] parseServiceKey(String serviceKey) { + String[] arr = new String[3]; + int i = serviceKey.indexOf('/'); + if (i > 0) { + arr[0] = serviceKey.substring(0, i); + serviceKey = serviceKey.substring(i + 1); + } + + int j = serviceKey.indexOf(':'); + if (j > 0) { + arr[2] = serviceKey.substring(j + 1); + serviceKey = serviceKey.substring(0, j); + } + arr[1] = serviceKey; + return arr; + } + + /** + * NOTICE: This method allocate too much objects, we can use {@link URLStrParser#parseDecodedStr(String)} instead. + *

+ * Parse url string + * + * @param url URL string + * @return URL instance + * @see URL + */ + public static URL valueOf(String url) { + if (url == null || (url = url.trim()).length() == 0) { + throw new IllegalArgumentException("url == null"); + } + String protocol = null; + String username = null; + String password = null; + String host = null; + int port = 0; + String path = null; + Map parameters = null; + int i = url.indexOf('?'); // separator between body and parameters + if (i >= 0) { + String[] parts = url.substring(i + 1).split("&"); + parameters = new HashMap<>(); + for (String part : parts) { + part = part.trim(); + if (part.length() > 0) { + int j = part.indexOf('='); + if (j >= 0) { + String key = part.substring(0, j); + String value = part.substring(j + 1); + parameters.put(key, value); + // compatible with lower versions registering "default." keys + if (key.startsWith(DEFAULT_KEY_PREFIX)) { + parameters.putIfAbsent(key.substring(DEFAULT_KEY_PREFIX.length()), value); + } + } else { + parameters.put(part, part); + } + } + } + url = url.substring(0, i); + } + i = url.indexOf("://"); + if (i >= 0) { + if (i == 0) { + throw new IllegalStateException("url missing protocol: \"" + url + "\""); + } + protocol = url.substring(0, i); + url = url.substring(i + 3); + } else { + // case: file:/path/to/file.txt + i = url.indexOf(":/"); + if (i >= 0) { + if (i == 0) { + throw new IllegalStateException("url missing protocol: \"" + url + "\""); + } + protocol = url.substring(0, i); + url = url.substring(i + 1); + } + } + + i = url.indexOf('/'); + if (i >= 0) { + path = url.substring(i + 1); + url = url.substring(0, i); + } + i = url.lastIndexOf('@'); + if (i >= 0) { + username = url.substring(0, i); + int j = username.indexOf(':'); + if (j >= 0) { + password = username.substring(j + 1); + username = username.substring(0, j); + } + url = url.substring(i + 1); + } + i = url.lastIndexOf(':'); + if (i >= 0 && i < url.length() - 1) { + if (url.lastIndexOf('%') > i) { + // ipv6 address with scope id + // e.g. fe80:0:0:0:894:aeec:f37d:23e1%en0 + // see https://howdoesinternetwork.com/2013/ipv6-zone-id + // ignore + } else { + port = Integer.parseInt(url.substring(i + 1)); + url = url.substring(0, i); + } + } + if (url.length() > 0) { + host = url; + } + + return new ServiceConfigURL(protocol, username, password, host, port, path, parameters); + } + + public static boolean isConsumer(URL url) { + return url.getProtocol().equalsIgnoreCase("consumer") || url.getPort() == 0; + } + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java index f5d68570d0..386b607df8 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java @@ -236,7 +236,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig { } private void verifyStubAndLocal(String className, String label, Class interfaceClass){ - if (ConfigUtils.isNotEmpty(className)) { + if (ConfigUtils.isNotEmpty(className)) { Class localClass = ConfigUtils.isDefault(className) ? ReflectUtils.forName(interfaceClass.getName() + label) : ReflectUtils.forName(className); verify(interfaceClass, localClass); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/ServiceConfigBase.java b/dubbo-common/src/main/java/org/apache/dubbo/config/ServiceConfigBase.java index 050bfa476a..73359e9eff 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/ServiceConfigBase.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/ServiceConfigBase.java @@ -435,4 +435,4 @@ public abstract class ServiceConfigBase extends AbstractServiceConfig { public abstract boolean isUnexported(); -} \ No newline at end of file +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/support/Parameter.java b/dubbo-common/src/main/java/org/apache/dubbo/config/support/Parameter.java index 14ba8ced19..9091100aa4 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/support/Parameter.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/support/Parameter.java @@ -60,4 +60,4 @@ public @interface Parameter { */ boolean append() default false; -} \ No newline at end of file +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ApplicationInitListener.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ApplicationInitListener.java index f38acc4ed3..8b0f488236 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ApplicationInitListener.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ApplicationInitListener.java @@ -24,4 +24,4 @@ public interface ApplicationInitListener { * init the application */ void init(); -} \ No newline at end of file +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/service/EchoService.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/service/EchoService.java index c9125dc5bf..592469d5b9 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/service/EchoService.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/service/EchoService.java @@ -30,4 +30,4 @@ public interface EchoService { */ Object $echo(Object message); -} \ No newline at end of file +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/service/GenericException.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/service/GenericException.java index 097f1fe7b5..0d3d784e82 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/service/GenericException.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/service/GenericException.java @@ -62,4 +62,4 @@ public class GenericException extends RuntimeException { this.exceptionMessage = exceptionMessage; } -} \ No newline at end of file +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/service/GenericService.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/service/GenericService.java index d93fa14930..1f144eac69 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/service/GenericService.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/service/GenericService.java @@ -45,4 +45,4 @@ public interface GenericService { return CompletableFuture.completedFuture(object); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.compiler.Compiler b/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.compiler.Compiler index c6d72aa21e..caa3741dac 100644 --- a/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.compiler.Compiler +++ b/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.compiler.Compiler @@ -1,3 +1,3 @@ -adaptive=org.apache.dubbo.common.compiler.support.AdaptiveCompiler -jdk=org.apache.dubbo.common.compiler.support.JdkCompiler +adaptive=org.apache.dubbo.common.compiler.support.AdaptiveCompiler +jdk=org.apache.dubbo.common.compiler.support.JdkCompiler javassist=org.apache.dubbo.common.compiler.support.JavassistCompiler \ No newline at end of file diff --git a/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.ExtensionFactory b/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.ExtensionFactory index 5ab75b071a..094382f773 100644 --- a/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.ExtensionFactory +++ b/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.ExtensionFactory @@ -1,2 +1,2 @@ -adaptive=org.apache.dubbo.common.extension.factory.AdaptiveExtensionFactory +adaptive=org.apache.dubbo.common.extension.factory.AdaptiveExtensionFactory spi=org.apache.dubbo.common.extension.factory.SpiExtensionFactory \ No newline at end of file diff --git a/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.logger.LoggerAdapter b/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.logger.LoggerAdapter index 90d653c988..d8e324e260 100644 --- a/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.logger.LoggerAdapter +++ b/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.logger.LoggerAdapter @@ -1,5 +1,5 @@ -slf4j=org.apache.dubbo.common.logger.slf4j.Slf4jLoggerAdapter -jcl=org.apache.dubbo.common.logger.jcl.JclLoggerAdapter -log4j=org.apache.dubbo.common.logger.log4j.Log4jLoggerAdapter -jdk=org.apache.dubbo.common.logger.jdk.JdkLoggerAdapter -log4j2=org.apache.dubbo.common.logger.log4j2.Log4j2LoggerAdapter +slf4j=org.apache.dubbo.common.logger.slf4j.Slf4jLoggerAdapter +jcl=org.apache.dubbo.common.logger.jcl.JclLoggerAdapter +log4j=org.apache.dubbo.common.logger.log4j.Log4jLoggerAdapter +jdk=org.apache.dubbo.common.logger.jdk.JdkLoggerAdapter +log4j2=org.apache.dubbo.common.logger.log4j2.Log4j2LoggerAdapter diff --git a/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.status.StatusChecker b/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.status.StatusChecker index 4e80075719..a84f833f81 100644 --- a/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.status.StatusChecker +++ b/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.status.StatusChecker @@ -1,2 +1,2 @@ -memory=org.apache.dubbo.common.status.support.MemoryStatusChecker +memory=org.apache.dubbo.common.status.support.MemoryStatusChecker load=org.apache.dubbo.common.status.support.LoadStatusChecker \ No newline at end of file diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/URLBuilderTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/URLBuilderTest.java index 8b1148e6a8..c3dd499b81 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/URLBuilderTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/URLBuilderTest.java @@ -1,144 +1,144 @@ -/* - * 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.common; - -import org.junit.jupiter.api.Test; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.MatcherAssert.assertThat; - -public class URLBuilderTest { - @Test - public void testNoArgConstructor() { - URL url = new URLBuilder().build(); - assertThat(url.toString(), equalTo("")); - } - - @Test - public void shouldAddParameter() { - URL url1 = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan"); - URL url2 = URLBuilder.from(url1) - .addParameter("newKey1", "newValue1") // string - .addParameter("newKey2", 2) // int - .addParameter("version", 1) // override - .build(); - assertThat(url2.getParameter("newKey1"), equalTo("newValue1")); - assertThat(url2.getParameter("newKey2"), equalTo("2")); - assertThat(url2.getVersion(), equalTo("1")); - } - - @Test - public void shouldSet() { - URL url1 = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan"); - URL url2 = URLBuilder.from(url1) - .setProtocol("rest") - .setUsername("newUsername") - .setPassword("newPassword") - .setHost("newHost") - .setPath("newContext") - .setPort(1234) - .build(); - assertThat(url2.getProtocol(), equalTo("rest")); - assertThat(url2.getUsername(), equalTo("newUsername")); - assertThat(url2.getPassword(), equalTo("newPassword")); - assertThat(url2.getHost(), equalTo("newHost")); - assertThat(url2.getPort(), equalTo(1234)); - assertThat(url2.getPath(), equalTo("newContext")); - - url2 = URLBuilder.from(url1) - .setAddress("newHost2:2345") - .build(); - assertThat(url2.getHost(), equalTo("newHost2")); - assertThat(url2.getPort(), equalTo(2345)); - } - - @Test - public void shouldClearParameters() { - URL url1 = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan"); - URL url2 = URLBuilder.from(url1) - .clearParameters() - .build(); - assertThat(url2.getParameters().size(), equalTo(0)); - } - - @Test - public void shouldRemoveParameters() { - URL url1 = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan&key2=v2"); - URL url2 = URLBuilder.from(url1) - .removeParameters(Arrays.asList("key2", "application")) - .build(); - assertThat(url2.getParameters().size(), equalTo(1)); - assertThat(url2.getVersion(), equalTo("1.0.0")); - } - - @Test - public void shouldAddIfAbsent() { - URL url1 = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan&key2=v2"); - URL url2 = URLBuilder.from(url1) - .addParameterIfAbsent("absentKey", "absentValue") - .addParameterIfAbsent("version", "2.0.0") // should not override - .build(); - assertThat(url2.getVersion(), equalTo("1.0.0")); - assertThat(url2.getParameter("absentKey"), equalTo("absentValue")); - } - - @Test - public void shouldAddParameters() { - URL url1 = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan&key2=v2"); - - // string pairs test - URL url2 = URLBuilder.from(url1) - .addParameters("version", "1.0.0", "absentKey1", "absentValue1") - .build(); - assertThat(url2.getParameter("version"), equalTo("1.0.0")); - assertThat(url2.getParameter("absentKey1"), equalTo("absentValue1")); - - // map test - Map parameters = new HashMap(){ - { - this.put("version", "2.0.0"); - this.put("absentKey2", "absentValue2"); - } - }; - url2 = URLBuilder.from(url1) - .addParameters(parameters) - .build(); - assertThat(url2.getParameter("version"), equalTo("2.0.0")); - assertThat(url2.getParameter("absentKey2"), equalTo("absentValue2")); - } - - @Test - public void shouldAddParametersIfAbsent() { - URL url1 = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan&key2=v2"); - - Map parameters = new HashMap(){ - { - this.put("version", "2.0.0"); - this.put("absentKey", "absentValue"); - } - }; - URL url2 = URLBuilder.from(url1) - .addParametersIfAbsent(parameters) - .build(); - assertThat(url2.getParameter("version"), equalTo("1.0.0")); - assertThat(url2.getParameter("absentKey"), equalTo("absentValue")); - } -} +/* + * 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.common; + +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +public class URLBuilderTest { + @Test + public void testNoArgConstructor() { + URL url = new URLBuilder().build(); + assertThat(url.toString(), equalTo("")); + } + + @Test + public void shouldAddParameter() { + URL url1 = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan"); + URL url2 = URLBuilder.from(url1) + .addParameter("newKey1", "newValue1") // string + .addParameter("newKey2", 2) // int + .addParameter("version", 1) // override + .build(); + assertThat(url2.getParameter("newKey1"), equalTo("newValue1")); + assertThat(url2.getParameter("newKey2"), equalTo("2")); + assertThat(url2.getVersion(), equalTo("1")); + } + + @Test + public void shouldSet() { + URL url1 = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan"); + URL url2 = URLBuilder.from(url1) + .setProtocol("rest") + .setUsername("newUsername") + .setPassword("newPassword") + .setHost("newHost") + .setPath("newContext") + .setPort(1234) + .build(); + assertThat(url2.getProtocol(), equalTo("rest")); + assertThat(url2.getUsername(), equalTo("newUsername")); + assertThat(url2.getPassword(), equalTo("newPassword")); + assertThat(url2.getHost(), equalTo("newHost")); + assertThat(url2.getPort(), equalTo(1234)); + assertThat(url2.getPath(), equalTo("newContext")); + + url2 = URLBuilder.from(url1) + .setAddress("newHost2:2345") + .build(); + assertThat(url2.getHost(), equalTo("newHost2")); + assertThat(url2.getPort(), equalTo(2345)); + } + + @Test + public void shouldClearParameters() { + URL url1 = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan"); + URL url2 = URLBuilder.from(url1) + .clearParameters() + .build(); + assertThat(url2.getParameters().size(), equalTo(0)); + } + + @Test + public void shouldRemoveParameters() { + URL url1 = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan&key2=v2"); + URL url2 = URLBuilder.from(url1) + .removeParameters(Arrays.asList("key2", "application")) + .build(); + assertThat(url2.getParameters().size(), equalTo(1)); + assertThat(url2.getVersion(), equalTo("1.0.0")); + } + + @Test + public void shouldAddIfAbsent() { + URL url1 = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan&key2=v2"); + URL url2 = URLBuilder.from(url1) + .addParameterIfAbsent("absentKey", "absentValue") + .addParameterIfAbsent("version", "2.0.0") // should not override + .build(); + assertThat(url2.getVersion(), equalTo("1.0.0")); + assertThat(url2.getParameter("absentKey"), equalTo("absentValue")); + } + + @Test + public void shouldAddParameters() { + URL url1 = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan&key2=v2"); + + // string pairs test + URL url2 = URLBuilder.from(url1) + .addParameters("version", "1.0.0", "absentKey1", "absentValue1") + .build(); + assertThat(url2.getParameter("version"), equalTo("1.0.0")); + assertThat(url2.getParameter("absentKey1"), equalTo("absentValue1")); + + // map test + Map parameters = new HashMap(){ + { + this.put("version", "2.0.0"); + this.put("absentKey2", "absentValue2"); + } + }; + url2 = URLBuilder.from(url1) + .addParameters(parameters) + .build(); + assertThat(url2.getParameter("version"), equalTo("2.0.0")); + assertThat(url2.getParameter("absentKey2"), equalTo("absentValue2")); + } + + @Test + public void shouldAddParametersIfAbsent() { + URL url1 = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan&key2=v2"); + + Map parameters = new HashMap(){ + { + this.put("version", "2.0.0"); + this.put("absentKey", "absentValue"); + } + }; + URL url2 = URLBuilder.from(url1) + .addParametersIfAbsent(parameters) + .build(); + assertThat(url2.getParameter("version"), equalTo("1.0.0")); + assertThat(url2.getParameter("absentKey"), equalTo("absentValue")); + } +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/bytecode/ClassGeneratorTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/bytecode/ClassGeneratorTest.java index c49554623e..dc1cbdf2d7 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/bytecode/ClassGeneratorTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/bytecode/ClassGeneratorTest.java @@ -105,4 +105,4 @@ class Bean { } public static volatile String abc = "df"; -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/bytecode/MixinTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/bytecode/MixinTest.java index 544c9c6fed..fa96d2e2ec 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/bytecode/MixinTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/bytecode/MixinTest.java @@ -69,4 +69,4 @@ public class MixinTest { System.out.println("setMixinInstance:" + mi); } } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/bytecode/ProxyTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/bytecode/ProxyTest.java index 56a70f60f3..423260a593 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/bytecode/ProxyTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/bytecode/ProxyTest.java @@ -71,4 +71,4 @@ public class ProxyTest { return "Bye!"; } } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/bytecode/WrapperTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/bytecode/WrapperTest.java index cc246f8ae9..683cadb68b 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/bytecode/WrapperTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/bytecode/WrapperTest.java @@ -1,246 +1,246 @@ -/* - * 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.common.bytecode; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertArrayEquals; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.fail; - -public class WrapperTest { - @Test - public void testMain() throws Exception { - Wrapper w = Wrapper.getWrapper(I1.class); - String[] ns = w.getDeclaredMethodNames(); - assertEquals(ns.length, 5); - ns = w.getMethodNames(); - assertEquals(ns.length, 6); - - Object obj = new Impl1(); - assertEquals(w.getPropertyValue(obj, "name"), "you name"); - - w.setPropertyValue(obj, "name", "changed"); - assertEquals(w.getPropertyValue(obj, "name"), "changed"); - - w.invokeMethod(obj, "hello", new Class[]{String.class}, new Object[]{"qianlei"}); - } - - // bug: DUBBO-132 - @Test - public void test_unwantedArgument() throws Exception { - Wrapper w = Wrapper.getWrapper(I1.class); - Object obj = new Impl1(); - try { - w.invokeMethod(obj, "hello", new Class[]{String.class, String.class}, - new Object[]{"qianlei", "badboy"}); - fail(); - } catch (NoSuchMethodException expected) { - } - } - - //bug: DUBBO-425 - @Test - public void test_makeEmptyClass() throws Exception { - Wrapper.getWrapper(EmptyServiceImpl.class); - } - - @Test - public void testHasMethod() throws Exception { - Wrapper w = Wrapper.getWrapper(I1.class); - Assertions.assertTrue(w.hasMethod("setName")); - Assertions.assertTrue(w.hasMethod("hello")); - Assertions.assertTrue(w.hasMethod("showInt")); - Assertions.assertTrue(w.hasMethod("getFloat")); - Assertions.assertTrue(w.hasMethod("setFloat")); - Assertions.assertFalse(w.hasMethod("setFloatXXX")); - } - - @Test - public void testWrapperObject() throws Exception { - Wrapper w = Wrapper.getWrapper(Object.class); - Assertions.assertEquals(4, w.getMethodNames().length); - Assertions.assertEquals(0, w.getPropertyNames().length); - Assertions.assertNull(w.getPropertyType(null)); - } - - @Test - public void testGetPropertyValue() throws Exception { - Assertions.assertThrows(NoSuchPropertyException.class, () -> { - Wrapper w = Wrapper.getWrapper(Object.class); - w.getPropertyValue(null, null); - }); - } - - @Test - public void testSetPropertyValue() throws Exception { - Assertions.assertThrows(NoSuchPropertyException.class, () -> { - Wrapper w = Wrapper.getWrapper(Object.class); - w.setPropertyValue(null, null, null); - }); - } - - @Test - public void testInvokeWrapperObject() throws Exception { - Wrapper w = Wrapper.getWrapper(Object.class); - Object instance = new Object(); - Assertions.assertEquals(instance.getClass(), (Class) w.invokeMethod(instance, "getClass", null, null)); - Assertions.assertEquals(instance.hashCode(), (int) w.invokeMethod(instance, "hashCode", null, null)); - Assertions.assertEquals(instance.toString(), (String) w.invokeMethod(instance, "toString", null, null)); - Assertions.assertTrue((boolean)w.invokeMethod(instance, "equals", null, new Object[] {instance})); - } - - @Test - public void testNoSuchMethod() throws Exception { - Assertions.assertThrows(NoSuchMethodException.class, () -> { - Wrapper w = Wrapper.getWrapper(Object.class); - w.invokeMethod(new Object(), "__XX__", null, null); - }); - } - - @Test - public void testOverloadMethod() throws Exception { - Wrapper w = Wrapper.getWrapper(I2.class); - assertEquals(2, w.getMethodNames().length); - - Impl2 impl = new Impl2(); - - w.invokeMethod(impl, "setFloat", new Class[]{float.class}, new Object[]{1F}); - assertEquals(1F, impl.getFloat1()); - assertNull(impl.getFloat2()); - - w.invokeMethod(impl, "setFloat", new Class[]{Float.class}, new Object[]{2f}); - assertEquals(1F, impl.getFloat1()); - assertEquals(2F, impl.getFloat2()); - - w.invokeMethod(impl, "setFloat", new Class[]{Float.class}, new Object[]{null}); - assertEquals(1F, impl.getFloat1()); - assertNull(impl.getFloat2()); - } - - @Test - public void test_getDeclaredMethodNames_ContainExtendsParentMethods() throws Exception { - assertArrayEquals(new String[]{"hello",}, Wrapper.getWrapper(Parent1.class).getMethodNames()); - - assertArrayEquals(new String[]{}, Wrapper.getWrapper(Son.class).getDeclaredMethodNames()); - } - - @Test - public void test_getMethodNames_ContainExtendsParentMethods() throws Exception { - assertArrayEquals(new String[]{"hello", "world"}, Wrapper.getWrapper(Son.class).getMethodNames()); - } - - public interface I0 { - String getName(); - } - - public interface I1 extends I0 { - void setName(String name); - - void hello(String name); - - int showInt(int v); - - float getFloat(); - - void setFloat(float f); - } - - public interface I2 { - void setFloat(float f); - - void setFloat(Float f); - } - - public interface EmptyService { - } - - public interface Parent1 { - void hello(); - } - - - public interface Parent2 { - void world(); - } - - public interface Son extends Parent1, Parent2 { - - } - - public static class Impl0 { - public float a, b, c; - } - - public static class Impl1 implements I1 { - private String name = "you name"; - - private float fv = 0; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public void hello(String name) { - System.out.println("hello " + name); - } - - public int showInt(int v) { - return v; - } - - public float getFloat() { - return fv; - } - - public void setFloat(float f) { - fv = f; - } - } - - public static class Impl2 implements I2 { - private float float1; - private Float float2; - - @Override - public void setFloat(float f) { - this.float1 = f; - } - - @Override - public void setFloat(Float f) { - this.float2 = f; - } - - public float getFloat1() { - return float1; - } - - public Float getFloat2() { - return float2; - } - } - - public static class EmptyServiceImpl implements EmptyService { - } -} +/* + * 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.common.bytecode; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.fail; + +public class WrapperTest { + @Test + public void testMain() throws Exception { + Wrapper w = Wrapper.getWrapper(I1.class); + String[] ns = w.getDeclaredMethodNames(); + assertEquals(ns.length, 5); + ns = w.getMethodNames(); + assertEquals(ns.length, 6); + + Object obj = new Impl1(); + assertEquals(w.getPropertyValue(obj, "name"), "you name"); + + w.setPropertyValue(obj, "name", "changed"); + assertEquals(w.getPropertyValue(obj, "name"), "changed"); + + w.invokeMethod(obj, "hello", new Class[]{String.class}, new Object[]{"qianlei"}); + } + + // bug: DUBBO-132 + @Test + public void test_unwantedArgument() throws Exception { + Wrapper w = Wrapper.getWrapper(I1.class); + Object obj = new Impl1(); + try { + w.invokeMethod(obj, "hello", new Class[]{String.class, String.class}, + new Object[]{"qianlei", "badboy"}); + fail(); + } catch (NoSuchMethodException expected) { + } + } + + //bug: DUBBO-425 + @Test + public void test_makeEmptyClass() throws Exception { + Wrapper.getWrapper(EmptyServiceImpl.class); + } + + @Test + public void testHasMethod() throws Exception { + Wrapper w = Wrapper.getWrapper(I1.class); + Assertions.assertTrue(w.hasMethod("setName")); + Assertions.assertTrue(w.hasMethod("hello")); + Assertions.assertTrue(w.hasMethod("showInt")); + Assertions.assertTrue(w.hasMethod("getFloat")); + Assertions.assertTrue(w.hasMethod("setFloat")); + Assertions.assertFalse(w.hasMethod("setFloatXXX")); + } + + @Test + public void testWrapperObject() throws Exception { + Wrapper w = Wrapper.getWrapper(Object.class); + Assertions.assertEquals(4, w.getMethodNames().length); + Assertions.assertEquals(0, w.getPropertyNames().length); + Assertions.assertNull(w.getPropertyType(null)); + } + + @Test + public void testGetPropertyValue() throws Exception { + Assertions.assertThrows(NoSuchPropertyException.class, () -> { + Wrapper w = Wrapper.getWrapper(Object.class); + w.getPropertyValue(null, null); + }); + } + + @Test + public void testSetPropertyValue() throws Exception { + Assertions.assertThrows(NoSuchPropertyException.class, () -> { + Wrapper w = Wrapper.getWrapper(Object.class); + w.setPropertyValue(null, null, null); + }); + } + + @Test + public void testInvokeWrapperObject() throws Exception { + Wrapper w = Wrapper.getWrapper(Object.class); + Object instance = new Object(); + Assertions.assertEquals(instance.getClass(), (Class) w.invokeMethod(instance, "getClass", null, null)); + Assertions.assertEquals(instance.hashCode(), (int) w.invokeMethod(instance, "hashCode", null, null)); + Assertions.assertEquals(instance.toString(), (String) w.invokeMethod(instance, "toString", null, null)); + Assertions.assertTrue((boolean)w.invokeMethod(instance, "equals", null, new Object[] {instance})); + } + + @Test + public void testNoSuchMethod() throws Exception { + Assertions.assertThrows(NoSuchMethodException.class, () -> { + Wrapper w = Wrapper.getWrapper(Object.class); + w.invokeMethod(new Object(), "__XX__", null, null); + }); + } + + @Test + public void testOverloadMethod() throws Exception { + Wrapper w = Wrapper.getWrapper(I2.class); + assertEquals(2, w.getMethodNames().length); + + Impl2 impl = new Impl2(); + + w.invokeMethod(impl, "setFloat", new Class[]{float.class}, new Object[]{1F}); + assertEquals(1F, impl.getFloat1()); + assertNull(impl.getFloat2()); + + w.invokeMethod(impl, "setFloat", new Class[]{Float.class}, new Object[]{2f}); + assertEquals(1F, impl.getFloat1()); + assertEquals(2F, impl.getFloat2()); + + w.invokeMethod(impl, "setFloat", new Class[]{Float.class}, new Object[]{null}); + assertEquals(1F, impl.getFloat1()); + assertNull(impl.getFloat2()); + } + + @Test + public void test_getDeclaredMethodNames_ContainExtendsParentMethods() throws Exception { + assertArrayEquals(new String[]{"hello",}, Wrapper.getWrapper(Parent1.class).getMethodNames()); + + assertArrayEquals(new String[]{}, Wrapper.getWrapper(Son.class).getDeclaredMethodNames()); + } + + @Test + public void test_getMethodNames_ContainExtendsParentMethods() throws Exception { + assertArrayEquals(new String[]{"hello", "world"}, Wrapper.getWrapper(Son.class).getMethodNames()); + } + + public interface I0 { + String getName(); + } + + public interface I1 extends I0 { + void setName(String name); + + void hello(String name); + + int showInt(int v); + + float getFloat(); + + void setFloat(float f); + } + + public interface I2 { + void setFloat(float f); + + void setFloat(Float f); + } + + public interface EmptyService { + } + + public interface Parent1 { + void hello(); + } + + + public interface Parent2 { + void world(); + } + + public interface Son extends Parent1, Parent2 { + + } + + public static class Impl0 { + public float a, b, c; + } + + public static class Impl1 implements I1 { + private String name = "you name"; + + private float fv = 0; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public void hello(String name) { + System.out.println("hello " + name); + } + + public int showInt(int v) { + return v; + } + + public float getFloat() { + return fv; + } + + public void setFloat(float f) { + fv = f; + } + } + + public static class Impl2 implements I2 { + private float float1; + private Float float2; + + @Override + public void setFloat(float f) { + this.float1 = f; + } + + @Override + public void setFloat(Float f) { + this.float2 = f; + } + + public float getFloat1() { + return float1; + } + + public Float getFloat2() { + return float2; + } + } + + public static class EmptyServiceImpl implements EmptyService { + } +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/concurrent/CompletableFutureTaskTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/concurrent/CompletableFutureTaskTest.java index 2d0cb48fef..cf2b709a1a 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/concurrent/CompletableFutureTaskTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/concurrent/CompletableFutureTaskTest.java @@ -92,4 +92,4 @@ public class CompletableFutureTaskTest { completableFuture.thenRunAsync(mock(Runnable.class), mockedExecutor).whenComplete((s, e) -> verify(mockedExecutor, times(1)).execute(any(Runnable.class))); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/config/EnvironmentConfigurationTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/config/EnvironmentConfigurationTest.java index 974e07c8a7..f0d6ab3f2e 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/config/EnvironmentConfigurationTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/config/EnvironmentConfigurationTest.java @@ -101,4 +101,4 @@ class EnvironmentConfigurationTest { } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/config/InmemoryConfigurationTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/config/InmemoryConfigurationTest.java index 9cdfcdd76c..b5071886fa 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/config/InmemoryConfigurationTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/config/InmemoryConfigurationTest.java @@ -107,4 +107,4 @@ class InmemoryConfigurationTest { } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/config/SystemConfigurationTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/config/SystemConfigurationTest.java index 75576be5b5..3fea755472 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/config/SystemConfigurationTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/config/SystemConfigurationTest.java @@ -114,4 +114,4 @@ class SystemConfigurationTest { MockTwo } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ExtensionLoader_Adaptive_UseJdkCompiler_Test.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ExtensionLoader_Adaptive_UseJdkCompiler_Test.java index 371f858974..f311555793 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ExtensionLoader_Adaptive_UseJdkCompiler_Test.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ExtensionLoader_Adaptive_UseJdkCompiler_Test.java @@ -31,4 +31,4 @@ public class ExtensionLoader_Adaptive_UseJdkCompiler_Test extends ExtensionLoade public static void tearDown() throws Exception { AdaptiveCompiler.setDefaultCompiler("javassist"); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ExtensionLoader_Compatible_Test.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ExtensionLoader_Compatible_Test.java index d9df136707..97904ae1c9 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ExtensionLoader_Compatible_Test.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ExtensionLoader_Compatible_Test.java @@ -31,4 +31,4 @@ public class ExtensionLoader_Compatible_Test { assertTrue(ExtensionLoader.getExtensionLoader(CompatibleExt.class).getExtension("impl1") instanceof CompatibleExtImpl1); assertTrue(ExtensionLoader.getExtensionLoader(CompatibleExt.class).getExtension("impl2") instanceof CompatibleExtImpl2); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/NoSpiExt.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/NoSpiExt.java index 44d77608d0..b93e615562 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/NoSpiExt.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/NoSpiExt.java @@ -24,4 +24,4 @@ import org.apache.dubbo.common.URL; public interface NoSpiExt { @Adaptive String echo(URL url, String s); -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/activate/impl/ActivateWrapperExt1Impl1.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/activate/impl/ActivateWrapperExt1Impl1.java index acbe959284..0ff2ef44f4 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/activate/impl/ActivateWrapperExt1Impl1.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/activate/impl/ActivateWrapperExt1Impl1.java @@ -25,4 +25,4 @@ public class ActivateWrapperExt1Impl1 implements ActivateWrapperExt1 { public String echo(String msg) { return msg; } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/activate/impl/ActivateWrapperExt1Impl2.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/activate/impl/ActivateWrapperExt1Impl2.java index 51ff0e5e4f..716d815040 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/activate/impl/ActivateWrapperExt1Impl2.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/activate/impl/ActivateWrapperExt1Impl2.java @@ -25,4 +25,4 @@ public class ActivateWrapperExt1Impl2 implements ActivateWrapperExt1 { public String echo(String msg) { return msg; } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/activate/impl/ActivateWrapperExt1Wrapper.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/activate/impl/ActivateWrapperExt1Wrapper.java index 5c29064fd9..671a3b9c00 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/activate/impl/ActivateWrapperExt1Wrapper.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/activate/impl/ActivateWrapperExt1Wrapper.java @@ -31,4 +31,4 @@ public class ActivateWrapperExt1Wrapper implements ActivateWrapperExt1 { public String echo(String msg) { return activateWrapperExt1.echo(msg); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/adaptive/impl/HasAdaptiveExtImpl1.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/adaptive/impl/HasAdaptiveExtImpl1.java index bf9afc3517..cd9454b874 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/adaptive/impl/HasAdaptiveExtImpl1.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/adaptive/impl/HasAdaptiveExtImpl1.java @@ -23,4 +23,4 @@ public class HasAdaptiveExtImpl1 implements HasAdaptiveExt { public String echo(URL url, String s) { return this.getClass().getSimpleName(); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/adaptive/impl/HasAdaptiveExt_ManualAdaptive.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/adaptive/impl/HasAdaptiveExt_ManualAdaptive.java index e08608ac41..3f273f55bc 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/adaptive/impl/HasAdaptiveExt_ManualAdaptive.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/adaptive/impl/HasAdaptiveExt_ManualAdaptive.java @@ -27,4 +27,4 @@ public class HasAdaptiveExt_ManualAdaptive implements HasAdaptiveExt { HasAdaptiveExt addExt1 = ExtensionLoader.getExtensionLoader(HasAdaptiveExt.class).getExtension(url.getParameter("key")); return addExt1.echo(url, s); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/compatible/CompatibleExt.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/compatible/CompatibleExt.java index a29cba996c..bf015fdf37 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/compatible/CompatibleExt.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/compatible/CompatibleExt.java @@ -24,4 +24,4 @@ import org.apache.dubbo.common.extension.SPI; public interface CompatibleExt { @Adaptive String echo(URL url, String s); -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/compatible/impl/CompatibleExtImpl1.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/compatible/impl/CompatibleExtImpl1.java index 9148fa18dc..375c6c3b71 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/compatible/impl/CompatibleExtImpl1.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/compatible/impl/CompatibleExtImpl1.java @@ -33,4 +33,4 @@ public class CompatibleExtImpl1 implements CompatibleExt { public String bang(URL url, int i) { return "bang1"; } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/compatible/impl/CompatibleExtImpl2.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/compatible/impl/CompatibleExtImpl2.java index 316f4fdc41..27d92a1da6 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/compatible/impl/CompatibleExtImpl2.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/compatible/impl/CompatibleExtImpl2.java @@ -32,4 +32,4 @@ public class CompatibleExtImpl2 implements CompatibleExt { return "bang2"; } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/convert/String2DoubleConverter.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/convert/String2DoubleConverter.java index 3cb2786689..c231495de2 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/convert/String2DoubleConverter.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/convert/String2DoubleConverter.java @@ -25,4 +25,4 @@ import org.apache.dubbo.common.convert.StringToDoubleConverter; * @since 2.7.7 */ public class String2DoubleConverter extends StringToDoubleConverter { -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext1/SimpleExt.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext1/SimpleExt.java index 5e6d32fd3a..95b97d5e60 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext1/SimpleExt.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext1/SimpleExt.java @@ -34,4 +34,4 @@ public interface SimpleExt { // no @Adaptive String bang(URL url, int i); -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext1/impl/SimpleExtImpl1.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext1/impl/SimpleExtImpl1.java index e1c840d69d..e7603b23d2 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext1/impl/SimpleExtImpl1.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext1/impl/SimpleExtImpl1.java @@ -31,4 +31,4 @@ public class SimpleExtImpl1 implements SimpleExt { public String bang(URL url, int i) { return "bang1"; } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext1/impl/SimpleExtImpl2.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext1/impl/SimpleExtImpl2.java index 133fffdc3f..33e63bb40f 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext1/impl/SimpleExtImpl2.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext1/impl/SimpleExtImpl2.java @@ -32,4 +32,4 @@ public class SimpleExtImpl2 implements SimpleExt { return "bang2"; } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext1/impl/SimpleExtImpl3.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext1/impl/SimpleExtImpl3.java index 78d177e6bf..dd78351a2e 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext1/impl/SimpleExtImpl3.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext1/impl/SimpleExtImpl3.java @@ -32,4 +32,4 @@ public class SimpleExtImpl3 implements SimpleExt { return "bang3"; } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext2/Ext2.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext2/Ext2.java index a7c8950657..0d15436d16 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext2/Ext2.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext2/Ext2.java @@ -30,4 +30,4 @@ public interface Ext2 { String echo(UrlHolder holder, String s); String bang(URL url, int i); -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext2/UrlHolder.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext2/UrlHolder.java index 47146763e9..adead615aa 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext2/UrlHolder.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext2/UrlHolder.java @@ -58,4 +58,4 @@ public class UrlHolder { public void setAge(int age) { this.age = age; } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext2/impl/Ext2Impl1.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext2/impl/Ext2Impl1.java index e5d2560711..c3d3b01426 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext2/impl/Ext2Impl1.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext2/impl/Ext2Impl1.java @@ -28,4 +28,4 @@ public class Ext2Impl1 implements Ext2 { public String bang(URL url, int i) { return "bang1"; } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext2/impl/Ext2Impl2.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext2/impl/Ext2Impl2.java index d9d67939f0..34077b2cfb 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext2/impl/Ext2Impl2.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext2/impl/Ext2Impl2.java @@ -29,4 +29,4 @@ public class Ext2Impl2 implements Ext2 { return "bang2"; } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext2/impl/Ext2Impl3.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext2/impl/Ext2Impl3.java index b7adde1a69..d308b36b4f 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext2/impl/Ext2Impl3.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext2/impl/Ext2Impl3.java @@ -29,4 +29,4 @@ public class Ext2Impl3 implements Ext2 { return "bang3"; } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext3/UseProtocolKeyExt.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext3/UseProtocolKeyExt.java index 1b42e9aa22..be34e21d47 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext3/UseProtocolKeyExt.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext3/UseProtocolKeyExt.java @@ -29,4 +29,4 @@ public interface UseProtocolKeyExt { // protocol key is the first @Adaptive({"protocol", "key2"}) String yell(URL url, String s); -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext3/impl/UseProtocolKeyExtImpl1.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext3/impl/UseProtocolKeyExtImpl1.java index d78297987e..6d0b74eff7 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext3/impl/UseProtocolKeyExtImpl1.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext3/impl/UseProtocolKeyExtImpl1.java @@ -27,4 +27,4 @@ public class UseProtocolKeyExtImpl1 implements UseProtocolKeyExt { public String yell(URL url, String s) { return "Ext3Impl1-yell"; } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext3/impl/UseProtocolKeyExtImpl2.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext3/impl/UseProtocolKeyExtImpl2.java index 958513d5a3..7269a165d8 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext3/impl/UseProtocolKeyExtImpl2.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext3/impl/UseProtocolKeyExtImpl2.java @@ -27,4 +27,4 @@ public class UseProtocolKeyExtImpl2 implements UseProtocolKeyExt { public String yell(URL url, String s) { return "Ext3Impl2-yell"; } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext3/impl/UseProtocolKeyExtImpl3.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext3/impl/UseProtocolKeyExtImpl3.java index 7293725f4e..d3bc5f718a 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext3/impl/UseProtocolKeyExtImpl3.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext3/impl/UseProtocolKeyExtImpl3.java @@ -27,4 +27,4 @@ public class UseProtocolKeyExtImpl3 implements UseProtocolKeyExt { public String yell(URL url, String s) { return "Ext3Impl3-yell"; } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext4/NoUrlParamExt.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext4/NoUrlParamExt.java index 2c9613bbbb..57d231b778 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext4/NoUrlParamExt.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext4/NoUrlParamExt.java @@ -26,4 +26,4 @@ public interface NoUrlParamExt { // method has no URL parameter @Adaptive String bark(String name, List list); -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext4/impl/Ext4Impl1.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext4/impl/Ext4Impl1.java index fe02b773f9..d3715f8765 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext4/impl/Ext4Impl1.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext4/impl/Ext4Impl1.java @@ -24,4 +24,4 @@ public class Ext4Impl1 implements NoUrlParamExt { public String bark(String name, List list) { return null; } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext4/impl/Ext4Impl2.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext4/impl/Ext4Impl2.java index 2f25a5f901..539342e89d 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext4/impl/Ext4Impl2.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext4/impl/Ext4Impl2.java @@ -25,4 +25,4 @@ public class Ext4Impl2 implements NoUrlParamExt { return null; } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext5/NoAdaptiveMethodExt.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext5/NoAdaptiveMethodExt.java index e4d157253b..f066087cf8 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext5/NoAdaptiveMethodExt.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext5/NoAdaptiveMethodExt.java @@ -25,4 +25,4 @@ import org.apache.dubbo.common.extension.SPI; @SPI("impl1") public interface NoAdaptiveMethodExt { String echo(URL url, String s); -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext5/impl/Ext5Impl1.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext5/impl/Ext5Impl1.java index e7c6519efb..026999dfc4 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext5/impl/Ext5Impl1.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext5/impl/Ext5Impl1.java @@ -23,4 +23,4 @@ public class Ext5Impl1 implements NoAdaptiveMethodExt { public String echo(URL url, String s) { return "Ext5Impl1-echo"; } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext5/impl/Ext5Impl2.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext5/impl/Ext5Impl2.java index d10602c688..f65dc3cf6c 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext5/impl/Ext5Impl2.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext5/impl/Ext5Impl2.java @@ -23,4 +23,4 @@ public class Ext5Impl2 implements NoAdaptiveMethodExt { public String echo(URL url, String s) { return "Ext5Impl2-echo"; } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext6_inject/Ext6.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext6_inject/Ext6.java index baa4bf254d..dc6c9536a1 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext6_inject/Ext6.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext6_inject/Ext6.java @@ -27,4 +27,4 @@ import org.apache.dubbo.common.extension.SPI; public interface Ext6 { @Adaptive String echo(URL url, String s); -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext6_inject/impl/Ext6Impl1.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext6_inject/impl/Ext6Impl1.java index 4f746dba8e..2b11b8cc59 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext6_inject/impl/Ext6Impl1.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext6_inject/impl/Ext6Impl1.java @@ -41,4 +41,4 @@ public class Ext6Impl1 implements Ext6 { } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext6_inject/impl/Ext6Impl2.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext6_inject/impl/Ext6Impl2.java index 75ced60571..b704cde273 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext6_inject/impl/Ext6Impl2.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext6_inject/impl/Ext6Impl2.java @@ -36,4 +36,4 @@ public class Ext6Impl2 implements Ext6 { throw new UnsupportedOperationException(); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext6_wrap/WrappedExt.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext6_wrap/WrappedExt.java index 164e0edd06..a4c7bf01c2 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext6_wrap/WrappedExt.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext6_wrap/WrappedExt.java @@ -26,4 +26,4 @@ import org.apache.dubbo.common.extension.SPI; public interface WrappedExt { String echo(URL url, String s); -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext6_wrap/impl/Ext5Impl1.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext6_wrap/impl/Ext5Impl1.java index 52064a1b0f..29338b8831 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext6_wrap/impl/Ext5Impl1.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext6_wrap/impl/Ext5Impl1.java @@ -23,4 +23,4 @@ public class Ext5Impl1 implements WrappedExt { public String echo(URL url, String s) { return "Ext5Impl1-echo"; } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext6_wrap/impl/Ext5Impl2.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext6_wrap/impl/Ext5Impl2.java index 82a8547603..981d023818 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext6_wrap/impl/Ext5Impl2.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext6_wrap/impl/Ext5Impl2.java @@ -23,4 +23,4 @@ public class Ext5Impl2 implements WrappedExt { public String echo(URL url, String s) { return "Ext5Impl2-echo"; } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext6_wrap/impl/Ext5Wrapper1.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext6_wrap/impl/Ext5Wrapper1.java index 54239b195f..9048037ea1 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext6_wrap/impl/Ext5Wrapper1.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext6_wrap/impl/Ext5Wrapper1.java @@ -33,4 +33,4 @@ public class Ext5Wrapper1 implements WrappedExt { echoCount.incrementAndGet(); return instance.echo(url, s); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext6_wrap/impl/Ext5Wrapper2.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext6_wrap/impl/Ext5Wrapper2.java index ec0acb9e1b..40d2e7d21e 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext6_wrap/impl/Ext5Wrapper2.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext6_wrap/impl/Ext5Wrapper2.java @@ -33,4 +33,4 @@ public class Ext5Wrapper2 implements WrappedExt { echoCount.incrementAndGet(); return instance.echo(url, s); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext7/InitErrorExt.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext7/InitErrorExt.java index 9329917a1a..26ad9e37d5 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext7/InitErrorExt.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext7/InitErrorExt.java @@ -28,4 +28,4 @@ import org.apache.dubbo.common.extension.SPI; public interface InitErrorExt { @Adaptive String echo(URL url, String s); -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext7/impl/Ext7Impl.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext7/impl/Ext7Impl.java index 0dbe3c3364..fe64029e5f 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext7/impl/Ext7Impl.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext7/impl/Ext7Impl.java @@ -24,4 +24,4 @@ public class Ext7Impl implements InitErrorExt { return ""; } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext7/impl/Ext7InitErrorImpl.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext7/impl/Ext7InitErrorImpl.java index 2aa04a89a0..4b54f649bd 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext7/impl/Ext7InitErrorImpl.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext7/impl/Ext7InitErrorImpl.java @@ -31,4 +31,4 @@ public class Ext7InitErrorImpl implements InitErrorExt { return ""; } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/AddExt1.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/AddExt1.java index 89da8e61d2..3e1b394c22 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/AddExt1.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/AddExt1.java @@ -27,4 +27,4 @@ import org.apache.dubbo.common.extension.SPI; public interface AddExt1 { @Adaptive String echo(URL url, String s); -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/AddExt2.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/AddExt2.java index ea06e809c6..36f4ec0fe6 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/AddExt2.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/AddExt2.java @@ -27,4 +27,4 @@ import org.apache.dubbo.common.extension.SPI; public interface AddExt2 { @Adaptive String echo(URL url, String s); -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/AddExt3.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/AddExt3.java index 5872469a8b..72429b9571 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/AddExt3.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/AddExt3.java @@ -27,4 +27,4 @@ import org.apache.dubbo.common.extension.SPI; public interface AddExt3 { @Adaptive String echo(URL url, String s); -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/AddExt4.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/AddExt4.java index e1839e4b4b..802ae44ab9 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/AddExt4.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/AddExt4.java @@ -27,4 +27,4 @@ import org.apache.dubbo.common.extension.SPI; public interface AddExt4 { @Adaptive String echo(URL url, String s); -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/impl/AddExt1Impl1.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/impl/AddExt1Impl1.java index 68fb586cd7..e33c7e7cd0 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/impl/AddExt1Impl1.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/impl/AddExt1Impl1.java @@ -23,4 +23,4 @@ public class AddExt1Impl1 implements AddExt1 { public String echo(URL url, String s) { return this.getClass().getSimpleName(); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/impl/AddExt1_ManualAdaptive.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/impl/AddExt1_ManualAdaptive.java index e0361d22a0..2512f721e5 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/impl/AddExt1_ManualAdaptive.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/impl/AddExt1_ManualAdaptive.java @@ -27,4 +27,4 @@ public class AddExt1_ManualAdaptive implements AddExt1 { AddExt1 addExt1 = ExtensionLoader.getExtensionLoader(AddExt1.class).getExtension(url.getParameter("add.ext1")); return addExt1.echo(url, s); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/impl/AddExt1_ManualAdd1.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/impl/AddExt1_ManualAdd1.java index 623d50596d..129840fafe 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/impl/AddExt1_ManualAdd1.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/impl/AddExt1_ManualAdd1.java @@ -23,4 +23,4 @@ public class AddExt1_ManualAdd1 implements AddExt1 { public String echo(URL url, String s) { return this.getClass().getSimpleName(); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/impl/AddExt1_ManualAdd2.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/impl/AddExt1_ManualAdd2.java index adbd88f182..b2ca4de2d3 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/impl/AddExt1_ManualAdd2.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/impl/AddExt1_ManualAdd2.java @@ -23,4 +23,4 @@ public class AddExt1_ManualAdd2 implements AddExt1 { public String echo(URL url, String s) { return this.getClass().getSimpleName(); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/impl/AddExt2Impl1.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/impl/AddExt2Impl1.java index 383f6588ab..e161f59885 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/impl/AddExt2Impl1.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/impl/AddExt2Impl1.java @@ -23,4 +23,4 @@ public class AddExt2Impl1 implements AddExt2 { public String echo(URL url, String s) { return this.getClass().getSimpleName(); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/impl/AddExt2_ManualAdaptive.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/impl/AddExt2_ManualAdaptive.java index 7673c770e7..b0b1d4309d 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/impl/AddExt2_ManualAdaptive.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/impl/AddExt2_ManualAdaptive.java @@ -27,4 +27,4 @@ public class AddExt2_ManualAdaptive implements AddExt2 { AddExt2 addExt1 = ExtensionLoader.getExtensionLoader(AddExt2.class).getExtension(url.getParameter("add.ext2")); return addExt1.echo(url, s); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/impl/AddExt3_ManualAdaptive.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/impl/AddExt3_ManualAdaptive.java index 4d8936582a..9e8f3fac2f 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/impl/AddExt3_ManualAdaptive.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/impl/AddExt3_ManualAdaptive.java @@ -27,4 +27,4 @@ public class AddExt3_ManualAdaptive implements AddExt3 { AddExt3 addExt1 = ExtensionLoader.getExtensionLoader(AddExt3.class).getExtension(url.getParameter("add.ext3")); return addExt1.echo(url, s); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/impl/AddExt4_ManualAdaptive.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/impl/AddExt4_ManualAdaptive.java index cfc69aa2e7..9269ee8325 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/impl/AddExt4_ManualAdaptive.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ext8_add/impl/AddExt4_ManualAdaptive.java @@ -27,4 +27,4 @@ public class AddExt4_ManualAdaptive implements AddExt4 { AddExt4 addExt1 = ExtensionLoader.getExtensionLoader(AddExt4.class).getExtension(url.getParameter("add.ext4")); return addExt1.echo(url, s); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/support/Order0Filter0.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/support/Order0Filter0.java index e30ee072ca..634e92f12f 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/support/Order0Filter0.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/support/Order0Filter0.java @@ -21,4 +21,4 @@ import org.apache.dubbo.common.extension.SPI; @SPI public interface Order0Filter0 { -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/support/Order0Filter1.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/support/Order0Filter1.java index dea8f08e70..cf23ffee94 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/support/Order0Filter1.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/support/Order0Filter1.java @@ -21,4 +21,4 @@ import org.apache.dubbo.common.extension.Activate; @Activate public class Order0Filter1 implements Order0Filter0 { -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/io/BytesTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/io/BytesTest.java index c9e6d8b355..f065164d98 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/io/BytesTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/io/BytesTest.java @@ -161,4 +161,4 @@ public class BytesTest { bb[7] = (byte) (x >> 0); return bb; } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/io/StreamUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/io/StreamUtilsTest.java index 7c2e6b9e21..79ac29e493 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/io/StreamUtilsTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/io/StreamUtilsTest.java @@ -177,4 +177,4 @@ public class StreamUtilsTest { } }); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/io/UnsafeByteArrayInputStreamTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/io/UnsafeByteArrayInputStreamTest.java index bc792fa3f2..9603b4c3d3 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/io/UnsafeByteArrayInputStreamTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/io/UnsafeByteArrayInputStreamTest.java @@ -91,4 +91,4 @@ public class UnsafeByteArrayInputStreamTest { assertThat(skip, is(0L)); assertThat(stream.position(), is(0)); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/io/UnsafeByteArrayOutputStreamTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/io/UnsafeByteArrayOutputStreamTest.java index 715c128e00..dde47f1338 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/io/UnsafeByteArrayOutputStreamTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/io/UnsafeByteArrayOutputStreamTest.java @@ -76,4 +76,4 @@ public class UnsafeByteArrayOutputStreamTest { assertThat(outputStream.toString("UTF-8"), is("Hòa Bình")); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/io/UnsafeStringReaderTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/io/UnsafeStringReaderTest.java index 1ee478f71d..ae7a2984e2 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/io/UnsafeStringReaderTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/io/UnsafeStringReaderTest.java @@ -72,4 +72,4 @@ public class UnsafeStringReaderTest { reader.read(chars, 0, 2); }); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/json/JSONReaderTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/json/JSONReaderTest.java index 2688fa26bf..03200ac44e 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/json/JSONReaderTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/json/JSONReaderTest.java @@ -41,4 +41,4 @@ public class JSONReaderTest { assertEquals(reader.nextToken().type, JSONToken.RSQUARE); assertEquals(reader.nextToken().type, JSONToken.RBRACE); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/json/JSONTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/json/JSONTest.java index 98c342c250..810aca2fa9 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/json/JSONTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/json/JSONTest.java @@ -224,4 +224,4 @@ public class JSONTest { this.name = name; } } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/json/JSONWriterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/json/JSONWriterTest.java index 0d7da710ca..8fccacfbc6 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/json/JSONWriterTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/json/JSONWriterTest.java @@ -47,4 +47,4 @@ public class JSONWriterTest { writer.objectItem("service").objectBegin().objectItem("type").valueString("org.apache.dubbo.TestService").objectItem("version").valueString("1.1.0").objectEnd(); writer.objectEnd(); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/json/MyException.java b/dubbo-common/src/test/java/org/apache/dubbo/common/json/MyException.java index 3d2df874cb..768d109595 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/json/MyException.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/json/MyException.java @@ -1,41 +1,41 @@ -/* - * 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.common.json; - -public class MyException extends Exception { - - private static final long serialVersionUID = 2905707783883694687L; - - private String code; - - public MyException() { - } - - public MyException(String code, String message) { - super(message); - this.code = code; - } - - public String getCode() { - return code; - } - - public void setCode(String code) { - this.code = code; - } - -} \ No newline at end of file +/* + * 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.common.json; + +public class MyException extends Exception { + + private static final long serialVersionUID = 2905707783883694687L; + + private String code; + + public MyException() { + } + + public MyException(String code, String message) { + super(message); + this.code = code; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/logger/LoggerAdapterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/logger/LoggerAdapterTest.java index 1d6fbe77e0..0a9686ff64 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/logger/LoggerAdapterTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/logger/LoggerAdapterTest.java @@ -68,4 +68,4 @@ public class LoggerAdapterTest { assertThat(loggerAdapter.getLevel(), is(targetLevel)); } } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/logger/LoggerTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/logger/LoggerTest.java index 81987f782d..6e6cd3c676 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/logger/LoggerTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/logger/LoggerTest.java @@ -82,4 +82,4 @@ public class LoggerTest { assertThat(logger.isInfoEnabled(), not(nullValue())); assertThat(logger.isDebugEnabled(), not(nullValue())); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/logger/slf4j/Slf4jLoggerTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/logger/slf4j/Slf4jLoggerTest.java index d53ce2e83b..0f2f2ce75b 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/logger/slf4j/Slf4jLoggerTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/logger/slf4j/Slf4jLoggerTest.java @@ -59,4 +59,4 @@ public class Slf4jLoggerTest { verify(locationAwareLogger, times(10)).log(isNull(Marker.class), anyString(), anyInt(), anyString(), isNull(Object[].class), any(Throwable.class)); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/logger/support/FailsafeLoggerTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/logger/support/FailsafeLoggerTest.java index 530c2a1d61..841c68eb7a 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/logger/support/FailsafeLoggerTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/logger/support/FailsafeLoggerTest.java @@ -103,4 +103,4 @@ public class FailsafeLoggerTest { failsafeLogger.getLogger().error("should get error"); }); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/model/Person.java b/dubbo-common/src/test/java/org/apache/dubbo/common/model/Person.java index 5a551a7f36..81b42722dc 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/model/Person.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/model/Person.java @@ -92,4 +92,4 @@ public class Person { return false; return true; } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/model/media/Image.java b/dubbo-common/src/test/java/org/apache/dubbo/common/model/media/Image.java index a59eff35be..1469b1ed8c 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/model/media/Image.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/model/media/Image.java @@ -117,4 +117,4 @@ public class Image implements java.io.Serializable { public enum Size { SMALL, LARGE } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/model/media/Media.java b/dubbo-common/src/test/java/org/apache/dubbo/common/model/media/Media.java index 042a3a5273..4132b96d41 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/model/media/Media.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/model/media/Media.java @@ -202,4 +202,4 @@ public class Media implements java.io.Serializable { public enum Player { JAVA, FLASH } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/model/person/BigPerson.java b/dubbo-common/src/test/java/org/apache/dubbo/common/model/person/BigPerson.java index 4ce79008fb..9a653e2988 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/model/person/BigPerson.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/model/person/BigPerson.java @@ -148,4 +148,4 @@ public class BigPerson implements Serializable { + infoProfile + "]"; } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/model/person/FullAddress.java b/dubbo-common/src/test/java/org/apache/dubbo/common/model/person/FullAddress.java index 38921670f9..d50492d23c 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/model/person/FullAddress.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/model/person/FullAddress.java @@ -199,4 +199,4 @@ public class FullAddress implements Serializable { return sb.toString(); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/model/person/PersonStatus.java b/dubbo-common/src/test/java/org/apache/dubbo/common/model/person/PersonStatus.java index 62869c2b80..fc10d88429 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/model/person/PersonStatus.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/model/person/PersonStatus.java @@ -19,4 +19,4 @@ package org.apache.dubbo.common.model.person; public enum PersonStatus { ENABLED, DISABLED -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/model/person/Phone.java b/dubbo-common/src/test/java/org/apache/dubbo/common/model/person/Phone.java index 41fd38a92d..e47656c787 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/model/person/Phone.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/model/person/Phone.java @@ -136,4 +136,4 @@ public class Phone implements Serializable { return sb.toString(); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/threadlocal/InternalThreadLocalTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/threadlocal/InternalThreadLocalTest.java index 8df34f8e35..460b953a67 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/threadlocal/InternalThreadLocalTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/threadlocal/InternalThreadLocalTest.java @@ -215,4 +215,4 @@ public class InternalThreadLocalTest { t.start(); LockSupport.park(mainThread); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/threadlocal/NamedInternalThreadFactoryTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/threadlocal/NamedInternalThreadFactoryTest.java index 346da3a523..06b072356f 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/threadlocal/NamedInternalThreadFactoryTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/threadlocal/NamedInternalThreadFactoryTest.java @@ -33,4 +33,4 @@ public class NamedInternalThreadFactoryTest { }); Assertions.assertEquals(t.getClass(), InternalThread.class, "thread is not InternalThread"); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/threadpool/support/AbortPolicyWithReportTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/threadpool/support/AbortPolicyWithReportTest.java index 122b54a217..1319d92cd2 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/threadpool/support/AbortPolicyWithReportTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/threadpool/support/AbortPolicyWithReportTest.java @@ -126,4 +126,4 @@ public class AbortPolicyWithReportTest { return threadPoolExhaustedEvent; } } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/threadpool/support/eager/EagerThreadPoolExecutorTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/threadpool/support/eager/EagerThreadPoolExecutorTest.java index f8fdbfb7e2..3836cd6702 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/threadpool/support/eager/EagerThreadPoolExecutorTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/threadpool/support/eager/EagerThreadPoolExecutorTest.java @@ -99,4 +99,4 @@ public class EagerThreadPoolExecutorTest { Assertions.assertEquals("EagerThreadPoolExecutor", executorService.getClass() .getSimpleName(), "test spi fail!"); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/timer/HashedWheelTimerTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/timer/HashedWheelTimerTest.java index 9b9c5ee120..6729b944a8 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/timer/HashedWheelTimerTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/timer/HashedWheelTimerTest.java @@ -195,4 +195,4 @@ public class HashedWheelTimerTest { () -> timer.newTimeout(new EmptyTask(), 5, TimeUnit.SECONDS)); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ArrayUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ArrayUtilsTest.java index 9d19f18b1d..4f7edf245e 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ArrayUtilsTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ArrayUtilsTest.java @@ -38,4 +38,4 @@ public class ArrayUtilsTest { assertTrue(ArrayUtils.isNotEmpty(new Object[]{"abc"})); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/AtomicPositiveIntegerTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/AtomicPositiveIntegerTest.java index f57b943a65..90d0430fcf 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/AtomicPositiveIntegerTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/AtomicPositiveIntegerTest.java @@ -203,4 +203,4 @@ public class AtomicPositiveIntegerTest { assertEquals(new AtomicPositiveInteger(), new AtomicPositiveInteger()); assertEquals(new AtomicPositiveInteger(1), new AtomicPositiveInteger(1)); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/CollectionUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/CollectionUtilsTest.java index d65e92ea0f..cdb6e45e5b 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/CollectionUtilsTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/CollectionUtilsTest.java @@ -215,4 +215,4 @@ public class CollectionUtilsTest { expectedSet.add("C"); assertEquals(expectedSet, set); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/CompatibleTypeUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/CompatibleTypeUtilsTest.java index 6a838c7cb7..ee9adc2c0e 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/CompatibleTypeUtilsTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/CompatibleTypeUtilsTest.java @@ -1,222 +1,222 @@ -/* - * 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.common.utils; - -import org.junit.jupiter.api.Test; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.text.SimpleDateFormat; -import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.CopyOnWriteArrayList; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertSame; -import static org.junit.jupiter.api.Assertions.assertTrue; - -public class CompatibleTypeUtilsTest { - - @SuppressWarnings("unchecked") - @Test - public void testCompatibleTypeConvert() throws Exception { - Object result; - - { - Object input = new Object(); - result = CompatibleTypeUtils.compatibleTypeConvert(input, Date.class); - assertSame(input, result); - - result = CompatibleTypeUtils.compatibleTypeConvert(input, null); - assertSame(input, result); - - result = CompatibleTypeUtils.compatibleTypeConvert(null, Date.class); - assertNull(result); - } - - { - result = CompatibleTypeUtils.compatibleTypeConvert("a", char.class); - assertEquals(Character.valueOf('a'), (Character) result); - - result = CompatibleTypeUtils.compatibleTypeConvert("A", MyEnum.class); - assertEquals(MyEnum.A, (MyEnum) result); - - result = CompatibleTypeUtils.compatibleTypeConvert("3", BigInteger.class); - assertEquals(new BigInteger("3"), (BigInteger) result); - - result = CompatibleTypeUtils.compatibleTypeConvert("3", BigDecimal.class); - assertEquals(new BigDecimal("3"), (BigDecimal) result); - - result = CompatibleTypeUtils.compatibleTypeConvert("2011-12-11 12:24:12", Date.class); - assertEquals(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2011-12-11 12:24:12"), (Date) result); - - result = CompatibleTypeUtils.compatibleTypeConvert("2011-12-11 12:24:12", java.sql.Date.class); - assertEquals(new SimpleDateFormat("yyyy-MM-dd").format((java.sql.Date) result), "2011-12-11"); - - result = CompatibleTypeUtils.compatibleTypeConvert("2011-12-11 12:24:12", java.sql.Time.class); - assertEquals(new SimpleDateFormat("HH:mm:ss").format((java.sql.Time) result), "12:24:12"); - - result = CompatibleTypeUtils.compatibleTypeConvert("2011-12-11 12:24:12", java.sql.Timestamp.class); - assertEquals(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((java.sql.Timestamp) result), "2011-12-11 12:24:12"); - - result = CompatibleTypeUtils.compatibleTypeConvert("2011-12-11T12:24:12.047", java.time.LocalDateTime.class); - assertEquals(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format((java.time.LocalDateTime) result), "2011-12-11 12:24:12"); - - result = CompatibleTypeUtils.compatibleTypeConvert("2011-12-11T12:24:12.047", java.time.LocalTime.class); - assertEquals(DateTimeFormatter.ofPattern("HH:mm:ss").format((java.time.LocalTime) result), "12:24:12"); - - result = CompatibleTypeUtils.compatibleTypeConvert("2011-12-11", java.time.LocalDate.class); - assertEquals(DateTimeFormatter.ofPattern("yyyy-MM-dd").format((java.time.LocalDate) result), "2011-12-11"); - - result = CompatibleTypeUtils.compatibleTypeConvert("ab", char[].class); - assertEquals(2, ((char[]) result).length); - assertEquals('a', ((char[]) result)[0]); - assertEquals('b', ((char[]) result)[1]); - - result = CompatibleTypeUtils.compatibleTypeConvert("", char[].class); - assertEquals(0, ((char[]) result).length); - - result = CompatibleTypeUtils.compatibleTypeConvert(null, char[].class); - assertNull(result); - } - - { - result = CompatibleTypeUtils.compatibleTypeConvert(3, byte.class); - assertEquals(Byte.valueOf((byte) 3), (Byte) result); - - result = CompatibleTypeUtils.compatibleTypeConvert((byte) 3, int.class); - assertEquals(Integer.valueOf(3), (Integer) result); - - result = CompatibleTypeUtils.compatibleTypeConvert(3, short.class); - assertEquals(Short.valueOf((short) 3), (Short) result); - - result = CompatibleTypeUtils.compatibleTypeConvert((short) 3, int.class); - assertEquals(Integer.valueOf(3), (Integer) result); - - result = CompatibleTypeUtils.compatibleTypeConvert(3, int.class); - assertEquals(Integer.valueOf(3), (Integer) result); - - result = CompatibleTypeUtils.compatibleTypeConvert(3, long.class); - assertEquals(Long.valueOf(3), (Long) result); - - result = CompatibleTypeUtils.compatibleTypeConvert(3L, int.class); - assertEquals(Integer.valueOf(3), (Integer) result); - - result = CompatibleTypeUtils.compatibleTypeConvert(3L, BigInteger.class); - assertEquals(BigInteger.valueOf(3L), (BigInteger) result); - - result = CompatibleTypeUtils.compatibleTypeConvert(BigInteger.valueOf(3L), int.class); - assertEquals(Integer.valueOf(3), (Integer) result); - } - - { - result = CompatibleTypeUtils.compatibleTypeConvert(3D, float.class); - assertEquals(Float.valueOf(3), (Float) result); - - result = CompatibleTypeUtils.compatibleTypeConvert(3F, double.class); - assertEquals(Double.valueOf(3), (Double) result); - - result = CompatibleTypeUtils.compatibleTypeConvert(3D, double.class); - assertEquals(Double.valueOf(3), (Double) result); - - result = CompatibleTypeUtils.compatibleTypeConvert(3D, BigDecimal.class); - assertEquals(BigDecimal.valueOf(3D), (BigDecimal) result); - - result = CompatibleTypeUtils.compatibleTypeConvert(BigDecimal.valueOf(3D), double.class); - assertEquals(Double.valueOf(3), (Double) result); - } - - { - List list = new ArrayList(); - list.add("a"); - list.add("b"); - - Set set = new HashSet(); - set.add("a"); - set.add("b"); - - String[] array = new String[]{"a", "b"}; - - result = CompatibleTypeUtils.compatibleTypeConvert(array, List.class); - assertEquals(ArrayList.class, result.getClass()); - assertEquals(2, ((List) result).size()); - assertTrue(((List) result).contains("a")); - assertTrue(((List) result).contains("b")); - - result = CompatibleTypeUtils.compatibleTypeConvert(set, List.class); - assertEquals(ArrayList.class, result.getClass()); - assertEquals(2, ((List) result).size()); - assertTrue(((List) result).contains("a")); - assertTrue(((List) result).contains("b")); - - result = CompatibleTypeUtils.compatibleTypeConvert(array, CopyOnWriteArrayList.class); - assertEquals(CopyOnWriteArrayList.class, result.getClass()); - assertEquals(2, ((List) result).size()); - assertTrue(((List) result).contains("a")); - assertTrue(((List) result).contains("b")); - - result = CompatibleTypeUtils.compatibleTypeConvert(set, CopyOnWriteArrayList.class); - assertEquals(CopyOnWriteArrayList.class, result.getClass()); - assertEquals(2, ((List) result).size()); - assertTrue(((List) result).contains("a")); - assertTrue(((List) result).contains("b")); - - result = CompatibleTypeUtils.compatibleTypeConvert(set, String[].class); - assertEquals(String[].class, result.getClass()); - assertEquals(2, ((String[]) result).length); - assertTrue(((String[]) result)[0].equals("a") || ((String[]) result)[0].equals("b")); - assertTrue(((String[]) result)[1].equals("a") || ((String[]) result)[1].equals("b")); - - result = CompatibleTypeUtils.compatibleTypeConvert(array, Set.class); - assertEquals(HashSet.class, result.getClass()); - assertEquals(2, ((Set) result).size()); - assertTrue(((Set) result).contains("a")); - assertTrue(((Set) result).contains("b")); - - result = CompatibleTypeUtils.compatibleTypeConvert(list, Set.class); - assertEquals(HashSet.class, result.getClass()); - assertEquals(2, ((Set) result).size()); - assertTrue(((Set) result).contains("a")); - assertTrue(((Set) result).contains("b")); - - result = CompatibleTypeUtils.compatibleTypeConvert(array, ConcurrentHashSet.class); - assertEquals(ConcurrentHashSet.class, result.getClass()); - assertEquals(2, ((Set) result).size()); - assertTrue(((Set) result).contains("a")); - assertTrue(((Set) result).contains("b")); - - result = CompatibleTypeUtils.compatibleTypeConvert(list, ConcurrentHashSet.class); - assertEquals(ConcurrentHashSet.class, result.getClass()); - assertEquals(2, ((Set) result).size()); - assertTrue(((Set) result).contains("a")); - assertTrue(((Set) result).contains("b")); - - result = CompatibleTypeUtils.compatibleTypeConvert(list, String[].class); - assertEquals(String[].class, result.getClass()); - assertEquals(2, ((String[]) result).length); - assertTrue(((String[]) result)[0].equals("a")); - assertTrue(((String[]) result)[1].equals("b")); - - } - - } -} \ No newline at end of file +/* + * 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.common.utils; + +import org.junit.jupiter.api.Test; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.text.SimpleDateFormat; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArrayList; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class CompatibleTypeUtilsTest { + + @SuppressWarnings("unchecked") + @Test + public void testCompatibleTypeConvert() throws Exception { + Object result; + + { + Object input = new Object(); + result = CompatibleTypeUtils.compatibleTypeConvert(input, Date.class); + assertSame(input, result); + + result = CompatibleTypeUtils.compatibleTypeConvert(input, null); + assertSame(input, result); + + result = CompatibleTypeUtils.compatibleTypeConvert(null, Date.class); + assertNull(result); + } + + { + result = CompatibleTypeUtils.compatibleTypeConvert("a", char.class); + assertEquals(Character.valueOf('a'), (Character) result); + + result = CompatibleTypeUtils.compatibleTypeConvert("A", MyEnum.class); + assertEquals(MyEnum.A, (MyEnum) result); + + result = CompatibleTypeUtils.compatibleTypeConvert("3", BigInteger.class); + assertEquals(new BigInteger("3"), (BigInteger) result); + + result = CompatibleTypeUtils.compatibleTypeConvert("3", BigDecimal.class); + assertEquals(new BigDecimal("3"), (BigDecimal) result); + + result = CompatibleTypeUtils.compatibleTypeConvert("2011-12-11 12:24:12", Date.class); + assertEquals(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2011-12-11 12:24:12"), (Date) result); + + result = CompatibleTypeUtils.compatibleTypeConvert("2011-12-11 12:24:12", java.sql.Date.class); + assertEquals(new SimpleDateFormat("yyyy-MM-dd").format((java.sql.Date) result), "2011-12-11"); + + result = CompatibleTypeUtils.compatibleTypeConvert("2011-12-11 12:24:12", java.sql.Time.class); + assertEquals(new SimpleDateFormat("HH:mm:ss").format((java.sql.Time) result), "12:24:12"); + + result = CompatibleTypeUtils.compatibleTypeConvert("2011-12-11 12:24:12", java.sql.Timestamp.class); + assertEquals(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((java.sql.Timestamp) result), "2011-12-11 12:24:12"); + + result = CompatibleTypeUtils.compatibleTypeConvert("2011-12-11T12:24:12.047", java.time.LocalDateTime.class); + assertEquals(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format((java.time.LocalDateTime) result), "2011-12-11 12:24:12"); + + result = CompatibleTypeUtils.compatibleTypeConvert("2011-12-11T12:24:12.047", java.time.LocalTime.class); + assertEquals(DateTimeFormatter.ofPattern("HH:mm:ss").format((java.time.LocalTime) result), "12:24:12"); + + result = CompatibleTypeUtils.compatibleTypeConvert("2011-12-11", java.time.LocalDate.class); + assertEquals(DateTimeFormatter.ofPattern("yyyy-MM-dd").format((java.time.LocalDate) result), "2011-12-11"); + + result = CompatibleTypeUtils.compatibleTypeConvert("ab", char[].class); + assertEquals(2, ((char[]) result).length); + assertEquals('a', ((char[]) result)[0]); + assertEquals('b', ((char[]) result)[1]); + + result = CompatibleTypeUtils.compatibleTypeConvert("", char[].class); + assertEquals(0, ((char[]) result).length); + + result = CompatibleTypeUtils.compatibleTypeConvert(null, char[].class); + assertNull(result); + } + + { + result = CompatibleTypeUtils.compatibleTypeConvert(3, byte.class); + assertEquals(Byte.valueOf((byte) 3), (Byte) result); + + result = CompatibleTypeUtils.compatibleTypeConvert((byte) 3, int.class); + assertEquals(Integer.valueOf(3), (Integer) result); + + result = CompatibleTypeUtils.compatibleTypeConvert(3, short.class); + assertEquals(Short.valueOf((short) 3), (Short) result); + + result = CompatibleTypeUtils.compatibleTypeConvert((short) 3, int.class); + assertEquals(Integer.valueOf(3), (Integer) result); + + result = CompatibleTypeUtils.compatibleTypeConvert(3, int.class); + assertEquals(Integer.valueOf(3), (Integer) result); + + result = CompatibleTypeUtils.compatibleTypeConvert(3, long.class); + assertEquals(Long.valueOf(3), (Long) result); + + result = CompatibleTypeUtils.compatibleTypeConvert(3L, int.class); + assertEquals(Integer.valueOf(3), (Integer) result); + + result = CompatibleTypeUtils.compatibleTypeConvert(3L, BigInteger.class); + assertEquals(BigInteger.valueOf(3L), (BigInteger) result); + + result = CompatibleTypeUtils.compatibleTypeConvert(BigInteger.valueOf(3L), int.class); + assertEquals(Integer.valueOf(3), (Integer) result); + } + + { + result = CompatibleTypeUtils.compatibleTypeConvert(3D, float.class); + assertEquals(Float.valueOf(3), (Float) result); + + result = CompatibleTypeUtils.compatibleTypeConvert(3F, double.class); + assertEquals(Double.valueOf(3), (Double) result); + + result = CompatibleTypeUtils.compatibleTypeConvert(3D, double.class); + assertEquals(Double.valueOf(3), (Double) result); + + result = CompatibleTypeUtils.compatibleTypeConvert(3D, BigDecimal.class); + assertEquals(BigDecimal.valueOf(3D), (BigDecimal) result); + + result = CompatibleTypeUtils.compatibleTypeConvert(BigDecimal.valueOf(3D), double.class); + assertEquals(Double.valueOf(3), (Double) result); + } + + { + List list = new ArrayList(); + list.add("a"); + list.add("b"); + + Set set = new HashSet(); + set.add("a"); + set.add("b"); + + String[] array = new String[]{"a", "b"}; + + result = CompatibleTypeUtils.compatibleTypeConvert(array, List.class); + assertEquals(ArrayList.class, result.getClass()); + assertEquals(2, ((List) result).size()); + assertTrue(((List) result).contains("a")); + assertTrue(((List) result).contains("b")); + + result = CompatibleTypeUtils.compatibleTypeConvert(set, List.class); + assertEquals(ArrayList.class, result.getClass()); + assertEquals(2, ((List) result).size()); + assertTrue(((List) result).contains("a")); + assertTrue(((List) result).contains("b")); + + result = CompatibleTypeUtils.compatibleTypeConvert(array, CopyOnWriteArrayList.class); + assertEquals(CopyOnWriteArrayList.class, result.getClass()); + assertEquals(2, ((List) result).size()); + assertTrue(((List) result).contains("a")); + assertTrue(((List) result).contains("b")); + + result = CompatibleTypeUtils.compatibleTypeConvert(set, CopyOnWriteArrayList.class); + assertEquals(CopyOnWriteArrayList.class, result.getClass()); + assertEquals(2, ((List) result).size()); + assertTrue(((List) result).contains("a")); + assertTrue(((List) result).contains("b")); + + result = CompatibleTypeUtils.compatibleTypeConvert(set, String[].class); + assertEquals(String[].class, result.getClass()); + assertEquals(2, ((String[]) result).length); + assertTrue(((String[]) result)[0].equals("a") || ((String[]) result)[0].equals("b")); + assertTrue(((String[]) result)[1].equals("a") || ((String[]) result)[1].equals("b")); + + result = CompatibleTypeUtils.compatibleTypeConvert(array, Set.class); + assertEquals(HashSet.class, result.getClass()); + assertEquals(2, ((Set) result).size()); + assertTrue(((Set) result).contains("a")); + assertTrue(((Set) result).contains("b")); + + result = CompatibleTypeUtils.compatibleTypeConvert(list, Set.class); + assertEquals(HashSet.class, result.getClass()); + assertEquals(2, ((Set) result).size()); + assertTrue(((Set) result).contains("a")); + assertTrue(((Set) result).contains("b")); + + result = CompatibleTypeUtils.compatibleTypeConvert(array, ConcurrentHashSet.class); + assertEquals(ConcurrentHashSet.class, result.getClass()); + assertEquals(2, ((Set) result).size()); + assertTrue(((Set) result).contains("a")); + assertTrue(((Set) result).contains("b")); + + result = CompatibleTypeUtils.compatibleTypeConvert(list, ConcurrentHashSet.class); + assertEquals(ConcurrentHashSet.class, result.getClass()); + assertEquals(2, ((Set) result).size()); + assertTrue(((Set) result).contains("a")); + assertTrue(((Set) result).contains("b")); + + result = CompatibleTypeUtils.compatibleTypeConvert(list, String[].class); + assertEquals(String[].class, result.getClass()); + assertEquals(2, ((String[]) result).length); + assertTrue(((String[]) result)[0].equals("a")); + assertTrue(((String[]) result)[1].equals("b")); + + } + + } +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/MyEnum.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/MyEnum.java index 8a6649a949..2d501e542d 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/MyEnum.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/MyEnum.java @@ -1,26 +1,26 @@ -/* - * 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.common.utils; - -/** - * MyEnum - */ -public enum MyEnum { - - A, B - -} \ No newline at end of file +/* + * 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.common.utils; + +/** + * MyEnum + */ +public enum MyEnum { + + A, B + +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/NetUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/NetUtilsTest.java index b6416aa302..6c3e1bdb12 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/NetUtilsTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/NetUtilsTest.java @@ -1,325 +1,325 @@ -/* - * 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.common.utils; - - -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.UnknownHostException; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.greaterThan; -import static org.hamcrest.Matchers.greaterThanOrEqualTo; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assumptions.assumeTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class NetUtilsTest { - - @Test - public void testGetRandomPort() throws Exception { - assertThat(NetUtils.getRandomPort(), greaterThanOrEqualTo(30000)); - assertThat(NetUtils.getRandomPort(), greaterThanOrEqualTo(30000)); - assertThat(NetUtils.getRandomPort(), greaterThanOrEqualTo(30000)); - } - - @Test - public void testGetAvailablePort() throws Exception { - assertThat(NetUtils.getAvailablePort(), greaterThan(0)); - assertThat(NetUtils.getAvailablePort(12345), greaterThanOrEqualTo(12345)); - assertThat(NetUtils.getAvailablePort(-1), greaterThanOrEqualTo(0)); - } - - @Test - public void testValidAddress() throws Exception { - assertTrue(NetUtils.isValidAddress("10.20.130.230:20880")); - assertFalse(NetUtils.isValidAddress("10.20.130.230")); - assertFalse(NetUtils.isValidAddress("10.20.130.230:666666")); - } - - @Test - public void testIsInvalidPort() throws Exception { - assertTrue(NetUtils.isInvalidPort(0)); - assertTrue(NetUtils.isInvalidPort(65536)); - assertFalse(NetUtils.isInvalidPort(1024)); - } - - @Test - public void testIsLocalHost() throws Exception { - assertTrue(NetUtils.isLocalHost("localhost")); - assertTrue(NetUtils.isLocalHost("127.1.2.3")); - assertFalse(NetUtils.isLocalHost("128.1.2.3")); - } - - @Test - public void testIsAnyHost() throws Exception { - assertTrue(NetUtils.isAnyHost("0.0.0.0")); - assertFalse(NetUtils.isAnyHost("1.1.1.1")); - } - - @Test - public void testIsInvalidLocalHost() throws Exception { - assertTrue(NetUtils.isInvalidLocalHost(null)); - assertTrue(NetUtils.isInvalidLocalHost("")); - assertTrue(NetUtils.isInvalidLocalHost("localhost")); - assertTrue(NetUtils.isInvalidLocalHost("0.0.0.0")); - assertTrue(NetUtils.isInvalidLocalHost("127.1.2.3")); - assertTrue(NetUtils.isInvalidLocalHost("127.0.0.1")); - assertFalse(NetUtils.isInvalidLocalHost("128.0.0.1")); - } - - @Test - public void testIsValidLocalHost() throws Exception { - assertTrue(NetUtils.isValidLocalHost("1.2.3.4")); - assertTrue(NetUtils.isValidLocalHost("128.0.0.1")); - } - - @Test - public void testGetLocalSocketAddress() throws Exception { - InetSocketAddress address = NetUtils.getLocalSocketAddress("localhost", 12345); - assertTrue(address.getAddress().isAnyLocalAddress()); - assertEquals(address.getPort(), 12345); - address = NetUtils.getLocalSocketAddress("dubbo-addr", 12345); - assertEquals(address.getHostName(), "dubbo-addr"); - assertEquals(address.getPort(), 12345); - } - - @Test - public void testIsValidAddress() throws Exception { - assertFalse(NetUtils.isValidV4Address((InetAddress) null)); - InetAddress address = mock(InetAddress.class); - when(address.isLoopbackAddress()).thenReturn(true); - assertFalse(NetUtils.isValidV4Address(address)); - address = mock(InetAddress.class); - when(address.getHostAddress()).thenReturn("localhost"); - assertFalse(NetUtils.isValidV4Address(address)); - address = mock(InetAddress.class); - when(address.getHostAddress()).thenReturn("0.0.0.0"); - assertFalse(NetUtils.isValidV4Address(address)); - address = mock(InetAddress.class); - when(address.getHostAddress()).thenReturn("127.0.0.1"); - assertFalse(NetUtils.isValidV4Address(address)); - address = mock(InetAddress.class); - when(address.getHostAddress()).thenReturn("1.2.3.4"); - assertTrue(NetUtils.isValidV4Address(address)); - } - - @Test - public void testGetLocalHost() throws Exception { - assertNotNull(NetUtils.getLocalHost()); - } - - @Test - public void testGetLocalAddress() throws Exception { - InetAddress address = NetUtils.getLocalAddress(); - assertNotNull(address); - assertTrue(NetUtils.isValidLocalHost(address.getHostAddress())); - } - - @Test - public void testFilterLocalHost() throws Exception { - assertNull(NetUtils.filterLocalHost(null)); - assertEquals(NetUtils.filterLocalHost(""), ""); - String host = NetUtils.filterLocalHost("dubbo://127.0.0.1:8080/foo"); - assertThat(host, equalTo("dubbo://" + NetUtils.getLocalHost() + ":8080/foo")); - host = NetUtils.filterLocalHost("127.0.0.1:8080"); - assertThat(host, equalTo(NetUtils.getLocalHost() + ":8080")); - host = NetUtils.filterLocalHost("0.0.0.0"); - assertThat(host, equalTo(NetUtils.getLocalHost())); - host = NetUtils.filterLocalHost("88.88.88.88"); - assertThat(host, equalTo(host)); - } - - @Test - public void testGetHostName() throws Exception { - assertNotNull(NetUtils.getHostName("127.0.0.1")); - } - - @Test - public void testGetIpByHost() throws Exception { - assertThat(NetUtils.getIpByHost("localhost"), equalTo("127.0.0.1")); - assertThat(NetUtils.getIpByHost("dubbo.local"), equalTo("dubbo.local")); - } - - @Test - public void testToAddressString() throws Exception { - InetAddress address = mock(InetAddress.class); - when(address.getHostAddress()).thenReturn("dubbo"); - InetSocketAddress socketAddress = new InetSocketAddress(address, 1234); - assertThat(NetUtils.toAddressString(socketAddress), equalTo("dubbo:1234")); - } - - @Test - public void testToAddress() throws Exception { - InetSocketAddress address = NetUtils.toAddress("localhost:1234"); - assertThat(address.getHostName(), equalTo("localhost")); - assertThat(address.getPort(), equalTo(1234)); - address = NetUtils.toAddress("localhost"); - assertThat(address.getHostName(), equalTo("localhost")); - assertThat(address.getPort(), equalTo(0)); - } - - @Test - public void testToURL() throws Exception { - String url = NetUtils.toURL("dubbo", "host", 1234, "foo"); - assertThat(url, equalTo("dubbo://host:1234/foo")); - } - - @Test - public void testIsValidV6Address() { - String saved = System.getProperty("java.net.preferIPv6Addresses", "false"); - System.setProperty("java.net.preferIPv6Addresses", "true"); - - InetAddress address = NetUtils.getLocalAddress(); - boolean isPreferIPV6Address = NetUtils.isPreferIPV6Address(); - - // Restore system property to previous value before executing test - System.setProperty("java.net.preferIPv6Addresses", saved); - - assumeTrue(address instanceof Inet6Address); - assertThat(isPreferIPV6Address, equalTo(true)); - } - - /** - * Mockito starts to support mocking final classes since 2.1.0 - * see https://github.com/mockito/mockito/wiki/What%27s-new-in-Mockito-2#unmockable - * But enable it will cause other UT to fail. - * Therefore currently disabling this UT. - */ - @Disabled - @Test - public void testNormalizeV6Address() { - Inet6Address address = mock(Inet6Address.class); - when(address.getHostAddress()).thenReturn("fe80:0:0:0:894:aeec:f37d:23e1%en0"); - when(address.getScopeId()).thenReturn(5); - InetAddress normalized = NetUtils.normalizeV6Address(address); - assertThat(normalized.getHostAddress(), equalTo("fe80:0:0:0:894:aeec:f37d:23e1%5")); - } - - @Test - public void testMatchIpRangeMatchWhenIpv4() throws UnknownHostException { - assertTrue(NetUtils.matchIpRange("*.*.*.*", "192.168.1.63", 90)); - assertTrue(NetUtils.matchIpRange("192.168.1.*", "192.168.1.63", 90)); - assertTrue(NetUtils.matchIpRange("192.168.1.63", "192.168.1.63", 90)); - assertTrue(NetUtils.matchIpRange("192.168.1.1-65", "192.168.1.63", 90)); - assertFalse(NetUtils.matchIpRange("192.168.1.1-61", "192.168.1.63", 90)); - assertFalse(NetUtils.matchIpRange("192.168.1.62", "192.168.1.63", 90)); - } - - @Test - public void testMatchIpRangeMatchWhenIpv6() throws UnknownHostException { - assertTrue(NetUtils.matchIpRange("*.*.*.*", "192.168.1.63", 90)); - assertTrue(NetUtils.matchIpRange("234e:0:4567:0:0:0:3d:*", "234e:0:4567::3d:ff", 90)); - assertTrue(NetUtils.matchIpRange("234e:0:4567:0:0:0:3d:ee", "234e:0:4567::3d:ee", 90)); - assertTrue(NetUtils.matchIpRange("234e:0:4567::3d:ee", "234e:0:4567::3d:ee", 90)); - assertTrue(NetUtils.matchIpRange("234e:0:4567:0:0:0:3d:0-ff", "234e:0:4567::3d:ee", 90)); - assertTrue(NetUtils.matchIpRange("234e:0:4567:0:0:0:3d:0-ee", "234e:0:4567::3d:ee", 90)); - - assertFalse(NetUtils.matchIpRange("234e:0:4567:0:0:0:3d:ff", "234e:0:4567::3d:ee", 90)); - assertFalse(NetUtils.matchIpRange("234e:0:4567:0:0:0:3d:0-ea", "234e:0:4567::3d:ee", 90)); - } - - @Test - public void testMatchIpRangeMatchWhenIpv6Exception() throws UnknownHostException { - IllegalArgumentException thrown = - assertThrows(IllegalArgumentException.class, () -> - NetUtils.matchIpRange("234e:0:4567::3d:*", "234e:0:4567::3d:ff", 90)); - assertTrue(thrown.getMessage().contains("If you config ip expression that contains '*'")); - - thrown = assertThrows(IllegalArgumentException.class, () -> - NetUtils.matchIpRange("234e:0:4567:3d", "234e:0:4567::3d:ff", 90)); - assertTrue(thrown.getMessage().contains("The host is ipv6, but the pattern is not ipv6 pattern")); - - thrown = - assertThrows(IllegalArgumentException.class, () -> - NetUtils.matchIpRange("192.168.1.1-65-3", "192.168.1.63", 90)); - assertTrue(thrown.getMessage().contains("There is wrong format of ip Address")); - } - - @Test - public void testMatchIpRangeMatchWhenIpWrongException() throws UnknownHostException { - UnknownHostException thrown = - assertThrows(UnknownHostException.class, () -> - NetUtils.matchIpRange("192.168.1.63", "192.168.1.ff", 90)); - assertTrue(thrown.getMessage().contains("192.168.1.ff")); - } - - @Test - public void testMatchIpMatch() throws UnknownHostException { - assertTrue(NetUtils.matchIpExpression("192.168.1.*", "192.168.1.63", 90)); - assertTrue(NetUtils.matchIpExpression("192.168.1.192/26", "192.168.1.199", 90)); - } - - @Test - public void testMatchIpv6WithIpPort() throws UnknownHostException { - assertTrue(NetUtils.matchIpRange("[234e:0:4567::3d:ee]", "234e:0:4567::3d:ee", 8090)); - assertTrue(NetUtils.matchIpRange("[234e:0:4567:0:0:0:3d:ee]", "234e:0:4567::3d:ee", 8090)); - assertTrue(NetUtils.matchIpRange("[234e:0:4567:0:0:0:3d:ee]:8090", "234e:0:4567::3d:ee", 8090)); - assertTrue(NetUtils.matchIpRange("[234e:0:4567:0:0:0:3d:0-ee]:8090", "234e:0:4567::3d:ee", 8090)); - assertTrue(NetUtils.matchIpRange("[234e:0:4567:0:0:0:3d:ee-ff]:8090", "234e:0:4567::3d:ee", 8090)); - assertTrue(NetUtils.matchIpRange("[234e:0:4567:0:0:0:3d:*]:90", "234e:0:4567::3d:ff", 90)); - - assertFalse(NetUtils.matchIpRange("[234e:0:4567:0:0:0:3d:ee]:7289", "234e:0:4567::3d:ee", 8090)); - assertFalse(NetUtils.matchIpRange("[234e:0:4567:0:0:0:3d:ee-ff]:8090", "234e:0:4567::3d:ee", 9090)); - } - - @Test - public void testMatchIpv4WithIpPort() throws UnknownHostException { - NumberFormatException thrown = - assertThrows(NumberFormatException.class, () -> NetUtils.matchIpExpression("192.168.1.192/26:90", "192.168.1.199", 90)); - assertTrue(thrown instanceof NumberFormatException); - - assertTrue(NetUtils.matchIpRange("*.*.*.*:90", "192.168.1.63", 90)); - assertTrue(NetUtils.matchIpRange("192.168.1.*:90", "192.168.1.63", 90)); - assertTrue(NetUtils.matchIpRange("192.168.1.63:90", "192.168.1.63", 90)); - assertTrue(NetUtils.matchIpRange("192.168.1.63-65:90", "192.168.1.63", 90)); - assertTrue(NetUtils.matchIpRange("192.168.1.1-63:90", "192.168.1.63", 90)); - - assertFalse(NetUtils.matchIpRange("*.*.*.*:80", "192.168.1.63", 90)); - assertFalse(NetUtils.matchIpRange("192.168.1.*:80", "192.168.1.63", 90)); - assertFalse(NetUtils.matchIpRange("192.168.1.63:80", "192.168.1.63", 90)); - assertFalse(NetUtils.matchIpRange("192.168.1.63-65:80", "192.168.1.63", 90)); - assertFalse(NetUtils.matchIpRange("192.168.1.1-63:80", "192.168.1.63", 90)); - - assertFalse(NetUtils.matchIpRange("192.168.1.1-61:90", "192.168.1.62", 90)); - assertFalse(NetUtils.matchIpRange("192.168.1.62:90", "192.168.1.63", 90)); - } - - @Test - public void testLocalHost() { - assertEquals(NetUtils.getLocalHost(), NetUtils.getLocalAddress().getHostAddress()); - assertTrue(NetUtils.isValidLocalHost(NetUtils.getLocalHost())); - assertFalse(NetUtils.isInvalidLocalHost(NetUtils.getLocalHost())); - } - - @Test - public void testIsMulticastAddress() { - assertTrue(NetUtils.isMulticastAddress("224.0.0.1")); - assertFalse(NetUtils.isMulticastAddress("127.0.0.1")); - } -} +/* + * 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.common.utils; + + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.UnknownHostException; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.greaterThanOrEqualTo; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assumptions.assumeTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class NetUtilsTest { + + @Test + public void testGetRandomPort() throws Exception { + assertThat(NetUtils.getRandomPort(), greaterThanOrEqualTo(30000)); + assertThat(NetUtils.getRandomPort(), greaterThanOrEqualTo(30000)); + assertThat(NetUtils.getRandomPort(), greaterThanOrEqualTo(30000)); + } + + @Test + public void testGetAvailablePort() throws Exception { + assertThat(NetUtils.getAvailablePort(), greaterThan(0)); + assertThat(NetUtils.getAvailablePort(12345), greaterThanOrEqualTo(12345)); + assertThat(NetUtils.getAvailablePort(-1), greaterThanOrEqualTo(0)); + } + + @Test + public void testValidAddress() throws Exception { + assertTrue(NetUtils.isValidAddress("10.20.130.230:20880")); + assertFalse(NetUtils.isValidAddress("10.20.130.230")); + assertFalse(NetUtils.isValidAddress("10.20.130.230:666666")); + } + + @Test + public void testIsInvalidPort() throws Exception { + assertTrue(NetUtils.isInvalidPort(0)); + assertTrue(NetUtils.isInvalidPort(65536)); + assertFalse(NetUtils.isInvalidPort(1024)); + } + + @Test + public void testIsLocalHost() throws Exception { + assertTrue(NetUtils.isLocalHost("localhost")); + assertTrue(NetUtils.isLocalHost("127.1.2.3")); + assertFalse(NetUtils.isLocalHost("128.1.2.3")); + } + + @Test + public void testIsAnyHost() throws Exception { + assertTrue(NetUtils.isAnyHost("0.0.0.0")); + assertFalse(NetUtils.isAnyHost("1.1.1.1")); + } + + @Test + public void testIsInvalidLocalHost() throws Exception { + assertTrue(NetUtils.isInvalidLocalHost(null)); + assertTrue(NetUtils.isInvalidLocalHost("")); + assertTrue(NetUtils.isInvalidLocalHost("localhost")); + assertTrue(NetUtils.isInvalidLocalHost("0.0.0.0")); + assertTrue(NetUtils.isInvalidLocalHost("127.1.2.3")); + assertTrue(NetUtils.isInvalidLocalHost("127.0.0.1")); + assertFalse(NetUtils.isInvalidLocalHost("128.0.0.1")); + } + + @Test + public void testIsValidLocalHost() throws Exception { + assertTrue(NetUtils.isValidLocalHost("1.2.3.4")); + assertTrue(NetUtils.isValidLocalHost("128.0.0.1")); + } + + @Test + public void testGetLocalSocketAddress() throws Exception { + InetSocketAddress address = NetUtils.getLocalSocketAddress("localhost", 12345); + assertTrue(address.getAddress().isAnyLocalAddress()); + assertEquals(address.getPort(), 12345); + address = NetUtils.getLocalSocketAddress("dubbo-addr", 12345); + assertEquals(address.getHostName(), "dubbo-addr"); + assertEquals(address.getPort(), 12345); + } + + @Test + public void testIsValidAddress() throws Exception { + assertFalse(NetUtils.isValidV4Address((InetAddress) null)); + InetAddress address = mock(InetAddress.class); + when(address.isLoopbackAddress()).thenReturn(true); + assertFalse(NetUtils.isValidV4Address(address)); + address = mock(InetAddress.class); + when(address.getHostAddress()).thenReturn("localhost"); + assertFalse(NetUtils.isValidV4Address(address)); + address = mock(InetAddress.class); + when(address.getHostAddress()).thenReturn("0.0.0.0"); + assertFalse(NetUtils.isValidV4Address(address)); + address = mock(InetAddress.class); + when(address.getHostAddress()).thenReturn("127.0.0.1"); + assertFalse(NetUtils.isValidV4Address(address)); + address = mock(InetAddress.class); + when(address.getHostAddress()).thenReturn("1.2.3.4"); + assertTrue(NetUtils.isValidV4Address(address)); + } + + @Test + public void testGetLocalHost() throws Exception { + assertNotNull(NetUtils.getLocalHost()); + } + + @Test + public void testGetLocalAddress() throws Exception { + InetAddress address = NetUtils.getLocalAddress(); + assertNotNull(address); + assertTrue(NetUtils.isValidLocalHost(address.getHostAddress())); + } + + @Test + public void testFilterLocalHost() throws Exception { + assertNull(NetUtils.filterLocalHost(null)); + assertEquals(NetUtils.filterLocalHost(""), ""); + String host = NetUtils.filterLocalHost("dubbo://127.0.0.1:8080/foo"); + assertThat(host, equalTo("dubbo://" + NetUtils.getLocalHost() + ":8080/foo")); + host = NetUtils.filterLocalHost("127.0.0.1:8080"); + assertThat(host, equalTo(NetUtils.getLocalHost() + ":8080")); + host = NetUtils.filterLocalHost("0.0.0.0"); + assertThat(host, equalTo(NetUtils.getLocalHost())); + host = NetUtils.filterLocalHost("88.88.88.88"); + assertThat(host, equalTo(host)); + } + + @Test + public void testGetHostName() throws Exception { + assertNotNull(NetUtils.getHostName("127.0.0.1")); + } + + @Test + public void testGetIpByHost() throws Exception { + assertThat(NetUtils.getIpByHost("localhost"), equalTo("127.0.0.1")); + assertThat(NetUtils.getIpByHost("dubbo.local"), equalTo("dubbo.local")); + } + + @Test + public void testToAddressString() throws Exception { + InetAddress address = mock(InetAddress.class); + when(address.getHostAddress()).thenReturn("dubbo"); + InetSocketAddress socketAddress = new InetSocketAddress(address, 1234); + assertThat(NetUtils.toAddressString(socketAddress), equalTo("dubbo:1234")); + } + + @Test + public void testToAddress() throws Exception { + InetSocketAddress address = NetUtils.toAddress("localhost:1234"); + assertThat(address.getHostName(), equalTo("localhost")); + assertThat(address.getPort(), equalTo(1234)); + address = NetUtils.toAddress("localhost"); + assertThat(address.getHostName(), equalTo("localhost")); + assertThat(address.getPort(), equalTo(0)); + } + + @Test + public void testToURL() throws Exception { + String url = NetUtils.toURL("dubbo", "host", 1234, "foo"); + assertThat(url, equalTo("dubbo://host:1234/foo")); + } + + @Test + public void testIsValidV6Address() { + String saved = System.getProperty("java.net.preferIPv6Addresses", "false"); + System.setProperty("java.net.preferIPv6Addresses", "true"); + + InetAddress address = NetUtils.getLocalAddress(); + boolean isPreferIPV6Address = NetUtils.isPreferIPV6Address(); + + // Restore system property to previous value before executing test + System.setProperty("java.net.preferIPv6Addresses", saved); + + assumeTrue(address instanceof Inet6Address); + assertThat(isPreferIPV6Address, equalTo(true)); + } + + /** + * Mockito starts to support mocking final classes since 2.1.0 + * see https://github.com/mockito/mockito/wiki/What%27s-new-in-Mockito-2#unmockable + * But enable it will cause other UT to fail. + * Therefore currently disabling this UT. + */ + @Disabled + @Test + public void testNormalizeV6Address() { + Inet6Address address = mock(Inet6Address.class); + when(address.getHostAddress()).thenReturn("fe80:0:0:0:894:aeec:f37d:23e1%en0"); + when(address.getScopeId()).thenReturn(5); + InetAddress normalized = NetUtils.normalizeV6Address(address); + assertThat(normalized.getHostAddress(), equalTo("fe80:0:0:0:894:aeec:f37d:23e1%5")); + } + + @Test + public void testMatchIpRangeMatchWhenIpv4() throws UnknownHostException { + assertTrue(NetUtils.matchIpRange("*.*.*.*", "192.168.1.63", 90)); + assertTrue(NetUtils.matchIpRange("192.168.1.*", "192.168.1.63", 90)); + assertTrue(NetUtils.matchIpRange("192.168.1.63", "192.168.1.63", 90)); + assertTrue(NetUtils.matchIpRange("192.168.1.1-65", "192.168.1.63", 90)); + assertFalse(NetUtils.matchIpRange("192.168.1.1-61", "192.168.1.63", 90)); + assertFalse(NetUtils.matchIpRange("192.168.1.62", "192.168.1.63", 90)); + } + + @Test + public void testMatchIpRangeMatchWhenIpv6() throws UnknownHostException { + assertTrue(NetUtils.matchIpRange("*.*.*.*", "192.168.1.63", 90)); + assertTrue(NetUtils.matchIpRange("234e:0:4567:0:0:0:3d:*", "234e:0:4567::3d:ff", 90)); + assertTrue(NetUtils.matchIpRange("234e:0:4567:0:0:0:3d:ee", "234e:0:4567::3d:ee", 90)); + assertTrue(NetUtils.matchIpRange("234e:0:4567::3d:ee", "234e:0:4567::3d:ee", 90)); + assertTrue(NetUtils.matchIpRange("234e:0:4567:0:0:0:3d:0-ff", "234e:0:4567::3d:ee", 90)); + assertTrue(NetUtils.matchIpRange("234e:0:4567:0:0:0:3d:0-ee", "234e:0:4567::3d:ee", 90)); + + assertFalse(NetUtils.matchIpRange("234e:0:4567:0:0:0:3d:ff", "234e:0:4567::3d:ee", 90)); + assertFalse(NetUtils.matchIpRange("234e:0:4567:0:0:0:3d:0-ea", "234e:0:4567::3d:ee", 90)); + } + + @Test + public void testMatchIpRangeMatchWhenIpv6Exception() throws UnknownHostException { + IllegalArgumentException thrown = + assertThrows(IllegalArgumentException.class, () -> + NetUtils.matchIpRange("234e:0:4567::3d:*", "234e:0:4567::3d:ff", 90)); + assertTrue(thrown.getMessage().contains("If you config ip expression that contains '*'")); + + thrown = assertThrows(IllegalArgumentException.class, () -> + NetUtils.matchIpRange("234e:0:4567:3d", "234e:0:4567::3d:ff", 90)); + assertTrue(thrown.getMessage().contains("The host is ipv6, but the pattern is not ipv6 pattern")); + + thrown = + assertThrows(IllegalArgumentException.class, () -> + NetUtils.matchIpRange("192.168.1.1-65-3", "192.168.1.63", 90)); + assertTrue(thrown.getMessage().contains("There is wrong format of ip Address")); + } + + @Test + public void testMatchIpRangeMatchWhenIpWrongException() throws UnknownHostException { + UnknownHostException thrown = + assertThrows(UnknownHostException.class, () -> + NetUtils.matchIpRange("192.168.1.63", "192.168.1.ff", 90)); + assertTrue(thrown.getMessage().contains("192.168.1.ff")); + } + + @Test + public void testMatchIpMatch() throws UnknownHostException { + assertTrue(NetUtils.matchIpExpression("192.168.1.*", "192.168.1.63", 90)); + assertTrue(NetUtils.matchIpExpression("192.168.1.192/26", "192.168.1.199", 90)); + } + + @Test + public void testMatchIpv6WithIpPort() throws UnknownHostException { + assertTrue(NetUtils.matchIpRange("[234e:0:4567::3d:ee]", "234e:0:4567::3d:ee", 8090)); + assertTrue(NetUtils.matchIpRange("[234e:0:4567:0:0:0:3d:ee]", "234e:0:4567::3d:ee", 8090)); + assertTrue(NetUtils.matchIpRange("[234e:0:4567:0:0:0:3d:ee]:8090", "234e:0:4567::3d:ee", 8090)); + assertTrue(NetUtils.matchIpRange("[234e:0:4567:0:0:0:3d:0-ee]:8090", "234e:0:4567::3d:ee", 8090)); + assertTrue(NetUtils.matchIpRange("[234e:0:4567:0:0:0:3d:ee-ff]:8090", "234e:0:4567::3d:ee", 8090)); + assertTrue(NetUtils.matchIpRange("[234e:0:4567:0:0:0:3d:*]:90", "234e:0:4567::3d:ff", 90)); + + assertFalse(NetUtils.matchIpRange("[234e:0:4567:0:0:0:3d:ee]:7289", "234e:0:4567::3d:ee", 8090)); + assertFalse(NetUtils.matchIpRange("[234e:0:4567:0:0:0:3d:ee-ff]:8090", "234e:0:4567::3d:ee", 9090)); + } + + @Test + public void testMatchIpv4WithIpPort() throws UnknownHostException { + NumberFormatException thrown = + assertThrows(NumberFormatException.class, () -> NetUtils.matchIpExpression("192.168.1.192/26:90", "192.168.1.199", 90)); + assertTrue(thrown instanceof NumberFormatException); + + assertTrue(NetUtils.matchIpRange("*.*.*.*:90", "192.168.1.63", 90)); + assertTrue(NetUtils.matchIpRange("192.168.1.*:90", "192.168.1.63", 90)); + assertTrue(NetUtils.matchIpRange("192.168.1.63:90", "192.168.1.63", 90)); + assertTrue(NetUtils.matchIpRange("192.168.1.63-65:90", "192.168.1.63", 90)); + assertTrue(NetUtils.matchIpRange("192.168.1.1-63:90", "192.168.1.63", 90)); + + assertFalse(NetUtils.matchIpRange("*.*.*.*:80", "192.168.1.63", 90)); + assertFalse(NetUtils.matchIpRange("192.168.1.*:80", "192.168.1.63", 90)); + assertFalse(NetUtils.matchIpRange("192.168.1.63:80", "192.168.1.63", 90)); + assertFalse(NetUtils.matchIpRange("192.168.1.63-65:80", "192.168.1.63", 90)); + assertFalse(NetUtils.matchIpRange("192.168.1.1-63:80", "192.168.1.63", 90)); + + assertFalse(NetUtils.matchIpRange("192.168.1.1-61:90", "192.168.1.62", 90)); + assertFalse(NetUtils.matchIpRange("192.168.1.62:90", "192.168.1.63", 90)); + } + + @Test + public void testLocalHost() { + assertEquals(NetUtils.getLocalHost(), NetUtils.getLocalAddress().getHostAddress()); + assertTrue(NetUtils.isValidLocalHost(NetUtils.getLocalHost())); + assertFalse(NetUtils.isInvalidLocalHost(NetUtils.getLocalHost())); + } + + @Test + public void testIsMulticastAddress() { + assertTrue(NetUtils.isMulticastAddress("224.0.0.1")); + assertFalse(NetUtils.isMulticastAddress("127.0.0.1")); + } +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ParametersTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ParametersTest.java index 1b86110a75..52a1f03c64 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ParametersTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ParametersTest.java @@ -44,4 +44,4 @@ public class ParametersTest { assertEquals(map.get("version"), ServiceVersion); assertEquals(map.get("lb"), LoadBalance); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ReflectUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ReflectUtilsTest.java index d9adde8443..e6a31e63cc 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ReflectUtilsTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ReflectUtilsTest.java @@ -544,4 +544,4 @@ public class ReflectUtilsTest { } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/UrlUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/UrlUtilsTest.java index dc0eda6c84..c843a7ab91 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/UrlUtilsTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/UrlUtilsTest.java @@ -1,379 +1,379 @@ -/* - * 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.common.utils; - -import org.apache.dubbo.common.URL; - -import org.junit.jupiter.api.Test; - -import java.util.ArrayList; -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.CommonConstants.GROUP_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -public class UrlUtilsTest { - - String localAddress = "127.0.0.1"; - - @Test - public void testAddressNull() { - assertNull(UrlUtils.parseURL(null, null)); - } - - @Test - public void testParseUrl() { - String address = "remote://root:alibaba@127.0.0.1:9090/dubbo.test.api"; - URL url = UrlUtils.parseURL(address, null); - assertEquals(localAddress + ":9090", url.getAddress()); - assertEquals("root", url.getUsername()); - assertEquals("alibaba", url.getPassword()); - assertEquals("dubbo.test.api", url.getPath()); - assertEquals(9090, url.getPort()); - assertEquals("remote", url.getProtocol()); - } - - @Test - public void testParseURLWithSpecial() { - String address = "127.0.0.1:2181?backup=127.0.0.1:2182,127.0.0.1:2183"; - assertEquals("dubbo://" + address, UrlUtils.parseURL(address, null).toString()); - } - - @Test - public void testDefaultUrl() { - String address = "127.0.0.1"; - URL url = UrlUtils.parseURL(address, null); - assertEquals(localAddress + ":9090", url.getAddress()); - assertEquals(9090, url.getPort()); - assertEquals("dubbo", url.getProtocol()); - assertNull(url.getUsername()); - assertNull(url.getPassword()); - assertNull(url.getPath()); - } - - @Test - public void testParseFromParameter() { - String address = "127.0.0.1"; - Map parameters = new HashMap(); - parameters.put("username", "root"); - parameters.put("password", "alibaba"); - parameters.put("port", "10000"); - parameters.put("protocol", "dubbo"); - parameters.put("path", "dubbo.test.api"); - parameters.put("aaa", "bbb"); - parameters.put("ccc", "ddd"); - URL url = UrlUtils.parseURL(address, parameters); - assertEquals(localAddress + ":10000", url.getAddress()); - assertEquals("root", url.getUsername()); - assertEquals("alibaba", url.getPassword()); - assertEquals(10000, url.getPort()); - assertEquals("dubbo", url.getProtocol()); - assertEquals("dubbo.test.api", url.getPath()); - assertEquals("bbb", url.getParameter("aaa")); - assertEquals("ddd", url.getParameter("ccc")); - } - - @Test - public void testParseUrl2() { - String address = "192.168.0.1"; - String backupAddress1 = "192.168.0.2"; - String backupAddress2 = "192.168.0.3"; - - Map parameters = new HashMap(); - parameters.put("username", "root"); - parameters.put("password", "alibaba"); - parameters.put("port", "10000"); - parameters.put("protocol", "dubbo"); - URL url = UrlUtils.parseURL(address + "," + backupAddress1 + "," + backupAddress2, parameters); - assertEquals("192.168.0.1:10000", url.getAddress()); - assertEquals("root", url.getUsername()); - assertEquals("alibaba", url.getPassword()); - assertEquals(10000, url.getPort()); - assertEquals("dubbo", url.getProtocol()); - assertEquals("192.168.0.2" + "," + "192.168.0.3", url.getParameter("backup")); - } - - @Test - public void testParseUrls() { - String addresses = "192.168.0.1|192.168.0.2|192.168.0.3"; - Map parameters = new HashMap(); - parameters.put("username", "root"); - parameters.put("password", "alibaba"); - parameters.put("port", "10000"); - parameters.put("protocol", "dubbo"); - List urls = UrlUtils.parseURLs(addresses, parameters); - assertEquals("192.168.0.1" + ":10000", urls.get(0).getAddress()); - assertEquals("192.168.0.2" + ":10000", urls.get(1).getAddress()); - } - - @Test - public void testParseUrlsAddressNull() { - assertNull(UrlUtils.parseURLs(null, null)); - } - - @Test - public void testConvertRegister() { - String key = "perf/dubbo.test.api.HelloService:1.0.0"; - Map> register = new HashMap>(); - register.put(key, null); - Map> newRegister = UrlUtils.convertRegister(register); - assertEquals(register, newRegister); - } - - @Test - public void testConvertRegister2() { - String key = "dubbo.test.api.HelloService"; - Map> register = new HashMap>(); - Map service = new HashMap(); - service.put("dubbo://127.0.0.1:20880/com.xxx.XxxService", "version=1.0.0&group=test&dubbo.version=2.0.0"); - register.put(key, service); - Map> newRegister = UrlUtils.convertRegister(register); - Map newService = new HashMap(); - newService.put("dubbo://127.0.0.1:20880/com.xxx.XxxService", "dubbo.version=2.0.0&group=test&version=1.0.0"); - assertEquals(newService, newRegister.get("test/dubbo.test.api.HelloService:1.0.0")); - } - - @Test - public void testSubscribe() { - String key = "perf/dubbo.test.api.HelloService:1.0.0"; - Map subscribe = new HashMap(); - subscribe.put(key, null); - Map newSubscribe = UrlUtils.convertSubscribe(subscribe); - assertEquals(subscribe, newSubscribe); - } - - @Test - public void testSubscribe2() { - String key = "dubbo.test.api.HelloService"; - Map subscribe = new HashMap(); - subscribe.put(key, "version=1.0.0&group=test&dubbo.version=2.0.0"); - Map newSubscribe = UrlUtils.convertSubscribe(subscribe); - assertEquals("dubbo.version=2.0.0&group=test&version=1.0.0", newSubscribe.get("test/dubbo.test.api.HelloService:1.0.0")); - } - - @Test - public void testRevertRegister() { - String key = "perf/dubbo.test.api.HelloService:1.0.0"; - Map> register = new HashMap>(); - Map service = new HashMap(); - service.put("dubbo://127.0.0.1:20880/com.xxx.XxxService", null); - register.put(key, service); - Map> newRegister = UrlUtils.revertRegister(register); - Map> expectedRegister = new HashMap>(); - service.put("dubbo://127.0.0.1:20880/com.xxx.XxxService", "group=perf&version=1.0.0"); - expectedRegister.put("dubbo.test.api.HelloService", service); - assertEquals(expectedRegister, newRegister); - } - - @Test - public void testRevertRegister2() { - String key = "dubbo.test.api.HelloService"; - Map> register = new HashMap>(); - Map service = new HashMap(); - service.put("dubbo://127.0.0.1:20880/com.xxx.XxxService", null); - register.put(key, service); - Map> newRegister = UrlUtils.revertRegister(register); - Map> expectedRegister = new HashMap>(); - service.put("dubbo://127.0.0.1:20880/com.xxx.XxxService", null); - expectedRegister.put("dubbo.test.api.HelloService", service); - assertEquals(expectedRegister, newRegister); - } - - @Test - public void testRevertSubscribe() { - String key = "perf/dubbo.test.api.HelloService:1.0.0"; - Map subscribe = new HashMap(); - subscribe.put(key, null); - Map newSubscribe = UrlUtils.revertSubscribe(subscribe); - Map expectSubscribe = new HashMap(); - expectSubscribe.put("dubbo.test.api.HelloService", "group=perf&version=1.0.0"); - assertEquals(expectSubscribe, newSubscribe); - } - - @Test - public void testRevertSubscribe2() { - String key = "dubbo.test.api.HelloService"; - Map subscribe = new HashMap(); - subscribe.put(key, null); - Map newSubscribe = UrlUtils.revertSubscribe(subscribe); - assertEquals(subscribe, newSubscribe); - } - - @Test - public void testRevertNotify() { - String key = "dubbo.test.api.HelloService"; - Map> notify = new HashMap>(); - Map service = new HashMap(); - service.put("dubbo://127.0.0.1:20880/com.xxx.XxxService", "group=perf&version=1.0.0"); - notify.put(key, service); - Map> newRegister = UrlUtils.revertNotify(notify); - Map> expectedRegister = new HashMap>(); - service.put("dubbo://127.0.0.1:20880/com.xxx.XxxService", "group=perf&version=1.0.0"); - expectedRegister.put("perf/dubbo.test.api.HelloService:1.0.0", service); - assertEquals(expectedRegister, newRegister); - } - - @Test - public void testRevertNotify2() { - String key = "perf/dubbo.test.api.HelloService:1.0.0"; - Map> notify = new HashMap>(); - Map service = new HashMap(); - service.put("dubbo://127.0.0.1:20880/com.xxx.XxxService", "group=perf&version=1.0.0"); - notify.put(key, service); - Map> newRegister = UrlUtils.revertNotify(notify); - Map> expectedRegister = new HashMap>(); - service.put("dubbo://127.0.0.1:20880/com.xxx.XxxService", "group=perf&version=1.0.0"); - expectedRegister.put("perf/dubbo.test.api.HelloService:1.0.0", service); - assertEquals(expectedRegister, newRegister); - } - - // backward compatibility for version 2.0.0 - @Test - public void testRevertForbid() { - String service = "dubbo.test.api.HelloService"; - List forbid = new ArrayList(); - forbid.add(service); - Set subscribed = new HashSet(); - subscribed.add(URL.valueOf("dubbo://127.0.0.1:20880/" + service + "?group=perf&version=1.0.0")); - List newForbid = UrlUtils.revertForbid(forbid, subscribed); - List expectForbid = new ArrayList(); - expectForbid.add("perf/" + service + ":1.0.0"); - assertEquals(expectForbid, newForbid); - } - - @Test - public void testRevertForbid2() { - List newForbid = UrlUtils.revertForbid(null, null); - assertNull(newForbid); - } - - @Test - public void testRevertForbid3() { - String service1 = "dubbo.test.api.HelloService:1.0.0"; - String service2 = "dubbo.test.api.HelloService:2.0.0"; - List forbid = new ArrayList(); - forbid.add(service1); - forbid.add(service2); - List newForbid = UrlUtils.revertForbid(forbid, null); - assertEquals(forbid, newForbid); - } - - @Test - public void testIsMatch() { - URL consumerUrl = URL.valueOf("dubbo://127.0.0.1:20880/com.xxx.XxxService?version=1.0.0&group=test"); - URL providerUrl = URL.valueOf("http://127.0.0.1:8080/com.xxx.XxxService?version=1.0.0&group=test"); - assertTrue(UrlUtils.isMatch(consumerUrl, providerUrl)); - } - - @Test - public void testIsMatch2() { - URL consumerUrl = URL.valueOf("dubbo://127.0.0.1:20880/com.xxx.XxxService?version=2.0.0&group=test"); - URL providerUrl = URL.valueOf("http://127.0.0.1:8080/com.xxx.XxxService?version=1.0.0&group=test"); - assertFalse(UrlUtils.isMatch(consumerUrl, providerUrl)); - } - - @Test - public void testIsMatch3() { - URL consumerUrl = URL.valueOf("dubbo://127.0.0.1:20880/com.xxx.XxxService?version=1.0.0&group=aa"); - URL providerUrl = URL.valueOf("http://127.0.0.1:8080/com.xxx.XxxService?version=1.0.0&group=test"); - assertFalse(UrlUtils.isMatch(consumerUrl, providerUrl)); - } - - @Test - public void testIsMatch4() { - URL consumerUrl = URL.valueOf("dubbo://127.0.0.1:20880/com.xxx.XxxService?version=1.0.0&group=*"); - URL providerUrl = URL.valueOf("http://127.0.0.1:8080/com.xxx.XxxService?version=1.0.0&group=test"); - assertTrue(UrlUtils.isMatch(consumerUrl, providerUrl)); - } - - @Test - public void testIsMatch5() { - URL consumerUrl = URL.valueOf("dubbo://127.0.0.1:20880/com.xxx.XxxService?version=*&group=test"); - URL providerUrl = URL.valueOf("http://127.0.0.1:8080/com.xxx.XxxService?version=1.0.0&group=test"); - assertTrue(UrlUtils.isMatch(consumerUrl, providerUrl)); - } - - @Test - public void testIsItemMatch() throws Exception { - assertTrue(UrlUtils.isItemMatch(null, null)); - assertTrue(!UrlUtils.isItemMatch("1", null)); - assertTrue(!UrlUtils.isItemMatch(null, "1")); - assertTrue(UrlUtils.isItemMatch("1", "1")); - assertTrue(UrlUtils.isItemMatch("*", null)); - assertTrue(UrlUtils.isItemMatch("*", "*")); - assertTrue(UrlUtils.isItemMatch("*", "1234")); - assertTrue(!UrlUtils.isItemMatch(null, "*")); - } - - @Test - public void testIsServiceKeyMatch() throws Exception { - URL url = URL.valueOf("test://127.0.0.1"); - URL pattern = url.addParameter(GROUP_KEY, "test") - .addParameter(INTERFACE_KEY, "test") - .addParameter(VERSION_KEY, "test"); - URL value = pattern; - assertTrue(UrlUtils.isServiceKeyMatch(pattern, value)); - - pattern = pattern.addParameter(GROUP_KEY, "*"); - assertTrue(UrlUtils.isServiceKeyMatch(pattern, value)); - - pattern = pattern.addParameter(VERSION_KEY, "*"); - assertTrue(UrlUtils.isServiceKeyMatch(pattern, value)); - } - - @Test - public void testGetEmptyUrl() throws Exception { - URL url = UrlUtils.getEmptyUrl("dubbo/a.b.c.Foo:1.0.0", "test"); - assertThat(url.toFullString(), equalTo("empty://0.0.0.0/a.b.c.Foo?category=test&group=dubbo&version=1.0.0")); - } - - @Test - public void testIsMatchGlobPattern() throws Exception { - assertTrue(UrlUtils.isMatchGlobPattern("*", "value")); - assertTrue(UrlUtils.isMatchGlobPattern("", null)); - assertFalse(UrlUtils.isMatchGlobPattern("", "value")); - assertTrue(UrlUtils.isMatchGlobPattern("value", "value")); - assertTrue(UrlUtils.isMatchGlobPattern("v*", "value")); - assertTrue(UrlUtils.isMatchGlobPattern("*e", "value")); - assertTrue(UrlUtils.isMatchGlobPattern("v*e", "value")); - assertTrue(UrlUtils.isMatchGlobPattern("$key", "value", URL.valueOf("dubbo://localhost:8080/Foo?key=v*e"))); - } - - @Test - public void testIsMatchUrlWithDefaultPrefix() { - URL url = URL.valueOf("dubbo://127.0.0.1:20880/com.xxx.XxxService?default.version=1.0.0&default.group=test"); - assertEquals("1.0.0", url.getVersion()); - assertEquals("1.0.0", url.getParameter("default.version")); - - URL consumerUrl = URL.valueOf("consumer://127.0.0.1/com.xxx.XxxService?version=1.0.0&group=test"); - assertTrue(UrlUtils.isMatch(consumerUrl, url)); - - URL consumerUrl1 = URL.valueOf("consumer://127.0.0.1/com.xxx.XxxService?default.version=1.0.0&default.group=test"); - assertTrue(UrlUtils.isMatch(consumerUrl, url)); - } -} +/* + * 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.common.utils; + +import org.apache.dubbo.common.URL; + +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +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.CommonConstants.GROUP_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class UrlUtilsTest { + + String localAddress = "127.0.0.1"; + + @Test + public void testAddressNull() { + assertNull(UrlUtils.parseURL(null, null)); + } + + @Test + public void testParseUrl() { + String address = "remote://root:alibaba@127.0.0.1:9090/dubbo.test.api"; + URL url = UrlUtils.parseURL(address, null); + assertEquals(localAddress + ":9090", url.getAddress()); + assertEquals("root", url.getUsername()); + assertEquals("alibaba", url.getPassword()); + assertEquals("dubbo.test.api", url.getPath()); + assertEquals(9090, url.getPort()); + assertEquals("remote", url.getProtocol()); + } + + @Test + public void testParseURLWithSpecial() { + String address = "127.0.0.1:2181?backup=127.0.0.1:2182,127.0.0.1:2183"; + assertEquals("dubbo://" + address, UrlUtils.parseURL(address, null).toString()); + } + + @Test + public void testDefaultUrl() { + String address = "127.0.0.1"; + URL url = UrlUtils.parseURL(address, null); + assertEquals(localAddress + ":9090", url.getAddress()); + assertEquals(9090, url.getPort()); + assertEquals("dubbo", url.getProtocol()); + assertNull(url.getUsername()); + assertNull(url.getPassword()); + assertNull(url.getPath()); + } + + @Test + public void testParseFromParameter() { + String address = "127.0.0.1"; + Map parameters = new HashMap(); + parameters.put("username", "root"); + parameters.put("password", "alibaba"); + parameters.put("port", "10000"); + parameters.put("protocol", "dubbo"); + parameters.put("path", "dubbo.test.api"); + parameters.put("aaa", "bbb"); + parameters.put("ccc", "ddd"); + URL url = UrlUtils.parseURL(address, parameters); + assertEquals(localAddress + ":10000", url.getAddress()); + assertEquals("root", url.getUsername()); + assertEquals("alibaba", url.getPassword()); + assertEquals(10000, url.getPort()); + assertEquals("dubbo", url.getProtocol()); + assertEquals("dubbo.test.api", url.getPath()); + assertEquals("bbb", url.getParameter("aaa")); + assertEquals("ddd", url.getParameter("ccc")); + } + + @Test + public void testParseUrl2() { + String address = "192.168.0.1"; + String backupAddress1 = "192.168.0.2"; + String backupAddress2 = "192.168.0.3"; + + Map parameters = new HashMap(); + parameters.put("username", "root"); + parameters.put("password", "alibaba"); + parameters.put("port", "10000"); + parameters.put("protocol", "dubbo"); + URL url = UrlUtils.parseURL(address + "," + backupAddress1 + "," + backupAddress2, parameters); + assertEquals("192.168.0.1:10000", url.getAddress()); + assertEquals("root", url.getUsername()); + assertEquals("alibaba", url.getPassword()); + assertEquals(10000, url.getPort()); + assertEquals("dubbo", url.getProtocol()); + assertEquals("192.168.0.2" + "," + "192.168.0.3", url.getParameter("backup")); + } + + @Test + public void testParseUrls() { + String addresses = "192.168.0.1|192.168.0.2|192.168.0.3"; + Map parameters = new HashMap(); + parameters.put("username", "root"); + parameters.put("password", "alibaba"); + parameters.put("port", "10000"); + parameters.put("protocol", "dubbo"); + List urls = UrlUtils.parseURLs(addresses, parameters); + assertEquals("192.168.0.1" + ":10000", urls.get(0).getAddress()); + assertEquals("192.168.0.2" + ":10000", urls.get(1).getAddress()); + } + + @Test + public void testParseUrlsAddressNull() { + assertNull(UrlUtils.parseURLs(null, null)); + } + + @Test + public void testConvertRegister() { + String key = "perf/dubbo.test.api.HelloService:1.0.0"; + Map> register = new HashMap>(); + register.put(key, null); + Map> newRegister = UrlUtils.convertRegister(register); + assertEquals(register, newRegister); + } + + @Test + public void testConvertRegister2() { + String key = "dubbo.test.api.HelloService"; + Map> register = new HashMap>(); + Map service = new HashMap(); + service.put("dubbo://127.0.0.1:20880/com.xxx.XxxService", "version=1.0.0&group=test&dubbo.version=2.0.0"); + register.put(key, service); + Map> newRegister = UrlUtils.convertRegister(register); + Map newService = new HashMap(); + newService.put("dubbo://127.0.0.1:20880/com.xxx.XxxService", "dubbo.version=2.0.0&group=test&version=1.0.0"); + assertEquals(newService, newRegister.get("test/dubbo.test.api.HelloService:1.0.0")); + } + + @Test + public void testSubscribe() { + String key = "perf/dubbo.test.api.HelloService:1.0.0"; + Map subscribe = new HashMap(); + subscribe.put(key, null); + Map newSubscribe = UrlUtils.convertSubscribe(subscribe); + assertEquals(subscribe, newSubscribe); + } + + @Test + public void testSubscribe2() { + String key = "dubbo.test.api.HelloService"; + Map subscribe = new HashMap(); + subscribe.put(key, "version=1.0.0&group=test&dubbo.version=2.0.0"); + Map newSubscribe = UrlUtils.convertSubscribe(subscribe); + assertEquals("dubbo.version=2.0.0&group=test&version=1.0.0", newSubscribe.get("test/dubbo.test.api.HelloService:1.0.0")); + } + + @Test + public void testRevertRegister() { + String key = "perf/dubbo.test.api.HelloService:1.0.0"; + Map> register = new HashMap>(); + Map service = new HashMap(); + service.put("dubbo://127.0.0.1:20880/com.xxx.XxxService", null); + register.put(key, service); + Map> newRegister = UrlUtils.revertRegister(register); + Map> expectedRegister = new HashMap>(); + service.put("dubbo://127.0.0.1:20880/com.xxx.XxxService", "group=perf&version=1.0.0"); + expectedRegister.put("dubbo.test.api.HelloService", service); + assertEquals(expectedRegister, newRegister); + } + + @Test + public void testRevertRegister2() { + String key = "dubbo.test.api.HelloService"; + Map> register = new HashMap>(); + Map service = new HashMap(); + service.put("dubbo://127.0.0.1:20880/com.xxx.XxxService", null); + register.put(key, service); + Map> newRegister = UrlUtils.revertRegister(register); + Map> expectedRegister = new HashMap>(); + service.put("dubbo://127.0.0.1:20880/com.xxx.XxxService", null); + expectedRegister.put("dubbo.test.api.HelloService", service); + assertEquals(expectedRegister, newRegister); + } + + @Test + public void testRevertSubscribe() { + String key = "perf/dubbo.test.api.HelloService:1.0.0"; + Map subscribe = new HashMap(); + subscribe.put(key, null); + Map newSubscribe = UrlUtils.revertSubscribe(subscribe); + Map expectSubscribe = new HashMap(); + expectSubscribe.put("dubbo.test.api.HelloService", "group=perf&version=1.0.0"); + assertEquals(expectSubscribe, newSubscribe); + } + + @Test + public void testRevertSubscribe2() { + String key = "dubbo.test.api.HelloService"; + Map subscribe = new HashMap(); + subscribe.put(key, null); + Map newSubscribe = UrlUtils.revertSubscribe(subscribe); + assertEquals(subscribe, newSubscribe); + } + + @Test + public void testRevertNotify() { + String key = "dubbo.test.api.HelloService"; + Map> notify = new HashMap>(); + Map service = new HashMap(); + service.put("dubbo://127.0.0.1:20880/com.xxx.XxxService", "group=perf&version=1.0.0"); + notify.put(key, service); + Map> newRegister = UrlUtils.revertNotify(notify); + Map> expectedRegister = new HashMap>(); + service.put("dubbo://127.0.0.1:20880/com.xxx.XxxService", "group=perf&version=1.0.0"); + expectedRegister.put("perf/dubbo.test.api.HelloService:1.0.0", service); + assertEquals(expectedRegister, newRegister); + } + + @Test + public void testRevertNotify2() { + String key = "perf/dubbo.test.api.HelloService:1.0.0"; + Map> notify = new HashMap>(); + Map service = new HashMap(); + service.put("dubbo://127.0.0.1:20880/com.xxx.XxxService", "group=perf&version=1.0.0"); + notify.put(key, service); + Map> newRegister = UrlUtils.revertNotify(notify); + Map> expectedRegister = new HashMap>(); + service.put("dubbo://127.0.0.1:20880/com.xxx.XxxService", "group=perf&version=1.0.0"); + expectedRegister.put("perf/dubbo.test.api.HelloService:1.0.0", service); + assertEquals(expectedRegister, newRegister); + } + + // backward compatibility for version 2.0.0 + @Test + public void testRevertForbid() { + String service = "dubbo.test.api.HelloService"; + List forbid = new ArrayList(); + forbid.add(service); + Set subscribed = new HashSet(); + subscribed.add(URL.valueOf("dubbo://127.0.0.1:20880/" + service + "?group=perf&version=1.0.0")); + List newForbid = UrlUtils.revertForbid(forbid, subscribed); + List expectForbid = new ArrayList(); + expectForbid.add("perf/" + service + ":1.0.0"); + assertEquals(expectForbid, newForbid); + } + + @Test + public void testRevertForbid2() { + List newForbid = UrlUtils.revertForbid(null, null); + assertNull(newForbid); + } + + @Test + public void testRevertForbid3() { + String service1 = "dubbo.test.api.HelloService:1.0.0"; + String service2 = "dubbo.test.api.HelloService:2.0.0"; + List forbid = new ArrayList(); + forbid.add(service1); + forbid.add(service2); + List newForbid = UrlUtils.revertForbid(forbid, null); + assertEquals(forbid, newForbid); + } + + @Test + public void testIsMatch() { + URL consumerUrl = URL.valueOf("dubbo://127.0.0.1:20880/com.xxx.XxxService?version=1.0.0&group=test"); + URL providerUrl = URL.valueOf("http://127.0.0.1:8080/com.xxx.XxxService?version=1.0.0&group=test"); + assertTrue(UrlUtils.isMatch(consumerUrl, providerUrl)); + } + + @Test + public void testIsMatch2() { + URL consumerUrl = URL.valueOf("dubbo://127.0.0.1:20880/com.xxx.XxxService?version=2.0.0&group=test"); + URL providerUrl = URL.valueOf("http://127.0.0.1:8080/com.xxx.XxxService?version=1.0.0&group=test"); + assertFalse(UrlUtils.isMatch(consumerUrl, providerUrl)); + } + + @Test + public void testIsMatch3() { + URL consumerUrl = URL.valueOf("dubbo://127.0.0.1:20880/com.xxx.XxxService?version=1.0.0&group=aa"); + URL providerUrl = URL.valueOf("http://127.0.0.1:8080/com.xxx.XxxService?version=1.0.0&group=test"); + assertFalse(UrlUtils.isMatch(consumerUrl, providerUrl)); + } + + @Test + public void testIsMatch4() { + URL consumerUrl = URL.valueOf("dubbo://127.0.0.1:20880/com.xxx.XxxService?version=1.0.0&group=*"); + URL providerUrl = URL.valueOf("http://127.0.0.1:8080/com.xxx.XxxService?version=1.0.0&group=test"); + assertTrue(UrlUtils.isMatch(consumerUrl, providerUrl)); + } + + @Test + public void testIsMatch5() { + URL consumerUrl = URL.valueOf("dubbo://127.0.0.1:20880/com.xxx.XxxService?version=*&group=test"); + URL providerUrl = URL.valueOf("http://127.0.0.1:8080/com.xxx.XxxService?version=1.0.0&group=test"); + assertTrue(UrlUtils.isMatch(consumerUrl, providerUrl)); + } + + @Test + public void testIsItemMatch() throws Exception { + assertTrue(UrlUtils.isItemMatch(null, null)); + assertTrue(!UrlUtils.isItemMatch("1", null)); + assertTrue(!UrlUtils.isItemMatch(null, "1")); + assertTrue(UrlUtils.isItemMatch("1", "1")); + assertTrue(UrlUtils.isItemMatch("*", null)); + assertTrue(UrlUtils.isItemMatch("*", "*")); + assertTrue(UrlUtils.isItemMatch("*", "1234")); + assertTrue(!UrlUtils.isItemMatch(null, "*")); + } + + @Test + public void testIsServiceKeyMatch() throws Exception { + URL url = URL.valueOf("test://127.0.0.1"); + URL pattern = url.addParameter(GROUP_KEY, "test") + .addParameter(INTERFACE_KEY, "test") + .addParameter(VERSION_KEY, "test"); + URL value = pattern; + assertTrue(UrlUtils.isServiceKeyMatch(pattern, value)); + + pattern = pattern.addParameter(GROUP_KEY, "*"); + assertTrue(UrlUtils.isServiceKeyMatch(pattern, value)); + + pattern = pattern.addParameter(VERSION_KEY, "*"); + assertTrue(UrlUtils.isServiceKeyMatch(pattern, value)); + } + + @Test + public void testGetEmptyUrl() throws Exception { + URL url = UrlUtils.getEmptyUrl("dubbo/a.b.c.Foo:1.0.0", "test"); + assertThat(url.toFullString(), equalTo("empty://0.0.0.0/a.b.c.Foo?category=test&group=dubbo&version=1.0.0")); + } + + @Test + public void testIsMatchGlobPattern() throws Exception { + assertTrue(UrlUtils.isMatchGlobPattern("*", "value")); + assertTrue(UrlUtils.isMatchGlobPattern("", null)); + assertFalse(UrlUtils.isMatchGlobPattern("", "value")); + assertTrue(UrlUtils.isMatchGlobPattern("value", "value")); + assertTrue(UrlUtils.isMatchGlobPattern("v*", "value")); + assertTrue(UrlUtils.isMatchGlobPattern("*e", "value")); + assertTrue(UrlUtils.isMatchGlobPattern("v*e", "value")); + assertTrue(UrlUtils.isMatchGlobPattern("$key", "value", URL.valueOf("dubbo://localhost:8080/Foo?key=v*e"))); + } + + @Test + public void testIsMatchUrlWithDefaultPrefix() { + URL url = URL.valueOf("dubbo://127.0.0.1:20880/com.xxx.XxxService?default.version=1.0.0&default.group=test"); + assertEquals("1.0.0", url.getVersion()); + assertEquals("1.0.0", url.getParameter("default.version")); + + URL consumerUrl = URL.valueOf("consumer://127.0.0.1/com.xxx.XxxService?version=1.0.0&group=test"); + assertTrue(UrlUtils.isMatch(consumerUrl, url)); + + URL consumerUrl1 = URL.valueOf("consumer://127.0.0.1/com.xxx.XxxService?default.version=1.0.0&default.group=test"); + assertTrue(UrlUtils.isMatch(consumerUrl, url)); + } +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/Person.java b/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/Person.java index 8cd13e46fe..d09fcc0a24 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/Person.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/Person.java @@ -92,4 +92,4 @@ public class Person { return false; return true; } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/SerializablePerson.java b/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/SerializablePerson.java index fa3015a4c6..6fff76c133 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/SerializablePerson.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/SerializablePerson.java @@ -94,4 +94,4 @@ public class SerializablePerson implements Serializable { return false; return true; } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/media/Image.java b/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/media/Image.java index 423c6a4938..a6444ebf2c 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/media/Image.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/media/Image.java @@ -117,4 +117,4 @@ public class Image implements java.io.Serializable { public enum Size { SMALL, LARGE } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/media/Media.java b/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/media/Media.java index bb2be00b29..462232f69e 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/media/Media.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/media/Media.java @@ -202,4 +202,4 @@ public class Media implements java.io.Serializable { public enum Player { JAVA, FLASH } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/person/BigPerson.java b/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/person/BigPerson.java index 9e0856c7f6..3c24fd9f95 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/person/BigPerson.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/person/BigPerson.java @@ -148,4 +148,4 @@ public class BigPerson implements Serializable { + infoProfile + "]"; } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/person/FullAddress.java b/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/person/FullAddress.java index 95363895c7..3a5b2b06b0 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/person/FullAddress.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/person/FullAddress.java @@ -199,4 +199,4 @@ public class FullAddress implements Serializable { return sb.toString(); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/person/PersonStatus.java b/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/person/PersonStatus.java index 8f432f48d5..24c86d66de 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/person/PersonStatus.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/person/PersonStatus.java @@ -19,4 +19,4 @@ package org.apache.dubbo.rpc.model.person; public enum PersonStatus { ENABLED, DISABLED -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/person/Phone.java b/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/person/Phone.java index ebc00ad495..ecd8798e4a 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/person/Phone.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/person/Phone.java @@ -136,4 +136,4 @@ public class Phone implements Serializable { return sb.toString(); } -} \ No newline at end of file +} diff --git a/dubbo-common/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.common.config.OrderedPropertiesProvider b/dubbo-common/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.common.config.OrderedPropertiesProvider index d2b3463f3f..47ec34159d 100644 --- a/dubbo-common/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.common.config.OrderedPropertiesProvider +++ b/dubbo-common/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.common.config.OrderedPropertiesProvider @@ -1,2 +1,2 @@ mock1=org.apache.dubbo.common.config.MockOrderedPropertiesProvider1 -mock2=org.apache.dubbo.common.config.MockOrderedPropertiesProvider2 \ No newline at end of file +mock2=org.apache.dubbo.common.config.MockOrderedPropertiesProvider2 diff --git a/dubbo-common/src/test/resources/dubbo.properties b/dubbo-common/src/test/resources/dubbo.properties index 15936f93a2..7598160408 100644 --- a/dubbo-common/src/test/resources/dubbo.properties +++ b/dubbo-common/src/test/resources/dubbo.properties @@ -15,4 +15,4 @@ # limitations under the License. # -dubbo=properties \ No newline at end of file +dubbo=properties diff --git a/dubbo-common/src/test/resources/log4j.xml b/dubbo-common/src/test/resources/log4j.xml index 21ea447138..cd3ab9b29d 100644 --- a/dubbo-common/src/test/resources/log4j.xml +++ b/dubbo-common/src/test/resources/log4j.xml @@ -1,34 +1,34 @@ - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dubbo-common/src/test/resources/parameters.properties b/dubbo-common/src/test/resources/parameters.properties index 103a61af73..e7ae159daf 100644 --- a/dubbo-common/src/test/resources/parameters.properties +++ b/dubbo-common/src/test/resources/parameters.properties @@ -1 +1 @@ -dubbo.parameters=[{a:b},{c_.d: r*}] \ No newline at end of file +dubbo.parameters=[{a:b},{c_.d: r*}] diff --git a/dubbo-common/src/test/resources/properties.load b/dubbo-common/src/test/resources/properties.load index 21bb7f2ddd..43bf492f5d 100644 --- a/dubbo-common/src/test/resources/properties.load +++ b/dubbo-common/src/test/resources/properties.load @@ -1,3 +1,3 @@ -a=12 -b=34 +a=12 +b=34 c=56 \ No newline at end of file diff --git a/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/spring/context/annotation/EnableDubbo.java b/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/spring/context/annotation/EnableDubbo.java index d5227ed7e9..bb13c8732b 100644 --- a/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/spring/context/annotation/EnableDubbo.java +++ b/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/spring/context/annotation/EnableDubbo.java @@ -72,4 +72,4 @@ public @interface EnableDubbo { @AliasFor(annotation = EnableDubboConfig.class, attribute = "multiple") boolean multipleConfig() default false; -} \ No newline at end of file +} diff --git a/dubbo-compatible/src/test/java/org/apache/dubbo/config/ArgumentConfigTest.java b/dubbo-compatible/src/test/java/org/apache/dubbo/config/ArgumentConfigTest.java index e23b27639c..6125d5c2d6 100644 --- a/dubbo-compatible/src/test/java/org/apache/dubbo/config/ArgumentConfigTest.java +++ b/dubbo-compatible/src/test/java/org/apache/dubbo/config/ArgumentConfigTest.java @@ -18,16 +18,15 @@ package org.apache.dubbo.config; import com.alibaba.dubbo.config.ArgumentConfig; - import org.junit.jupiter.api.Test; import java.util.HashMap; import java.util.Map; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasEntry; import static org.hamcrest.Matchers.is; -import static org.hamcrest.MatcherAssert.assertThat; public class ArgumentConfigTest { @Test @@ -62,4 +61,4 @@ public class ArgumentConfigTest { assertThat(parameters, hasEntry("callback", "true")); assertThat(parameters.size(), is(1)); } -} \ No newline at end of file +} diff --git a/dubbo-compatible/src/test/java/org/apache/dubbo/config/ConsumerConfigTest.java b/dubbo-compatible/src/test/java/org/apache/dubbo/config/ConsumerConfigTest.java index 5a3569f230..96282d2f15 100644 --- a/dubbo-compatible/src/test/java/org/apache/dubbo/config/ConsumerConfigTest.java +++ b/dubbo-compatible/src/test/java/org/apache/dubbo/config/ConsumerConfigTest.java @@ -18,12 +18,11 @@ package org.apache.dubbo.config; import com.alibaba.dubbo.config.ConsumerConfig; - import org.junit.jupiter.api.Test; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; -import static org.hamcrest.MatcherAssert.assertThat; public class ConsumerConfigTest { @Test @@ -52,4 +51,4 @@ public class ConsumerConfigTest { consumer.setClient("client"); assertThat(consumer.getClient(), equalTo("client")); } -} \ No newline at end of file +} diff --git a/dubbo-compatible/src/test/java/org/apache/dubbo/config/ModuleConfigTest.java b/dubbo-compatible/src/test/java/org/apache/dubbo/config/ModuleConfigTest.java index 7ff725f43b..96082f0dee 100644 --- a/dubbo-compatible/src/test/java/org/apache/dubbo/config/ModuleConfigTest.java +++ b/dubbo-compatible/src/test/java/org/apache/dubbo/config/ModuleConfigTest.java @@ -103,4 +103,4 @@ public class ModuleConfigTest { module.setDefault(true); assertThat(module.isDefault(), is(true)); } -} \ No newline at end of file +} diff --git a/dubbo-compatible/src/test/java/org/apache/dubbo/config/ProtocolConfigTest.java b/dubbo-compatible/src/test/java/org/apache/dubbo/config/ProtocolConfigTest.java index b1fbdc66e9..edec18cac0 100644 --- a/dubbo-compatible/src/test/java/org/apache/dubbo/config/ProtocolConfigTest.java +++ b/dubbo-compatible/src/test/java/org/apache/dubbo/config/ProtocolConfigTest.java @@ -18,17 +18,16 @@ package org.apache.dubbo.config; import com.alibaba.dubbo.config.ProtocolConfig; - import org.junit.jupiter.api.Test; import java.util.Collections; import java.util.HashMap; import java.util.Map; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasEntry; import static org.hamcrest.Matchers.is; -import static org.hamcrest.MatcherAssert.assertThat; public class ProtocolConfigTest { @@ -153,4 +152,4 @@ public class ProtocolConfigTest { protocol.setExtension("extension"); assertThat(protocol.getExtension(), equalTo("extension")); } -} \ No newline at end of file +} diff --git a/dubbo-compatible/src/test/java/org/apache/dubbo/config/ProviderConfigTest.java b/dubbo-compatible/src/test/java/org/apache/dubbo/config/ProviderConfigTest.java index b26e26e31e..fd5fa2dcf3 100644 --- a/dubbo-compatible/src/test/java/org/apache/dubbo/config/ProviderConfigTest.java +++ b/dubbo-compatible/src/test/java/org/apache/dubbo/config/ProviderConfigTest.java @@ -18,18 +18,17 @@ package org.apache.dubbo.config; import com.alibaba.dubbo.config.ProviderConfig; - import org.junit.jupiter.api.Test; import java.util.HashMap; import java.util.Map; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasEntry; import static org.hamcrest.Matchers.hasKey; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; -import static org.hamcrest.MatcherAssert.assertThat; public class ProviderConfigTest { @Test @@ -184,4 +183,4 @@ public class ProviderConfigTest { provider.setWait(10); assertThat(provider.getWait(), equalTo(10)); } -} \ No newline at end of file +} diff --git a/dubbo-compatible/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java b/dubbo-compatible/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java index 037a2fd587..d4a55ab4f8 100644 --- a/dubbo-compatible/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java +++ b/dubbo-compatible/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java @@ -80,4 +80,4 @@ public class ReferenceConfigTest { bootstrap.stop(); } } -} \ No newline at end of file +} diff --git a/dubbo-compatible/src/test/java/org/apache/dubbo/serialization/SerializationTest.java b/dubbo-compatible/src/test/java/org/apache/dubbo/serialization/SerializationTest.java index 8957950a92..e53b6a5eb0 100644 --- a/dubbo-compatible/src/test/java/org/apache/dubbo/serialization/SerializationTest.java +++ b/dubbo-compatible/src/test/java/org/apache/dubbo/serialization/SerializationTest.java @@ -31,8 +31,8 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import static org.hamcrest.Matchers.is; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; import static org.mockito.Mockito.mock; public class SerializationTest { @@ -91,4 +91,4 @@ public class SerializationTest { this.byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); this.myObjectInput = new MyObjectInput(byteArrayInputStream); } -} \ No newline at end of file +} diff --git a/dubbo-compatible/src/test/java/org/apache/dubbo/service/CustomArgument.java b/dubbo-compatible/src/test/java/org/apache/dubbo/service/CustomArgument.java index 76ffeb429d..220b3f178f 100644 --- a/dubbo-compatible/src/test/java/org/apache/dubbo/service/CustomArgument.java +++ b/dubbo-compatible/src/test/java/org/apache/dubbo/service/CustomArgument.java @@ -47,4 +47,4 @@ public class CustomArgument implements Serializable { public void setName(String name) { this.name = name; } -} \ No newline at end of file +} diff --git a/dubbo-compatible/src/test/java/org/apache/dubbo/service/DemoService.java b/dubbo-compatible/src/test/java/org/apache/dubbo/service/DemoService.java index ba63c59674..cdd0d278d5 100644 --- a/dubbo-compatible/src/test/java/org/apache/dubbo/service/DemoService.java +++ b/dubbo-compatible/src/test/java/org/apache/dubbo/service/DemoService.java @@ -35,7 +35,7 @@ public interface DemoService { Type enumlength(Type... types); -// Type enumlength(Type type); +// Type enumlength(Type type); String get(CustomArgument arg1); diff --git a/dubbo-compatible/src/test/java/org/apache/dubbo/service/Person.java b/dubbo-compatible/src/test/java/org/apache/dubbo/service/Person.java index 3a856a1940..fe334737ad 100644 --- a/dubbo-compatible/src/test/java/org/apache/dubbo/service/Person.java +++ b/dubbo-compatible/src/test/java/org/apache/dubbo/service/Person.java @@ -1,45 +1,45 @@ -/* - * 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.service; - -import java.io.Serializable; - -/** - * Person.java - */ -public class Person implements Serializable { - - private static final long serialVersionUID = 1L; - private String name; - private int age; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public int getAge() { - return age; - } - - public void setAge(int age) { - this.age = age; - } -} \ No newline at end of file +/* + * 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.service; + +import java.io.Serializable; + +/** + * Person.java + */ +public class Person implements Serializable { + + private static final long serialVersionUID = 1L; + private String name; + private int age; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } +} diff --git a/dubbo-compatible/src/test/java/org/apache/dubbo/service/Type.java b/dubbo-compatible/src/test/java/org/apache/dubbo/service/Type.java index 070ceaad12..8bdb392b76 100644 --- a/dubbo-compatible/src/test/java/org/apache/dubbo/service/Type.java +++ b/dubbo-compatible/src/test/java/org/apache/dubbo/service/Type.java @@ -1,21 +1,21 @@ -/* - * 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.service; - -public enum Type { - High, Normal, Lower -} \ No newline at end of file +/* + * 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.service; + +public enum Type { + High, Normal, Lower +} diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrap.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrap.java index e60214eec4..e5dc8ef34b 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrap.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrap.java @@ -1254,12 +1254,12 @@ public class DubboBootstrap { if (exportAsync) { ExecutorService executor = executorRepository.getServiceExporterExecutor(); Future future = executor.submit(() -> { - try { + try { sc.export(); exportedServices.add(sc); - }catch (Throwable t) { - logger.error("export async catch error : " + t.getMessage(), t); - } + }catch (Throwable t) { + logger.error("export async catch error : " + t.getMessage(), t); + } }); asyncExportingFutures.add(future); } else { diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/builders/ConfigCenterBuilder.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/builders/ConfigCenterBuilder.java index 5bced0f790..d50bf3dc8e 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/builders/ConfigCenterBuilder.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/builders/ConfigCenterBuilder.java @@ -48,7 +48,7 @@ public class ConfigCenterBuilder extends AbstractBuilder extractProperties(ConfigurableEnvironment environment) { - return Collections.unmodifiableMap(doExtraProperties(environment)); - } - -// /** -// * Gets {@link PropertySource} Map , the {@link PropertySource#getName()} as key -// * -// * @param environment {@link ConfigurableEnvironment} -// * @return Read-only Map -// */ -// public static Map> getPropertySources(ConfigurableEnvironment environment) { -// return Collections.unmodifiableMap(doGetPropertySources(environment)); -// } - - private static Map doExtraProperties(ConfigurableEnvironment environment) { - - Map properties = new LinkedHashMap<>(); // orderly - - Map> map = doGetPropertySources(environment); - - for (PropertySource source : map.values()) { - - if (source instanceof EnumerablePropertySource) { - - EnumerablePropertySource propertySource = (EnumerablePropertySource) source; - - String[] propertyNames = propertySource.getPropertyNames(); - - if (ObjectUtils.isEmpty(propertyNames)) { - continue; - } - - for (String propertyName : propertyNames) { - - if (!properties.containsKey(propertyName)) { // put If absent - properties.put(propertyName, propertySource.getProperty(propertyName)); - } - - } - - } - - } - - return properties; - - } - - private static Map> doGetPropertySources(ConfigurableEnvironment environment) { - Map> map = new LinkedHashMap>(); - MutablePropertySources sources = environment.getPropertySources(); - for (PropertySource source : sources) { - extract("", map, source); - } - return map; - } - - private static void extract(String root, Map> map, - PropertySource source) { - if (source instanceof CompositePropertySource) { - for (PropertySource nest : ((CompositePropertySource) source) - .getPropertySources()) { - extract(source.getName() + ":", map, nest); - } - } else { - map.put(root + source.getName(), source); - } - } - - /** - * Filters Dubbo Properties from {@link ConfigurableEnvironment} - * - * @param environment {@link ConfigurableEnvironment} - * @return Read-only SortedMap - */ - public static SortedMap filterDubboProperties(ConfigurableEnvironment environment) { - - SortedMap dubboProperties = new TreeMap<>(); - - Map properties = extractProperties(environment); - - for (Map.Entry entry : properties.entrySet()) { - String propertyName = entry.getKey(); - - if (propertyName.startsWith(DUBBO_PREFIX + PROPERTY_NAME_SEPARATOR) - && entry.getValue() != null) { - dubboProperties.put(propertyName, environment.resolvePlaceholders(entry.getValue().toString())); - } - } - - return Collections.unmodifiableSortedMap(dubboProperties); - } -} +/* + * 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.spring.util; + +import org.springframework.core.env.CompositePropertySource; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.EnumerablePropertySource; +import org.springframework.core.env.Environment; +import org.springframework.core.env.MutablePropertySources; +import org.springframework.core.env.PropertySource; +import org.springframework.util.ObjectUtils; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + +/** + * The utilities class for {@link Environment} + * + * @see Environment + * @since 2.7.0 + */ +public abstract class EnvironmentUtils { + + /** + * The separator of property name + */ + public static final String PROPERTY_NAME_SEPARATOR = "."; + + /** + * The prefix of property name of Dubbo + */ + public static final String DUBBO_PREFIX = "dubbo"; + + /** + * Extras The properties from {@link ConfigurableEnvironment} + * + * @param environment {@link ConfigurableEnvironment} + * @return Read-only Map + */ + public static Map extractProperties(ConfigurableEnvironment environment) { + return Collections.unmodifiableMap(doExtraProperties(environment)); + } + +// /** +// * Gets {@link PropertySource} Map , the {@link PropertySource#getName()} as key +// * +// * @param environment {@link ConfigurableEnvironment} +// * @return Read-only Map +// */ +// public static Map> getPropertySources(ConfigurableEnvironment environment) { +// return Collections.unmodifiableMap(doGetPropertySources(environment)); +// } + + private static Map doExtraProperties(ConfigurableEnvironment environment) { + + Map properties = new LinkedHashMap<>(); // orderly + + Map> map = doGetPropertySources(environment); + + for (PropertySource source : map.values()) { + + if (source instanceof EnumerablePropertySource) { + + EnumerablePropertySource propertySource = (EnumerablePropertySource) source; + + String[] propertyNames = propertySource.getPropertyNames(); + + if (ObjectUtils.isEmpty(propertyNames)) { + continue; + } + + for (String propertyName : propertyNames) { + + if (!properties.containsKey(propertyName)) { // put If absent + properties.put(propertyName, propertySource.getProperty(propertyName)); + } + + } + + } + + } + + return properties; + + } + + private static Map> doGetPropertySources(ConfigurableEnvironment environment) { + Map> map = new LinkedHashMap>(); + MutablePropertySources sources = environment.getPropertySources(); + for (PropertySource source : sources) { + extract("", map, source); + } + return map; + } + + private static void extract(String root, Map> map, + PropertySource source) { + if (source instanceof CompositePropertySource) { + for (PropertySource nest : ((CompositePropertySource) source) + .getPropertySources()) { + extract(source.getName() + ":", map, nest); + } + } else { + map.put(root + source.getName(), source); + } + } + + /** + * Filters Dubbo Properties from {@link ConfigurableEnvironment} + * + * @param environment {@link ConfigurableEnvironment} + * @return Read-only SortedMap + */ + public static SortedMap filterDubboProperties(ConfigurableEnvironment environment) { + + SortedMap dubboProperties = new TreeMap<>(); + + Map properties = extractProperties(environment); + + for (Map.Entry entry : properties.entrySet()) { + String propertyName = entry.getKey(); + + if (propertyName.startsWith(DUBBO_PREFIX + PROPERTY_NAME_SEPARATOR) + && entry.getValue() != null) { + dubboProperties.put(propertyName, environment.resolvePlaceholders(entry.getValue().toString())); + } + } + + return Collections.unmodifiableSortedMap(dubboProperties); + } +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/ConfigTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/ConfigTest.java index 949fa6da3a..d7274ba409 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/ConfigTest.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/ConfigTest.java @@ -1157,4 +1157,4 @@ public class ConfigTest { } } -} \ No newline at end of file +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/ServiceBeanTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/ServiceBeanTest.java index 86cef42a56..518a4e85f8 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/ServiceBeanTest.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/ServiceBeanTest.java @@ -52,4 +52,4 @@ public class ServiceBeanTest { abstract class TestService implements Service { } -} \ No newline at end of file +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/SimpleRegistryService.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/SimpleRegistryService.java index e13fef6fd8..f4168654a7 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/SimpleRegistryService.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/SimpleRegistryService.java @@ -140,4 +140,4 @@ public class SimpleRegistryService extends AbstractRegistryService { this.registries = registries; } -} \ No newline at end of file +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/action/DemoActionByAnnotation.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/action/DemoActionByAnnotation.java index 6f0ea41055..1163b860ed 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/action/DemoActionByAnnotation.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/action/DemoActionByAnnotation.java @@ -32,4 +32,4 @@ public class DemoActionByAnnotation { return demoService; } -} \ No newline at end of file +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/action/DemoActionBySetter.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/action/DemoActionBySetter.java index c14758b514..1e3d762d4f 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/action/DemoActionBySetter.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/action/DemoActionBySetter.java @@ -33,4 +33,4 @@ public class DemoActionBySetter { this.demoService = demoService; } -} \ No newline at end of file +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/action/DemoInterceptor.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/action/DemoInterceptor.java index e842b4a471..a8f3faeec1 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/action/DemoInterceptor.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/action/DemoInterceptor.java @@ -28,4 +28,4 @@ public class DemoInterceptor implements MethodInterceptor { return "aop:" + invocation.proceed(); } -} \ No newline at end of file +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/annotation/provider/AnnotationServiceImpl.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/annotation/provider/AnnotationServiceImpl.java index baebb80694..c5b5ba20c1 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/annotation/provider/AnnotationServiceImpl.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/annotation/provider/AnnotationServiceImpl.java @@ -34,4 +34,4 @@ public class AnnotationServiceImpl implements DemoService { return null; } -} \ No newline at end of file +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/api/Box.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/api/Box.java index e45f7d4efa..ed168fc37a 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/api/Box.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/api/Box.java @@ -20,4 +20,4 @@ public interface Box { String getName(); -} \ No newline at end of file +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/api/DemoService.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/api/DemoService.java index 6a43a25acd..84fd939716 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/api/DemoService.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/api/DemoService.java @@ -25,4 +25,4 @@ public interface DemoService { Box getBox(); -} \ No newline at end of file +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/api/DemoServiceSon.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/api/DemoServiceSon.java index 1a2d4382ca..52f1b8fda3 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/api/DemoServiceSon.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/api/DemoServiceSon.java @@ -21,4 +21,4 @@ package org.apache.dubbo.config.spring.api; */ public interface DemoServiceSon extends DemoService { // no methods -} \ No newline at end of file +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessorTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessorTest.java index 97c7a7ba48..72d939e0e7 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessorTest.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessorTest.java @@ -349,4 +349,4 @@ public class ReferenceAnnotationBeanPostProcessorTest { } } -} \ No newline at end of file +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationTestConfiguration.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationTestConfiguration.java index 71719b7ef1..59f1385a13 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationTestConfiguration.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationTestConfiguration.java @@ -106,4 +106,4 @@ public class ServiceAnnotationTestConfiguration { }; } -} \ No newline at end of file +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceBeanNameBuilderTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceBeanNameBuilderTest.java index 32d59dc1bf..c57667c98f 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceBeanNameBuilderTest.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceBeanNameBuilderTest.java @@ -74,4 +74,4 @@ public class ServiceBeanNameBuilderTest { builder.build()); } -} \ No newline at end of file +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/EnableDubboConfigTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/EnableDubboConfigTest.java index dfd0fe5964..830dd3eede 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/EnableDubboConfigTest.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/EnableDubboConfigTest.java @@ -139,4 +139,4 @@ public class EnableDubboConfigTest { private static class TestConfig { } -} \ No newline at end of file +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/impl/DemoServiceImpl.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/impl/DemoServiceImpl.java index 8681298423..0413314630 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/impl/DemoServiceImpl.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/impl/DemoServiceImpl.java @@ -42,4 +42,4 @@ public class DemoServiceImpl implements DemoService { this.prefix = prefix; } -} \ No newline at end of file +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/impl/DemoServiceImpl_LongWaiting.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/impl/DemoServiceImpl_LongWaiting.java index e4d5c521f4..5677984795 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/impl/DemoServiceImpl_LongWaiting.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/impl/DemoServiceImpl_LongWaiting.java @@ -36,4 +36,4 @@ public class DemoServiceImpl_LongWaiting implements DemoService { public Box getBox() { return null; } -} \ No newline at end of file +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/impl/DemoServiceSonImpl.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/impl/DemoServiceSonImpl.java index 6207d8ff8f..f97d3b307a 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/impl/DemoServiceSonImpl.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/impl/DemoServiceSonImpl.java @@ -39,4 +39,4 @@ public class DemoServiceSonImpl implements DemoServiceSon { this.prefix = prefix; } -} \ No newline at end of file +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/impl/NotifyService.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/impl/NotifyService.java index f41f63af45..fac95025ba 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/impl/NotifyService.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/impl/NotifyService.java @@ -26,4 +26,4 @@ public class NotifyService { public void onThrow(Throwable ex, int id) { } -} \ No newline at end of file +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/impl/UnserializableBox.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/impl/UnserializableBox.java index 1b14016163..c84f87e7f7 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/impl/UnserializableBox.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/impl/UnserializableBox.java @@ -44,4 +44,4 @@ public class UnserializableBox implements Box { public String toString() { return "Box [count=" + count + ", name=" + name + "]"; } -} \ No newline at end of file +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/impl/UnserializableBoxDemoServiceImpl.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/impl/UnserializableBoxDemoServiceImpl.java index 90101cb9c5..14df2a0dff 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/impl/UnserializableBoxDemoServiceImpl.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/impl/UnserializableBoxDemoServiceImpl.java @@ -32,4 +32,4 @@ public class UnserializableBoxDemoServiceImpl implements DemoService { return new UnserializableBox(); } -} \ No newline at end of file +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/issues/issue6000/adubbo/HelloDubbo.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/issues/issue6000/adubbo/HelloDubbo.java index d09460facf..c66ced0fd6 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/issues/issue6000/adubbo/HelloDubbo.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/issues/issue6000/adubbo/HelloDubbo.java @@ -32,4 +32,4 @@ public class HelloDubbo { public String sayHello(String name) { return helloService.sayHello(name); } -} \ No newline at end of file +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/issues/issue6000/dubbo/MyReferenceConfig.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/issues/issue6000/dubbo/MyReferenceConfig.java index a4e231593b..a235115001 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/issues/issue6000/dubbo/MyReferenceConfig.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/issues/issue6000/dubbo/MyReferenceConfig.java @@ -28,4 +28,4 @@ import org.springframework.context.annotation.Configuration; public class MyReferenceConfig { @Reference(version = "1.0.0", check = false) HelloService helloService; -} \ No newline at end of file +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer/app.properties b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer/app.properties index 8433911fc5..fcda447cfa 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer/app.properties +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer/app.properties @@ -1,4 +1,4 @@ dubbo.registry.address=zookeeper://127.0.0.1:2181?registry-type=service biz.group=greeting biz.group2=group2 -dubbo.call-timeout=2000 \ No newline at end of file +dubbo.call-timeout=2000 diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer/dubbo-consumer.xml b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer/dubbo-consumer.xml index 4af3753d18..8b25aa1516 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer/dubbo-consumer.xml +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer/dubbo-consumer.xml @@ -1,42 +1,42 @@ - - - - - - - classpath:/org/apache/dubbo/config/spring/propertyconfigurer/consumer/app.properties - - - - - - - - - - - - - - - + + + + + + + classpath:/org/apache/dubbo/config/spring/propertyconfigurer/consumer/app.properties + + + + + + + + + + + + + + + diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer2/app.properties b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer2/app.properties index 8433911fc5..fcda447cfa 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer2/app.properties +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer2/app.properties @@ -1,4 +1,4 @@ dubbo.registry.address=zookeeper://127.0.0.1:2181?registry-type=service biz.group=greeting biz.group2=group2 -dubbo.call-timeout=2000 \ No newline at end of file +dubbo.call-timeout=2000 diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer2/dubbo-consumer.xml b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer2/dubbo-consumer.xml index 7836817905..fe30acb29d 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer2/dubbo-consumer.xml +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer2/dubbo-consumer.xml @@ -1,42 +1,42 @@ - - - - - - - classpath:/org/apache/dubbo/config/spring/propertyconfigurer/consumer2/app.properties - - - - - - - - - - - - - - - + + + + + + + classpath:/org/apache/dubbo/config/spring/propertyconfigurer/consumer2/app.properties + + + + + + + + + + + + + + + diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/provider/HelloServiceImpl.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/provider/HelloServiceImpl.java index 392b59555c..ef58855ceb 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/provider/HelloServiceImpl.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/provider/HelloServiceImpl.java @@ -1,38 +1,39 @@ -/* - * 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.spring.propertyconfigurer.provider; - -import org.apache.dubbo.config.spring.api.HelloService; -import org.apache.dubbo.rpc.RpcContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class HelloServiceImpl implements HelloService { - private static final Logger logger = LoggerFactory.getLogger(HelloServiceImpl.class); - - @Override - public String sayHello(String name) { - logger.info("Hello " + name + ", request from consumer: " + RpcContext.getContext().getRemoteAddress()); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - return "Hello " + name + ", response from provider: " + RpcContext.getContext().getLocalAddress(); - } - -} +/* + * 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.spring.propertyconfigurer.provider; + +import org.apache.dubbo.config.spring.api.HelloService; +import org.apache.dubbo.rpc.RpcContext; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class HelloServiceImpl implements HelloService { + private static final Logger logger = LoggerFactory.getLogger(HelloServiceImpl.class); + + @Override + public String sayHello(String name) { + logger.info("Hello " + name + ", request from consumer: " + RpcContext.getContext().getRemoteAddress()); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return "Hello " + name + ", response from provider: " + RpcContext.getContext().getLocalAddress(); + } + +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/provider/app.properties b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/provider/app.properties index 7d57575362..56d423ab85 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/provider/app.properties +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/provider/app.properties @@ -3,4 +3,4 @@ dubbo.registry.address=zookeeper://127.0.0.1:2181?registry-type=service dubbo.config-center.address=zookeeper://127.0.0.1:2181 dubbo.metadata-report.address=zookeeper://127.0.0.1:2181 biz.group=greeting -biz.group2=group2 \ No newline at end of file +biz.group2=group2 diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/javaconfig/consumer.properties b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/javaconfig/consumer.properties index fe04107bb4..0eaff3202f 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/javaconfig/consumer.properties +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/javaconfig/consumer.properties @@ -3,4 +3,4 @@ dubbo.protocol.name=dubbo dubbo.protocol.port=-1 dubbo.registry.address=N/A dubbo.reference.org.apache.dubbo.config.spring.api.HelloService.init=false -myapp.group=demo \ No newline at end of file +myapp.group=demo diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/localcalla/local-call-config.properties b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/localcalla/local-call-config.properties index c3ce30c478..bfeadc522f 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/localcalla/local-call-config.properties +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/localcalla/local-call-config.properties @@ -1,4 +1,4 @@ dubbo.application.name=local-call-demo dubbo.protocol.name=dubbo dubbo.protocol.port=-1 -dubbo.registry.address=N/A \ No newline at end of file +dubbo.registry.address=N/A diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/localcallam/local-call-config.properties b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/localcallam/local-call-config.properties index cc5d59ab76..55b14daa56 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/localcallam/local-call-config.properties +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/localcallam/local-call-config.properties @@ -2,4 +2,4 @@ dubbo.application.name=local-call-demo dubbo.protocol.name=dubbo dubbo.protocol.port=-1 dubbo.registry.address=N/A -biz.group=demo \ No newline at end of file +biz.group=demo diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/localcallmix/local-call-config.properties b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/localcallmix/local-call-config.properties index c3ce30c478..bfeadc522f 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/localcallmix/local-call-config.properties +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/localcallmix/local-call-config.properties @@ -1,4 +1,4 @@ dubbo.application.name=local-call-demo dubbo.protocol.name=dubbo dubbo.protocol.port=-1 -dubbo.registry.address=N/A \ No newline at end of file +dubbo.registry.address=N/A diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/registry/nacos/demo/service/DemoService.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/registry/nacos/demo/service/DemoService.java index 313625d456..f685f3d268 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/registry/nacos/demo/service/DemoService.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/registry/nacos/demo/service/DemoService.java @@ -25,4 +25,4 @@ public interface DemoService { String sayName(String name); -} \ No newline at end of file +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandlerTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandlerTest.java index 9f125a2e63..d0b2816015 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandlerTest.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandlerTest.java @@ -242,4 +242,4 @@ public class DubboNamespaceHandlerTest { String prefix = ((DemoServiceImpl) serviceBean.getRef()).getPrefix(); assertThat(prefix, is("welcome:")); } -} \ No newline at end of file +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/util/EnvironmentUtilsTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/util/EnvironmentUtilsTest.java index 48ea424c61..f68dc089b5 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/util/EnvironmentUtilsTest.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/util/EnvironmentUtilsTest.java @@ -1,88 +1,88 @@ -/* - * 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.spring.util; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.springframework.core.env.CompositePropertySource; -import org.springframework.core.env.MapPropertySource; -import org.springframework.core.env.MutablePropertySources; -import org.springframework.core.env.StandardEnvironment; -import org.springframework.mock.env.MockEnvironment; - -import java.util.HashMap; -import java.util.Map; -import java.util.SortedMap; - -import static org.apache.dubbo.config.spring.util.EnvironmentUtils.filterDubboProperties; - -/** - * {@link EnvironmentUtils} Test - * - * @see EnvironmentUtils - * @since 2.7.0 - */ -public class EnvironmentUtilsTest { - - @Test - public void testExtraProperties() { - - String key = "test.name"; - System.setProperty(key, "Tom"); - - try { - StandardEnvironment environment = new StandardEnvironment(); - - Map map = new HashMap<>(); - - map.put(key, "Mercy"); - - MapPropertySource propertySource = new MapPropertySource("first", map); - - CompositePropertySource compositePropertySource = new CompositePropertySource("comp"); - - compositePropertySource.addFirstPropertySource(propertySource); - - MutablePropertySources propertySources = environment.getPropertySources(); - - propertySources.addFirst(compositePropertySource); - - Map properties = EnvironmentUtils.extractProperties(environment); - - Assertions.assertEquals("Mercy", properties.get(key)); - } finally { - System.clearProperty(key); - } - - } - - @Test - public void testFilterDubboProperties() { - - MockEnvironment environment = new MockEnvironment(); - environment.setProperty("message", "Hello,World"); - environment.setProperty("dubbo.registry.address", "zookeeper://10.10.10.1:2181"); - environment.setProperty("dubbo.consumer.check", "false"); - - SortedMap dubboProperties = filterDubboProperties(environment); - - Assertions.assertEquals(2, dubboProperties.size()); - Assertions.assertEquals("zookeeper://10.10.10.1:2181", dubboProperties.get("dubbo.registry.address")); - Assertions.assertEquals("false", dubboProperties.get("dubbo.consumer.check")); - - } -} +/* + * 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.spring.util; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.core.env.CompositePropertySource; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.MutablePropertySources; +import org.springframework.core.env.StandardEnvironment; +import org.springframework.mock.env.MockEnvironment; + +import java.util.HashMap; +import java.util.Map; +import java.util.SortedMap; + +import static org.apache.dubbo.config.spring.util.EnvironmentUtils.filterDubboProperties; + +/** + * {@link EnvironmentUtils} Test + * + * @see EnvironmentUtils + * @since 2.7.0 + */ +public class EnvironmentUtilsTest { + + @Test + public void testExtraProperties() { + + String key = "test.name"; + System.setProperty(key, "Tom"); + + try { + StandardEnvironment environment = new StandardEnvironment(); + + Map map = new HashMap<>(); + + map.put(key, "Mercy"); + + MapPropertySource propertySource = new MapPropertySource("first", map); + + CompositePropertySource compositePropertySource = new CompositePropertySource("comp"); + + compositePropertySource.addFirstPropertySource(propertySource); + + MutablePropertySources propertySources = environment.getPropertySources(); + + propertySources.addFirst(compositePropertySource); + + Map properties = EnvironmentUtils.extractProperties(environment); + + Assertions.assertEquals("Mercy", properties.get(key)); + } finally { + System.clearProperty(key); + } + + } + + @Test + public void testFilterDubboProperties() { + + MockEnvironment environment = new MockEnvironment(); + environment.setProperty("message", "Hello,World"); + environment.setProperty("dubbo.registry.address", "zookeeper://10.10.10.1:2181"); + environment.setProperty("dubbo.consumer.check", "false"); + + SortedMap dubboProperties = filterDubboProperties(environment); + + Assertions.assertEquals(2, dubboProperties.size()); + Assertions.assertEquals("zookeeper://10.10.10.1:2181", dubboProperties.get("dubbo.registry.address")); + Assertions.assertEquals("false", dubboProperties.get("dubbo.consumer.check")); + + } +} diff --git a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/config.properties b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/config.properties index 1f315e37ce..51b587ea4f 100644 --- a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/config.properties +++ b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/config.properties @@ -33,4 +33,4 @@ dubbo.consumer.client = netty # multiple Bean definition dubbo.registries.registry1.address = zookeeper://localhost:2181 -dubbo.registries.registry2.address = zookeeper://localhost:2182 \ No newline at end of file +dubbo.registries.registry2.address = zookeeper://localhost:2182 diff --git a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/dubbb-consumer.properties b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/dubbb-consumer.properties index 4583323bbd..736358a499 100644 --- a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/dubbb-consumer.properties +++ b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/dubbb-consumer.properties @@ -9,4 +9,4 @@ dubbo.applications.dubbo-demo-application.name = dubbo-demo-application ### dubbo.registries.my-registry.address = N/A -dubbo.registries.my-registry2.address = N/A \ No newline at end of file +dubbo.registries.my-registry2.address = N/A diff --git a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/dubbb-provider.properties b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/dubbb-provider.properties index f2e20c4df9..24b479e712 100644 --- a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/dubbb-provider.properties +++ b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/dubbb-provider.properties @@ -21,4 +21,4 @@ dubbo.registry.address = N/A ### dubbo.protocol.id = dubbo dubbo.protocol.name = dubbo -dubbo.protocol.port = 12345 \ No newline at end of file +dubbo.protocol.port = 12345 diff --git a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/dubbo-consumer.properties b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/dubbo-consumer.properties index 094b709165..f841d6a7fb 100644 --- a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/dubbo-consumer.properties +++ b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/dubbo-consumer.properties @@ -10,4 +10,4 @@ dubbo.applications.dubbo-demo-application.name = dubbo-demo-application ### dubbo.registries.my-registry.address = N/A -dubbo.registries.my-registry2.address = N/A \ No newline at end of file +dubbo.registries.my-registry2.address = N/A diff --git a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/dubbo-provider.properties b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/dubbo-provider.properties index 0cbed904be..63c984d1ce 100644 --- a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/dubbo-provider.properties +++ b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/dubbo-provider.properties @@ -21,4 +21,4 @@ dubbo.registry.address = N/A ### dubbo.protocol.name = dubbo dubbo.protocol.port = 12345 -dubbo.monitor.address=N/A \ No newline at end of file +dubbo.monitor.address=N/A diff --git a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/init-reference.properties b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/init-reference.properties index 55050c2876..59408e1d44 100644 --- a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/init-reference.properties +++ b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/init-reference.properties @@ -2,4 +2,4 @@ call.timeout=1000 connection.timeout=1000 -sayName.retry=false \ No newline at end of file +sayName.retry=false diff --git a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/issues/issue6252/config.properties b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/issues/issue6252/config.properties index 4acd7f015d..5d0ff91aeb 100644 --- a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/issues/issue6252/config.properties +++ b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/issues/issue6252/config.properties @@ -12,4 +12,4 @@ dubbo.registries.z214.useAsMetadataCenter=false dubbo.registries.z205.address=zookeeper://127.0.0.1:2182 dubbo.registries.z205.timeout=20000 dubbo.registries.z205.useAsConfigCenter=false -dubbo.registries.z205.useAsMetadataCenter=false \ No newline at end of file +dubbo.registries.z205.useAsMetadataCenter=false diff --git a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/service-introspection/zookeeper-dubbb-consumer.properties b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/service-introspection/zookeeper-dubbb-consumer.properties index 1795afac93..89e59a4846 100644 --- a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/service-introspection/zookeeper-dubbb-consumer.properties +++ b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/service-introspection/zookeeper-dubbb-consumer.properties @@ -11,4 +11,4 @@ dubbo.protocol.port = -1 dubbo.provider.name = zookeeper-dubbo-spring-provider dubbo.provider.name1 = zookeeper-dubbo-spring-provider-1 -dubbo.provider.name2 = zookeeper-dubbo-spring-provider-2 \ No newline at end of file +dubbo.provider.name2 = zookeeper-dubbo-spring-provider-2 diff --git a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/service-introspection/zookeeper-dubbb-provider.properties b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/service-introspection/zookeeper-dubbb-provider.properties index 1b977a57f9..d81a529124 100644 --- a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/service-introspection/zookeeper-dubbb-provider.properties +++ b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/service-introspection/zookeeper-dubbb-provider.properties @@ -7,4 +7,4 @@ dubbo.registry.useAsConfigCenter = true dubbo.registry.useAsMetadataCenter = true dubbo.protocol.name = dubbo -dubbo.protocol.port = -1 \ No newline at end of file +dubbo.protocol.port = -1 diff --git a/dubbo-config/dubbo-config-spring/src/test/resources/dubbo-binder.properties b/dubbo-config/dubbo-config-spring/src/test/resources/dubbo-binder.properties index 2f0f594b8e..ae41dc9d0e 100644 --- a/dubbo-config/dubbo-config-spring/src/test/resources/dubbo-binder.properties +++ b/dubbo-config/dubbo-config-spring/src/test/resources/dubbo-binder.properties @@ -3,4 +3,4 @@ dubbo.application.owner=world dubbo.registry.address=10.20.153.17 dubbo.protocol.port=20881 dubbo.service.invoke.timeout=2000 -dubbo.consumer.timeout \ No newline at end of file +dubbo.consumer.timeout diff --git a/dubbo-config/dubbo-config-spring/src/test/resources/dubbo.properties b/dubbo-config/dubbo-config-spring/src/test/resources/dubbo.properties index 6b4019dff3..9a20f23327 100644 --- a/dubbo-config/dubbo-config-spring/src/test/resources/dubbo.properties +++ b/dubbo-config/dubbo-config-spring/src/test/resources/dubbo.properties @@ -1 +1 @@ -dubbo.application.enable-file-cache=false \ No newline at end of file +dubbo.application.enable-file-cache=false diff --git a/dubbo-config/dubbo-config-spring/src/test/resources/nacos-consumer-config.properties b/dubbo-config/dubbo-config-spring/src/test/resources/nacos-consumer-config.properties index d32e6e8a64..9a60c47a9c 100644 --- a/dubbo-config/dubbo-config-spring/src/test/resources/nacos-consumer-config.properties +++ b/dubbo-config/dubbo-config-spring/src/test/resources/nacos-consumer-config.properties @@ -3,4 +3,4 @@ dubbo.application.name=dubbo-consumer-demo ## Nacos registry address dubbo.registry.address=nacos://127.0.0.1:8848 # @Reference version -demo.service.version=1.0.0 \ No newline at end of file +demo.service.version=1.0.0 diff --git a/dubbo-config/dubbo-config-spring/src/test/resources/nacos-provider-config.properties b/dubbo-config/dubbo-config-spring/src/test/resources/nacos-provider-config.properties index 7e2046b5c4..093af1fe1f 100644 --- a/dubbo-config/dubbo-config-spring/src/test/resources/nacos-provider-config.properties +++ b/dubbo-config/dubbo-config-spring/src/test/resources/nacos-provider-config.properties @@ -8,4 +8,4 @@ dubbo.registry.address=127.0.0.1:8848 dubbo.protocols.dubbo.port=-1 # Provider @Service info demo.service.version=1.0.0 -demo.service.name=demoService \ No newline at end of file +demo.service.name=demoService diff --git a/dubbo-configcenter/dubbo-configcenter-apollo/src/test/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfigurationTest.java b/dubbo-configcenter/dubbo-configcenter-apollo/src/test/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfigurationTest.java index b14f172bb9..6b2d3d2b42 100644 --- a/dubbo-configcenter/dubbo-configcenter-apollo/src/test/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfigurationTest.java +++ b/dubbo-configcenter/dubbo-configcenter-apollo/src/test/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfigurationTest.java @@ -187,4 +187,4 @@ public class ApolloDynamicConfigurationTest { } -} \ No newline at end of file +} diff --git a/dubbo-configcenter/dubbo-configcenter-apollo/src/test/resources/META-INF/app.properties b/dubbo-configcenter/dubbo-configcenter-apollo/src/test/resources/META-INF/app.properties index 4d963e24a8..dca1d42b34 100644 --- a/dubbo-configcenter/dubbo-configcenter-apollo/src/test/resources/META-INF/app.properties +++ b/dubbo-configcenter/dubbo-configcenter-apollo/src/test/resources/META-INF/app.properties @@ -1 +1 @@ -app.id=someAppId \ No newline at end of file +app.id=someAppId diff --git a/dubbo-configcenter/dubbo-configcenter-apollo/src/test/resources/mockdata-dubbo.properties b/dubbo-configcenter/dubbo-configcenter-apollo/src/test/resources/mockdata-dubbo.properties index f995a3b85e..48580bfcce 100644 --- a/dubbo-configcenter/dubbo-configcenter-apollo/src/test/resources/mockdata-dubbo.properties +++ b/dubbo-configcenter/dubbo-configcenter-apollo/src/test/resources/mockdata-dubbo.properties @@ -1,2 +1,2 @@ key1=value1 -key2=value2 \ No newline at end of file +key2=value2 diff --git a/dubbo-configcenter/dubbo-configcenter-zookeeper/src/test/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfigurationTest.java b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/test/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfigurationTest.java index 175eef8a73..bae736a54f 100644 --- a/dubbo-configcenter/dubbo-configcenter-zookeeper/src/test/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfigurationTest.java +++ b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/test/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfigurationTest.java @@ -32,6 +32,7 @@ import org.apache.curator.test.TestingServer; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import java.util.HashMap; @@ -48,6 +49,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; /** * TODO refactor using mockito */ +@Disabled("Disabled Due to Zookeeper in Github Actions") public class ZookeeperDynamicConfigurationTest { private static CuratorFramework client; diff --git a/dubbo-container/dubbo-container-api/src/main/java/org/apache/dubbo/container/Container.java b/dubbo-container/dubbo-container-api/src/main/java/org/apache/dubbo/container/Container.java index bb3cc5cc10..66b76b496e 100644 --- a/dubbo-container/dubbo-container-api/src/main/java/org/apache/dubbo/container/Container.java +++ b/dubbo-container/dubbo-container-api/src/main/java/org/apache/dubbo/container/Container.java @@ -1,37 +1,37 @@ -/* - * 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.container; - -import org.apache.dubbo.common.extension.SPI; - -/** - * Container. (SPI, Singleton, ThreadSafe) - */ -@SPI("spring") -public interface Container { - - /** - * start method to load the container. - */ - void start(); - - /** - * stop method to unload the container. - */ - void stop(); - -} \ No newline at end of file +/* + * 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.container; + +import org.apache.dubbo.common.extension.SPI; + +/** + * Container. (SPI, Singleton, ThreadSafe) + */ +@SPI("spring") +public interface Container { + + /** + * start method to load the container. + */ + void start(); + + /** + * stop method to unload the container. + */ + void stop(); + +} diff --git a/dubbo-container/dubbo-container-api/src/main/java/org/apache/dubbo/container/Main.java b/dubbo-container/dubbo-container-api/src/main/java/org/apache/dubbo/container/Main.java index 91c76efe06..c0f1c9bc1d 100644 --- a/dubbo-container/dubbo-container-api/src/main/java/org/apache/dubbo/container/Main.java +++ b/dubbo-container/dubbo-container-api/src/main/java/org/apache/dubbo/container/Main.java @@ -1,108 +1,108 @@ -/* - * 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.container; - -import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.utils.ArrayUtils; -import org.apache.dubbo.common.utils.ConfigUtils; - -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Date; -import java.util.List; -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.ReentrantLock; - -import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN; - -/** - * Main. (API, Static, ThreadSafe) - * - * This class is entry point loading containers. - */ -public class Main { - - public static final String CONTAINER_KEY = "dubbo.container"; - - public static final String SHUTDOWN_HOOK_KEY = "dubbo.shutdown.hook"; - - private static final Logger logger = LoggerFactory.getLogger(Main.class); - - private static final ExtensionLoader LOADER = ExtensionLoader.getExtensionLoader(Container.class); - - private static final ReentrantLock LOCK = new ReentrantLock(); - - private static final Condition STOP = LOCK.newCondition(); - - public static void main(String[] args) { - try { - if (ArrayUtils.isEmpty(args)) { - String config = ConfigUtils.getProperty(CONTAINER_KEY, LOADER.getDefaultExtensionName()); - args = COMMA_SPLIT_PATTERN.split(config); - } - - final List containers = new ArrayList(); - for (int i = 0; i < args.length; i++) { - containers.add(LOADER.getExtension(args[i])); - } - logger.info("Use container type(" + Arrays.toString(args) + ") to run dubbo serivce."); - - if ("true".equals(System.getProperty(SHUTDOWN_HOOK_KEY))) { - Runtime.getRuntime().addShutdownHook(new Thread("dubbo-container-shutdown-hook") { - @Override - public void run() { - for (Container container : containers) { - try { - container.stop(); - logger.info("Dubbo " + container.getClass().getSimpleName() + " stopped!"); - } catch (Throwable t) { - logger.error(t.getMessage(), t); - } - try { - LOCK.lock(); - STOP.signal(); - } finally { - LOCK.unlock(); - } - } - } - }); - } - - for (Container container : containers) { - container.start(); - logger.info("Dubbo " + container.getClass().getSimpleName() + " started!"); - } - System.out.println(new SimpleDateFormat("[yyyy-MM-dd HH:mm:ss]").format(new Date()) + " Dubbo service server started!"); - } catch (RuntimeException e) { - logger.error(e.getMessage(), e); - System.exit(1); - } - try { - LOCK.lock(); - STOP.await(); - } catch (InterruptedException e) { - logger.warn("Dubbo service server stopped, interrupted by other thread!", e); - } finally { - LOCK.unlock(); - } - } - -} +/* + * 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.container; + +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.ArrayUtils; +import org.apache.dubbo.common.utils.ConfigUtils; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; + +import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN; + +/** + * Main. (API, Static, ThreadSafe) + * + * This class is entry point loading containers. + */ +public class Main { + + public static final String CONTAINER_KEY = "dubbo.container"; + + public static final String SHUTDOWN_HOOK_KEY = "dubbo.shutdown.hook"; + + private static final Logger logger = LoggerFactory.getLogger(Main.class); + + private static final ExtensionLoader LOADER = ExtensionLoader.getExtensionLoader(Container.class); + + private static final ReentrantLock LOCK = new ReentrantLock(); + + private static final Condition STOP = LOCK.newCondition(); + + public static void main(String[] args) { + try { + if (ArrayUtils.isEmpty(args)) { + String config = ConfigUtils.getProperty(CONTAINER_KEY, LOADER.getDefaultExtensionName()); + args = COMMA_SPLIT_PATTERN.split(config); + } + + final List containers = new ArrayList(); + for (int i = 0; i < args.length; i++) { + containers.add(LOADER.getExtension(args[i])); + } + logger.info("Use container type(" + Arrays.toString(args) + ") to run dubbo serivce."); + + if ("true".equals(System.getProperty(SHUTDOWN_HOOK_KEY))) { + Runtime.getRuntime().addShutdownHook(new Thread("dubbo-container-shutdown-hook") { + @Override + public void run() { + for (Container container : containers) { + try { + container.stop(); + logger.info("Dubbo " + container.getClass().getSimpleName() + " stopped!"); + } catch (Throwable t) { + logger.error(t.getMessage(), t); + } + try { + LOCK.lock(); + STOP.signal(); + } finally { + LOCK.unlock(); + } + } + } + }); + } + + for (Container container : containers) { + container.start(); + logger.info("Dubbo " + container.getClass().getSimpleName() + " started!"); + } + System.out.println(new SimpleDateFormat("[yyyy-MM-dd HH:mm:ss]").format(new Date()) + " Dubbo service server started!"); + } catch (RuntimeException e) { + logger.error(e.getMessage(), e); + System.exit(1); + } + try { + LOCK.lock(); + STOP.await(); + } catch (InterruptedException e) { + logger.warn("Dubbo service server stopped, interrupted by other thread!", e); + } finally { + LOCK.unlock(); + } + } + +} diff --git a/dubbo-container/dubbo-container-api/src/main/resources/META-INF/assembly/bin/start.bat b/dubbo-container/dubbo-container-api/src/main/resources/META-INF/assembly/bin/start.bat index 21a0b2128b..f14d2e8b1e 100644 --- a/dubbo-container/dubbo-container-api/src/main/resources/META-INF/assembly/bin/start.bat +++ b/dubbo-container/dubbo-container-api/src/main/resources/META-INF/assembly/bin/start.bat @@ -1,44 +1,44 @@ -@echo off & setlocal enabledelayedexpansion - -REM Licensed to the Apache Software Foundation (ASF) under one or more -REM contributor license agreements. See the NOTICE file distributed with -REM this work for additional information regarding copyright ownership. -REM The ASF licenses this file to You under the Apache License, Version 2.0 -REM (the "License"); you may not use this file except in compliance with -REM the License. You may obtain a copy of the License at -REM -REM http://www.apache.org/licenses/LICENSE-2.0 -REM -REM Unless required by applicable law or agreed to in writing, software -REM distributed under the License is distributed on an "AS IS" BASIS, -REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -REM See the License for the specific language governing permissions and -REM limitations under the License. - -set LIB_JARS="" -set VM_ARGS_PERM_SIZE="MaxPermSize" -set VM_ARGS_METASPACE_SIZE="MaxMetaspaceSize" -set JAVA_8_VERSION="180" -cd ..\lib -for %%i in (*) do set LIB_JARS=!LIB_JARS!;..\lib\%%i -cd ..\bin - -@REM set jvm args by different java version -for /f tokens^=2-4^ delims^=.-_+^" %%j in ('java -fullversion 2^>^&1') do set "JAVA_VERSION=%%j%%k%%l" -set VM_ARGS=%VM_ARGS_PERM_SIZE% -if "%JAVA_VERSION%" GEQ %JAVA_8_VERSION% set VM_ARGS=%VM_ARGS_METASPACE_SIZE% -if ""%1"" == ""debug"" goto debug -if ""%1"" == ""jmx"" goto jmx - -java -Xms64m -Xmx1024m -XX:%VM_ARGS%=64M -classpath ..\conf;%LIB_JARS% org.apache.dubbo.container.Main -goto end - -:debug -java -Xms64m -Xmx1024m -XX:%VM_ARGS%=64M -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n -classpath ..\conf;%LIB_JARS% org.apache.dubbo.container.Main -goto end - -:jmx -java -Xms64m -Xmx1024m -XX:%VM_ARGS%=64M -Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -classpath ..\conf;%LIB_JARS% org.apache.dubbo.container.Main - -:end +@echo off & setlocal enabledelayedexpansion + +REM Licensed to the Apache Software Foundation (ASF) under one or more +REM contributor license agreements. See the NOTICE file distributed with +REM this work for additional information regarding copyright ownership. +REM The ASF licenses this file to You under the Apache License, Version 2.0 +REM (the "License"); you may not use this file except in compliance with +REM the License. You may obtain a copy of the License at +REM +REM http://www.apache.org/licenses/LICENSE-2.0 +REM +REM Unless required by applicable law or agreed to in writing, software +REM distributed under the License is distributed on an "AS IS" BASIS, +REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +REM See the License for the specific language governing permissions and +REM limitations under the License. + +set LIB_JARS="" +set VM_ARGS_PERM_SIZE="MaxPermSize" +set VM_ARGS_METASPACE_SIZE="MaxMetaspaceSize" +set JAVA_8_VERSION="180" +cd ..\lib +for %%i in (*) do set LIB_JARS=!LIB_JARS!;..\lib\%%i +cd ..\bin + +@REM set jvm args by different java version +for /f tokens^=2-4^ delims^=.-_+^" %%j in ('java -fullversion 2^>^&1') do set "JAVA_VERSION=%%j%%k%%l" +set VM_ARGS=%VM_ARGS_PERM_SIZE% +if "%JAVA_VERSION%" GEQ %JAVA_8_VERSION% set VM_ARGS=%VM_ARGS_METASPACE_SIZE% +if ""%1"" == ""debug"" goto debug +if ""%1"" == ""jmx"" goto jmx + +java -Xms64m -Xmx1024m -XX:%VM_ARGS%=64M -classpath ..\conf;%LIB_JARS% org.apache.dubbo.container.Main +goto end + +:debug +java -Xms64m -Xmx1024m -XX:%VM_ARGS%=64M -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n -classpath ..\conf;%LIB_JARS% org.apache.dubbo.container.Main +goto end + +:jmx +java -Xms64m -Xmx1024m -XX:%VM_ARGS%=64M -Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -classpath ..\conf;%LIB_JARS% org.apache.dubbo.container.Main + +:end pause \ No newline at end of file diff --git a/dubbo-container/dubbo-container-spring/src/main/java/org/apache/dubbo/container/spring/SpringContainer.java b/dubbo-container/dubbo-container-spring/src/main/java/org/apache/dubbo/container/spring/SpringContainer.java index 884fe098e3..390a57a5dd 100644 --- a/dubbo-container/dubbo-container-spring/src/main/java/org/apache/dubbo/container/spring/SpringContainer.java +++ b/dubbo-container/dubbo-container-spring/src/main/java/org/apache/dubbo/container/spring/SpringContainer.java @@ -1,67 +1,67 @@ -/* - * 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.container.spring; - -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.utils.ConfigUtils; -import org.apache.dubbo.common.utils.StringUtils; -import org.apache.dubbo.container.Container; - -import org.springframework.context.support.ClassPathXmlApplicationContext; - -/** - * SpringContainer. (SPI, Singleton, ThreadSafe) - * - * The container class implementation for Spring - */ -public class SpringContainer implements Container { - - public static final String SPRING_CONFIG = "dubbo.spring.config"; - public static final String DEFAULT_SPRING_CONFIG = "classpath*:META-INF/spring/*.xml"; - private static final Logger logger = LoggerFactory.getLogger(SpringContainer.class); - static ClassPathXmlApplicationContext context; - - public static ClassPathXmlApplicationContext getContext() { - return context; - } - - @Override - public void start() { - String configPath = ConfigUtils.getProperty(SPRING_CONFIG); - if (StringUtils.isEmpty(configPath)) { - configPath = DEFAULT_SPRING_CONFIG; - } - context = new ClassPathXmlApplicationContext(configPath.split("[,\\s]+"), false); - context.refresh(); - context.start(); - } - - @Override - public void stop() { - try { - if (context != null) { - context.stop(); - context.close(); - context = null; - } - } catch (Throwable e) { - logger.error(e.getMessage(), e); - } - } - -} +/* + * 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.container.spring; + +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.ConfigUtils; +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.container.Container; + +import org.springframework.context.support.ClassPathXmlApplicationContext; + +/** + * SpringContainer. (SPI, Singleton, ThreadSafe) + * + * The container class implementation for Spring + */ +public class SpringContainer implements Container { + + public static final String SPRING_CONFIG = "dubbo.spring.config"; + public static final String DEFAULT_SPRING_CONFIG = "classpath*:META-INF/spring/*.xml"; + private static final Logger logger = LoggerFactory.getLogger(SpringContainer.class); + static ClassPathXmlApplicationContext context; + + public static ClassPathXmlApplicationContext getContext() { + return context; + } + + @Override + public void start() { + String configPath = ConfigUtils.getProperty(SPRING_CONFIG); + if (StringUtils.isEmpty(configPath)) { + configPath = DEFAULT_SPRING_CONFIG; + } + context = new ClassPathXmlApplicationContext(configPath.split("[,\\s]+"), false); + context.refresh(); + context.start(); + } + + @Override + public void stop() { + try { + if (context != null) { + context.stop(); + context.close(); + context = null; + } + } catch (Throwable e) { + logger.error(e.getMessage(), e); + } + } + +} diff --git a/dubbo-container/dubbo-container-spring/src/test/java/org/apache/dubbo/container/spring/SpringContainerTest.java b/dubbo-container/dubbo-container-spring/src/test/java/org/apache/dubbo/container/spring/SpringContainerTest.java index 05acbb8e5c..a09a1bf349 100644 --- a/dubbo-container/dubbo-container-spring/src/test/java/org/apache/dubbo/container/spring/SpringContainerTest.java +++ b/dubbo-container/dubbo-container-spring/src/test/java/org/apache/dubbo/container/spring/SpringContainerTest.java @@ -1,38 +1,38 @@ -/* - * 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.container.spring; - -import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.container.Container; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -/** - * StandaloneContainerTest - */ -public class SpringContainerTest { - - @Test - public void testContainer() { - SpringContainer container = (SpringContainer) ExtensionLoader.getExtensionLoader(Container.class).getExtension("spring"); - container.start(); - Assertions.assertEquals(SpringContainer.class, container.context.getBean("container").getClass()); - container.stop(); - } - -} \ No newline at end of file +/* + * 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.container.spring; + +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.container.Container; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +/** + * StandaloneContainerTest + */ +public class SpringContainerTest { + + @Test + public void testContainer() { + SpringContainer container = (SpringContainer) ExtensionLoader.getExtensionLoader(Container.class).getExtension("spring"); + container.start(); + Assertions.assertEquals(SpringContainer.class, container.context.getBean("container").getClass()); + container.stop(); + } + +} diff --git a/dubbo-container/dubbo-container-spring/src/test/resources/META-INF/spring/test.xml b/dubbo-container/dubbo-container-spring/src/test/resources/META-INF/spring/test.xml index 282519cea4..2bdf7a1485 100644 --- a/dubbo-container/dubbo-container-spring/src/test/resources/META-INF/spring/test.xml +++ b/dubbo-container/dubbo-container-spring/src/test/resources/META-INF/spring/test.xml @@ -1,24 +1,24 @@ - - - - - - + + + + + + \ No newline at end of file diff --git a/dubbo-container/dubbo-container-spring/src/test/resources/log4j.xml b/dubbo-container/dubbo-container-spring/src/test/resources/log4j.xml index f037070087..6bf9bd85ff 100644 --- a/dubbo-container/dubbo-container-spring/src/test/resources/log4j.xml +++ b/dubbo-container/dubbo-container-spring/src/test/resources/log4j.xml @@ -1,29 +1,29 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + \ No newline at end of file diff --git a/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-consumer/src/main/resources/log4j.properties b/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-consumer/src/main/resources/log4j.properties index 15a0900f0d..8de4c4fddb 100644 --- a/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-consumer/src/main/resources/log4j.properties +++ b/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-consumer/src/main/resources/log4j.properties @@ -4,4 +4,4 @@ log4j.rootLogger=info, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy HH:mm:ss:SSS z}] %t %5p %c{2}: %m%n \ No newline at end of file +log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy HH:mm:ss:SSS z}] %t %5p %c{2}: %m%n diff --git a/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-provider/src/main/java/org/apache/dubbo/demo/provider/DemoServiceImpl.java b/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-provider/src/main/java/org/apache/dubbo/demo/provider/DemoServiceImpl.java index 7b4002714f..8983ed287b 100644 --- a/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-provider/src/main/java/org/apache/dubbo/demo/provider/DemoServiceImpl.java +++ b/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-provider/src/main/java/org/apache/dubbo/demo/provider/DemoServiceImpl.java @@ -1,43 +1,43 @@ -/* - * 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.demo.provider; - -import org.apache.dubbo.config.annotation.DubboService; -import org.apache.dubbo.demo.DemoService; -import org.apache.dubbo.rpc.RpcContext; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.concurrent.CompletableFuture; - -@DubboService -public class DemoServiceImpl implements DemoService { - private static final Logger logger = LoggerFactory.getLogger(DemoServiceImpl.class); - - @Override - public String sayHello(String name) { - logger.info("Hello " + name + ", request from consumer: " + RpcContext.getServiceContext().getRemoteAddress()); - return "Hello " + name + ", response from provider: " + RpcContext.getServiceContext().getLocalAddress(); - } - - @Override - public CompletableFuture sayHelloAsync(String name) { - return null; - } - -} +/* + * 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.demo.provider; + +import org.apache.dubbo.config.annotation.DubboService; +import org.apache.dubbo.demo.DemoService; +import org.apache.dubbo.rpc.RpcContext; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.CompletableFuture; + +@DubboService +public class DemoServiceImpl implements DemoService { + private static final Logger logger = LoggerFactory.getLogger(DemoServiceImpl.class); + + @Override + public String sayHello(String name) { + logger.info("Hello " + name + ", request from consumer: " + RpcContext.getServiceContext().getRemoteAddress()); + return "Hello " + name + ", response from provider: " + RpcContext.getServiceContext().getLocalAddress(); + } + + @Override + public CompletableFuture sayHelloAsync(String name) { + return null; + } + +} diff --git a/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-provider/src/main/resources/log4j.properties b/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-provider/src/main/resources/log4j.properties index 15a0900f0d..8de4c4fddb 100644 --- a/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-provider/src/main/resources/log4j.properties +++ b/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-provider/src/main/resources/log4j.properties @@ -4,4 +4,4 @@ log4j.rootLogger=info, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy HH:mm:ss:SSS z}] %t %5p %c{2}: %m%n \ No newline at end of file +log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy HH:mm:ss:SSS z}] %t %5p %c{2}: %m%n diff --git a/dubbo-demo/dubbo-demo-api/dubbo-demo-api-consumer/src/main/resources/log4j.properties b/dubbo-demo/dubbo-demo-api/dubbo-demo-api-consumer/src/main/resources/log4j.properties index 15a0900f0d..8de4c4fddb 100644 --- a/dubbo-demo/dubbo-demo-api/dubbo-demo-api-consumer/src/main/resources/log4j.properties +++ b/dubbo-demo/dubbo-demo-api/dubbo-demo-api-consumer/src/main/resources/log4j.properties @@ -4,4 +4,4 @@ log4j.rootLogger=info, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy HH:mm:ss:SSS z}] %t %5p %c{2}: %m%n \ No newline at end of file +log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy HH:mm:ss:SSS z}] %t %5p %c{2}: %m%n diff --git a/dubbo-demo/dubbo-demo-api/dubbo-demo-api-provider/src/main/resources/log4j.properties b/dubbo-demo/dubbo-demo-api/dubbo-demo-api-provider/src/main/resources/log4j.properties index 15a0900f0d..8de4c4fddb 100644 --- a/dubbo-demo/dubbo-demo-api/dubbo-demo-api-provider/src/main/resources/log4j.properties +++ b/dubbo-demo/dubbo-demo-api/dubbo-demo-api-provider/src/main/resources/log4j.properties @@ -4,4 +4,4 @@ log4j.rootLogger=info, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy HH:mm:ss:SSS z}] %t %5p %c{2}: %m%n \ No newline at end of file +log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy HH:mm:ss:SSS z}] %t %5p %c{2}: %m%n diff --git a/dubbo-demo/dubbo-demo-generic-call/src/main/resources/log4j.properties b/dubbo-demo/dubbo-demo-generic-call/src/main/resources/log4j.properties index 15a0900f0d..8de4c4fddb 100644 --- a/dubbo-demo/dubbo-demo-generic-call/src/main/resources/log4j.properties +++ b/dubbo-demo/dubbo-demo-generic-call/src/main/resources/log4j.properties @@ -4,4 +4,4 @@ log4j.rootLogger=info, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy HH:mm:ss:SSS z}] %t %5p %c{2}: %m%n \ No newline at end of file +log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy HH:mm:ss:SSS z}] %t %5p %c{2}: %m%n diff --git a/dubbo-demo/dubbo-demo-interface/src/main/java/org/apache/dubbo/demo/DemoService.java b/dubbo-demo/dubbo-demo-interface/src/main/java/org/apache/dubbo/demo/DemoService.java index 32337acdfd..09bdafa1f6 100644 --- a/dubbo-demo/dubbo-demo-interface/src/main/java/org/apache/dubbo/demo/DemoService.java +++ b/dubbo-demo/dubbo-demo-interface/src/main/java/org/apache/dubbo/demo/DemoService.java @@ -1,29 +1,29 @@ -/* - * 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.demo; - -import java.util.concurrent.CompletableFuture; - -public interface DemoService { - - String sayHello(String name); - - default CompletableFuture sayHelloAsync(String name) { - return CompletableFuture.completedFuture(sayHello(name)); - } - -} \ No newline at end of file +/* + * 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.demo; + +import java.util.concurrent.CompletableFuture; + +public interface DemoService { + + String sayHello(String name); + + default CompletableFuture sayHelloAsync(String name) { + return CompletableFuture.completedFuture(sayHello(name)); + } + +} diff --git a/dubbo-demo/dubbo-demo-triple/src/main/resources/log4j.properties b/dubbo-demo/dubbo-demo-triple/src/main/resources/log4j.properties index 6b82abab9e..3fa75995b9 100644 --- a/dubbo-demo/dubbo-demo-triple/src/main/resources/log4j.properties +++ b/dubbo-demo/dubbo-demo-triple/src/main/resources/log4j.properties @@ -23,4 +23,4 @@ log4j.rootLogger=debug, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy hh:mm:ss:sss z}] %t %5p %c{2}: %m%n \ No newline at end of file +log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy hh:mm:ss:sss z}] %t %5p %c{2}: %m%n diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-consumer/src/main/resources/log4j.properties b/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-consumer/src/main/resources/log4j.properties index 2424381490..a92647d964 100644 --- a/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-consumer/src/main/resources/log4j.properties +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-consumer/src/main/resources/log4j.properties @@ -4,4 +4,4 @@ log4j.rootLogger=info, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy HH:mm:ss:SSS z}] %t %5p %c{2}: %m%n \ No newline at end of file +log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy HH:mm:ss:SSS z}] %t %5p %c{2}: %m%n diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-consumer/src/main/resources/spring/dubbo-consumer.xml b/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-consumer/src/main/resources/spring/dubbo-consumer.xml index 46bf9eb0ec..cb9021594c 100644 --- a/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-consumer/src/main/resources/spring/dubbo-consumer.xml +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-consumer/src/main/resources/spring/dubbo-consumer.xml @@ -1,40 +1,40 @@ - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-provider-backend/src/main/resources/log4j.properties b/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-provider-backend/src/main/resources/log4j.properties index 15a0900f0d..8de4c4fddb 100644 --- a/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-provider-backend/src/main/resources/log4j.properties +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-provider-backend/src/main/resources/log4j.properties @@ -4,4 +4,4 @@ log4j.rootLogger=info, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy HH:mm:ss:SSS z}] %t %5p %c{2}: %m%n \ No newline at end of file +log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy HH:mm:ss:SSS z}] %t %5p %c{2}: %m%n diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-provider/src/main/java/org/apache/dubbo/demo/provider/DemoServiceImpl.java b/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-provider/src/main/java/org/apache/dubbo/demo/provider/DemoServiceImpl.java index e55170709d..8b36c98969 100644 --- a/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-provider/src/main/java/org/apache/dubbo/demo/provider/DemoServiceImpl.java +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-provider/src/main/java/org/apache/dubbo/demo/provider/DemoServiceImpl.java @@ -1,53 +1,53 @@ -/* - * 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.demo.provider; - -import org.apache.dubbo.demo.DemoService; -import org.apache.dubbo.rpc.RpcContext; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.concurrent.CompletableFuture; - -public class DemoServiceImpl implements DemoService { - private static final Logger logger = LoggerFactory.getLogger(DemoServiceImpl.class); - - @Override - public String sayHello(String name) { - logger.info("Hello " + name + ", request from consumer: " + RpcContext.getServiceContext().getRemoteAddress()); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - return "Hello " + name + ", response from provider: " + RpcContext.getServiceContext().getLocalAddress(); - } - - @Override - public CompletableFuture sayHelloAsync(String name) { - CompletableFuture cf = CompletableFuture.supplyAsync(() -> { -// try { -// Thread.sleep(1000); -// } catch (InterruptedException e) { -// e.printStackTrace(); -// } - return "async result"; - }); - return cf; - } -} +/* + * 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.demo.provider; + +import org.apache.dubbo.demo.DemoService; +import org.apache.dubbo.rpc.RpcContext; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.CompletableFuture; + +public class DemoServiceImpl implements DemoService { + private static final Logger logger = LoggerFactory.getLogger(DemoServiceImpl.class); + + @Override + public String sayHello(String name) { + logger.info("Hello " + name + ", request from consumer: " + RpcContext.getServiceContext().getRemoteAddress()); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return "Hello " + name + ", response from provider: " + RpcContext.getServiceContext().getLocalAddress(); + } + + @Override + public CompletableFuture sayHelloAsync(String name) { + CompletableFuture cf = CompletableFuture.supplyAsync(() -> { +// try { +// Thread.sleep(1000); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } + return "async result"; + }); + return cf; + } +} diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-provider/src/main/resources/log4j.properties b/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-provider/src/main/resources/log4j.properties index 15a0900f0d..8de4c4fddb 100644 --- a/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-provider/src/main/resources/log4j.properties +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-provider/src/main/resources/log4j.properties @@ -4,4 +4,4 @@ log4j.rootLogger=info, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy HH:mm:ss:SSS z}] %t %5p %c{2}: %m%n \ No newline at end of file +log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy HH:mm:ss:SSS z}] %t %5p %c{2}: %m%n diff --git a/dubbo-filter/dubbo-filter-cache/src/test/java/org/apache/dubbo/cache/support/AbstractCacheFactoryTest.java b/dubbo-filter/dubbo-filter-cache/src/test/java/org/apache/dubbo/cache/support/AbstractCacheFactoryTest.java index f93a453eeb..8887bdd952 100644 --- a/dubbo-filter/dubbo-filter-cache/src/test/java/org/apache/dubbo/cache/support/AbstractCacheFactoryTest.java +++ b/dubbo-filter/dubbo-filter-cache/src/test/java/org/apache/dubbo/cache/support/AbstractCacheFactoryTest.java @@ -30,4 +30,4 @@ public abstract class AbstractCacheFactoryTest { } protected abstract AbstractCacheFactory getCacheFactory(); -} \ No newline at end of file +} diff --git a/dubbo-filter/dubbo-filter-cache/src/test/java/org/apache/dubbo/cache/support/expiring/ExpiringCacheFactoryTest.java b/dubbo-filter/dubbo-filter-cache/src/test/java/org/apache/dubbo/cache/support/expiring/ExpiringCacheFactoryTest.java index d793460d85..8ceac15220 100644 --- a/dubbo-filter/dubbo-filter-cache/src/test/java/org/apache/dubbo/cache/support/expiring/ExpiringCacheFactoryTest.java +++ b/dubbo-filter/dubbo-filter-cache/src/test/java/org/apache/dubbo/cache/support/expiring/ExpiringCacheFactoryTest.java @@ -107,4 +107,4 @@ public class ExpiringCacheFactoryTest extends AbstractCacheFactoryTest { protected AbstractCacheFactory getCacheFactory() { return new ExpiringCacheFactory(); } -} \ No newline at end of file +} diff --git a/dubbo-filter/dubbo-filter-cache/src/test/java/org/apache/dubbo/cache/support/jcache/JCacheFactoryTest.java b/dubbo-filter/dubbo-filter-cache/src/test/java/org/apache/dubbo/cache/support/jcache/JCacheFactoryTest.java index 3260fa6eb9..0250bc8192 100644 --- a/dubbo-filter/dubbo-filter-cache/src/test/java/org/apache/dubbo/cache/support/jcache/JCacheFactoryTest.java +++ b/dubbo-filter/dubbo-filter-cache/src/test/java/org/apache/dubbo/cache/support/jcache/JCacheFactoryTest.java @@ -52,4 +52,4 @@ public class JCacheFactoryTest extends AbstractCacheFactoryTest { protected AbstractCacheFactory getCacheFactory() { return new JCacheFactory(); } -} \ No newline at end of file +} diff --git a/dubbo-filter/dubbo-filter-cache/src/test/java/org/apache/dubbo/cache/support/lru/LruCacheFactoryTest.java b/dubbo-filter/dubbo-filter-cache/src/test/java/org/apache/dubbo/cache/support/lru/LruCacheFactoryTest.java index 149c1227fd..8244d4a176 100644 --- a/dubbo-filter/dubbo-filter-cache/src/test/java/org/apache/dubbo/cache/support/lru/LruCacheFactoryTest.java +++ b/dubbo-filter/dubbo-filter-cache/src/test/java/org/apache/dubbo/cache/support/lru/LruCacheFactoryTest.java @@ -35,4 +35,4 @@ public class LruCacheFactoryTest extends AbstractCacheFactoryTest{ protected AbstractCacheFactory getCacheFactory() { return new LruCacheFactory(); } -} \ No newline at end of file +} diff --git a/dubbo-filter/dubbo-filter-cache/src/test/java/org/apache/dubbo/cache/support/threadlocal/ThreadLocalCacheFactoryTest.java b/dubbo-filter/dubbo-filter-cache/src/test/java/org/apache/dubbo/cache/support/threadlocal/ThreadLocalCacheFactoryTest.java index 800f5ad628..f84e05e688 100644 --- a/dubbo-filter/dubbo-filter-cache/src/test/java/org/apache/dubbo/cache/support/threadlocal/ThreadLocalCacheFactoryTest.java +++ b/dubbo-filter/dubbo-filter-cache/src/test/java/org/apache/dubbo/cache/support/threadlocal/ThreadLocalCacheFactoryTest.java @@ -35,4 +35,4 @@ public class ThreadLocalCacheFactoryTest extends AbstractCacheFactoryTest { protected AbstractCacheFactory getCacheFactory() { return new ThreadLocalCacheFactory(); } -} \ No newline at end of file +} diff --git a/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidation.java b/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidation.java index e8b48cf1d0..6b4b71f9c6 100644 --- a/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidation.java +++ b/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidation.java @@ -37,4 +37,4 @@ public class JValidation extends AbstractValidation { return new JValidator(url); } -} \ No newline at end of file +} diff --git a/dubbo-filter/dubbo-filter-validation/src/test/java/org/apache/dubbo/validation/filter/ValidationFilterTest.java b/dubbo-filter/dubbo-filter-validation/src/test/java/org/apache/dubbo/validation/filter/ValidationFilterTest.java index f2efdd517f..4f21514f26 100644 --- a/dubbo-filter/dubbo-filter-validation/src/test/java/org/apache/dubbo/validation/filter/ValidationFilterTest.java +++ b/dubbo-filter/dubbo-filter-validation/src/test/java/org/apache/dubbo/validation/filter/ValidationFilterTest.java @@ -134,4 +134,4 @@ public class ValidationFilterTest { validationFilter.invoke(invoker, invocation); }); } -} \ No newline at end of file +} diff --git a/dubbo-filter/dubbo-filter-validation/src/test/java/org/apache/dubbo/validation/support/jvalidation/JValidationTest.java b/dubbo-filter/dubbo-filter-validation/src/test/java/org/apache/dubbo/validation/support/jvalidation/JValidationTest.java index fbace3f21b..80b1d07aa6 100644 --- a/dubbo-filter/dubbo-filter-validation/src/test/java/org/apache/dubbo/validation/support/jvalidation/JValidationTest.java +++ b/dubbo-filter/dubbo-filter-validation/src/test/java/org/apache/dubbo/validation/support/jvalidation/JValidationTest.java @@ -47,4 +47,4 @@ public class JValidationTest { Validator validator = jValidation.getValidator(url); assertThat(validator instanceof JValidator, is(true)); } -} \ No newline at end of file +} diff --git a/dubbo-filter/dubbo-filter-validation/src/test/java/org/apache/dubbo/validation/support/jvalidation/JValidatorTest.java b/dubbo-filter/dubbo-filter-validation/src/test/java/org/apache/dubbo/validation/support/jvalidation/JValidatorTest.java index 94768d26a3..01db4b96a0 100644 --- a/dubbo-filter/dubbo-filter-validation/src/test/java/org/apache/dubbo/validation/support/jvalidation/JValidatorTest.java +++ b/dubbo-filter/dubbo-filter-validation/src/test/java/org/apache/dubbo/validation/support/jvalidation/JValidatorTest.java @@ -83,4 +83,4 @@ public class JValidatorTest { map.put("key", "value"); jValidator.validate("someMethod5", new Class[]{Map.class}, new Object[]{map}); } -} \ No newline at end of file +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/DemoService.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/DemoService.java index 33bcbc71d6..3de6ab8bfb 100644 --- a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/DemoService.java +++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/DemoService.java @@ -34,4 +34,4 @@ public interface DemoService { int echo(int i); -} \ No newline at end of file +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/test/resources/META-INF/dubbo/service-name-mapping.properties b/dubbo-metadata/dubbo-metadata-api/src/test/resources/META-INF/dubbo/service-name-mapping.properties index 5f3863d100..0ae294ebd7 100644 --- a/dubbo-metadata/dubbo-metadata-api/src/test/resources/META-INF/dubbo/service-name-mapping.properties +++ b/dubbo-metadata/dubbo-metadata-api/src/test/resources/META-INF/dubbo/service-name-mapping.properties @@ -1,3 +1,3 @@ dubbo\:com.acme.Interface1\:default = Service1 thirft\:com.acme.InterfaceX = Service1,Service2 -rest\:com.acme.interfaceN = Service3 \ No newline at end of file +rest\:com.acme.interfaceN = Service3 diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/PrimitiveTypeDefinitionBuilder.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/PrimitiveTypeDefinitionBuilder.java index 9c7ede8a3d..72a5184a98 100644 --- a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/PrimitiveTypeDefinitionBuilder.java +++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/PrimitiveTypeDefinitionBuilder.java @@ -48,4 +48,4 @@ public class PrimitiveTypeDefinitionBuilder implements TypeBuilder lookup(URL query); - -} +/* + * 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.monitor; + + +import org.apache.dubbo.common.URL; + +import java.util.List; + +import static org.apache.dubbo.rpc.Constants.INPUT_KEY; +import static org.apache.dubbo.rpc.Constants.OUTPUT_KEY; +/** + * MonitorService. (SPI, Prototype, ThreadSafe) + */ +public interface MonitorService { + + String APPLICATION = "application"; + + String INTERFACE = "interface"; + + String METHOD = "method"; + + String GROUP = "group"; + + String VERSION = "version"; + + String CONSUMER = "consumer"; + + String PROVIDER = "provider"; + + String TIMESTAMP = "timestamp"; + + String SUCCESS = "success"; + + String FAILURE = "failure"; + + String INPUT = INPUT_KEY; + + String OUTPUT = OUTPUT_KEY; + + String ELAPSED = "elapsed"; + + String CONCURRENT = "concurrent"; + + String MAX_INPUT = "max.input"; + + String MAX_OUTPUT = "max.output"; + + String MAX_ELAPSED = "max.elapsed"; + + String MAX_CONCURRENT = "max.concurrent"; + + /** + * Collect monitor data + * 1. support invocation count: count://host/interface?application=foo&method=foo&provider=10.20.153.11:20880&success=12&failure=2&elapsed=135423423 + * 1.1 host,application,interface,group,version,method: record source host/application/interface/method + * 1.2 add provider address parameter if it's data sent from consumer, otherwise, add source consumer's address in parameters + * 1.3 success,failure,elapsed: record success count, failure count, and total cost for success invocations, average cost (total cost/success calls) + * + * @param statistics + */ + void collect(URL statistics); + + /** + * Lookup monitor data + * 1. support lookup by day: count://host/interface?application=foo&method=foo&side=provider&view=chart&date=2012-07-03 + * 1.1 host,application,interface,group,version,method: query criteria for looking up by host, application, interface, method. When one criterion is not present, it means ALL will be accepted, but 0.0.0.0 is ALL for host + * 1.2 side=consumer,provider: decide the data from which side, both provider and consumer are returned by default + * 1.3 default value is view=summary, to return the summarized data for the whole day. view=chart will return the URL address showing the whole day trend which is convenient for embedding in other web page + * 1.4 date=2012-07-03: specify the date to collect the data, today is the default value + * + * @param query + * @return statistics + */ + List lookup(URL query); + +} diff --git a/dubbo-monitor/dubbo-monitor-api/src/main/java/org/apache/dubbo/monitor/support/AbstractMonitorFactory.java b/dubbo-monitor/dubbo-monitor-api/src/main/java/org/apache/dubbo/monitor/support/AbstractMonitorFactory.java index a620d06b0b..fe9c6a2aa3 100644 --- a/dubbo-monitor/dubbo-monitor-api/src/main/java/org/apache/dubbo/monitor/support/AbstractMonitorFactory.java +++ b/dubbo-monitor/dubbo-monitor-api/src/main/java/org/apache/dubbo/monitor/support/AbstractMonitorFactory.java @@ -1,107 +1,107 @@ -/* - * 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.monitor.support; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.utils.NamedThreadFactory; -import org.apache.dubbo.monitor.Monitor; -import org.apache.dubbo.monitor.MonitorFactory; -import org.apache.dubbo.monitor.MonitorService; - -import java.util.Collection; -import java.util.Collections; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; -import java.util.concurrent.SynchronousQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.ReentrantLock; - -import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY; - -/** - * AbstractMonitorFactory. (SPI, Singleton, ThreadSafe) - */ -public abstract class AbstractMonitorFactory implements MonitorFactory { - private static final Logger logger = LoggerFactory.getLogger(AbstractMonitorFactory.class); - - /** - * The lock for getting monitor center - */ - private static final ReentrantLock LOCK = new ReentrantLock(); - - /** - * The monitor centers Map - */ - private static final Map MONITORS = new ConcurrentHashMap(); - - private static final Map> FUTURES = new ConcurrentHashMap>(); - - /** - * The monitor create executor - */ - private static final ExecutorService EXECUTOR = new ThreadPoolExecutor(0, 10, 60L, TimeUnit.SECONDS, new SynchronousQueue(), new NamedThreadFactory("DubboMonitorCreator", true)); - - public static Collection getMonitors() { - return Collections.unmodifiableCollection(MONITORS.values()); - } - - @Override - public Monitor getMonitor(URL url) { - url = url.setPath(MonitorService.class.getName()).addParameter(INTERFACE_KEY, MonitorService.class.getName()); - String key = url.toServiceStringWithoutResolving(); - Monitor monitor = MONITORS.get(key); - Future future = FUTURES.get(key); - if (monitor != null || future != null) { - return monitor; - } - - LOCK.lock(); - try { - monitor = MONITORS.get(key); - future = FUTURES.get(key); - if (monitor != null || future != null) { - return monitor; - } - - final URL monitorUrl = url; - future = EXECUTOR.submit(() -> { - try { - Monitor m = createMonitor(monitorUrl); - MONITORS.put(key, m); - FUTURES.remove(key); - return m; - } catch (Throwable e) { - logger.warn("Create monitor failed, monitor data will not be collected until you fix this problem. monitorUrl: " + monitorUrl, e); - return null; - } - }); - FUTURES.put(key, future); - return null; - } finally { - // unlock - LOCK.unlock(); - } - } - - protected abstract Monitor createMonitor(URL url); - -} +/* + * 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.monitor.support; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.NamedThreadFactory; +import org.apache.dubbo.monitor.Monitor; +import org.apache.dubbo.monitor.MonitorFactory; +import org.apache.dubbo.monitor.MonitorService; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReentrantLock; + +import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY; + +/** + * AbstractMonitorFactory. (SPI, Singleton, ThreadSafe) + */ +public abstract class AbstractMonitorFactory implements MonitorFactory { + private static final Logger logger = LoggerFactory.getLogger(AbstractMonitorFactory.class); + + /** + * The lock for getting monitor center + */ + private static final ReentrantLock LOCK = new ReentrantLock(); + + /** + * The monitor centers Map + */ + private static final Map MONITORS = new ConcurrentHashMap(); + + private static final Map> FUTURES = new ConcurrentHashMap>(); + + /** + * The monitor create executor + */ + private static final ExecutorService EXECUTOR = new ThreadPoolExecutor(0, 10, 60L, TimeUnit.SECONDS, new SynchronousQueue(), new NamedThreadFactory("DubboMonitorCreator", true)); + + public static Collection getMonitors() { + return Collections.unmodifiableCollection(MONITORS.values()); + } + + @Override + public Monitor getMonitor(URL url) { + url = url.setPath(MonitorService.class.getName()).addParameter(INTERFACE_KEY, MonitorService.class.getName()); + String key = url.toServiceStringWithoutResolving(); + Monitor monitor = MONITORS.get(key); + Future future = FUTURES.get(key); + if (monitor != null || future != null) { + return monitor; + } + + LOCK.lock(); + try { + monitor = MONITORS.get(key); + future = FUTURES.get(key); + if (monitor != null || future != null) { + return monitor; + } + + final URL monitorUrl = url; + future = EXECUTOR.submit(() -> { + try { + Monitor m = createMonitor(monitorUrl); + MONITORS.put(key, m); + FUTURES.remove(key); + return m; + } catch (Throwable e) { + logger.warn("Create monitor failed, monitor data will not be collected until you fix this problem. monitorUrl: " + monitorUrl, e); + return null; + } + }); + FUTURES.put(key, future); + return null; + } finally { + // unlock + LOCK.unlock(); + } + } + + protected abstract Monitor createMonitor(URL url); + +} diff --git a/dubbo-monitor/dubbo-monitor-api/src/main/java/org/apache/dubbo/monitor/support/MonitorFilter.java b/dubbo-monitor/dubbo-monitor-api/src/main/java/org/apache/dubbo/monitor/support/MonitorFilter.java index c9b7fa091f..3ed92c4e25 100644 --- a/dubbo-monitor/dubbo-monitor-api/src/main/java/org/apache/dubbo/monitor/support/MonitorFilter.java +++ b/dubbo-monitor/dubbo-monitor-api/src/main/java/org/apache/dubbo/monitor/support/MonitorFilter.java @@ -1,187 +1,187 @@ -/* - * 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.monitor.support; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.extension.Activate; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.url.component.ServiceConfigURL; -import org.apache.dubbo.common.utils.NetUtils; -import org.apache.dubbo.monitor.Monitor; -import org.apache.dubbo.monitor.MonitorFactory; -import org.apache.dubbo.monitor.MonitorService; -import org.apache.dubbo.rpc.Filter; -import org.apache.dubbo.rpc.Invocation; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.Result; -import org.apache.dubbo.rpc.RpcContext; -import org.apache.dubbo.rpc.RpcException; -import org.apache.dubbo.rpc.support.RpcUtils; - -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.atomic.AtomicInteger; - -import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER_SIDE; -import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.MONITOR_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.PATH_SEPARATOR; -import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER; -import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY; -import static org.apache.dubbo.monitor.Constants.COUNT_PROTOCOL; -import static org.apache.dubbo.rpc.Constants.INPUT_KEY; -import static org.apache.dubbo.rpc.Constants.OUTPUT_KEY; -/** - * MonitorFilter. (SPI, Singleton, ThreadSafe) - */ -@Activate(group = {PROVIDER}) -public class MonitorFilter implements Filter, Filter.Listener { - - private static final Logger logger = LoggerFactory.getLogger(MonitorFilter.class); - private static final String MONITOR_FILTER_START_TIME = "monitor_filter_start_time"; - private static final String MONITOR_REMOTE_HOST_STORE = "monitor_remote_host_store"; - - /** - * The Concurrent counter - */ - private final ConcurrentMap concurrents = new ConcurrentHashMap(); - - /** - * The MonitorFactory - */ - private MonitorFactory monitorFactory; - - public void setMonitorFactory(MonitorFactory monitorFactory) { - this.monitorFactory = monitorFactory; - } - - - /** - * The invocation interceptor,it will collect the invoke data about this invocation and send it to monitor center - * - * @param invoker service - * @param invocation invocation. - * @return {@link Result} the invoke result - * @throws RpcException - */ - @Override - public Result invoke(Invoker invoker, Invocation invocation) throws RpcException { - if (invoker.getUrl().hasAttribute(MONITOR_KEY)) { - invocation.put(MONITOR_FILTER_START_TIME, System.currentTimeMillis()); - invocation.put(MONITOR_REMOTE_HOST_STORE, RpcContext.getServiceContext().getRemoteHost()); - getConcurrent(invoker, invocation).incrementAndGet(); // count up - } - return invoker.invoke(invocation); // proceed invocation chain - } - - // concurrent counter - private AtomicInteger getConcurrent(Invoker invoker, Invocation invocation) { - String key = invoker.getInterface().getName() + "." + invocation.getMethodName(); - return concurrents.computeIfAbsent(key, k -> new AtomicInteger()); - } - - @Override - public void onResponse(Result result, Invoker invoker, Invocation invocation) { - if (invoker.getUrl().hasAttribute(MONITOR_KEY)) { - collect(invoker, invocation, result, (String) invocation.get(MONITOR_REMOTE_HOST_STORE), (long) invocation.get(MONITOR_FILTER_START_TIME), false); - getConcurrent(invoker, invocation).decrementAndGet(); // count down - } - } - - @Override - public void onError(Throwable t, Invoker invoker, Invocation invocation) { - if (invoker.getUrl().hasAttribute(MONITOR_KEY)) { - collect(invoker, invocation, null, (String) invocation.get(MONITOR_REMOTE_HOST_STORE), (long) invocation.get(MONITOR_FILTER_START_TIME), true); - getConcurrent(invoker, invocation).decrementAndGet(); // count down - } - } - - /** - * The collector logic, it will be handled by the default monitor - * - * @param invoker - * @param invocation - * @param result the invoke result - * @param remoteHost the remote host address - * @param start the timestamp the invoke begin - * @param error if there is an error on the invoke - */ - private void collect(Invoker invoker, Invocation invocation, Result result, String remoteHost, long start, boolean error) { - try { - Object monitorUrl; - monitorUrl = invoker.getUrl().getAttribute(MONITOR_KEY); - if(monitorUrl instanceof URL) { - Monitor monitor = monitorFactory.getMonitor((URL) monitorUrl); - if (monitor == null) { - return; - } - URL statisticsURL = createStatisticsUrl(invoker, invocation, result, remoteHost, start, error); - monitor.collect(statisticsURL); - } - } catch (Throwable t) { - logger.warn("Failed to monitor count service " + invoker.getUrl() + ", cause: " + t.getMessage(), t); - } - } - - /** - * Create statistics url - * - * @param invoker - * @param invocation - * @param result - * @param remoteHost - * @param start - * @param error - * @return - */ - private URL createStatisticsUrl(Invoker invoker, Invocation invocation, Result result, String remoteHost, long start, boolean error) { - // ---- service statistics ---- - long elapsed = System.currentTimeMillis() - start; // invocation cost - int concurrent = getConcurrent(invoker, invocation).get(); // current concurrent count - String application = invoker.getUrl().getApplication(); - String service = invoker.getInterface().getName(); // service name - String method = RpcUtils.getMethodName(invocation); // method name - String group = invoker.getUrl().getGroup(); - String version = invoker.getUrl().getVersion(); - - int localPort; - String remoteKey, remoteValue; - if (CONSUMER_SIDE.equals(invoker.getUrl().getSide())) { - // ---- for service consumer ---- - localPort = 0; - remoteKey = MonitorService.PROVIDER; - remoteValue = invoker.getUrl().getAddress(); - } else { - // ---- for service provider ---- - localPort = invoker.getUrl().getPort(); - remoteKey = MonitorService.CONSUMER; - remoteValue = remoteHost; - } - String input = "", output = ""; - if (invocation.getAttachment(INPUT_KEY) != null) { - input = invocation.getAttachment(INPUT_KEY); - } - if (result != null && result.getAttachment(OUTPUT_KEY) != null) { - output = result.getAttachment(OUTPUT_KEY); - } - - return new ServiceConfigURL(COUNT_PROTOCOL, NetUtils.getLocalHost(), localPort, service + PATH_SEPARATOR + method, MonitorService.APPLICATION, application, MonitorService.INTERFACE, service, MonitorService.METHOD, method, remoteKey, remoteValue, error ? MonitorService.FAILURE : MonitorService.SUCCESS, "1", MonitorService.ELAPSED, String.valueOf(elapsed), MonitorService.CONCURRENT, String.valueOf(concurrent), INPUT_KEY, input, OUTPUT_KEY, output, GROUP_KEY, group, VERSION_KEY, version); - } - - -} +/* + * 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.monitor.support; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.Activate; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.url.component.ServiceConfigURL; +import org.apache.dubbo.common.utils.NetUtils; +import org.apache.dubbo.monitor.Monitor; +import org.apache.dubbo.monitor.MonitorFactory; +import org.apache.dubbo.monitor.MonitorService; +import org.apache.dubbo.rpc.Filter; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.Result; +import org.apache.dubbo.rpc.RpcContext; +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.support.RpcUtils; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER_SIDE; +import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.MONITOR_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.PATH_SEPARATOR; +import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER; +import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY; +import static org.apache.dubbo.monitor.Constants.COUNT_PROTOCOL; +import static org.apache.dubbo.rpc.Constants.INPUT_KEY; +import static org.apache.dubbo.rpc.Constants.OUTPUT_KEY; +/** + * MonitorFilter. (SPI, Singleton, ThreadSafe) + */ +@Activate(group = {PROVIDER}) +public class MonitorFilter implements Filter, Filter.Listener { + + private static final Logger logger = LoggerFactory.getLogger(MonitorFilter.class); + private static final String MONITOR_FILTER_START_TIME = "monitor_filter_start_time"; + private static final String MONITOR_REMOTE_HOST_STORE = "monitor_remote_host_store"; + + /** + * The Concurrent counter + */ + private final ConcurrentMap concurrents = new ConcurrentHashMap(); + + /** + * The MonitorFactory + */ + private MonitorFactory monitorFactory; + + public void setMonitorFactory(MonitorFactory monitorFactory) { + this.monitorFactory = monitorFactory; + } + + + /** + * The invocation interceptor,it will collect the invoke data about this invocation and send it to monitor center + * + * @param invoker service + * @param invocation invocation. + * @return {@link Result} the invoke result + * @throws RpcException + */ + @Override + public Result invoke(Invoker invoker, Invocation invocation) throws RpcException { + if (invoker.getUrl().hasAttribute(MONITOR_KEY)) { + invocation.put(MONITOR_FILTER_START_TIME, System.currentTimeMillis()); + invocation.put(MONITOR_REMOTE_HOST_STORE, RpcContext.getServiceContext().getRemoteHost()); + getConcurrent(invoker, invocation).incrementAndGet(); // count up + } + return invoker.invoke(invocation); // proceed invocation chain + } + + // concurrent counter + private AtomicInteger getConcurrent(Invoker invoker, Invocation invocation) { + String key = invoker.getInterface().getName() + "." + invocation.getMethodName(); + return concurrents.computeIfAbsent(key, k -> new AtomicInteger()); + } + + @Override + public void onResponse(Result result, Invoker invoker, Invocation invocation) { + if (invoker.getUrl().hasAttribute(MONITOR_KEY)) { + collect(invoker, invocation, result, (String) invocation.get(MONITOR_REMOTE_HOST_STORE), (long) invocation.get(MONITOR_FILTER_START_TIME), false); + getConcurrent(invoker, invocation).decrementAndGet(); // count down + } + } + + @Override + public void onError(Throwable t, Invoker invoker, Invocation invocation) { + if (invoker.getUrl().hasAttribute(MONITOR_KEY)) { + collect(invoker, invocation, null, (String) invocation.get(MONITOR_REMOTE_HOST_STORE), (long) invocation.get(MONITOR_FILTER_START_TIME), true); + getConcurrent(invoker, invocation).decrementAndGet(); // count down + } + } + + /** + * The collector logic, it will be handled by the default monitor + * + * @param invoker + * @param invocation + * @param result the invoke result + * @param remoteHost the remote host address + * @param start the timestamp the invoke begin + * @param error if there is an error on the invoke + */ + private void collect(Invoker invoker, Invocation invocation, Result result, String remoteHost, long start, boolean error) { + try { + Object monitorUrl; + monitorUrl = invoker.getUrl().getAttribute(MONITOR_KEY); + if(monitorUrl instanceof URL) { + Monitor monitor = monitorFactory.getMonitor((URL) monitorUrl); + if (monitor == null) { + return; + } + URL statisticsURL = createStatisticsUrl(invoker, invocation, result, remoteHost, start, error); + monitor.collect(statisticsURL); + } + } catch (Throwable t) { + logger.warn("Failed to monitor count service " + invoker.getUrl() + ", cause: " + t.getMessage(), t); + } + } + + /** + * Create statistics url + * + * @param invoker + * @param invocation + * @param result + * @param remoteHost + * @param start + * @param error + * @return + */ + private URL createStatisticsUrl(Invoker invoker, Invocation invocation, Result result, String remoteHost, long start, boolean error) { + // ---- service statistics ---- + long elapsed = System.currentTimeMillis() - start; // invocation cost + int concurrent = getConcurrent(invoker, invocation).get(); // current concurrent count + String application = invoker.getUrl().getApplication(); + String service = invoker.getInterface().getName(); // service name + String method = RpcUtils.getMethodName(invocation); // method name + String group = invoker.getUrl().getGroup(); + String version = invoker.getUrl().getVersion(); + + int localPort; + String remoteKey, remoteValue; + if (CONSUMER_SIDE.equals(invoker.getUrl().getSide())) { + // ---- for service consumer ---- + localPort = 0; + remoteKey = MonitorService.PROVIDER; + remoteValue = invoker.getUrl().getAddress(); + } else { + // ---- for service provider ---- + localPort = invoker.getUrl().getPort(); + remoteKey = MonitorService.CONSUMER; + remoteValue = remoteHost; + } + String input = "", output = ""; + if (invocation.getAttachment(INPUT_KEY) != null) { + input = invocation.getAttachment(INPUT_KEY); + } + if (result != null && result.getAttachment(OUTPUT_KEY) != null) { + output = result.getAttachment(OUTPUT_KEY); + } + + return new ServiceConfigURL(COUNT_PROTOCOL, NetUtils.getLocalHost(), localPort, service + PATH_SEPARATOR + method, MonitorService.APPLICATION, application, MonitorService.INTERFACE, service, MonitorService.METHOD, method, remoteKey, remoteValue, error ? MonitorService.FAILURE : MonitorService.SUCCESS, "1", MonitorService.ELAPSED, String.valueOf(elapsed), MonitorService.CONCURRENT, String.valueOf(concurrent), INPUT_KEY, input, OUTPUT_KEY, output, GROUP_KEY, group, VERSION_KEY, version); + } + + +} diff --git a/dubbo-monitor/dubbo-monitor-api/src/test/java/org/apache/dubbo/monitor/support/MonitorFilterTest.java b/dubbo-monitor/dubbo-monitor-api/src/test/java/org/apache/dubbo/monitor/support/MonitorFilterTest.java index d9cf38718a..6ae5bd428b 100644 --- a/dubbo-monitor/dubbo-monitor-api/src/test/java/org/apache/dubbo/monitor/support/MonitorFilterTest.java +++ b/dubbo-monitor/dubbo-monitor-api/src/test/java/org/apache/dubbo/monitor/support/MonitorFilterTest.java @@ -1,199 +1,199 @@ -/* - * 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.monitor.support; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.utils.NetUtils; -import org.apache.dubbo.monitor.Monitor; -import org.apache.dubbo.monitor.MonitorFactory; -import org.apache.dubbo.monitor.MonitorService; -import org.apache.dubbo.rpc.AsyncRpcResult; -import org.apache.dubbo.rpc.Invocation; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.Result; -import org.apache.dubbo.rpc.RpcContext; -import org.apache.dubbo.rpc.RpcException; -import org.apache.dubbo.rpc.RpcInvocation; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.mockito.Mockito; - -import java.util.Arrays; -import java.util.List; - -import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER_SIDE; -import static org.apache.dubbo.common.constants.CommonConstants.MONITOR_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; - -/** - * MonitorFilterTest - */ -public class MonitorFilterTest { - - private volatile URL lastStatistics; - - private volatile Invocation lastInvocation; - - private final Invoker serviceInvoker = new Invoker() { - @Override - public Class getInterface() { - return MonitorService.class; - } - - public URL getUrl() { - return URL.valueOf("dubbo://" + NetUtils.getLocalHost() + ":20880?" + - APPLICATION_KEY + "=abc&" + SIDE_KEY + "=" + CONSUMER_SIDE) - .putAttribute(MONITOR_KEY, URL.valueOf("dubbo://" + NetUtils.getLocalHost() + ":7070")); - } - - @Override - public boolean isAvailable() { - return false; - } - - @Override - public Result invoke(Invocation invocation) throws RpcException { - lastInvocation = invocation; - return AsyncRpcResult.newDefaultAsyncResult(invocation); - } - - @Override - public void destroy() { - } - }; - - private MonitorFactory monitorFactory = new MonitorFactory() { - @Override - public Monitor getMonitor(final URL url) { - return new Monitor() { - public URL getUrl() { - return url; - } - - @Override - public boolean isAvailable() { - return true; - } - - @Override - public void destroy() { - } - - public void collect(URL statistics) { - MonitorFilterTest.this.lastStatistics = statistics; - } - - public List lookup(URL query) { - return Arrays.asList(MonitorFilterTest.this.lastStatistics); - } - }; - } - }; - - @Test - public void testFilter() throws Exception { - MonitorFilter monitorFilter = new MonitorFilter(); - monitorFilter.setMonitorFactory(monitorFactory); - Invocation invocation = new RpcInvocation("aaa", MonitorService.class.getName(), "", new Class[0], new Object[0]); - RpcContext.getServiceContext().setRemoteAddress(NetUtils.getLocalHost(), 20880).setLocalAddress(NetUtils.getLocalHost(), 2345); - Result result = monitorFilter.invoke(serviceInvoker, invocation); - result.whenCompleteWithContext((r, t) -> { - if (t == null) { - monitorFilter.onResponse(r, serviceInvoker, invocation); - } else { - monitorFilter.onError(t, serviceInvoker, invocation); - } - }); - while (lastStatistics == null) { - Thread.sleep(10); - } - Assertions.assertEquals("abc", lastStatistics.getParameter(MonitorService.APPLICATION)); - Assertions.assertEquals(MonitorService.class.getName(), lastStatistics.getParameter(MonitorService.INTERFACE)); - Assertions.assertEquals("aaa", lastStatistics.getParameter(MonitorService.METHOD)); - Assertions.assertEquals(NetUtils.getLocalHost() + ":20880", lastStatistics.getParameter(MonitorService.PROVIDER)); - Assertions.assertEquals(NetUtils.getLocalHost(), lastStatistics.getAddress()); - Assertions.assertNull(lastStatistics.getParameter(MonitorService.CONSUMER)); - Assertions.assertEquals(1, lastStatistics.getParameter(MonitorService.SUCCESS, 0)); - Assertions.assertEquals(0, lastStatistics.getParameter(MonitorService.FAILURE, 0)); - Assertions.assertEquals(1, lastStatistics.getParameter(MonitorService.CONCURRENT, 0)); - Assertions.assertEquals(invocation, lastInvocation); - } - - @Test - public void testSkipMonitorIfNotHasKey() { - MonitorFilter monitorFilter = new MonitorFilter(); - MonitorFactory mockMonitorFactory = mock(MonitorFactory.class); - monitorFilter.setMonitorFactory(mockMonitorFactory); - Invocation invocation = new RpcInvocation("aaa", MonitorService.class.getName(), "", new Class[0], new Object[0]); - Invoker invoker = mock(Invoker.class); - given(invoker.getUrl()).willReturn(URL.valueOf("dubbo://" + NetUtils.getLocalHost() + ":20880?" + APPLICATION_KEY + "=abc&" + SIDE_KEY + "=" + CONSUMER_SIDE)); - - monitorFilter.invoke(invoker, invocation); - - verify(mockMonitorFactory, never()).getMonitor(any(URL.class)); - } - - @Test - public void testGenericFilter() throws Exception { - MonitorFilter monitorFilter = new MonitorFilter(); - monitorFilter.setMonitorFactory(monitorFactory); - Invocation invocation = new RpcInvocation("$invoke", MonitorService.class.getName(), "", new Class[]{String.class, String[].class, Object[].class}, new Object[]{"xxx", new String[]{}, new Object[]{}}); - RpcContext.getServiceContext().setRemoteAddress(NetUtils.getLocalHost(), 20880).setLocalAddress(NetUtils.getLocalHost(), 2345); - Result result = monitorFilter.invoke(serviceInvoker, invocation); - result.whenCompleteWithContext((r, t) -> { - if (t == null) { - monitorFilter.onResponse(r, serviceInvoker, invocation); - } else { - monitorFilter.onError(t, serviceInvoker, invocation); - } - }); - while (lastStatistics == null) { - Thread.sleep(10); - } - Assertions.assertEquals("abc", lastStatistics.getParameter(MonitorService.APPLICATION)); - Assertions.assertEquals(MonitorService.class.getName(), lastStatistics.getParameter(MonitorService.INTERFACE)); - Assertions.assertEquals("xxx", lastStatistics.getParameter(MonitorService.METHOD)); - Assertions.assertEquals(NetUtils.getLocalHost() + ":20880", lastStatistics.getParameter(MonitorService.PROVIDER)); - Assertions.assertEquals(NetUtils.getLocalHost(), lastStatistics.getAddress()); - Assertions.assertNull(lastStatistics.getParameter(MonitorService.CONSUMER)); - Assertions.assertEquals(1, lastStatistics.getParameter(MonitorService.SUCCESS, 0)); - Assertions.assertEquals(0, lastStatistics.getParameter(MonitorService.FAILURE, 0)); - Assertions.assertEquals(1, lastStatistics.getParameter(MonitorService.CONCURRENT, 0)); - Assertions.assertEquals(invocation, lastInvocation); - } - - @Test - public void testSafeFailForMonitorCollectFail() { - MonitorFilter monitorFilter = new MonitorFilter(); - MonitorFactory mockMonitorFactory = mock(MonitorFactory.class); - Monitor mockMonitor = mock(Monitor.class); - Mockito.doThrow(new RuntimeException()).when(mockMonitor).collect(any(URL.class)); - - monitorFilter.setMonitorFactory(mockMonitorFactory); - given(mockMonitorFactory.getMonitor(any(URL.class))).willReturn(mockMonitor); - Invocation invocation = new RpcInvocation("aaa", MonitorService.class.getName(), "", new Class[0], new Object[0]); - - monitorFilter.invoke(serviceInvoker, invocation); - } -} +/* + * 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.monitor.support; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.utils.NetUtils; +import org.apache.dubbo.monitor.Monitor; +import org.apache.dubbo.monitor.MonitorFactory; +import org.apache.dubbo.monitor.MonitorService; +import org.apache.dubbo.rpc.AsyncRpcResult; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.Result; +import org.apache.dubbo.rpc.RpcContext; +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.RpcInvocation; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.util.Arrays; +import java.util.List; + +import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER_SIDE; +import static org.apache.dubbo.common.constants.CommonConstants.MONITOR_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +/** + * MonitorFilterTest + */ +public class MonitorFilterTest { + + private volatile URL lastStatistics; + + private volatile Invocation lastInvocation; + + private final Invoker serviceInvoker = new Invoker() { + @Override + public Class getInterface() { + return MonitorService.class; + } + + public URL getUrl() { + return URL.valueOf("dubbo://" + NetUtils.getLocalHost() + ":20880?" + + APPLICATION_KEY + "=abc&" + SIDE_KEY + "=" + CONSUMER_SIDE) + .putAttribute(MONITOR_KEY, URL.valueOf("dubbo://" + NetUtils.getLocalHost() + ":7070")); + } + + @Override + public boolean isAvailable() { + return false; + } + + @Override + public Result invoke(Invocation invocation) throws RpcException { + lastInvocation = invocation; + return AsyncRpcResult.newDefaultAsyncResult(invocation); + } + + @Override + public void destroy() { + } + }; + + private MonitorFactory monitorFactory = new MonitorFactory() { + @Override + public Monitor getMonitor(final URL url) { + return new Monitor() { + public URL getUrl() { + return url; + } + + @Override + public boolean isAvailable() { + return true; + } + + @Override + public void destroy() { + } + + public void collect(URL statistics) { + MonitorFilterTest.this.lastStatistics = statistics; + } + + public List lookup(URL query) { + return Arrays.asList(MonitorFilterTest.this.lastStatistics); + } + }; + } + }; + + @Test + public void testFilter() throws Exception { + MonitorFilter monitorFilter = new MonitorFilter(); + monitorFilter.setMonitorFactory(monitorFactory); + Invocation invocation = new RpcInvocation("aaa", MonitorService.class.getName(), "", new Class[0], new Object[0]); + RpcContext.getServiceContext().setRemoteAddress(NetUtils.getLocalHost(), 20880).setLocalAddress(NetUtils.getLocalHost(), 2345); + Result result = monitorFilter.invoke(serviceInvoker, invocation); + result.whenCompleteWithContext((r, t) -> { + if (t == null) { + monitorFilter.onResponse(r, serviceInvoker, invocation); + } else { + monitorFilter.onError(t, serviceInvoker, invocation); + } + }); + while (lastStatistics == null) { + Thread.sleep(10); + } + Assertions.assertEquals("abc", lastStatistics.getParameter(MonitorService.APPLICATION)); + Assertions.assertEquals(MonitorService.class.getName(), lastStatistics.getParameter(MonitorService.INTERFACE)); + Assertions.assertEquals("aaa", lastStatistics.getParameter(MonitorService.METHOD)); + Assertions.assertEquals(NetUtils.getLocalHost() + ":20880", lastStatistics.getParameter(MonitorService.PROVIDER)); + Assertions.assertEquals(NetUtils.getLocalHost(), lastStatistics.getAddress()); + Assertions.assertNull(lastStatistics.getParameter(MonitorService.CONSUMER)); + Assertions.assertEquals(1, lastStatistics.getParameter(MonitorService.SUCCESS, 0)); + Assertions.assertEquals(0, lastStatistics.getParameter(MonitorService.FAILURE, 0)); + Assertions.assertEquals(1, lastStatistics.getParameter(MonitorService.CONCURRENT, 0)); + Assertions.assertEquals(invocation, lastInvocation); + } + + @Test + public void testSkipMonitorIfNotHasKey() { + MonitorFilter monitorFilter = new MonitorFilter(); + MonitorFactory mockMonitorFactory = mock(MonitorFactory.class); + monitorFilter.setMonitorFactory(mockMonitorFactory); + Invocation invocation = new RpcInvocation("aaa", MonitorService.class.getName(), "", new Class[0], new Object[0]); + Invoker invoker = mock(Invoker.class); + given(invoker.getUrl()).willReturn(URL.valueOf("dubbo://" + NetUtils.getLocalHost() + ":20880?" + APPLICATION_KEY + "=abc&" + SIDE_KEY + "=" + CONSUMER_SIDE)); + + monitorFilter.invoke(invoker, invocation); + + verify(mockMonitorFactory, never()).getMonitor(any(URL.class)); + } + + @Test + public void testGenericFilter() throws Exception { + MonitorFilter monitorFilter = new MonitorFilter(); + monitorFilter.setMonitorFactory(monitorFactory); + Invocation invocation = new RpcInvocation("$invoke", MonitorService.class.getName(), "", new Class[]{String.class, String[].class, Object[].class}, new Object[]{"xxx", new String[]{}, new Object[]{}}); + RpcContext.getServiceContext().setRemoteAddress(NetUtils.getLocalHost(), 20880).setLocalAddress(NetUtils.getLocalHost(), 2345); + Result result = monitorFilter.invoke(serviceInvoker, invocation); + result.whenCompleteWithContext((r, t) -> { + if (t == null) { + monitorFilter.onResponse(r, serviceInvoker, invocation); + } else { + monitorFilter.onError(t, serviceInvoker, invocation); + } + }); + while (lastStatistics == null) { + Thread.sleep(10); + } + Assertions.assertEquals("abc", lastStatistics.getParameter(MonitorService.APPLICATION)); + Assertions.assertEquals(MonitorService.class.getName(), lastStatistics.getParameter(MonitorService.INTERFACE)); + Assertions.assertEquals("xxx", lastStatistics.getParameter(MonitorService.METHOD)); + Assertions.assertEquals(NetUtils.getLocalHost() + ":20880", lastStatistics.getParameter(MonitorService.PROVIDER)); + Assertions.assertEquals(NetUtils.getLocalHost(), lastStatistics.getAddress()); + Assertions.assertNull(lastStatistics.getParameter(MonitorService.CONSUMER)); + Assertions.assertEquals(1, lastStatistics.getParameter(MonitorService.SUCCESS, 0)); + Assertions.assertEquals(0, lastStatistics.getParameter(MonitorService.FAILURE, 0)); + Assertions.assertEquals(1, lastStatistics.getParameter(MonitorService.CONCURRENT, 0)); + Assertions.assertEquals(invocation, lastInvocation); + } + + @Test + public void testSafeFailForMonitorCollectFail() { + MonitorFilter monitorFilter = new MonitorFilter(); + MonitorFactory mockMonitorFactory = mock(MonitorFactory.class); + Monitor mockMonitor = mock(Monitor.class); + Mockito.doThrow(new RuntimeException()).when(mockMonitor).collect(any(URL.class)); + + monitorFilter.setMonitorFactory(mockMonitorFactory); + given(mockMonitorFactory.getMonitor(any(URL.class))).willReturn(mockMonitor); + Invocation invocation = new RpcInvocation("aaa", MonitorService.class.getName(), "", new Class[0], new Object[0]); + + monitorFilter.invoke(serviceInvoker, invocation); + } +} diff --git a/dubbo-monitor/dubbo-monitor-default/src/main/java/org/apache/dubbo/monitor/dubbo/DubboMonitor.java b/dubbo-monitor/dubbo-monitor-default/src/main/java/org/apache/dubbo/monitor/dubbo/DubboMonitor.java index a2021b3e23..329d635758 100644 --- a/dubbo-monitor/dubbo-monitor-default/src/main/java/org/apache/dubbo/monitor/dubbo/DubboMonitor.java +++ b/dubbo-monitor/dubbo-monitor-default/src/main/java/org/apache/dubbo/monitor/dubbo/DubboMonitor.java @@ -1,216 +1,216 @@ -/* - * 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.monitor.dubbo; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.utils.ExecutorUtil; -import org.apache.dubbo.common.utils.NamedThreadFactory; -import org.apache.dubbo.monitor.Monitor; -import org.apache.dubbo.monitor.MonitorService; -import org.apache.dubbo.rpc.Invoker; - -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; - -import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_PROTOCOL; - -/** - * DubboMonitor - */ -public class DubboMonitor implements Monitor { - - private static final Logger logger = LoggerFactory.getLogger(DubboMonitor.class); - - /** - * The length of the array which is a container of the statistics - */ - private static final int LENGTH = 10; - - /** - * The timer for sending statistics - */ - private final ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3, new NamedThreadFactory("DubboMonitorSendTimer", true)); - - /** - * The future that can cancel the scheduledExecutorService - */ - private final ScheduledFuture sendFuture; - - private final Invoker monitorInvoker; - - private final MonitorService monitorService; - - private final ConcurrentMap> statisticsMap = new ConcurrentHashMap>(); - - public DubboMonitor(Invoker monitorInvoker, MonitorService monitorService) { - this.monitorInvoker = monitorInvoker; - this.monitorService = monitorService; - // The time interval for timer scheduledExecutorService to send data - final long monitorInterval = monitorInvoker.getUrl().getPositiveParameter("interval", 60000); - // collect timer for collecting statistics data - sendFuture = scheduledExecutorService.scheduleWithFixedDelay(() -> { - try { - // collect data - send(); - } catch (Throwable t) { - logger.error("Unexpected error occur at send statistic, cause: " + t.getMessage(), t); - } - }, monitorInterval, monitorInterval, TimeUnit.MILLISECONDS); - } - - public void send() { - if (logger.isDebugEnabled()) { - logger.debug("Send statistics to monitor " + getUrl()); - } - - String timestamp = String.valueOf(System.currentTimeMillis()); - for (Map.Entry> entry : statisticsMap.entrySet()) { - // get statistics data - Statistics statistics = entry.getKey(); - AtomicReference reference = entry.getValue(); - long[] numbers = reference.get(); - long success = numbers[0]; - long failure = numbers[1]; - long input = numbers[2]; - long output = numbers[3]; - long elapsed = numbers[4]; - long concurrent = numbers[5]; - long maxInput = numbers[6]; - long maxOutput = numbers[7]; - long maxElapsed = numbers[8]; - long maxConcurrent = numbers[9]; - String protocol = getUrl().getParameter(DEFAULT_PROTOCOL); - - // send statistics data - URL url = statistics.getUrl() - .addParameters(MonitorService.TIMESTAMP, timestamp, - MonitorService.SUCCESS, String.valueOf(success), - MonitorService.FAILURE, String.valueOf(failure), - MonitorService.INPUT, String.valueOf(input), - MonitorService.OUTPUT, String.valueOf(output), - MonitorService.ELAPSED, String.valueOf(elapsed), - MonitorService.CONCURRENT, String.valueOf(concurrent), - MonitorService.MAX_INPUT, String.valueOf(maxInput), - MonitorService.MAX_OUTPUT, String.valueOf(maxOutput), - MonitorService.MAX_ELAPSED, String.valueOf(maxElapsed), - MonitorService.MAX_CONCURRENT, String.valueOf(maxConcurrent), - DEFAULT_PROTOCOL, protocol - ); - monitorService.collect(url); - - // reset - long[] current; - long[] update = new long[LENGTH]; - do { - current = reference.get(); - if (current == null) { - update[0] = 0; - update[1] = 0; - update[2] = 0; - update[3] = 0; - update[4] = 0; - update[5] = 0; - } else { - update[0] = current[0] - success; - update[1] = current[1] - failure; - update[2] = current[2] - input; - update[3] = current[3] - output; - update[4] = current[4] - elapsed; - update[5] = current[5] - concurrent; - } - } while (!reference.compareAndSet(current, update)); - } - } - - @Override - public void collect(URL url) { - // data to collect from url - int success = url.getParameter(MonitorService.SUCCESS, 0); - int failure = url.getParameter(MonitorService.FAILURE, 0); - int input = url.getParameter(MonitorService.INPUT, 0); - int output = url.getParameter(MonitorService.OUTPUT, 0); - int elapsed = url.getParameter(MonitorService.ELAPSED, 0); - int concurrent = url.getParameter(MonitorService.CONCURRENT, 0); - // init atomic reference - Statistics statistics = new Statistics(url); - AtomicReference reference = statisticsMap.computeIfAbsent(statistics, k -> new AtomicReference<>()); - // use CompareAndSet to sum - long[] current; - long[] update = new long[LENGTH]; - do { - current = reference.get(); - if (current == null) { - update[0] = success; - update[1] = failure; - update[2] = input; - update[3] = output; - update[4] = elapsed; - update[5] = concurrent; - update[6] = input; - update[7] = output; - update[8] = elapsed; - update[9] = concurrent; - } else { - update[0] = current[0] + success; - update[1] = current[1] + failure; - update[2] = current[2] + input; - update[3] = current[3] + output; - update[4] = current[4] + elapsed; - update[5] = (current[5] + concurrent) / 2; - update[6] = current[6] > input ? current[6] : input; - update[7] = current[7] > output ? current[7] : output; - update[8] = current[8] > elapsed ? current[8] : elapsed; - update[9] = current[9] > concurrent ? current[9] : concurrent; - } - } while (!reference.compareAndSet(current, update)); - } - - @Override - public List lookup(URL query) { - return monitorService.lookup(query); - } - - @Override - public URL getUrl() { - return monitorInvoker.getUrl(); - } - - @Override - public boolean isAvailable() { - return monitorInvoker.isAvailable(); - } - - @Override - public void destroy() { - try { - ExecutorUtil.cancelScheduledFuture(sendFuture); - } catch (Throwable t) { - logger.error("Unexpected error occur at cancel sender timer, cause: " + t.getMessage(), t); - } - monitorInvoker.destroy(); - } - -} +/* + * 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.monitor.dubbo; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.ExecutorUtil; +import org.apache.dubbo.common.utils.NamedThreadFactory; +import org.apache.dubbo.monitor.Monitor; +import org.apache.dubbo.monitor.MonitorService; +import org.apache.dubbo.rpc.Invoker; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + +import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_PROTOCOL; + +/** + * DubboMonitor + */ +public class DubboMonitor implements Monitor { + + private static final Logger logger = LoggerFactory.getLogger(DubboMonitor.class); + + /** + * The length of the array which is a container of the statistics + */ + private static final int LENGTH = 10; + + /** + * The timer for sending statistics + */ + private final ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3, new NamedThreadFactory("DubboMonitorSendTimer", true)); + + /** + * The future that can cancel the scheduledExecutorService + */ + private final ScheduledFuture sendFuture; + + private final Invoker monitorInvoker; + + private final MonitorService monitorService; + + private final ConcurrentMap> statisticsMap = new ConcurrentHashMap>(); + + public DubboMonitor(Invoker monitorInvoker, MonitorService monitorService) { + this.monitorInvoker = monitorInvoker; + this.monitorService = monitorService; + // The time interval for timer scheduledExecutorService to send data + final long monitorInterval = monitorInvoker.getUrl().getPositiveParameter("interval", 60000); + // collect timer for collecting statistics data + sendFuture = scheduledExecutorService.scheduleWithFixedDelay(() -> { + try { + // collect data + send(); + } catch (Throwable t) { + logger.error("Unexpected error occur at send statistic, cause: " + t.getMessage(), t); + } + }, monitorInterval, monitorInterval, TimeUnit.MILLISECONDS); + } + + public void send() { + if (logger.isDebugEnabled()) { + logger.debug("Send statistics to monitor " + getUrl()); + } + + String timestamp = String.valueOf(System.currentTimeMillis()); + for (Map.Entry> entry : statisticsMap.entrySet()) { + // get statistics data + Statistics statistics = entry.getKey(); + AtomicReference reference = entry.getValue(); + long[] numbers = reference.get(); + long success = numbers[0]; + long failure = numbers[1]; + long input = numbers[2]; + long output = numbers[3]; + long elapsed = numbers[4]; + long concurrent = numbers[5]; + long maxInput = numbers[6]; + long maxOutput = numbers[7]; + long maxElapsed = numbers[8]; + long maxConcurrent = numbers[9]; + String protocol = getUrl().getParameter(DEFAULT_PROTOCOL); + + // send statistics data + URL url = statistics.getUrl() + .addParameters(MonitorService.TIMESTAMP, timestamp, + MonitorService.SUCCESS, String.valueOf(success), + MonitorService.FAILURE, String.valueOf(failure), + MonitorService.INPUT, String.valueOf(input), + MonitorService.OUTPUT, String.valueOf(output), + MonitorService.ELAPSED, String.valueOf(elapsed), + MonitorService.CONCURRENT, String.valueOf(concurrent), + MonitorService.MAX_INPUT, String.valueOf(maxInput), + MonitorService.MAX_OUTPUT, String.valueOf(maxOutput), + MonitorService.MAX_ELAPSED, String.valueOf(maxElapsed), + MonitorService.MAX_CONCURRENT, String.valueOf(maxConcurrent), + DEFAULT_PROTOCOL, protocol + ); + monitorService.collect(url); + + // reset + long[] current; + long[] update = new long[LENGTH]; + do { + current = reference.get(); + if (current == null) { + update[0] = 0; + update[1] = 0; + update[2] = 0; + update[3] = 0; + update[4] = 0; + update[5] = 0; + } else { + update[0] = current[0] - success; + update[1] = current[1] - failure; + update[2] = current[2] - input; + update[3] = current[3] - output; + update[4] = current[4] - elapsed; + update[5] = current[5] - concurrent; + } + } while (!reference.compareAndSet(current, update)); + } + } + + @Override + public void collect(URL url) { + // data to collect from url + int success = url.getParameter(MonitorService.SUCCESS, 0); + int failure = url.getParameter(MonitorService.FAILURE, 0); + int input = url.getParameter(MonitorService.INPUT, 0); + int output = url.getParameter(MonitorService.OUTPUT, 0); + int elapsed = url.getParameter(MonitorService.ELAPSED, 0); + int concurrent = url.getParameter(MonitorService.CONCURRENT, 0); + // init atomic reference + Statistics statistics = new Statistics(url); + AtomicReference reference = statisticsMap.computeIfAbsent(statistics, k -> new AtomicReference<>()); + // use CompareAndSet to sum + long[] current; + long[] update = new long[LENGTH]; + do { + current = reference.get(); + if (current == null) { + update[0] = success; + update[1] = failure; + update[2] = input; + update[3] = output; + update[4] = elapsed; + update[5] = concurrent; + update[6] = input; + update[7] = output; + update[8] = elapsed; + update[9] = concurrent; + } else { + update[0] = current[0] + success; + update[1] = current[1] + failure; + update[2] = current[2] + input; + update[3] = current[3] + output; + update[4] = current[4] + elapsed; + update[5] = (current[5] + concurrent) / 2; + update[6] = current[6] > input ? current[6] : input; + update[7] = current[7] > output ? current[7] : output; + update[8] = current[8] > elapsed ? current[8] : elapsed; + update[9] = current[9] > concurrent ? current[9] : concurrent; + } + } while (!reference.compareAndSet(current, update)); + } + + @Override + public List lookup(URL query) { + return monitorService.lookup(query); + } + + @Override + public URL getUrl() { + return monitorInvoker.getUrl(); + } + + @Override + public boolean isAvailable() { + return monitorInvoker.isAvailable(); + } + + @Override + public void destroy() { + try { + ExecutorUtil.cancelScheduledFuture(sendFuture); + } catch (Throwable t) { + logger.error("Unexpected error occur at cancel sender timer, cause: " + t.getMessage(), t); + } + monitorInvoker.destroy(); + } + +} diff --git a/dubbo-monitor/dubbo-monitor-default/src/main/java/org/apache/dubbo/monitor/dubbo/Statistics.java b/dubbo-monitor/dubbo-monitor-default/src/main/java/org/apache/dubbo/monitor/dubbo/Statistics.java index bba7ac2bb1..37f905524d 100644 --- a/dubbo-monitor/dubbo-monitor-default/src/main/java/org/apache/dubbo/monitor/dubbo/Statistics.java +++ b/dubbo-monitor/dubbo-monitor-default/src/main/java/org/apache/dubbo/monitor/dubbo/Statistics.java @@ -1,210 +1,210 @@ -/* - * 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.monitor.dubbo; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.monitor.MonitorService; - -import java.io.Serializable; - -/** - * Statistics. (SPI, Prototype, ThreadSafe) - */ -public class Statistics implements Serializable { - - private static final long serialVersionUID = -6921183057683641441L; - - private URL url; - - private String application; - - private String service; - - private String method; - - private String group; - - private String version; - - private String client; - - private String server; - - public Statistics(URL url) { - this.url = url; - this.application = url.getParameter(MonitorService.APPLICATION); - this.service = url.getParameter(MonitorService.INTERFACE); - this.method = url.getParameter(MonitorService.METHOD); - this.group = url.getParameter(MonitorService.GROUP); - this.version = url.getParameter(MonitorService.VERSION); - this.client = url.getParameter(MonitorService.CONSUMER, url.getAddress()); - this.server = url.getParameter(MonitorService.PROVIDER, url.getAddress()); - } - - public URL getUrl() { - return url; - } - - public void setUrl(URL url) { - this.url = url; - } - - public String getApplication() { - return application; - } - - public Statistics setApplication(String application) { - this.application = application; - return this; - } - - public String getService() { - return service; - } - - public Statistics setService(String service) { - this.service = service; - return this; - } - - public String getGroup() { - return group; - } - - public void setGroup(String group) { - this.group = group; - } - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - public String getMethod() { - return method; - } - - public Statistics setMethod(String method) { - this.method = method; - return this; - } - - public String getClient() { - return client; - } - - public Statistics setClient(String client) { - this.client = client; - return this; - } - - public String getServer() { - return server; - } - - public Statistics setServer(String server) { - this.server = server; - return this; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((application == null) ? 0 : application.hashCode()); - result = prime * result + ((client == null) ? 0 : client.hashCode()); - result = prime * result + ((group == null) ? 0 : group.hashCode()); - result = prime * result + ((method == null) ? 0 : method.hashCode()); - result = prime * result + ((server == null) ? 0 : server.hashCode()); - result = prime * result + ((service == null) ? 0 : service.hashCode()); - result = prime * result + ((version == null) ? 0 : version.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - Statistics other = (Statistics) obj; - if (application == null) { - if (other.application != null) { - return false; - } - } else if (!application.equals(other.application)) { - return false; - } - if (client == null) { - if (other.client != null) { - return false; - } - } else if (!client.equals(other.client)) { - return false; - } - if (group == null) { - if (other.group != null) { - return false; - } - } else if (!group.equals(other.group)) { - return false; - } - if (method == null) { - if (other.method != null) { - return false; - } - } else if (!method.equals(other.method)) { - return false; - } - if (server == null) { - if (other.server != null) { - return false; - } - } else if (!server.equals(other.server)) { - return false; - } - if (service == null) { - if (other.service != null) { - return false; - } - } else if (!service.equals(other.service)) { - return false; - } - if (version == null) { - if (other.version != null) { - return false; - } - } else if (!version.equals(other.version)) { - return false; - } - return true; - } - - @Override - public String toString() { - return url.toString(); - } - -} \ No newline at end of file +/* + * 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.monitor.dubbo; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.monitor.MonitorService; + +import java.io.Serializable; + +/** + * Statistics. (SPI, Prototype, ThreadSafe) + */ +public class Statistics implements Serializable { + + private static final long serialVersionUID = -6921183057683641441L; + + private URL url; + + private String application; + + private String service; + + private String method; + + private String group; + + private String version; + + private String client; + + private String server; + + public Statistics(URL url) { + this.url = url; + this.application = url.getParameter(MonitorService.APPLICATION); + this.service = url.getParameter(MonitorService.INTERFACE); + this.method = url.getParameter(MonitorService.METHOD); + this.group = url.getParameter(MonitorService.GROUP); + this.version = url.getParameter(MonitorService.VERSION); + this.client = url.getParameter(MonitorService.CONSUMER, url.getAddress()); + this.server = url.getParameter(MonitorService.PROVIDER, url.getAddress()); + } + + public URL getUrl() { + return url; + } + + public void setUrl(URL url) { + this.url = url; + } + + public String getApplication() { + return application; + } + + public Statistics setApplication(String application) { + this.application = application; + return this; + } + + public String getService() { + return service; + } + + public Statistics setService(String service) { + this.service = service; + return this; + } + + public String getGroup() { + return group; + } + + public void setGroup(String group) { + this.group = group; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getMethod() { + return method; + } + + public Statistics setMethod(String method) { + this.method = method; + return this; + } + + public String getClient() { + return client; + } + + public Statistics setClient(String client) { + this.client = client; + return this; + } + + public String getServer() { + return server; + } + + public Statistics setServer(String server) { + this.server = server; + return this; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((application == null) ? 0 : application.hashCode()); + result = prime * result + ((client == null) ? 0 : client.hashCode()); + result = prime * result + ((group == null) ? 0 : group.hashCode()); + result = prime * result + ((method == null) ? 0 : method.hashCode()); + result = prime * result + ((server == null) ? 0 : server.hashCode()); + result = prime * result + ((service == null) ? 0 : service.hashCode()); + result = prime * result + ((version == null) ? 0 : version.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Statistics other = (Statistics) obj; + if (application == null) { + if (other.application != null) { + return false; + } + } else if (!application.equals(other.application)) { + return false; + } + if (client == null) { + if (other.client != null) { + return false; + } + } else if (!client.equals(other.client)) { + return false; + } + if (group == null) { + if (other.group != null) { + return false; + } + } else if (!group.equals(other.group)) { + return false; + } + if (method == null) { + if (other.method != null) { + return false; + } + } else if (!method.equals(other.method)) { + return false; + } + if (server == null) { + if (other.server != null) { + return false; + } + } else if (!server.equals(other.server)) { + return false; + } + if (service == null) { + if (other.service != null) { + return false; + } + } else if (!service.equals(other.service)) { + return false; + } + if (version == null) { + if (other.version != null) { + return false; + } + } else if (!version.equals(other.version)) { + return false; + } + return true; + } + + @Override + public String toString() { + return url.toString(); + } + +} diff --git a/dubbo-monitor/dubbo-monitor-default/src/test/java/org/apache/dubbo/monitor/dubbo/DubboMonitorFactoryTest.java b/dubbo-monitor/dubbo-monitor-default/src/test/java/org/apache/dubbo/monitor/dubbo/DubboMonitorFactoryTest.java index a51c7e7500..44247d8000 100644 --- a/dubbo-monitor/dubbo-monitor-default/src/test/java/org/apache/dubbo/monitor/dubbo/DubboMonitorFactoryTest.java +++ b/dubbo-monitor/dubbo-monitor-default/src/test/java/org/apache/dubbo/monitor/dubbo/DubboMonitorFactoryTest.java @@ -65,4 +65,4 @@ public class DubboMonitorFactoryTest { Invoker invoker = invokerArgumentCaptor.getValue(); assertThat(invoker.getUrl().getParameter(REFERENCE_FILTER_KEY), containsString("testFilter")); } -} \ No newline at end of file +} diff --git a/dubbo-monitor/dubbo-monitor-default/src/test/java/org/apache/dubbo/monitor/dubbo/DubboMonitorTest.java b/dubbo-monitor/dubbo-monitor-default/src/test/java/org/apache/dubbo/monitor/dubbo/DubboMonitorTest.java index f94553c037..71042ff893 100644 --- a/dubbo-monitor/dubbo-monitor-default/src/test/java/org/apache/dubbo/monitor/dubbo/DubboMonitorTest.java +++ b/dubbo-monitor/dubbo-monitor-default/src/test/java/org/apache/dubbo/monitor/dubbo/DubboMonitorTest.java @@ -1,249 +1,249 @@ -/* - * 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.monitor.dubbo; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.URLBuilder; -import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.monitor.Monitor; -import org.apache.dubbo.monitor.MonitorFactory; -import org.apache.dubbo.monitor.MonitorService; -import org.apache.dubbo.rpc.Exporter; -import org.apache.dubbo.rpc.Invocation; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.Protocol; -import org.apache.dubbo.rpc.ProxyFactory; -import org.apache.dubbo.rpc.Result; -import org.apache.dubbo.rpc.RpcException; - -import org.hamcrest.CustomMatcher; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; - -import java.util.Arrays; -import java.util.List; - -import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_PROTOCOL; -import static org.hamcrest.CoreMatchers.hasItem; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.not; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.atLeastOnce; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - -/** - * DubboMonitorTest - */ -public class DubboMonitorTest { - - private final Invoker monitorInvoker = new Invoker() { - @Override - public Class getInterface() { - return MonitorService.class; - } - - public URL getUrl() { - return URL.valueOf("dubbo://127.0.0.1:7070?interval=1000"); - } - - @Override - public boolean isAvailable() { - return false; - } - - @Override - public Result invoke(Invocation invocation) throws RpcException { - return null; - } - - @Override - public void destroy() { - } - }; - private volatile URL lastStatistics; - private final MonitorService monitorService = new MonitorService() { - - public void collect(URL statistics) { - DubboMonitorTest.this.lastStatistics = statistics; - } - - public List lookup(URL query) { - return Arrays.asList(DubboMonitorTest.this.lastStatistics); - } - - }; - - @Test - public void testCount() throws Exception { - DubboMonitor monitor = new DubboMonitor(monitorInvoker, monitorService); - URL statistics = new URLBuilder(DUBBO_PROTOCOL, "10.20.153.10", 0) - .addParameter(MonitorService.APPLICATION, "morgan") - .addParameter(MonitorService.INTERFACE, "MemberService") - .addParameter(MonitorService.METHOD, "findPerson") - .addParameter(MonitorService.CONSUMER, "10.20.153.11") - .addParameter(MonitorService.SUCCESS, 1) - .addParameter(MonitorService.FAILURE, 0) - .addParameter(MonitorService.ELAPSED, 3) - .addParameter(MonitorService.MAX_ELAPSED, 3) - .addParameter(MonitorService.CONCURRENT, 1) - .addParameter(MonitorService.MAX_CONCURRENT, 1) - .build(); - monitor.collect(statistics); - monitor.send(); - while (lastStatistics == null) { - Thread.sleep(10); - } - Assertions.assertEquals("morgan", lastStatistics.getParameter(MonitorService.APPLICATION)); - Assertions.assertEquals("dubbo", lastStatistics.getProtocol()); - Assertions.assertEquals("10.20.153.10", lastStatistics.getHost()); - Assertions.assertEquals("morgan", lastStatistics.getParameter(MonitorService.APPLICATION)); - Assertions.assertEquals("MemberService", lastStatistics.getParameter(MonitorService.INTERFACE)); - Assertions.assertEquals("findPerson", lastStatistics.getParameter(MonitorService.METHOD)); - Assertions.assertEquals("10.20.153.11", lastStatistics.getParameter(MonitorService.CONSUMER)); - Assertions.assertEquals("1", lastStatistics.getParameter(MonitorService.SUCCESS)); - Assertions.assertEquals("0", lastStatistics.getParameter(MonitorService.FAILURE)); - Assertions.assertEquals("3", lastStatistics.getParameter(MonitorService.ELAPSED)); - Assertions.assertEquals("3", lastStatistics.getParameter(MonitorService.MAX_ELAPSED)); - Assertions.assertEquals("1", lastStatistics.getParameter(MonitorService.CONCURRENT)); - Assertions.assertEquals("1", lastStatistics.getParameter(MonitorService.MAX_CONCURRENT)); - monitor.destroy(); - } - - @Test - public void testMonitorFactory() throws Exception { - MockMonitorService monitorService = new MockMonitorService(); - URL statistics = new URLBuilder(DUBBO_PROTOCOL, "10.20.153.10", 0) - .addParameter(MonitorService.APPLICATION, "morgan") - .addParameter(MonitorService.INTERFACE, "MemberService") - .addParameter(MonitorService.METHOD, "findPerson") - .addParameter(MonitorService.CONSUMER, "10.20.153.11") - .addParameter(MonitorService.SUCCESS, 1) - .addParameter(MonitorService.FAILURE, 0) - .addParameter(MonitorService.ELAPSED, 3) - .addParameter(MonitorService.MAX_ELAPSED, 3) - .addParameter(MonitorService.CONCURRENT, 1) - .addParameter(MonitorService.MAX_CONCURRENT, 1) - .build(); - - Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); - ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); - MonitorFactory monitorFactory = ExtensionLoader.getExtensionLoader(MonitorFactory.class).getAdaptiveExtension(); - - Exporter exporter = protocol.export(proxyFactory.getInvoker(monitorService, MonitorService.class, URL.valueOf("dubbo://127.0.0.1:17979/" + MonitorService.class.getName()))); - try { - Monitor monitor = null; - long start = System.currentTimeMillis(); - while (System.currentTimeMillis() - start < 60000) { - monitor = monitorFactory.getMonitor(URL.valueOf("dubbo://127.0.0.1:17979?interval=10")); - if (monitor == null) { - continue; - } - try { - monitor.collect(statistics); - int i = 0; - while (monitorService.getStatistics() == null && i < 200) { - i++; - Thread.sleep(10); - } - URL result = monitorService.getStatistics(); - Assertions.assertEquals(1, result.getParameter(MonitorService.SUCCESS, 0)); - Assertions.assertEquals(3, result.getParameter(MonitorService.ELAPSED, 0)); - } finally { - monitor.destroy(); - } - break; - } - Assertions.assertNotNull(monitor); - } finally { - exporter.unexport(); - } - } - - @Test - public void testAvailable() { - Invoker invoker = mock(Invoker.class); - MonitorService monitorService = mock(MonitorService.class); - - given(invoker.isAvailable()).willReturn(true); - given(invoker.getUrl()).willReturn(URL.valueOf("dubbo://127.0.0.1:7070?interval=20")); - DubboMonitor dubboMonitor = new DubboMonitor(invoker, monitorService); - - assertThat(dubboMonitor.isAvailable(), is(true)); - verify(invoker).isAvailable(); - } - - @Test - public void testSum() { - URL statistics = new URLBuilder(DUBBO_PROTOCOL, "10.20.153.11", 0) - .addParameter(MonitorService.APPLICATION, "morgan") - .addParameter(MonitorService.INTERFACE, "MemberService") - .addParameter(MonitorService.METHOD, "findPerson") - .addParameter(MonitorService.CONSUMER, "10.20.153.11") - .addParameter(MonitorService.SUCCESS, 1) - .addParameter(MonitorService.FAILURE, 0) - .addParameter(MonitorService.ELAPSED, 3) - .addParameter(MonitorService.MAX_ELAPSED, 3) - .addParameter(MonitorService.CONCURRENT, 1) - .addParameter(MonitorService.MAX_CONCURRENT, 1) - .build(); - Invoker invoker = mock(Invoker.class); - MonitorService monitorService = mock(MonitorService.class); - - given(invoker.getUrl()).willReturn(URL.valueOf("dubbo://127.0.0.1:7070?interval=20")); - DubboMonitor dubboMonitor = new DubboMonitor(invoker, monitorService); - - dubboMonitor.collect(statistics); - dubboMonitor.collect(statistics.addParameter(MonitorService.SUCCESS, 3).addParameter(MonitorService.CONCURRENT, 2) - .addParameter(MonitorService.INPUT, 1).addParameter(MonitorService.OUTPUT, 2)); - dubboMonitor.collect(statistics.addParameter(MonitorService.SUCCESS, 6).addParameter(MonitorService.ELAPSED, 2)); - - dubboMonitor.send(); - - ArgumentCaptor summaryCaptor = ArgumentCaptor.forClass(URL.class); - verify(monitorService, atLeastOnce()).collect(summaryCaptor.capture()); - - List allValues = summaryCaptor.getAllValues(); - - assertThat(allValues, not(nullValue())); - assertThat(allValues, hasItem(new CustomMatcher("Monitor count should greater than 1") { - @Override - public boolean matches(Object item) { - URL url = (URL) item; - return Integer.valueOf(url.getParameter(MonitorService.SUCCESS)) > 1; - } - })); - } - - @Test - public void testLookUp() { - Invoker invoker = mock(Invoker.class); - MonitorService monitorService = mock(MonitorService.class); - - URL queryUrl = URL.valueOf("dubbo://127.0.0.1:7070?interval=20"); - given(invoker.getUrl()).willReturn(queryUrl); - DubboMonitor dubboMonitor = new DubboMonitor(invoker, monitorService); - - dubboMonitor.lookup(queryUrl); - - verify(monitorService).lookup(eq(queryUrl)); - } -} +/* + * 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.monitor.dubbo; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.URLBuilder; +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.monitor.Monitor; +import org.apache.dubbo.monitor.MonitorFactory; +import org.apache.dubbo.monitor.MonitorService; +import org.apache.dubbo.rpc.Exporter; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.Protocol; +import org.apache.dubbo.rpc.ProxyFactory; +import org.apache.dubbo.rpc.Result; +import org.apache.dubbo.rpc.RpcException; + +import org.hamcrest.CustomMatcher; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; + +import java.util.Arrays; +import java.util.List; + +import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_PROTOCOL; +import static org.hamcrest.CoreMatchers.hasItem; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.not; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +/** + * DubboMonitorTest + */ +public class DubboMonitorTest { + + private final Invoker monitorInvoker = new Invoker() { + @Override + public Class getInterface() { + return MonitorService.class; + } + + public URL getUrl() { + return URL.valueOf("dubbo://127.0.0.1:7070?interval=1000"); + } + + @Override + public boolean isAvailable() { + return false; + } + + @Override + public Result invoke(Invocation invocation) throws RpcException { + return null; + } + + @Override + public void destroy() { + } + }; + private volatile URL lastStatistics; + private final MonitorService monitorService = new MonitorService() { + + public void collect(URL statistics) { + DubboMonitorTest.this.lastStatistics = statistics; + } + + public List lookup(URL query) { + return Arrays.asList(DubboMonitorTest.this.lastStatistics); + } + + }; + + @Test + public void testCount() throws Exception { + DubboMonitor monitor = new DubboMonitor(monitorInvoker, monitorService); + URL statistics = new URLBuilder(DUBBO_PROTOCOL, "10.20.153.10", 0) + .addParameter(MonitorService.APPLICATION, "morgan") + .addParameter(MonitorService.INTERFACE, "MemberService") + .addParameter(MonitorService.METHOD, "findPerson") + .addParameter(MonitorService.CONSUMER, "10.20.153.11") + .addParameter(MonitorService.SUCCESS, 1) + .addParameter(MonitorService.FAILURE, 0) + .addParameter(MonitorService.ELAPSED, 3) + .addParameter(MonitorService.MAX_ELAPSED, 3) + .addParameter(MonitorService.CONCURRENT, 1) + .addParameter(MonitorService.MAX_CONCURRENT, 1) + .build(); + monitor.collect(statistics); + monitor.send(); + while (lastStatistics == null) { + Thread.sleep(10); + } + Assertions.assertEquals("morgan", lastStatistics.getParameter(MonitorService.APPLICATION)); + Assertions.assertEquals("dubbo", lastStatistics.getProtocol()); + Assertions.assertEquals("10.20.153.10", lastStatistics.getHost()); + Assertions.assertEquals("morgan", lastStatistics.getParameter(MonitorService.APPLICATION)); + Assertions.assertEquals("MemberService", lastStatistics.getParameter(MonitorService.INTERFACE)); + Assertions.assertEquals("findPerson", lastStatistics.getParameter(MonitorService.METHOD)); + Assertions.assertEquals("10.20.153.11", lastStatistics.getParameter(MonitorService.CONSUMER)); + Assertions.assertEquals("1", lastStatistics.getParameter(MonitorService.SUCCESS)); + Assertions.assertEquals("0", lastStatistics.getParameter(MonitorService.FAILURE)); + Assertions.assertEquals("3", lastStatistics.getParameter(MonitorService.ELAPSED)); + Assertions.assertEquals("3", lastStatistics.getParameter(MonitorService.MAX_ELAPSED)); + Assertions.assertEquals("1", lastStatistics.getParameter(MonitorService.CONCURRENT)); + Assertions.assertEquals("1", lastStatistics.getParameter(MonitorService.MAX_CONCURRENT)); + monitor.destroy(); + } + + @Test + public void testMonitorFactory() throws Exception { + MockMonitorService monitorService = new MockMonitorService(); + URL statistics = new URLBuilder(DUBBO_PROTOCOL, "10.20.153.10", 0) + .addParameter(MonitorService.APPLICATION, "morgan") + .addParameter(MonitorService.INTERFACE, "MemberService") + .addParameter(MonitorService.METHOD, "findPerson") + .addParameter(MonitorService.CONSUMER, "10.20.153.11") + .addParameter(MonitorService.SUCCESS, 1) + .addParameter(MonitorService.FAILURE, 0) + .addParameter(MonitorService.ELAPSED, 3) + .addParameter(MonitorService.MAX_ELAPSED, 3) + .addParameter(MonitorService.CONCURRENT, 1) + .addParameter(MonitorService.MAX_CONCURRENT, 1) + .build(); + + Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); + ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); + MonitorFactory monitorFactory = ExtensionLoader.getExtensionLoader(MonitorFactory.class).getAdaptiveExtension(); + + Exporter exporter = protocol.export(proxyFactory.getInvoker(monitorService, MonitorService.class, URL.valueOf("dubbo://127.0.0.1:17979/" + MonitorService.class.getName()))); + try { + Monitor monitor = null; + long start = System.currentTimeMillis(); + while (System.currentTimeMillis() - start < 60000) { + monitor = monitorFactory.getMonitor(URL.valueOf("dubbo://127.0.0.1:17979?interval=10")); + if (monitor == null) { + continue; + } + try { + monitor.collect(statistics); + int i = 0; + while (monitorService.getStatistics() == null && i < 200) { + i++; + Thread.sleep(10); + } + URL result = monitorService.getStatistics(); + Assertions.assertEquals(1, result.getParameter(MonitorService.SUCCESS, 0)); + Assertions.assertEquals(3, result.getParameter(MonitorService.ELAPSED, 0)); + } finally { + monitor.destroy(); + } + break; + } + Assertions.assertNotNull(monitor); + } finally { + exporter.unexport(); + } + } + + @Test + public void testAvailable() { + Invoker invoker = mock(Invoker.class); + MonitorService monitorService = mock(MonitorService.class); + + given(invoker.isAvailable()).willReturn(true); + given(invoker.getUrl()).willReturn(URL.valueOf("dubbo://127.0.0.1:7070?interval=20")); + DubboMonitor dubboMonitor = new DubboMonitor(invoker, monitorService); + + assertThat(dubboMonitor.isAvailable(), is(true)); + verify(invoker).isAvailable(); + } + + @Test + public void testSum() { + URL statistics = new URLBuilder(DUBBO_PROTOCOL, "10.20.153.11", 0) + .addParameter(MonitorService.APPLICATION, "morgan") + .addParameter(MonitorService.INTERFACE, "MemberService") + .addParameter(MonitorService.METHOD, "findPerson") + .addParameter(MonitorService.CONSUMER, "10.20.153.11") + .addParameter(MonitorService.SUCCESS, 1) + .addParameter(MonitorService.FAILURE, 0) + .addParameter(MonitorService.ELAPSED, 3) + .addParameter(MonitorService.MAX_ELAPSED, 3) + .addParameter(MonitorService.CONCURRENT, 1) + .addParameter(MonitorService.MAX_CONCURRENT, 1) + .build(); + Invoker invoker = mock(Invoker.class); + MonitorService monitorService = mock(MonitorService.class); + + given(invoker.getUrl()).willReturn(URL.valueOf("dubbo://127.0.0.1:7070?interval=20")); + DubboMonitor dubboMonitor = new DubboMonitor(invoker, monitorService); + + dubboMonitor.collect(statistics); + dubboMonitor.collect(statistics.addParameter(MonitorService.SUCCESS, 3).addParameter(MonitorService.CONCURRENT, 2) + .addParameter(MonitorService.INPUT, 1).addParameter(MonitorService.OUTPUT, 2)); + dubboMonitor.collect(statistics.addParameter(MonitorService.SUCCESS, 6).addParameter(MonitorService.ELAPSED, 2)); + + dubboMonitor.send(); + + ArgumentCaptor summaryCaptor = ArgumentCaptor.forClass(URL.class); + verify(monitorService, atLeastOnce()).collect(summaryCaptor.capture()); + + List allValues = summaryCaptor.getAllValues(); + + assertThat(allValues, not(nullValue())); + assertThat(allValues, hasItem(new CustomMatcher("Monitor count should greater than 1") { + @Override + public boolean matches(Object item) { + URL url = (URL) item; + return Integer.valueOf(url.getParameter(MonitorService.SUCCESS)) > 1; + } + })); + } + + @Test + public void testLookUp() { + Invoker invoker = mock(Invoker.class); + MonitorService monitorService = mock(MonitorService.class); + + URL queryUrl = URL.valueOf("dubbo://127.0.0.1:7070?interval=20"); + given(invoker.getUrl()).willReturn(queryUrl); + DubboMonitor dubboMonitor = new DubboMonitor(invoker, monitorService); + + dubboMonitor.lookup(queryUrl); + + verify(monitorService).lookup(eq(queryUrl)); + } +} diff --git a/dubbo-monitor/dubbo-monitor-default/src/test/java/org/apache/dubbo/monitor/dubbo/MockMonitorService.java b/dubbo-monitor/dubbo-monitor-default/src/test/java/org/apache/dubbo/monitor/dubbo/MockMonitorService.java index 77be5359e3..ee8b39c1a0 100644 --- a/dubbo-monitor/dubbo-monitor-default/src/test/java/org/apache/dubbo/monitor/dubbo/MockMonitorService.java +++ b/dubbo-monitor/dubbo-monitor-default/src/test/java/org/apache/dubbo/monitor/dubbo/MockMonitorService.java @@ -1,44 +1,44 @@ -/* - * 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.monitor.dubbo; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.monitor.MonitorService; - -import java.util.Arrays; -import java.util.List; - -/** - * MockMonitorService - */ -public class MockMonitorService implements MonitorService { - - private URL statistics; - - public void collect(URL statistics) { - this.statistics = statistics; - } - - public URL getStatistics() { - return statistics; - } - - public List lookup(URL query) { - return Arrays.asList(statistics); - } - -} +/* + * 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.monitor.dubbo; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.monitor.MonitorService; + +import java.util.Arrays; +import java.util.List; + +/** + * MockMonitorService + */ +public class MockMonitorService implements MonitorService { + + private URL statistics; + + public void collect(URL statistics) { + this.statistics = statistics; + } + + public URL getStatistics() { + return statistics; + } + + public List lookup(URL query) { + return Arrays.asList(statistics); + } + +} diff --git a/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/AccessKeyAuthenticatorTest.java b/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/AccessKeyAuthenticatorTest.java index 11f0b08f55..946a4e5065 100644 --- a/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/AccessKeyAuthenticatorTest.java +++ b/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/AccessKeyAuthenticatorTest.java @@ -22,6 +22,7 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.common.constants.CommonConstants; import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.RpcInvocation; + import org.junit.jupiter.api.Test; import java.util.ArrayList; @@ -133,4 +134,4 @@ class AccessKeyAuthenticatorTest { assertNotEquals(signature, signature1); } -} \ No newline at end of file +} diff --git a/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/DefaultAccessKeyStorageTest.java b/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/DefaultAccessKeyStorageTest.java index e757cc815b..296be9f986 100644 --- a/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/DefaultAccessKeyStorageTest.java +++ b/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/DefaultAccessKeyStorageTest.java @@ -19,6 +19,7 @@ package org.apache.dubbo.auth; import org.apache.dubbo.auth.model.AccessKeyPair; import org.apache.dubbo.common.URL; import org.apache.dubbo.rpc.Invocation; + import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -39,4 +40,4 @@ class DefaultAccessKeyStorageTest { assertEquals(accessKey.getAccessKey(), "ak"); assertEquals(accessKey.getSecretKey(), "sk"); } -} \ No newline at end of file +} diff --git a/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/filter/ConsumerSignFilterTest.java b/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/filter/ConsumerSignFilterTest.java index b335e3bfa2..167bc8fabd 100644 --- a/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/filter/ConsumerSignFilterTest.java +++ b/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/filter/ConsumerSignFilterTest.java @@ -21,6 +21,7 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.common.constants.CommonConstants; import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; + import org.junit.jupiter.api.Test; import static org.mockito.ArgumentMatchers.anyString; @@ -59,4 +60,4 @@ class ConsumerSignFilterTest { consumerSignFilter.invoke(invoker, invocation); verify(invocation, times(1)).setAttachment(eq(Constants.REQUEST_SIGNATURE_KEY), anyString()); } -} \ No newline at end of file +} diff --git a/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/filter/ProviderAuthFilterTest.java b/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/filter/ProviderAuthFilterTest.java index ca2cd57387..cbb9379948 100644 --- a/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/filter/ProviderAuthFilterTest.java +++ b/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/filter/ProviderAuthFilterTest.java @@ -185,4 +185,4 @@ class ProviderAuthFilterTest { Result result = providerAuthFilter.invoke(invoker, invocation); assertNull(result); } -} \ No newline at end of file +} diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/BaseOffline.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/BaseOffline.java index 4aeaa92821..85c4321925 100644 --- a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/BaseOffline.java +++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/BaseOffline.java @@ -82,4 +82,4 @@ public class BaseOffline implements BaseCommand { registry.unregister(statedURL.getProviderUrl()); statedURL.setRegistered(false); } -} \ No newline at end of file +} diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/textui/TComponent.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/textui/TComponent.java index 7f0c003ed2..12aca73c12 100644 --- a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/textui/TComponent.java +++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/textui/TComponent.java @@ -26,4 +26,4 @@ public interface TComponent { */ String rendering(); -} \ No newline at end of file +} diff --git a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/ChangeTelnetHandlerTest.java b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/ChangeTelnetHandlerTest.java index 7a0a6255c0..be57f2bf92 100644 --- a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/ChangeTelnetHandlerTest.java +++ b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/ChangeTelnetHandlerTest.java @@ -121,4 +121,4 @@ public class ChangeTelnetHandlerTest { String result = change.telnet(mockChannel, "/"); assertEquals("Cancelled default service org.apache.dubbo.rpc.protocol.dubbo.support.DemoService.", result); } -} \ No newline at end of file +} diff --git a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/CurrentTelnetHandlerTest.java b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/CurrentTelnetHandlerTest.java index 40d0382048..10728ba9e9 100644 --- a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/CurrentTelnetHandlerTest.java +++ b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/CurrentTelnetHandlerTest.java @@ -60,4 +60,4 @@ public class CurrentTelnetHandlerTest { String result = count.telnet(mockChannel, "test"); assertEquals("Unsupported parameter test for pwd.", result); } -} \ No newline at end of file +} diff --git a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/LogTelnetHandlerTest.java b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/LogTelnetHandlerTest.java index 68d46fb077..6417b44d2d 100644 --- a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/LogTelnetHandlerTest.java +++ b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/LogTelnetHandlerTest.java @@ -51,4 +51,4 @@ public class LogTelnetHandlerTest { assertTrue(result.contains("CURRENT LOG APPENDER")); } -} \ No newline at end of file +} diff --git a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/PortTelnetHandlerTest.java b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/PortTelnetHandlerTest.java index a69f76384a..37c018c00f 100644 --- a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/PortTelnetHandlerTest.java +++ b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/PortTelnetHandlerTest.java @@ -102,4 +102,4 @@ public class PortTelnetHandlerTest { assertEquals("No such port 20880", result); } -} \ No newline at end of file +} diff --git a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/ProtocolUtils.java b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/ProtocolUtils.java index 41d64fc9fa..eb6b59f845 100644 --- a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/ProtocolUtils.java +++ b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/ProtocolUtils.java @@ -57,4 +57,4 @@ public class ProtocolUtils { server.close(); } } -} \ No newline at end of file +} diff --git a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/service/CustomArgument.java b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/service/CustomArgument.java index 0178fecbaa..cb1114d7cc 100644 --- a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/service/CustomArgument.java +++ b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/service/CustomArgument.java @@ -49,4 +49,4 @@ public class CustomArgument implements Serializable { public void setName(String name) { this.name = name; } -} \ No newline at end of file +} diff --git a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/service/DemoService.java b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/service/DemoService.java index 8ffa550639..3950380256 100644 --- a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/service/DemoService.java +++ b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/service/DemoService.java @@ -68,4 +68,4 @@ public interface DemoService { String getRemoteApplicationName(); Map getMap(Map map); -} \ No newline at end of file +} diff --git a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/service/DemoServiceImpl.java b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/service/DemoServiceImpl.java index 1ea3e3a139..a42cc12a2e 100644 --- a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/service/DemoServiceImpl.java +++ b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/service/DemoServiceImpl.java @@ -131,4 +131,4 @@ public class DemoServiceImpl implements DemoService { public Map getMap(Map map) { return map; } -} \ No newline at end of file +} diff --git a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/service/Man.java b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/service/Man.java index 0ccc6c19e4..09154632c2 100644 --- a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/service/Man.java +++ b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/service/Man.java @@ -43,4 +43,4 @@ public class Man implements Serializable { public void setAge(int age) { this.age = age; } -} \ No newline at end of file +} diff --git a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/service/Person.java b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/service/Person.java index cef3c5a842..b59263d5fd 100644 --- a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/service/Person.java +++ b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/service/Person.java @@ -42,4 +42,4 @@ public class Person implements Serializable { public void setAge(int age) { this.age = age; } -} \ No newline at end of file +} diff --git a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/service/Type.java b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/service/Type.java index f5e96d9437..9588c9a8c0 100644 --- a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/service/Type.java +++ b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/legacy/service/Type.java @@ -18,4 +18,4 @@ package org.apache.dubbo.qos.legacy.service; public enum Type { High, Normal, Lower -} \ No newline at end of file +} diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/NotifyListener.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/NotifyListener.java index 4c02cdc81a..6486131ba1 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/NotifyListener.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/NotifyListener.java @@ -1,52 +1,52 @@ -/* - * 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.registry; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener; - -import java.util.List; - -/** - * NotifyListener. (API, Prototype, ThreadSafe) - * - * @see org.apache.dubbo.registry.RegistryService#subscribe(URL, NotifyListener) - */ -public interface NotifyListener { - - /** - * Triggered when a service change notification is received. - *

- * Notify needs to support the contract:
- * 1. Always notifications on the service interface and the dimension of the data type. that is, won't notify part of the same type data belonging to one service. Users do not need to compare the results of the previous notification.
- * 2. The first notification at a subscription must be a full notification of all types of data of a service.
- * 3. At the time of change, different types of data are allowed to be notified separately, e.g.: providers, consumers, routers, overrides. It allows only one of these types to be notified, but the data of this type must be full, not incremental.
- * 4. If a data type is empty, need to notify a empty protocol with category parameter identification of url data.
- * 5. The order of notifications to be guaranteed by the notifications(That is, the implementation of the registry). Such as: single thread push, queue serialization, and version comparison.
- * - * @param urls The list of registered information , is always not empty. The meaning is the same as the return value of {@link org.apache.dubbo.registry.RegistryService#lookup(URL)}. - */ - void notify(List urls); - - default void addServiceListener(ServiceInstancesChangedListener instanceListener) { - } - - default URL getConsumerUrl() { - return null; - } - -} \ No newline at end of file +/* + * 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.registry; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener; + +import java.util.List; + +/** + * NotifyListener. (API, Prototype, ThreadSafe) + * + * @see org.apache.dubbo.registry.RegistryService#subscribe(URL, NotifyListener) + */ +public interface NotifyListener { + + /** + * Triggered when a service change notification is received. + *

+ * Notify needs to support the contract:
+ * 1. Always notifications on the service interface and the dimension of the data type. that is, won't notify part of the same type data belonging to one service. Users do not need to compare the results of the previous notification.
+ * 2. The first notification at a subscription must be a full notification of all types of data of a service.
+ * 3. At the time of change, different types of data are allowed to be notified separately, e.g.: providers, consumers, routers, overrides. It allows only one of these types to be notified, but the data of this type must be full, not incremental.
+ * 4. If a data type is empty, need to notify a empty protocol with category parameter identification of url data.
+ * 5. The order of notifications to be guaranteed by the notifications(That is, the implementation of the registry). Such as: single thread push, queue serialization, and version comparison.
+ * + * @param urls The list of registered information , is always not empty. The meaning is the same as the return value of {@link org.apache.dubbo.registry.RegistryService#lookup(URL)}. + */ + void notify(List urls); + + default void addServiceListener(ServiceInstancesChangedListener instanceListener) { + } + + default URL getConsumerUrl() { + return null; + } + +} diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/Registry.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/Registry.java index e5f5cbad1a..95137e5feb 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/Registry.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/Registry.java @@ -1,42 +1,42 @@ -/* - * 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.registry; - -import org.apache.dubbo.common.Node; -import org.apache.dubbo.common.URL; - -import static org.apache.dubbo.common.constants.CommonConstants.REGISTRY_DELAY_NOTIFICATION_KEY; - -/** - * Registry. (SPI, Prototype, ThreadSafe) - * - * @see org.apache.dubbo.registry.RegistryFactory#getRegistry(URL) - * @see org.apache.dubbo.registry.support.AbstractRegistry - */ -public interface Registry extends Node, RegistryService { - default int getDelay() { - return getUrl().getParameter(REGISTRY_DELAY_NOTIFICATION_KEY, 5000); - } - - default void reExportRegister(URL url) { - register(url); - } - - default void reExportUnregister(URL url) { - unregister(url); - } -} \ No newline at end of file +/* + * 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.registry; + +import org.apache.dubbo.common.Node; +import org.apache.dubbo.common.URL; + +import static org.apache.dubbo.common.constants.CommonConstants.REGISTRY_DELAY_NOTIFICATION_KEY; + +/** + * Registry. (SPI, Prototype, ThreadSafe) + * + * @see org.apache.dubbo.registry.RegistryFactory#getRegistry(URL) + * @see org.apache.dubbo.registry.support.AbstractRegistry + */ +public interface Registry extends Node, RegistryService { + default int getDelay() { + return getUrl().getParameter(REGISTRY_DELAY_NOTIFICATION_KEY, 5000); + } + + default void reExportRegister(URL url) { + register(url); + } + + default void reExportUnregister(URL url) { + unregister(url); + } +} diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryFactory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryFactory.java index 5db2e77d59..24011399c7 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryFactory.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryFactory.java @@ -1,48 +1,48 @@ -/* - * 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.registry; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.extension.Adaptive; -import org.apache.dubbo.common.extension.SPI; - -/** - * RegistryFactory. (SPI, Singleton, ThreadSafe) - * - * @see org.apache.dubbo.registry.support.AbstractRegistryFactory - */ -@SPI("dubbo") -public interface RegistryFactory { - - /** - * Connect to the registry - *

- * Connecting the registry needs to support the contract:
- * 1. When the check=false is set, the connection is not checked, otherwise the exception is thrown when disconnection
- * 2. Support username:password authority authentication on URL.
- * 3. Support the backup=10.20.153.10 candidate registry cluster address.
- * 4. Support file=registry.cache local disk file cache.
- * 5. Support the timeout=1000 request timeout setting.
- * 6. Support session=60000 session timeout or expiration settings.
- * - * @param url Registry address, is not allowed to be empty - * @return Registry reference, never return empty value - */ - @Adaptive({"protocol"}) - Registry getRegistry(URL url); - -} \ No newline at end of file +/* + * 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.registry; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.Adaptive; +import org.apache.dubbo.common.extension.SPI; + +/** + * RegistryFactory. (SPI, Singleton, ThreadSafe) + * + * @see org.apache.dubbo.registry.support.AbstractRegistryFactory + */ +@SPI("dubbo") +public interface RegistryFactory { + + /** + * Connect to the registry + *

+ * Connecting the registry needs to support the contract:
+ * 1. When the check=false is set, the connection is not checked, otherwise the exception is thrown when disconnection
+ * 2. Support username:password authority authentication on URL.
+ * 3. Support the backup=10.20.153.10 candidate registry cluster address.
+ * 4. Support file=registry.cache local disk file cache.
+ * 5. Support the timeout=1000 request timeout setting.
+ * 6. Support session=60000 session timeout or expiration settings.
+ * + * @param url Registry address, is not allowed to be empty + * @return Registry reference, never return empty value + */ + @Adaptive({"protocol"}) + Registry getRegistry(URL url); + +} diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryService.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryService.java index 53a5c102eb..6bd9259544 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryService.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryService.java @@ -1,94 +1,94 @@ -/* - * 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.registry; - -import org.apache.dubbo.common.URL; - -import java.util.List; - -/** - * RegistryService. (SPI, Prototype, ThreadSafe) - * - * @see org.apache.dubbo.registry.Registry - * @see org.apache.dubbo.registry.RegistryFactory#getRegistry(URL) - */ -public interface RegistryService { - - /** - * Register data, such as : provider service, consumer address, route rule, override rule and other data. - *

- * Registering is required to support the contract:
- * 1. When the URL sets the check=false parameter. When the registration fails, the exception is not thrown and retried in the background. Otherwise, the exception will be thrown.
- * 2. When URL sets the dynamic=false parameter, it needs to be stored persistently, otherwise, it should be deleted automatically when the registrant has an abnormal exit.
- * 3. When the URL sets category=routers, it means classified storage, the default category is providers, and the data can be notified by the classified section.
- * 4. When the registry is restarted, network jitter, data can not be lost, including automatically deleting data from the broken line.
- * 5. Allow URLs which have the same URL but different parameters to coexist,they can't cover each other.
- * - * @param url Registration information , is not allowed to be empty, e.g: dubbo://10.20.153.10/org.apache.dubbo.foo.BarService?version=1.0.0&application=kylin - */ - void register(URL url); - - /** - * Unregister - *

- * Unregistering is required to support the contract:
- * 1. If it is the persistent stored data of dynamic=false, the registration data can not be found, then the IllegalStateException is thrown, otherwise it is ignored.
- * 2. Unregister according to the full url match.
- * - * @param url Registration information , is not allowed to be empty, e.g: dubbo://10.20.153.10/org.apache.dubbo.foo.BarService?version=1.0.0&application=kylin - */ - void unregister(URL url); - - /** - * Subscribe to eligible registered data and automatically push when the registered data is changed. - *

- * Subscribing need to support contracts:
- * 1. When the URL sets the check=false parameter. When the registration fails, the exception is not thrown and retried in the background.
- * 2. When URL sets category=routers, it only notifies the specified classification data. Multiple classifications are separated by commas, and allows asterisk to match, which indicates that all categorical data are subscribed.
- * 3. Allow interface, group, version, and classifier as a conditional query, e.g.: interface=org.apache.dubbo.foo.BarService&version=1.0.0
- * 4. And the query conditions allow the asterisk to be matched, subscribe to all versions of all the packets of all interfaces, e.g. :interface=*&group=*&version=*&classifier=*
- * 5. When the registry is restarted and network jitter, it is necessary to automatically restore the subscription request.
- * 6. Allow URLs which have the same URL but different parameters to coexist,they can't cover each other.
- * 7. The subscription process must be blocked, when the first notice is finished and then returned.
- * - * @param url Subscription condition, not allowed to be empty, e.g. consumer://10.20.153.10/org.apache.dubbo.foo.BarService?version=1.0.0&application=kylin - * @param listener A listener of the change event, not allowed to be empty - */ - void subscribe(URL url, NotifyListener listener); - - /** - * Unsubscribe - *

- * Unsubscribing is required to support the contract:
- * 1. If don't subscribe, ignore it directly.
- * 2. Unsubscribe by full URL match.
- * - * @param url Subscription condition, not allowed to be empty, e.g. consumer://10.20.153.10/org.apache.dubbo.foo.BarService?version=1.0.0&application=kylin - * @param listener A listener of the change event, not allowed to be empty - */ - void unsubscribe(URL url, NotifyListener listener); - - /** - * Query the registered data that matches the conditions. Corresponding to the push mode of the subscription, this is the pull mode and returns only one result. - * - * @param url Query condition, is not allowed to be empty, e.g. consumer://10.20.153.10/org.apache.dubbo.foo.BarService?version=1.0.0&application=kylin - * @return The registered information list, which may be empty, the meaning is the same as the parameters of {@link org.apache.dubbo.registry.NotifyListener#notify(List)}. - * @see org.apache.dubbo.registry.NotifyListener#notify(List) - */ - List lookup(URL url); - -} \ No newline at end of file +/* + * 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.registry; + +import org.apache.dubbo.common.URL; + +import java.util.List; + +/** + * RegistryService. (SPI, Prototype, ThreadSafe) + * + * @see org.apache.dubbo.registry.Registry + * @see org.apache.dubbo.registry.RegistryFactory#getRegistry(URL) + */ +public interface RegistryService { + + /** + * Register data, such as : provider service, consumer address, route rule, override rule and other data. + *

+ * Registering is required to support the contract:
+ * 1. When the URL sets the check=false parameter. When the registration fails, the exception is not thrown and retried in the background. Otherwise, the exception will be thrown.
+ * 2. When URL sets the dynamic=false parameter, it needs to be stored persistently, otherwise, it should be deleted automatically when the registrant has an abnormal exit.
+ * 3. When the URL sets category=routers, it means classified storage, the default category is providers, and the data can be notified by the classified section.
+ * 4. When the registry is restarted, network jitter, data can not be lost, including automatically deleting data from the broken line.
+ * 5. Allow URLs which have the same URL but different parameters to coexist,they can't cover each other.
+ * + * @param url Registration information , is not allowed to be empty, e.g: dubbo://10.20.153.10/org.apache.dubbo.foo.BarService?version=1.0.0&application=kylin + */ + void register(URL url); + + /** + * Unregister + *

+ * Unregistering is required to support the contract:
+ * 1. If it is the persistent stored data of dynamic=false, the registration data can not be found, then the IllegalStateException is thrown, otherwise it is ignored.
+ * 2. Unregister according to the full url match.
+ * + * @param url Registration information , is not allowed to be empty, e.g: dubbo://10.20.153.10/org.apache.dubbo.foo.BarService?version=1.0.0&application=kylin + */ + void unregister(URL url); + + /** + * Subscribe to eligible registered data and automatically push when the registered data is changed. + *

+ * Subscribing need to support contracts:
+ * 1. When the URL sets the check=false parameter. When the registration fails, the exception is not thrown and retried in the background.
+ * 2. When URL sets category=routers, it only notifies the specified classification data. Multiple classifications are separated by commas, and allows asterisk to match, which indicates that all categorical data are subscribed.
+ * 3. Allow interface, group, version, and classifier as a conditional query, e.g.: interface=org.apache.dubbo.foo.BarService&version=1.0.0
+ * 4. And the query conditions allow the asterisk to be matched, subscribe to all versions of all the packets of all interfaces, e.g. :interface=*&group=*&version=*&classifier=*
+ * 5. When the registry is restarted and network jitter, it is necessary to automatically restore the subscription request.
+ * 6. Allow URLs which have the same URL but different parameters to coexist,they can't cover each other.
+ * 7. The subscription process must be blocked, when the first notice is finished and then returned.
+ * + * @param url Subscription condition, not allowed to be empty, e.g. consumer://10.20.153.10/org.apache.dubbo.foo.BarService?version=1.0.0&application=kylin + * @param listener A listener of the change event, not allowed to be empty + */ + void subscribe(URL url, NotifyListener listener); + + /** + * Unsubscribe + *

+ * Unsubscribing is required to support the contract:
+ * 1. If don't subscribe, ignore it directly.
+ * 2. Unsubscribe by full URL match.
+ * + * @param url Subscription condition, not allowed to be empty, e.g. consumer://10.20.153.10/org.apache.dubbo.foo.BarService?version=1.0.0&application=kylin + * @param listener A listener of the change event, not allowed to be empty + */ + void unsubscribe(URL url, NotifyListener listener); + + /** + * Query the registered data that matches the conditions. Corresponding to the push mode of the subscription, this is the pull mode and returns only one result. + * + * @param url Query condition, is not allowed to be empty, e.g. consumer://10.20.153.10/org.apache.dubbo.foo.BarService?version=1.0.0&application=kylin + * @return The registered information list, which may be empty, the meaning is the same as the parameters of {@link org.apache.dubbo.registry.NotifyListener#notify(List)}. + * @see org.apache.dubbo.registry.NotifyListener#notify(List) + */ + List lookup(URL url); + +} diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java index c9a6ad4ed2..771e66148a 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java @@ -518,4 +518,4 @@ public class ServiceDiscoveryRegistry implements Registry { } } } -} \ No newline at end of file +} diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceInstancesChangedEvent.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceInstancesChangedEvent.java index 2053bf44ea..2b6b2e375a 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceInstancesChangedEvent.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceInstancesChangedEvent.java @@ -66,4 +66,4 @@ public class ServiceInstancesChangedEvent { return serviceInstances; } -} \ No newline at end of file +} diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/MigrationClusterInvoker.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/MigrationClusterInvoker.java index 2de95c5ba2..4d1958fd88 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/MigrationClusterInvoker.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/MigrationClusterInvoker.java @@ -45,4 +45,4 @@ public interface MigrationClusterInvoker extends ClusterInvoker { void migrateToApplicationFirstInvoker(MigrationRule newRule); void reRefer(URL newSubscribeUrl); -} \ No newline at end of file +} diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/ServiceDiscoveryMigrationInvoker.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/ServiceDiscoveryMigrationInvoker.java index 38a0501738..9ebbc3d326 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/ServiceDiscoveryMigrationInvoker.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/ServiceDiscoveryMigrationInvoker.java @@ -54,4 +54,4 @@ public class ServiceDiscoveryMigrationInvoker extends MigrationInvoker { } return invoker.invoke(invocation); } -} \ No newline at end of file +} diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/package-info.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/package-info.java index 6cb6b54ff8..b4579c6973 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/package-info.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/package-info.java @@ -20,4 +20,4 @@ * * @since 2.7.5 */ -package org.apache.dubbo.registry.client; \ No newline at end of file +package org.apache.dubbo.registry.client; diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java index 000ce9c66f..911ab181dd 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java @@ -1,653 +1,653 @@ -/* - * 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.registry.integration; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.URLBuilder; -import org.apache.dubbo.common.Version; -import org.apache.dubbo.common.config.configcenter.DynamicConfiguration; -import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.url.component.DubboServiceAddressURL; -import org.apache.dubbo.common.url.component.ServiceAddressURL; -import org.apache.dubbo.common.url.component.ServiceConfigURL; -import org.apache.dubbo.common.utils.Assert; -import org.apache.dubbo.common.utils.CollectionUtils; -import org.apache.dubbo.common.utils.NetUtils; -import org.apache.dubbo.common.utils.StringUtils; -import org.apache.dubbo.common.utils.UrlUtils; -import org.apache.dubbo.registry.AddressListener; -import org.apache.dubbo.remoting.Constants; -import org.apache.dubbo.rpc.Invocation; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.Protocol; -import org.apache.dubbo.rpc.RpcException; -import org.apache.dubbo.rpc.cluster.Configurator; -import org.apache.dubbo.rpc.cluster.Router; -import org.apache.dubbo.rpc.cluster.directory.StaticDirectory; -import org.apache.dubbo.rpc.cluster.support.ClusterUtils; -import org.apache.dubbo.rpc.model.ApplicationModel; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; - -import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.DISABLED_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_PROTOCOL; -import static org.apache.dubbo.common.constants.CommonConstants.ENABLED_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.TAG_KEY; -import static org.apache.dubbo.common.constants.RegistryConstants.APP_DYNAMIC_CONFIGURATORS_CATEGORY; -import static org.apache.dubbo.common.constants.RegistryConstants.CATEGORY_KEY; -import static org.apache.dubbo.common.constants.RegistryConstants.COMPATIBLE_CONFIG_KEY; -import static org.apache.dubbo.common.constants.RegistryConstants.CONFIGURATORS_CATEGORY; -import static org.apache.dubbo.common.constants.RegistryConstants.CONSUMERS_CATEGORY; -import static org.apache.dubbo.common.constants.RegistryConstants.DEFAULT_CATEGORY; -import static org.apache.dubbo.common.constants.RegistryConstants.DYNAMIC_CONFIGURATORS_CATEGORY; -import static org.apache.dubbo.common.constants.RegistryConstants.EMPTY_PROTOCOL; -import static org.apache.dubbo.common.constants.RegistryConstants.PROVIDERS_CATEGORY; -import static org.apache.dubbo.common.constants.RegistryConstants.ROUTERS_CATEGORY; -import static org.apache.dubbo.common.constants.RegistryConstants.ROUTE_PROTOCOL; -import static org.apache.dubbo.registry.Constants.CONFIGURATORS_SUFFIX; -import static org.apache.dubbo.registry.integration.InterfaceCompatibleRegistryProtocol.DEFAULT_REGISTER_CONSUMER_KEYS; -import static org.apache.dubbo.remoting.Constants.CHECK_KEY; -import static org.apache.dubbo.rpc.Constants.MOCK_KEY; -import static org.apache.dubbo.rpc.cluster.Constants.ROUTER_KEY; - - -/** - * RegistryDirectory - */ -public class RegistryDirectory extends DynamicDirectory { - private static final Logger logger = LoggerFactory.getLogger(RegistryDirectory.class); - - private static final ConsumerConfigurationListener CONSUMER_CONFIGURATION_LISTENER = new ConsumerConfigurationListener(); - private ReferenceConfigurationListener referenceConfigurationListener; - - // Map cache service url to invoker mapping. - // The initial value is null and the midway may be assigned to null, please use the local variable reference - protected volatile Map> urlInvokerMap; - // The initial value is null and the midway may be assigned to null, please use the local variable reference - protected volatile Set cachedInvokerUrls; - - public RegistryDirectory(Class serviceType, URL url) { - super(serviceType, url); - } - - @Override - public void subscribe(URL url) { - setConsumerUrl(url); - CONSUMER_CONFIGURATION_LISTENER.addNotifyListener(this); - referenceConfigurationListener = new ReferenceConfigurationListener(this, url); - registry.subscribe(url, this); - } - - @Override - public void unSubscribe(URL url) { - setConsumerUrl(null); - CONSUMER_CONFIGURATION_LISTENER.removeNotifyListener(this); - referenceConfigurationListener.stop(); - registry.unsubscribe(url, this); - } - - @Override - public synchronized void notify(List urls) { - if (isDestroyed()) { - return; - } - - Map> categoryUrls = urls.stream() - .filter(Objects::nonNull) - .filter(this::isValidCategory) - .filter(this::isNotCompatibleFor26x) - .collect(Collectors.groupingBy(this::judgeCategory)); - - List configuratorURLs = categoryUrls.getOrDefault(CONFIGURATORS_CATEGORY, Collections.emptyList()); - this.configurators = Configurator.toConfigurators(configuratorURLs).orElse(this.configurators); - - List routerURLs = categoryUrls.getOrDefault(ROUTERS_CATEGORY, Collections.emptyList()); - toRouters(routerURLs).ifPresent(this::addRouters); - - // providers - List providerURLs = categoryUrls.getOrDefault(PROVIDERS_CATEGORY, Collections.emptyList()); - /** - * 3.x added for extend URL address - */ - ExtensionLoader addressListenerExtensionLoader = ExtensionLoader.getExtensionLoader(AddressListener.class); - List supportedListeners = addressListenerExtensionLoader.getActivateExtension(getUrl(), (String[]) null); - if (supportedListeners != null && !supportedListeners.isEmpty()) { - for (AddressListener addressListener : supportedListeners) { - providerURLs = addressListener.notify(providerURLs, getConsumerUrl(),this); - } - } - refreshOverrideAndInvoker(providerURLs); - } - - @Override - public boolean isServiceDiscovery() { - return false; - } - - private String judgeCategory(URL url) { - if (UrlUtils.isConfigurator(url)) { - return CONFIGURATORS_CATEGORY; - } else if (UrlUtils.isRoute(url)) { - return ROUTERS_CATEGORY; - } else if (UrlUtils.isProvider(url)) { - return PROVIDERS_CATEGORY; - } - return ""; - } - - // RefreshOverrideAndInvoker will be executed by registryCenter and configCenter, so it should be synchronized. - private synchronized void refreshOverrideAndInvoker(List urls) { - // mock zookeeper://xxx?mock=return null - overrideDirectoryUrl(); - refreshInvoker(urls); - } - - /** - * Convert the invokerURL list to the Invoker Map. The rules of the conversion are as follows: - *

    - *
  1. If URL has been converted to invoker, it is no longer re-referenced and obtained directly from the cache, - * and notice that any parameter changes in the URL will be re-referenced.
  2. - *
  3. If the incoming invoker list is not empty, it means that it is the latest invoker list.
  4. - *
  5. If the list of incoming invokerUrl is empty, It means that the rule is only a override rule or a route - * rule, which needs to be re-contrasted to decide whether to re-reference.
  6. - *
- * - * @param invokerUrls this parameter can't be null - */ - private void refreshInvoker(List invokerUrls) { - Assert.notNull(invokerUrls, "invokerUrls should not be null"); - - if (invokerUrls.size() == 1 - && invokerUrls.get(0) != null - && EMPTY_PROTOCOL.equals(invokerUrls.get(0).getProtocol())) { - this.forbidden = true; // Forbid to access - this.invokers = Collections.emptyList(); - routerChain.setInvokers(this.invokers); - destroyAllInvokers(); // Close all invokers - } else { - this.forbidden = false; // Allow to access - Map> oldUrlInvokerMap = this.urlInvokerMap; // local reference - if (invokerUrls == Collections.emptyList()) { - invokerUrls = new ArrayList<>(); - } - if (invokerUrls.isEmpty() && this.cachedInvokerUrls != null) { - invokerUrls.addAll(this.cachedInvokerUrls); - } else { - this.cachedInvokerUrls = new HashSet<>(); - this.cachedInvokerUrls.addAll(invokerUrls);//Cached invoker urls, convenient for comparison - } - if (invokerUrls.isEmpty()) { - return; - } - Map> newUrlInvokerMap = toInvokers(invokerUrls);// Translate url list to Invoker map - - /** - * If the calculation is wrong, it is not processed. - * - * 1. The protocol configured by the client is inconsistent with the protocol of the server. - * eg: consumer protocol = dubbo, provider only has other protocol services(rest). - * 2. The registration center is not robust and pushes illegal specification data. - * - */ - if (CollectionUtils.isEmptyMap(newUrlInvokerMap)) { - logger.error(new IllegalStateException("urls to invokers error .invokerUrls.size :" + invokerUrls.size() + ", invoker.size :0. urls :" + invokerUrls - .toString())); - return; - } - - List> newInvokers = Collections.unmodifiableList(new ArrayList<>(newUrlInvokerMap.values())); - // pre-route and build cache, notice that route cache should build on original Invoker list. - // toMergeMethodInvokerMap() will wrap some invokers having different groups, those wrapped invokers not should be routed. - routerChain.setInvokers(newInvokers); - this.invokers = multiGroup ? toMergeInvokerList(newInvokers) : newInvokers; - this.urlInvokerMap = newUrlInvokerMap; - - try { - destroyUnusedInvokers(oldUrlInvokerMap, newUrlInvokerMap); // Close the unused Invoker - } catch (Exception e) { - logger.warn("destroyUnusedInvokers error. ", e); - } - - // notify invokers refreshed - this.invokersChanged(); - } - } - - private List> toMergeInvokerList(List> invokers) { - List> mergedInvokers = new ArrayList<>(); - Map>> groupMap = new HashMap<>(); - for (Invoker invoker : invokers) { - String group = invoker.getUrl().getGroup(""); - groupMap.computeIfAbsent(group, k -> new ArrayList<>()); - groupMap.get(group).add(invoker); - } - - if (groupMap.size() == 1) { - mergedInvokers.addAll(groupMap.values().iterator().next()); - } else if (groupMap.size() > 1) { - for (List> groupList : groupMap.values()) { - StaticDirectory staticDirectory = new StaticDirectory<>(groupList); - staticDirectory.buildRouterChain(); - mergedInvokers.add(CLUSTER.join(staticDirectory)); - } - } else { - mergedInvokers = invokers; - } - return mergedInvokers; - } - - /** - * @param urls - * @return null : no routers ,do nothing - * else :routers list - */ - private Optional> toRouters(List urls) { - if (urls == null || urls.isEmpty()) { - return Optional.empty(); - } - - List routers = new ArrayList<>(); - for (URL url : urls) { - if (EMPTY_PROTOCOL.equals(url.getProtocol())) { - continue; - } - String routerType = url.getParameter(ROUTER_KEY); - if (routerType != null && routerType.length() > 0) { - url = url.setProtocol(routerType); - } - try { - Router router = ROUTER_FACTORY.getRouter(url); - if (!routers.contains(router)) { - routers.add(router); - } - } catch (Throwable t) { - logger.error("convert router url to router error, url: " + url, t); - } - } - - return Optional.of(routers); - } - - /** - * Turn urls into invokers, and if url has been refer, will not re-reference. - * - * @param urls - * @return invokers - */ - private Map> toInvokers(List urls) { - Map> newUrlInvokerMap = new ConcurrentHashMap<>(); - if (urls == null || urls.isEmpty()) { - return newUrlInvokerMap; - } - String queryProtocols = this.queryMap.get(PROTOCOL_KEY); - for (URL providerUrl : urls) { - // If protocol is configured at the reference side, only the matching protocol is selected - if (queryProtocols != null && queryProtocols.length() > 0) { - boolean accept = false; - String[] acceptProtocols = queryProtocols.split(","); - for (String acceptProtocol : acceptProtocols) { - if (providerUrl.getProtocol().equals(acceptProtocol)) { - accept = true; - break; - } - } - if (!accept) { - continue; - } - } - if (EMPTY_PROTOCOL.equals(providerUrl.getProtocol())) { - continue; - } - if (!ExtensionLoader.getExtensionLoader(Protocol.class).hasExtension(providerUrl.getProtocol())) { - logger.error(new IllegalStateException("Unsupported protocol " + providerUrl.getProtocol() + - " in notified url: " + providerUrl + " from registry " + getUrl().getAddress() + - " to consumer " + NetUtils.getLocalHost() + ", supported protocol: " + - ExtensionLoader.getExtensionLoader(Protocol.class).getSupportedExtensions())); - continue; - } - URL url = mergeUrl(providerUrl); - - // Cache key is url that does not merge with consumer side parameters, regardless of how the consumer combines parameters, if the server url changes, then refer again - Map> localUrlInvokerMap = this.urlInvokerMap; // local reference - Invoker invoker = localUrlInvokerMap == null ? null : localUrlInvokerMap.remove(url); - if (invoker == null) { // Not in the cache, refer again - try { - boolean enabled = true; - if (url.hasParameter(DISABLED_KEY)) { - enabled = !url.getParameter(DISABLED_KEY, false); - } else { - enabled = url.getParameter(ENABLED_KEY, true); - } - if (enabled) { - invoker = protocol.refer(serviceType, url); - } - } catch (Throwable t) { - logger.error("Failed to refer invoker for interface:" + serviceType + ",url:(" + url + ")" + t.getMessage(), t); - } - if (invoker != null) { // Put new invoker in cache - newUrlInvokerMap.put(url, invoker); - } - } else { - newUrlInvokerMap.put(url, invoker); - } - } - return newUrlInvokerMap; - } - - /** - * Merge url parameters. the order is: override > -D >Consumer > Provider - * - * @param providerUrl - * @return - */ - private URL mergeUrl(URL providerUrl) { - if (providerUrl instanceof ServiceAddressURL) { - providerUrl = overrideWithConfigurator(providerUrl); - } else { - providerUrl = ClusterUtils.mergeUrl(providerUrl, queryMap); // Merge the consumer side parameters - providerUrl = overrideWithConfigurator(providerUrl); - providerUrl = providerUrl.addParameter(Constants.CHECK_KEY, String.valueOf(false)); // Do not check whether the connection is successful or not, always create Invoker! - } - - // FIXME, kept for mock - if (providerUrl.hasParameter(MOCK_KEY) || providerUrl.getAnyMethodParameter(MOCK_KEY) != null) { - providerUrl = providerUrl.removeParameter(TAG_KEY); - this.overrideDirectoryUrl = this.overrideDirectoryUrl.addParametersIfAbsent(providerUrl.getParameters()); - } - - if ((providerUrl.getPath() == null || providerUrl.getPath() - .length() == 0) && DUBBO_PROTOCOL.equals(providerUrl.getProtocol())) { // Compatible version 1.0 - //fix by tony.chenl DUBBO-44 - String path = directoryUrl.getServiceInterface(); - if (path != null) { - int i = path.indexOf('/'); - if (i >= 0) { - path = path.substring(i + 1); - } - i = path.lastIndexOf(':'); - if (i >= 0) { - path = path.substring(0, i); - } - providerUrl = providerUrl.setPath(path); - } - } - return providerUrl; - } - - private URL overrideWithConfigurator(URL providerUrl) { - // override url with configurator from "override://" URL for dubbo 2.6 and before - providerUrl = overrideWithConfigurators(this.configurators, providerUrl); - - // override url with configurator from configurator from "app-name.configurators" - providerUrl = overrideWithConfigurators(CONSUMER_CONFIGURATION_LISTENER.getConfigurators(), providerUrl); - - // override url with configurator from configurators from "service-name.configurators" - if (referenceConfigurationListener != null) { - providerUrl = overrideWithConfigurators(referenceConfigurationListener.getConfigurators(), providerUrl); - } - - return providerUrl; - } - - private URL overrideWithConfigurators(List configurators, URL url) { - if (CollectionUtils.isNotEmpty(configurators)) { - if (url instanceof DubboServiceAddressURL) { - DubboServiceAddressURL interfaceAddressURL = (DubboServiceAddressURL) url; - URL overriddenURL = interfaceAddressURL.getOverrideURL(); - if (overriddenURL == null) { - String appName = interfaceAddressURL.getApplication(); - String side = interfaceAddressURL.getSide(); - overriddenURL = URLBuilder.from(interfaceAddressURL) - .clearParameters() - .addParameter(APPLICATION_KEY, appName) - .addParameter(SIDE_KEY, side).build(); - } - for (Configurator configurator : configurators) { - overriddenURL = configurator.configure(overriddenURL); - } - url = new DubboServiceAddressURL( - interfaceAddressURL.getUrlAddress(), - interfaceAddressURL.getUrlParam(), - interfaceAddressURL.getConsumerURL(), - (ServiceConfigURL) overriddenURL); - } else { - for (Configurator configurator : configurators) { - url = configurator.configure(url); - } - } - } - return url; - } - - /** - * Close all invokers - */ - @Override - protected void destroyAllInvokers() { - Map> localUrlInvokerMap = this.urlInvokerMap; // local reference - if (localUrlInvokerMap != null) { - for (Invoker invoker : new ArrayList<>(localUrlInvokerMap.values())) { - try { - invoker.destroy(); - } catch (Throwable t) { - logger.warn("Failed to destroy service " + serviceKey + " to provider " + invoker.getUrl(), t); - } - } - localUrlInvokerMap.clear(); - } - invokers = null; - cachedInvokerUrls = null; - } - - private void destroyUnusedInvokers(Map> oldUrlInvokerMap, Map> newUrlInvokerMap) { - if (newUrlInvokerMap == null || newUrlInvokerMap.size() == 0) { - destroyAllInvokers(); - return; - } - - if (oldUrlInvokerMap == null || oldUrlInvokerMap.size() == 0) { - return; - } - - for (Map.Entry> entry : oldUrlInvokerMap.entrySet()) { - Invoker invoker = entry.getValue(); - if (invoker != null) { - try { - invoker.destroy(); - if (logger.isDebugEnabled()) { - logger.debug("destroy invoker[" + invoker.getUrl() + "] success. "); - } - } catch (Exception e) { - logger.warn("destroy invoker[" + invoker.getUrl() + "] failed. " + e.getMessage(), e); - } - } - } - - logger.info("New url total size, " + newUrlInvokerMap.size() + ", destroyed total size " + oldUrlInvokerMap.size()); - } - - @Override - public List> doList(Invocation invocation) { - if (forbidden) { - // 1. No service provider 2. Service providers are disabled - throw new RpcException(RpcException.FORBIDDEN_EXCEPTION, "No provider available from registry " + - getUrl().getAddress() + " for service " + getConsumerUrl().getServiceKey() + " on consumer " + - NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() + - ", please check status of providers(disabled, not registered or in blacklist)."); - } - - if (multiGroup) { - return this.invokers == null ? Collections.emptyList() : this.invokers; - } - - List> invokers = null; - try { - // Get invokers from cache, only runtime routers will be executed. - invokers = routerChain.route(getConsumerUrl(), invocation); - } catch (Throwable t) { - logger.error("Failed to execute router: " + getUrl() + ", cause: " + t.getMessage(), t); - } - - return invokers == null ? Collections.emptyList() : invokers; - } - - @Override - public Class getInterface() { - return serviceType; - } - - @Override - public List> getAllInvokers() { - return invokers; - } - - @Override - public URL getConsumerUrl() { - return this.overrideDirectoryUrl; - } - - public URL getRegisteredConsumerUrl() { - return registeredConsumerUrl; - } - - public void setRegisteredConsumerUrl(URL url) { - if (!shouldSimplified) { - this.registeredConsumerUrl = url.addParameters(CATEGORY_KEY, CONSUMERS_CATEGORY, CHECK_KEY, - String.valueOf(false)); - } else { - this.registeredConsumerUrl = URL.valueOf(url, DEFAULT_REGISTER_CONSUMER_KEYS, null).addParameters( - CATEGORY_KEY, CONSUMERS_CATEGORY, CHECK_KEY, String.valueOf(false)); - } - } - - @Override - public boolean isAvailable() { - if (isDestroyed()) { - return false; - } - Map> localUrlInvokerMap = urlInvokerMap; - return CollectionUtils.isNotEmptyMap(localUrlInvokerMap) - && localUrlInvokerMap.values().stream().anyMatch(Invoker::isAvailable); - } - - /** - * Haomin: added for test purpose - */ - public Map> getUrlInvokerMap() { - return urlInvokerMap; - } - - public List> getInvokers() { - return invokers; - } - - private boolean isValidCategory(URL url) { - String category = url.getCategory(DEFAULT_CATEGORY); - if ((ROUTERS_CATEGORY.equals(category) || ROUTE_PROTOCOL.equals(url.getProtocol())) || - PROVIDERS_CATEGORY.equals(category) || - CONFIGURATORS_CATEGORY.equals(category) || DYNAMIC_CONFIGURATORS_CATEGORY.equals(category) || - APP_DYNAMIC_CONFIGURATORS_CATEGORY.equals(category)) { - return true; - } - logger.warn("Unsupported category " + category + " in notified url: " + url + " from registry " + - getUrl().getAddress() + " to consumer " + NetUtils.getLocalHost()); - return false; - } - - private boolean isNotCompatibleFor26x(URL url) { - return StringUtils.isEmpty(url.getParameter(COMPATIBLE_CONFIG_KEY)); - } - - private void overrideDirectoryUrl() { - // merge override parameters - this.overrideDirectoryUrl = directoryUrl; - List localConfigurators = this.configurators; // local reference - doOverrideUrl(localConfigurators); - List localAppDynamicConfigurators = CONSUMER_CONFIGURATION_LISTENER.getConfigurators(); // local reference - doOverrideUrl(localAppDynamicConfigurators); - if (referenceConfigurationListener != null) { - List localDynamicConfigurators = referenceConfigurationListener.getConfigurators(); // local reference - doOverrideUrl(localDynamicConfigurators); - } - } - - private void doOverrideUrl(List configurators) { - if (CollectionUtils.isNotEmpty(configurators)) { - for (Configurator configurator : configurators) { - this.overrideDirectoryUrl = configurator.configure(overrideDirectoryUrl); - } - } - } - - private static class ReferenceConfigurationListener extends AbstractConfiguratorListener { - private RegistryDirectory directory; - private URL url; - - ReferenceConfigurationListener(RegistryDirectory directory, URL url) { - this.directory = directory; - this.url = url; - this.initWith(DynamicConfiguration.getRuleKey(url) + CONFIGURATORS_SUFFIX); - } - - void stop() { - this.stopListen(DynamicConfiguration.getRuleKey(url) + CONFIGURATORS_SUFFIX); - } - - @Override - protected void notifyOverrides() { - // to notify configurator/router changes - directory.refreshOverrideAndInvoker(Collections.emptyList()); - } - } - - private static class ConsumerConfigurationListener extends AbstractConfiguratorListener { - List listeners = new ArrayList<>(); - - ConsumerConfigurationListener() { - this.initWith(ApplicationModel.getApplication() + CONFIGURATORS_SUFFIX); - } - - void addNotifyListener(RegistryDirectory listener) { - this.listeners.add(listener); - } - - void removeNotifyListener(RegistryDirectory listener) { - this.listeners.remove(listener); - } - - @Override - protected void notifyOverrides() { - listeners.forEach(listener -> listener.refreshOverrideAndInvoker(Collections.emptyList())); - } - } - -} +/* + * 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.registry.integration; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.URLBuilder; +import org.apache.dubbo.common.Version; +import org.apache.dubbo.common.config.configcenter.DynamicConfiguration; +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.url.component.DubboServiceAddressURL; +import org.apache.dubbo.common.url.component.ServiceAddressURL; +import org.apache.dubbo.common.url.component.ServiceConfigURL; +import org.apache.dubbo.common.utils.Assert; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.common.utils.NetUtils; +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.common.utils.UrlUtils; +import org.apache.dubbo.registry.AddressListener; +import org.apache.dubbo.remoting.Constants; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.Protocol; +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.cluster.Configurator; +import org.apache.dubbo.rpc.cluster.Router; +import org.apache.dubbo.rpc.cluster.directory.StaticDirectory; +import org.apache.dubbo.rpc.cluster.support.ClusterUtils; +import org.apache.dubbo.rpc.model.ApplicationModel; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.DISABLED_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_PROTOCOL; +import static org.apache.dubbo.common.constants.CommonConstants.ENABLED_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.TAG_KEY; +import static org.apache.dubbo.common.constants.RegistryConstants.APP_DYNAMIC_CONFIGURATORS_CATEGORY; +import static org.apache.dubbo.common.constants.RegistryConstants.CATEGORY_KEY; +import static org.apache.dubbo.common.constants.RegistryConstants.COMPATIBLE_CONFIG_KEY; +import static org.apache.dubbo.common.constants.RegistryConstants.CONFIGURATORS_CATEGORY; +import static org.apache.dubbo.common.constants.RegistryConstants.CONSUMERS_CATEGORY; +import static org.apache.dubbo.common.constants.RegistryConstants.DEFAULT_CATEGORY; +import static org.apache.dubbo.common.constants.RegistryConstants.DYNAMIC_CONFIGURATORS_CATEGORY; +import static org.apache.dubbo.common.constants.RegistryConstants.EMPTY_PROTOCOL; +import static org.apache.dubbo.common.constants.RegistryConstants.PROVIDERS_CATEGORY; +import static org.apache.dubbo.common.constants.RegistryConstants.ROUTERS_CATEGORY; +import static org.apache.dubbo.common.constants.RegistryConstants.ROUTE_PROTOCOL; +import static org.apache.dubbo.registry.Constants.CONFIGURATORS_SUFFIX; +import static org.apache.dubbo.registry.integration.InterfaceCompatibleRegistryProtocol.DEFAULT_REGISTER_CONSUMER_KEYS; +import static org.apache.dubbo.remoting.Constants.CHECK_KEY; +import static org.apache.dubbo.rpc.Constants.MOCK_KEY; +import static org.apache.dubbo.rpc.cluster.Constants.ROUTER_KEY; + + +/** + * RegistryDirectory + */ +public class RegistryDirectory extends DynamicDirectory { + private static final Logger logger = LoggerFactory.getLogger(RegistryDirectory.class); + + private static final ConsumerConfigurationListener CONSUMER_CONFIGURATION_LISTENER = new ConsumerConfigurationListener(); + private ReferenceConfigurationListener referenceConfigurationListener; + + // Map cache service url to invoker mapping. + // The initial value is null and the midway may be assigned to null, please use the local variable reference + protected volatile Map> urlInvokerMap; + // The initial value is null and the midway may be assigned to null, please use the local variable reference + protected volatile Set cachedInvokerUrls; + + public RegistryDirectory(Class serviceType, URL url) { + super(serviceType, url); + } + + @Override + public void subscribe(URL url) { + setConsumerUrl(url); + CONSUMER_CONFIGURATION_LISTENER.addNotifyListener(this); + referenceConfigurationListener = new ReferenceConfigurationListener(this, url); + registry.subscribe(url, this); + } + + @Override + public void unSubscribe(URL url) { + setConsumerUrl(null); + CONSUMER_CONFIGURATION_LISTENER.removeNotifyListener(this); + referenceConfigurationListener.stop(); + registry.unsubscribe(url, this); + } + + @Override + public synchronized void notify(List urls) { + if (isDestroyed()) { + return; + } + + Map> categoryUrls = urls.stream() + .filter(Objects::nonNull) + .filter(this::isValidCategory) + .filter(this::isNotCompatibleFor26x) + .collect(Collectors.groupingBy(this::judgeCategory)); + + List configuratorURLs = categoryUrls.getOrDefault(CONFIGURATORS_CATEGORY, Collections.emptyList()); + this.configurators = Configurator.toConfigurators(configuratorURLs).orElse(this.configurators); + + List routerURLs = categoryUrls.getOrDefault(ROUTERS_CATEGORY, Collections.emptyList()); + toRouters(routerURLs).ifPresent(this::addRouters); + + // providers + List providerURLs = categoryUrls.getOrDefault(PROVIDERS_CATEGORY, Collections.emptyList()); + /** + * 3.x added for extend URL address + */ + ExtensionLoader addressListenerExtensionLoader = ExtensionLoader.getExtensionLoader(AddressListener.class); + List supportedListeners = addressListenerExtensionLoader.getActivateExtension(getUrl(), (String[]) null); + if (supportedListeners != null && !supportedListeners.isEmpty()) { + for (AddressListener addressListener : supportedListeners) { + providerURLs = addressListener.notify(providerURLs, getConsumerUrl(),this); + } + } + refreshOverrideAndInvoker(providerURLs); + } + + @Override + public boolean isServiceDiscovery() { + return false; + } + + private String judgeCategory(URL url) { + if (UrlUtils.isConfigurator(url)) { + return CONFIGURATORS_CATEGORY; + } else if (UrlUtils.isRoute(url)) { + return ROUTERS_CATEGORY; + } else if (UrlUtils.isProvider(url)) { + return PROVIDERS_CATEGORY; + } + return ""; + } + + // RefreshOverrideAndInvoker will be executed by registryCenter and configCenter, so it should be synchronized. + private synchronized void refreshOverrideAndInvoker(List urls) { + // mock zookeeper://xxx?mock=return null + overrideDirectoryUrl(); + refreshInvoker(urls); + } + + /** + * Convert the invokerURL list to the Invoker Map. The rules of the conversion are as follows: + *
    + *
  1. If URL has been converted to invoker, it is no longer re-referenced and obtained directly from the cache, + * and notice that any parameter changes in the URL will be re-referenced.
  2. + *
  3. If the incoming invoker list is not empty, it means that it is the latest invoker list.
  4. + *
  5. If the list of incoming invokerUrl is empty, It means that the rule is only a override rule or a route + * rule, which needs to be re-contrasted to decide whether to re-reference.
  6. + *
+ * + * @param invokerUrls this parameter can't be null + */ + private void refreshInvoker(List invokerUrls) { + Assert.notNull(invokerUrls, "invokerUrls should not be null"); + + if (invokerUrls.size() == 1 + && invokerUrls.get(0) != null + && EMPTY_PROTOCOL.equals(invokerUrls.get(0).getProtocol())) { + this.forbidden = true; // Forbid to access + this.invokers = Collections.emptyList(); + routerChain.setInvokers(this.invokers); + destroyAllInvokers(); // Close all invokers + } else { + this.forbidden = false; // Allow to access + Map> oldUrlInvokerMap = this.urlInvokerMap; // local reference + if (invokerUrls == Collections.emptyList()) { + invokerUrls = new ArrayList<>(); + } + if (invokerUrls.isEmpty() && this.cachedInvokerUrls != null) { + invokerUrls.addAll(this.cachedInvokerUrls); + } else { + this.cachedInvokerUrls = new HashSet<>(); + this.cachedInvokerUrls.addAll(invokerUrls);//Cached invoker urls, convenient for comparison + } + if (invokerUrls.isEmpty()) { + return; + } + Map> newUrlInvokerMap = toInvokers(invokerUrls);// Translate url list to Invoker map + + /** + * If the calculation is wrong, it is not processed. + * + * 1. The protocol configured by the client is inconsistent with the protocol of the server. + * eg: consumer protocol = dubbo, provider only has other protocol services(rest). + * 2. The registration center is not robust and pushes illegal specification data. + * + */ + if (CollectionUtils.isEmptyMap(newUrlInvokerMap)) { + logger.error(new IllegalStateException("urls to invokers error .invokerUrls.size :" + invokerUrls.size() + ", invoker.size :0. urls :" + invokerUrls + .toString())); + return; + } + + List> newInvokers = Collections.unmodifiableList(new ArrayList<>(newUrlInvokerMap.values())); + // pre-route and build cache, notice that route cache should build on original Invoker list. + // toMergeMethodInvokerMap() will wrap some invokers having different groups, those wrapped invokers not should be routed. + routerChain.setInvokers(newInvokers); + this.invokers = multiGroup ? toMergeInvokerList(newInvokers) : newInvokers; + this.urlInvokerMap = newUrlInvokerMap; + + try { + destroyUnusedInvokers(oldUrlInvokerMap, newUrlInvokerMap); // Close the unused Invoker + } catch (Exception e) { + logger.warn("destroyUnusedInvokers error. ", e); + } + + // notify invokers refreshed + this.invokersChanged(); + } + } + + private List> toMergeInvokerList(List> invokers) { + List> mergedInvokers = new ArrayList<>(); + Map>> groupMap = new HashMap<>(); + for (Invoker invoker : invokers) { + String group = invoker.getUrl().getGroup(""); + groupMap.computeIfAbsent(group, k -> new ArrayList<>()); + groupMap.get(group).add(invoker); + } + + if (groupMap.size() == 1) { + mergedInvokers.addAll(groupMap.values().iterator().next()); + } else if (groupMap.size() > 1) { + for (List> groupList : groupMap.values()) { + StaticDirectory staticDirectory = new StaticDirectory<>(groupList); + staticDirectory.buildRouterChain(); + mergedInvokers.add(CLUSTER.join(staticDirectory)); + } + } else { + mergedInvokers = invokers; + } + return mergedInvokers; + } + + /** + * @param urls + * @return null : no routers ,do nothing + * else :routers list + */ + private Optional> toRouters(List urls) { + if (urls == null || urls.isEmpty()) { + return Optional.empty(); + } + + List routers = new ArrayList<>(); + for (URL url : urls) { + if (EMPTY_PROTOCOL.equals(url.getProtocol())) { + continue; + } + String routerType = url.getParameter(ROUTER_KEY); + if (routerType != null && routerType.length() > 0) { + url = url.setProtocol(routerType); + } + try { + Router router = ROUTER_FACTORY.getRouter(url); + if (!routers.contains(router)) { + routers.add(router); + } + } catch (Throwable t) { + logger.error("convert router url to router error, url: " + url, t); + } + } + + return Optional.of(routers); + } + + /** + * Turn urls into invokers, and if url has been refer, will not re-reference. + * + * @param urls + * @return invokers + */ + private Map> toInvokers(List urls) { + Map> newUrlInvokerMap = new ConcurrentHashMap<>(); + if (urls == null || urls.isEmpty()) { + return newUrlInvokerMap; + } + String queryProtocols = this.queryMap.get(PROTOCOL_KEY); + for (URL providerUrl : urls) { + // If protocol is configured at the reference side, only the matching protocol is selected + if (queryProtocols != null && queryProtocols.length() > 0) { + boolean accept = false; + String[] acceptProtocols = queryProtocols.split(","); + for (String acceptProtocol : acceptProtocols) { + if (providerUrl.getProtocol().equals(acceptProtocol)) { + accept = true; + break; + } + } + if (!accept) { + continue; + } + } + if (EMPTY_PROTOCOL.equals(providerUrl.getProtocol())) { + continue; + } + if (!ExtensionLoader.getExtensionLoader(Protocol.class).hasExtension(providerUrl.getProtocol())) { + logger.error(new IllegalStateException("Unsupported protocol " + providerUrl.getProtocol() + + " in notified url: " + providerUrl + " from registry " + getUrl().getAddress() + + " to consumer " + NetUtils.getLocalHost() + ", supported protocol: " + + ExtensionLoader.getExtensionLoader(Protocol.class).getSupportedExtensions())); + continue; + } + URL url = mergeUrl(providerUrl); + + // Cache key is url that does not merge with consumer side parameters, regardless of how the consumer combines parameters, if the server url changes, then refer again + Map> localUrlInvokerMap = this.urlInvokerMap; // local reference + Invoker invoker = localUrlInvokerMap == null ? null : localUrlInvokerMap.remove(url); + if (invoker == null) { // Not in the cache, refer again + try { + boolean enabled = true; + if (url.hasParameter(DISABLED_KEY)) { + enabled = !url.getParameter(DISABLED_KEY, false); + } else { + enabled = url.getParameter(ENABLED_KEY, true); + } + if (enabled) { + invoker = protocol.refer(serviceType, url); + } + } catch (Throwable t) { + logger.error("Failed to refer invoker for interface:" + serviceType + ",url:(" + url + ")" + t.getMessage(), t); + } + if (invoker != null) { // Put new invoker in cache + newUrlInvokerMap.put(url, invoker); + } + } else { + newUrlInvokerMap.put(url, invoker); + } + } + return newUrlInvokerMap; + } + + /** + * Merge url parameters. the order is: override > -D >Consumer > Provider + * + * @param providerUrl + * @return + */ + private URL mergeUrl(URL providerUrl) { + if (providerUrl instanceof ServiceAddressURL) { + providerUrl = overrideWithConfigurator(providerUrl); + } else { + providerUrl = ClusterUtils.mergeUrl(providerUrl, queryMap); // Merge the consumer side parameters + providerUrl = overrideWithConfigurator(providerUrl); + providerUrl = providerUrl.addParameter(Constants.CHECK_KEY, String.valueOf(false)); // Do not check whether the connection is successful or not, always create Invoker! + } + + // FIXME, kept for mock + if (providerUrl.hasParameter(MOCK_KEY) || providerUrl.getAnyMethodParameter(MOCK_KEY) != null) { + providerUrl = providerUrl.removeParameter(TAG_KEY); + this.overrideDirectoryUrl = this.overrideDirectoryUrl.addParametersIfAbsent(providerUrl.getParameters()); + } + + if ((providerUrl.getPath() == null || providerUrl.getPath() + .length() == 0) && DUBBO_PROTOCOL.equals(providerUrl.getProtocol())) { // Compatible version 1.0 + //fix by tony.chenl DUBBO-44 + String path = directoryUrl.getServiceInterface(); + if (path != null) { + int i = path.indexOf('/'); + if (i >= 0) { + path = path.substring(i + 1); + } + i = path.lastIndexOf(':'); + if (i >= 0) { + path = path.substring(0, i); + } + providerUrl = providerUrl.setPath(path); + } + } + return providerUrl; + } + + private URL overrideWithConfigurator(URL providerUrl) { + // override url with configurator from "override://" URL for dubbo 2.6 and before + providerUrl = overrideWithConfigurators(this.configurators, providerUrl); + + // override url with configurator from configurator from "app-name.configurators" + providerUrl = overrideWithConfigurators(CONSUMER_CONFIGURATION_LISTENER.getConfigurators(), providerUrl); + + // override url with configurator from configurators from "service-name.configurators" + if (referenceConfigurationListener != null) { + providerUrl = overrideWithConfigurators(referenceConfigurationListener.getConfigurators(), providerUrl); + } + + return providerUrl; + } + + private URL overrideWithConfigurators(List configurators, URL url) { + if (CollectionUtils.isNotEmpty(configurators)) { + if (url instanceof DubboServiceAddressURL) { + DubboServiceAddressURL interfaceAddressURL = (DubboServiceAddressURL) url; + URL overriddenURL = interfaceAddressURL.getOverrideURL(); + if (overriddenURL == null) { + String appName = interfaceAddressURL.getApplication(); + String side = interfaceAddressURL.getSide(); + overriddenURL = URLBuilder.from(interfaceAddressURL) + .clearParameters() + .addParameter(APPLICATION_KEY, appName) + .addParameter(SIDE_KEY, side).build(); + } + for (Configurator configurator : configurators) { + overriddenURL = configurator.configure(overriddenURL); + } + url = new DubboServiceAddressURL( + interfaceAddressURL.getUrlAddress(), + interfaceAddressURL.getUrlParam(), + interfaceAddressURL.getConsumerURL(), + (ServiceConfigURL) overriddenURL); + } else { + for (Configurator configurator : configurators) { + url = configurator.configure(url); + } + } + } + return url; + } + + /** + * Close all invokers + */ + @Override + protected void destroyAllInvokers() { + Map> localUrlInvokerMap = this.urlInvokerMap; // local reference + if (localUrlInvokerMap != null) { + for (Invoker invoker : new ArrayList<>(localUrlInvokerMap.values())) { + try { + invoker.destroy(); + } catch (Throwable t) { + logger.warn("Failed to destroy service " + serviceKey + " to provider " + invoker.getUrl(), t); + } + } + localUrlInvokerMap.clear(); + } + invokers = null; + cachedInvokerUrls = null; + } + + private void destroyUnusedInvokers(Map> oldUrlInvokerMap, Map> newUrlInvokerMap) { + if (newUrlInvokerMap == null || newUrlInvokerMap.size() == 0) { + destroyAllInvokers(); + return; + } + + if (oldUrlInvokerMap == null || oldUrlInvokerMap.size() == 0) { + return; + } + + for (Map.Entry> entry : oldUrlInvokerMap.entrySet()) { + Invoker invoker = entry.getValue(); + if (invoker != null) { + try { + invoker.destroy(); + if (logger.isDebugEnabled()) { + logger.debug("destroy invoker[" + invoker.getUrl() + "] success. "); + } + } catch (Exception e) { + logger.warn("destroy invoker[" + invoker.getUrl() + "] failed. " + e.getMessage(), e); + } + } + } + + logger.info("New url total size, " + newUrlInvokerMap.size() + ", destroyed total size " + oldUrlInvokerMap.size()); + } + + @Override + public List> doList(Invocation invocation) { + if (forbidden) { + // 1. No service provider 2. Service providers are disabled + throw new RpcException(RpcException.FORBIDDEN_EXCEPTION, "No provider available from registry " + + getUrl().getAddress() + " for service " + getConsumerUrl().getServiceKey() + " on consumer " + + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() + + ", please check status of providers(disabled, not registered or in blacklist)."); + } + + if (multiGroup) { + return this.invokers == null ? Collections.emptyList() : this.invokers; + } + + List> invokers = null; + try { + // Get invokers from cache, only runtime routers will be executed. + invokers = routerChain.route(getConsumerUrl(), invocation); + } catch (Throwable t) { + logger.error("Failed to execute router: " + getUrl() + ", cause: " + t.getMessage(), t); + } + + return invokers == null ? Collections.emptyList() : invokers; + } + + @Override + public Class getInterface() { + return serviceType; + } + + @Override + public List> getAllInvokers() { + return invokers; + } + + @Override + public URL getConsumerUrl() { + return this.overrideDirectoryUrl; + } + + public URL getRegisteredConsumerUrl() { + return registeredConsumerUrl; + } + + public void setRegisteredConsumerUrl(URL url) { + if (!shouldSimplified) { + this.registeredConsumerUrl = url.addParameters(CATEGORY_KEY, CONSUMERS_CATEGORY, CHECK_KEY, + String.valueOf(false)); + } else { + this.registeredConsumerUrl = URL.valueOf(url, DEFAULT_REGISTER_CONSUMER_KEYS, null).addParameters( + CATEGORY_KEY, CONSUMERS_CATEGORY, CHECK_KEY, String.valueOf(false)); + } + } + + @Override + public boolean isAvailable() { + if (isDestroyed()) { + return false; + } + Map> localUrlInvokerMap = urlInvokerMap; + return CollectionUtils.isNotEmptyMap(localUrlInvokerMap) + && localUrlInvokerMap.values().stream().anyMatch(Invoker::isAvailable); + } + + /** + * Haomin: added for test purpose + */ + public Map> getUrlInvokerMap() { + return urlInvokerMap; + } + + public List> getInvokers() { + return invokers; + } + + private boolean isValidCategory(URL url) { + String category = url.getCategory(DEFAULT_CATEGORY); + if ((ROUTERS_CATEGORY.equals(category) || ROUTE_PROTOCOL.equals(url.getProtocol())) || + PROVIDERS_CATEGORY.equals(category) || + CONFIGURATORS_CATEGORY.equals(category) || DYNAMIC_CONFIGURATORS_CATEGORY.equals(category) || + APP_DYNAMIC_CONFIGURATORS_CATEGORY.equals(category)) { + return true; + } + logger.warn("Unsupported category " + category + " in notified url: " + url + " from registry " + + getUrl().getAddress() + " to consumer " + NetUtils.getLocalHost()); + return false; + } + + private boolean isNotCompatibleFor26x(URL url) { + return StringUtils.isEmpty(url.getParameter(COMPATIBLE_CONFIG_KEY)); + } + + private void overrideDirectoryUrl() { + // merge override parameters + this.overrideDirectoryUrl = directoryUrl; + List localConfigurators = this.configurators; // local reference + doOverrideUrl(localConfigurators); + List localAppDynamicConfigurators = CONSUMER_CONFIGURATION_LISTENER.getConfigurators(); // local reference + doOverrideUrl(localAppDynamicConfigurators); + if (referenceConfigurationListener != null) { + List localDynamicConfigurators = referenceConfigurationListener.getConfigurators(); // local reference + doOverrideUrl(localDynamicConfigurators); + } + } + + private void doOverrideUrl(List configurators) { + if (CollectionUtils.isNotEmpty(configurators)) { + for (Configurator configurator : configurators) { + this.overrideDirectoryUrl = configurator.configure(overrideDirectoryUrl); + } + } + } + + private static class ReferenceConfigurationListener extends AbstractConfiguratorListener { + private RegistryDirectory directory; + private URL url; + + ReferenceConfigurationListener(RegistryDirectory directory, URL url) { + this.directory = directory; + this.url = url; + this.initWith(DynamicConfiguration.getRuleKey(url) + CONFIGURATORS_SUFFIX); + } + + void stop() { + this.stopListen(DynamicConfiguration.getRuleKey(url) + CONFIGURATORS_SUFFIX); + } + + @Override + protected void notifyOverrides() { + // to notify configurator/router changes + directory.refreshOverrideAndInvoker(Collections.emptyList()); + } + } + + private static class ConsumerConfigurationListener extends AbstractConfiguratorListener { + List listeners = new ArrayList<>(); + + ConsumerConfigurationListener() { + this.initWith(ApplicationModel.getApplication() + CONFIGURATORS_SUFFIX); + } + + void addNotifyListener(RegistryDirectory listener) { + this.listeners.add(listener); + } + + void removeNotifyListener(RegistryDirectory listener) { + this.listeners.remove(listener); + } + + @Override + protected void notifyOverrides() { + listeners.forEach(listener -> listener.refreshOverrideAndInvoker(Collections.emptyList())); + } + } + +} diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/status/RegistryStatusChecker.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/status/RegistryStatusChecker.java index 4e64cf7ca9..0da0f87479 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/status/RegistryStatusChecker.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/status/RegistryStatusChecker.java @@ -1,57 +1,57 @@ -/* - * 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.registry.status; - -import org.apache.dubbo.common.extension.Activate; -import org.apache.dubbo.common.status.Status; -import org.apache.dubbo.common.status.StatusChecker; -import org.apache.dubbo.registry.Registry; -import org.apache.dubbo.registry.support.AbstractRegistryFactory; - -import java.util.Collection; - -/** - * RegistryStatusChecker - * - */ -@Activate -public class RegistryStatusChecker implements StatusChecker { - - @Override - public Status check() { - Collection registries = AbstractRegistryFactory.getRegistries(); - if (registries.isEmpty()) { - return new Status(Status.Level.UNKNOWN); - } - Status.Level level = Status.Level.OK; - StringBuilder buf = new StringBuilder(); - for (Registry registry : registries) { - if (buf.length() > 0) { - buf.append(","); - } - buf.append(registry.getUrl().getAddress()); - if (!registry.isAvailable()) { - level = Status.Level.ERROR; - buf.append("(disconnected)"); - } else { - buf.append("(connected)"); - } - } - return new Status(level, buf.toString()); - } - -} +/* + * 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.registry.status; + +import org.apache.dubbo.common.extension.Activate; +import org.apache.dubbo.common.status.Status; +import org.apache.dubbo.common.status.StatusChecker; +import org.apache.dubbo.registry.Registry; +import org.apache.dubbo.registry.support.AbstractRegistryFactory; + +import java.util.Collection; + +/** + * RegistryStatusChecker + * + */ +@Activate +public class RegistryStatusChecker implements StatusChecker { + + @Override + public Status check() { + Collection registries = AbstractRegistryFactory.getRegistries(); + if (registries.isEmpty()) { + return new Status(Status.Level.UNKNOWN); + } + Status.Level level = Status.Level.OK; + StringBuilder buf = new StringBuilder(); + for (Registry registry : registries) { + if (buf.length() > 0) { + buf.append(","); + } + buf.append(registry.getUrl().getAddress()); + if (!registry.isAvailable()) { + level = Status.Level.ERROR; + buf.append("(disconnected)"); + } else { + buf.append("(connected)"); + } + } + return new Status(level, buf.toString()); + } + +} diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/AbstractRegistry.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/AbstractRegistry.java index bd0dd595af..ee45bfa9f6 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/AbstractRegistry.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/AbstractRegistry.java @@ -1,539 +1,539 @@ -/* - * 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.registry.support; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.utils.CollectionUtils; -import org.apache.dubbo.common.utils.ConcurrentHashSet; -import org.apache.dubbo.common.utils.ConfigUtils; -import org.apache.dubbo.common.utils.NamedThreadFactory; -import org.apache.dubbo.common.utils.StringUtils; -import org.apache.dubbo.common.utils.UrlUtils; -import org.apache.dubbo.registry.NotifyListener; -import org.apache.dubbo.registry.Registry; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.RandomAccessFile; -import java.nio.channels.FileChannel; -import java.nio.channels.FileLock; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.atomic.AtomicReference; - -import static org.apache.dubbo.common.constants.CommonConstants.ANY_VALUE; -import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN; -import static org.apache.dubbo.common.constants.CommonConstants.FILE_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.REGISTRY_LOCAL_FILE_CACHE_ENABLED; -import static org.apache.dubbo.common.constants.RegistryConstants.ACCEPTS_KEY; -import static org.apache.dubbo.common.constants.RegistryConstants.DEFAULT_CATEGORY; -import static org.apache.dubbo.common.constants.RegistryConstants.DYNAMIC_KEY; -import static org.apache.dubbo.common.constants.RegistryConstants.EMPTY_PROTOCOL; -import static org.apache.dubbo.registry.Constants.REGISTRY_FILESAVE_SYNC_KEY; - -/** - * AbstractRegistry. (SPI, Prototype, ThreadSafe) - */ -public abstract class AbstractRegistry implements Registry { - - // URL address separator, used in file cache, service provider URL separation - private static final char URL_SEPARATOR = ' '; - // URL address separated regular expression for parsing the service provider URL list in the file cache - private static final String URL_SPLIT = "\\s+"; - // Max times to retry to save properties to local cache file - private static final int MAX_RETRY_TIMES_SAVE_PROPERTIES = 3; - // Log output - protected final Logger logger = LoggerFactory.getLogger(getClass()); - // Local disk cache, where the special key value.registries records the list of registry centers, and the others are the list of notified service providers - private final Properties properties = new Properties(); - // File cache timing writing - private final ExecutorService registryCacheExecutor = Executors.newFixedThreadPool(1, new NamedThreadFactory("DubboSaveRegistryCache", true)); - // Is it synchronized to save the file - private boolean syncSaveFile; - private final AtomicLong lastCacheChanged = new AtomicLong(); - private final AtomicInteger savePropertiesRetryTimes = new AtomicInteger(); - private final Set registered = new ConcurrentHashSet<>(); - private final ConcurrentMap> subscribed = new ConcurrentHashMap<>(); - private final ConcurrentMap>> notified = new ConcurrentHashMap<>(); - private URL registryUrl; - // Local disk cache file - private File file; - private boolean localCacheEnabled; - - public AbstractRegistry(URL url) { - setUrl(url); - localCacheEnabled = url.getParameter(REGISTRY_LOCAL_FILE_CACHE_ENABLED, true); - if (localCacheEnabled) { - // Start file save timer - syncSaveFile = url.getParameter(REGISTRY_FILESAVE_SYNC_KEY, false); - String defaultFilename = System.getProperty("user.home") + "/.dubbo/dubbo-registry-" + url.getApplication() + "-" + url.getAddress().replaceAll(":", "-") + ".cache"; - String filename = url.getParameter(FILE_KEY, defaultFilename); - File file = null; - if (ConfigUtils.isNotEmpty(filename)) { - file = new File(filename); - if (!file.exists() && file.getParentFile() != null && !file.getParentFile().exists()) { - if (!file.getParentFile().mkdirs()) { - throw new IllegalArgumentException("Invalid registry cache file " + file + ", cause: Failed to create directory " + file.getParentFile() + "!"); - } - } - } - this.file = file; - // When starting the subscription center, - // we need to read the local cache file for future Registry fault tolerance processing. - loadProperties(); - notify(url.getBackupUrls()); - } - } - - protected static List filterEmpty(URL url, List urls) { - if (CollectionUtils.isEmpty(urls)) { - List result = new ArrayList<>(1); - result.add(url.setProtocol(EMPTY_PROTOCOL)); - return result; - } - return urls; - } - - @Override - public URL getUrl() { - return registryUrl; - } - - protected void setUrl(URL url) { - if (url == null) { - throw new IllegalArgumentException("registry url == null"); - } - this.registryUrl = url; - } - - public Set getRegistered() { - return Collections.unmodifiableSet(registered); - } - - public Map> getSubscribed() { - return Collections.unmodifiableMap(subscribed); - } - - public Map>> getNotified() { - return Collections.unmodifiableMap(notified); - } - - public File getCacheFile() { - return file; - } - - public Properties getCacheProperties() { - return properties; - } - - public AtomicLong getLastCacheChanged() { - return lastCacheChanged; - } - - public void doSaveProperties(long version) { - if (version < lastCacheChanged.get()) { - return; - } - if (file == null) { - return; - } - // Save - try { - File lockfile = new File(file.getAbsolutePath() + ".lock"); - if (!lockfile.exists()) { - lockfile.createNewFile(); - } - try (RandomAccessFile raf = new RandomAccessFile(lockfile, "rw"); - FileChannel channel = raf.getChannel()) { - FileLock lock = channel.tryLock(); - if (lock == null) { - throw new IOException("Can not lock the registry cache file " + file.getAbsolutePath() + ", ignore and retry later, maybe multi java process use the file, please config: dubbo.registry.file=xxx.properties"); - } - // Save - try { - if (!file.exists()) { - file.createNewFile(); - } - try (FileOutputStream outputFile = new FileOutputStream(file)) { - properties.store(outputFile, "Dubbo Registry Cache"); - } - } finally { - lock.release(); - } - } - } catch (Throwable e) { - savePropertiesRetryTimes.incrementAndGet(); - if (savePropertiesRetryTimes.get() >= MAX_RETRY_TIMES_SAVE_PROPERTIES) { - logger.warn("Failed to save registry cache file after retrying " + MAX_RETRY_TIMES_SAVE_PROPERTIES + " times, cause: " + e.getMessage(), e); - savePropertiesRetryTimes.set(0); - return; - } - if (version < lastCacheChanged.get()) { - savePropertiesRetryTimes.set(0); - return; - } else { - registryCacheExecutor.execute(new SaveProperties(lastCacheChanged.incrementAndGet())); - } - logger.warn("Failed to save registry cache file, will retry, cause: " + e.getMessage(), e); - } - } - - private void loadProperties() { - if (file != null && file.exists()) { - InputStream in = null; - try { - in = new FileInputStream(file); - properties.load(in); - if (logger.isInfoEnabled()) { - logger.info("Loaded registry cache file " + file); - } - } catch (Throwable e) { - logger.warn("Failed to load registry cache file " + file, e); - } finally { - if (in != null) { - try { - in.close(); - } catch (IOException e) { - logger.warn(e.getMessage(), e); - } - } - } - } - } - - public List getCacheUrls(URL url) { - for (Map.Entry entry : properties.entrySet()) { - String key = (String) entry.getKey(); - String value = (String) entry.getValue(); - if (StringUtils.isNotEmpty(key) && key.equals(url.getServiceKey()) - && (Character.isLetter(key.charAt(0)) || key.charAt(0) == '_') - && StringUtils.isNotEmpty(value)) { - String[] arr = value.trim().split(URL_SPLIT); - List urls = new ArrayList<>(); - for (String u : arr) { - urls.add(URL.valueOf(u)); - } - return urls; - } - } - return null; - } - - @Override - public List lookup(URL url) { - List result = new ArrayList<>(); - Map> notifiedUrls = getNotified().get(url); - if (CollectionUtils.isNotEmptyMap(notifiedUrls)) { - for (List urls : notifiedUrls.values()) { - for (URL u : urls) { - if (!EMPTY_PROTOCOL.equals(u.getProtocol())) { - result.add(u); - } - } - } - } else { - final AtomicReference> reference = new AtomicReference<>(); - NotifyListener listener = reference::set; - subscribe(url, listener); // Subscribe logic guarantees the first notify to return - List urls = reference.get(); - if (CollectionUtils.isNotEmpty(urls)) { - for (URL u : urls) { - if (!EMPTY_PROTOCOL.equals(u.getProtocol())) { - result.add(u); - } - } - } - } - return result; - } - - @Override - public void register(URL url) { - if (url == null) { - throw new IllegalArgumentException("register url == null"); - } - if (url.getPort() != 0) { - if (logger.isInfoEnabled()) { - logger.info("Register: " + url); - } - } - registered.add(url); - } - - @Override - public void unregister(URL url) { - if (url == null) { - throw new IllegalArgumentException("unregister url == null"); - } - if (url.getPort() != 0) { - if (logger.isInfoEnabled()) { - logger.info("Unregister: " + url); - } - } - registered.remove(url); - } - - @Override - public void subscribe(URL url, NotifyListener listener) { - if (url == null) { - throw new IllegalArgumentException("subscribe url == null"); - } - if (listener == null) { - throw new IllegalArgumentException("subscribe listener == null"); - } - if (logger.isInfoEnabled()) { - logger.info("Subscribe: " + url); - } - Set listeners = subscribed.computeIfAbsent(url, n -> new ConcurrentHashSet<>()); - listeners.add(listener); - } - - @Override - public void unsubscribe(URL url, NotifyListener listener) { - if (url == null) { - throw new IllegalArgumentException("unsubscribe url == null"); - } - if (listener == null) { - throw new IllegalArgumentException("unsubscribe listener == null"); - } - if (logger.isInfoEnabled()) { - logger.info("Unsubscribe: " + url); - } - Set listeners = subscribed.get(url); - if (listeners != null) { - listeners.remove(listener); - } - - // do not forget remove notified - notified.remove(url); - } - - protected void recover() throws Exception { - // register - Set recoverRegistered = new HashSet<>(getRegistered()); - if (!recoverRegistered.isEmpty()) { - if (logger.isInfoEnabled()) { - logger.info("Recover register url " + recoverRegistered); - } - for (URL url : recoverRegistered) { - register(url); - } - } - // subscribe - Map> recoverSubscribed = new HashMap<>(getSubscribed()); - if (!recoverSubscribed.isEmpty()) { - if (logger.isInfoEnabled()) { - logger.info("Recover subscribe url " + recoverSubscribed.keySet()); - } - for (Map.Entry> entry : recoverSubscribed.entrySet()) { - URL url = entry.getKey(); - for (NotifyListener listener : entry.getValue()) { - subscribe(url, listener); - } - } - } - } - - protected void notify(List urls) { - if (CollectionUtils.isEmpty(urls)) { - return; - } - - for (Map.Entry> entry : getSubscribed().entrySet()) { - URL url = entry.getKey(); - - if (!UrlUtils.isMatch(url, urls.get(0))) { - continue; - } - - Set listeners = entry.getValue(); - if (listeners != null) { - for (NotifyListener listener : listeners) { - try { - notify(url, listener, filterEmpty(url, urls)); - } catch (Throwable t) { - logger.error("Failed to notify registry event, urls: " + urls + ", cause: " + t.getMessage(), t); - } - } - } - } - } - - /** - * Notify changes from the Provider side. - * - * @param url consumer side url - * @param listener listener - * @param urls provider latest urls - */ - protected void notify(URL url, NotifyListener listener, List urls) { - if (url == null) { - throw new IllegalArgumentException("notify url == null"); - } - if (listener == null) { - throw new IllegalArgumentException("notify listener == null"); - } - if ((CollectionUtils.isEmpty(urls)) - && !ANY_VALUE.equals(url.getServiceInterface())) { - logger.warn("Ignore empty notify urls for subscribe url " + url); - return; - } - if (logger.isInfoEnabled()) { - logger.info("Notify urls for subscribe url " + url + ", url size: " + urls.size()); - } - // keep every provider's category. - Map> result = new HashMap<>(); - for (URL u : urls) { - if (UrlUtils.isMatch(url, u)) { - String category = u.getCategory(DEFAULT_CATEGORY); - List categoryList = result.computeIfAbsent(category, k -> new ArrayList<>()); - categoryList.add(u); - } - } - if (result.size() == 0) { - return; - } - Map> categoryNotified = notified.computeIfAbsent(url, u -> new ConcurrentHashMap<>()); - for (Map.Entry> entry : result.entrySet()) { - String category = entry.getKey(); - List categoryList = entry.getValue(); - categoryNotified.put(category, categoryList); - listener.notify(categoryList); - // We will update our cache file after each notification. - // When our Registry has a subscribe failure due to network jitter, we can return at least the existing cache URL. - if (localCacheEnabled) { - saveProperties(url); - } - } - } - - private void saveProperties(URL url) { - if (file == null) { - return; - } - - try { - StringBuilder buf = new StringBuilder(); - Map> categoryNotified = notified.get(url); - if (categoryNotified != null) { - for (List us : categoryNotified.values()) { - for (URL u : us) { - if (buf.length() > 0) { - buf.append(URL_SEPARATOR); - } - buf.append(u.toFullString()); - } - } - } - properties.setProperty(url.getServiceKey(), buf.toString()); - long version = lastCacheChanged.incrementAndGet(); - if (syncSaveFile) { - doSaveProperties(version); - } else { - registryCacheExecutor.execute(new SaveProperties(version)); - } - } catch (Throwable t) { - logger.warn(t.getMessage(), t); - } - } - - @Override - public void destroy() { - if (logger.isInfoEnabled()) { - logger.info("Destroy registry:" + getUrl()); - } - Set destroyRegistered = new HashSet<>(getRegistered()); - if (!destroyRegistered.isEmpty()) { - for (URL url : new HashSet<>(destroyRegistered)) { - if (url.getParameter(DYNAMIC_KEY, true)) { - try { - unregister(url); - if (logger.isInfoEnabled()) { - logger.info("Destroy unregister url " + url); - } - } catch (Throwable t) { - logger.warn("Failed to unregister url " + url + " to registry " + getUrl() + " on destroy, cause: " + t.getMessage(), t); - } - } - } - } - Map> destroySubscribed = new HashMap<>(getSubscribed()); - if (!destroySubscribed.isEmpty()) { - for (Map.Entry> entry : destroySubscribed.entrySet()) { - URL url = entry.getKey(); - for (NotifyListener listener : entry.getValue()) { - try { - unsubscribe(url, listener); - if (logger.isInfoEnabled()) { - logger.info("Destroy unsubscribe url " + url); - } - } catch (Throwable t) { - logger.warn("Failed to unsubscribe url " + url + " to registry " + getUrl() + " on destroy, cause: " + t.getMessage(), t); - } - } - } - } - AbstractRegistryFactory.removeDestroyedRegistry(this); - } - - protected boolean acceptable(URL urlToRegistry) { - String pattern = registryUrl.getParameter(ACCEPTS_KEY); - if (StringUtils.isEmpty(pattern)) { - return true; - } - - return Arrays.stream(COMMA_SPLIT_PATTERN.split(pattern)) - .anyMatch(p -> p.equalsIgnoreCase(urlToRegistry.getProtocol())); - } - - @Override - public String toString() { - return getUrl().toString(); - } - - private class SaveProperties implements Runnable { - private long version; - - private SaveProperties(long version) { - this.version = version; - } - - @Override - public void run() { - doSaveProperties(version); - } - } - -} +/* + * 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.registry.support; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.common.utils.ConcurrentHashSet; +import org.apache.dubbo.common.utils.ConfigUtils; +import org.apache.dubbo.common.utils.NamedThreadFactory; +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.common.utils.UrlUtils; +import org.apache.dubbo.registry.NotifyListener; +import org.apache.dubbo.registry.Registry; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.RandomAccessFile; +import java.nio.channels.FileChannel; +import java.nio.channels.FileLock; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +import static org.apache.dubbo.common.constants.CommonConstants.ANY_VALUE; +import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN; +import static org.apache.dubbo.common.constants.CommonConstants.FILE_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.REGISTRY_LOCAL_FILE_CACHE_ENABLED; +import static org.apache.dubbo.common.constants.RegistryConstants.ACCEPTS_KEY; +import static org.apache.dubbo.common.constants.RegistryConstants.DEFAULT_CATEGORY; +import static org.apache.dubbo.common.constants.RegistryConstants.DYNAMIC_KEY; +import static org.apache.dubbo.common.constants.RegistryConstants.EMPTY_PROTOCOL; +import static org.apache.dubbo.registry.Constants.REGISTRY_FILESAVE_SYNC_KEY; + +/** + * AbstractRegistry. (SPI, Prototype, ThreadSafe) + */ +public abstract class AbstractRegistry implements Registry { + + // URL address separator, used in file cache, service provider URL separation + private static final char URL_SEPARATOR = ' '; + // URL address separated regular expression for parsing the service provider URL list in the file cache + private static final String URL_SPLIT = "\\s+"; + // Max times to retry to save properties to local cache file + private static final int MAX_RETRY_TIMES_SAVE_PROPERTIES = 3; + // Log output + protected final Logger logger = LoggerFactory.getLogger(getClass()); + // Local disk cache, where the special key value.registries records the list of registry centers, and the others are the list of notified service providers + private final Properties properties = new Properties(); + // File cache timing writing + private final ExecutorService registryCacheExecutor = Executors.newFixedThreadPool(1, new NamedThreadFactory("DubboSaveRegistryCache", true)); + // Is it synchronized to save the file + private boolean syncSaveFile; + private final AtomicLong lastCacheChanged = new AtomicLong(); + private final AtomicInteger savePropertiesRetryTimes = new AtomicInteger(); + private final Set registered = new ConcurrentHashSet<>(); + private final ConcurrentMap> subscribed = new ConcurrentHashMap<>(); + private final ConcurrentMap>> notified = new ConcurrentHashMap<>(); + private URL registryUrl; + // Local disk cache file + private File file; + private boolean localCacheEnabled; + + public AbstractRegistry(URL url) { + setUrl(url); + localCacheEnabled = url.getParameter(REGISTRY_LOCAL_FILE_CACHE_ENABLED, true); + if (localCacheEnabled) { + // Start file save timer + syncSaveFile = url.getParameter(REGISTRY_FILESAVE_SYNC_KEY, false); + String defaultFilename = System.getProperty("user.home") + "/.dubbo/dubbo-registry-" + url.getApplication() + "-" + url.getAddress().replaceAll(":", "-") + ".cache"; + String filename = url.getParameter(FILE_KEY, defaultFilename); + File file = null; + if (ConfigUtils.isNotEmpty(filename)) { + file = new File(filename); + if (!file.exists() && file.getParentFile() != null && !file.getParentFile().exists()) { + if (!file.getParentFile().mkdirs()) { + throw new IllegalArgumentException("Invalid registry cache file " + file + ", cause: Failed to create directory " + file.getParentFile() + "!"); + } + } + } + this.file = file; + // When starting the subscription center, + // we need to read the local cache file for future Registry fault tolerance processing. + loadProperties(); + notify(url.getBackupUrls()); + } + } + + protected static List filterEmpty(URL url, List urls) { + if (CollectionUtils.isEmpty(urls)) { + List result = new ArrayList<>(1); + result.add(url.setProtocol(EMPTY_PROTOCOL)); + return result; + } + return urls; + } + + @Override + public URL getUrl() { + return registryUrl; + } + + protected void setUrl(URL url) { + if (url == null) { + throw new IllegalArgumentException("registry url == null"); + } + this.registryUrl = url; + } + + public Set getRegistered() { + return Collections.unmodifiableSet(registered); + } + + public Map> getSubscribed() { + return Collections.unmodifiableMap(subscribed); + } + + public Map>> getNotified() { + return Collections.unmodifiableMap(notified); + } + + public File getCacheFile() { + return file; + } + + public Properties getCacheProperties() { + return properties; + } + + public AtomicLong getLastCacheChanged() { + return lastCacheChanged; + } + + public void doSaveProperties(long version) { + if (version < lastCacheChanged.get()) { + return; + } + if (file == null) { + return; + } + // Save + try { + File lockfile = new File(file.getAbsolutePath() + ".lock"); + if (!lockfile.exists()) { + lockfile.createNewFile(); + } + try (RandomAccessFile raf = new RandomAccessFile(lockfile, "rw"); + FileChannel channel = raf.getChannel()) { + FileLock lock = channel.tryLock(); + if (lock == null) { + throw new IOException("Can not lock the registry cache file " + file.getAbsolutePath() + ", ignore and retry later, maybe multi java process use the file, please config: dubbo.registry.file=xxx.properties"); + } + // Save + try { + if (!file.exists()) { + file.createNewFile(); + } + try (FileOutputStream outputFile = new FileOutputStream(file)) { + properties.store(outputFile, "Dubbo Registry Cache"); + } + } finally { + lock.release(); + } + } + } catch (Throwable e) { + savePropertiesRetryTimes.incrementAndGet(); + if (savePropertiesRetryTimes.get() >= MAX_RETRY_TIMES_SAVE_PROPERTIES) { + logger.warn("Failed to save registry cache file after retrying " + MAX_RETRY_TIMES_SAVE_PROPERTIES + " times, cause: " + e.getMessage(), e); + savePropertiesRetryTimes.set(0); + return; + } + if (version < lastCacheChanged.get()) { + savePropertiesRetryTimes.set(0); + return; + } else { + registryCacheExecutor.execute(new SaveProperties(lastCacheChanged.incrementAndGet())); + } + logger.warn("Failed to save registry cache file, will retry, cause: " + e.getMessage(), e); + } + } + + private void loadProperties() { + if (file != null && file.exists()) { + InputStream in = null; + try { + in = new FileInputStream(file); + properties.load(in); + if (logger.isInfoEnabled()) { + logger.info("Loaded registry cache file " + file); + } + } catch (Throwable e) { + logger.warn("Failed to load registry cache file " + file, e); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException e) { + logger.warn(e.getMessage(), e); + } + } + } + } + } + + public List getCacheUrls(URL url) { + for (Map.Entry entry : properties.entrySet()) { + String key = (String) entry.getKey(); + String value = (String) entry.getValue(); + if (StringUtils.isNotEmpty(key) && key.equals(url.getServiceKey()) + && (Character.isLetter(key.charAt(0)) || key.charAt(0) == '_') + && StringUtils.isNotEmpty(value)) { + String[] arr = value.trim().split(URL_SPLIT); + List urls = new ArrayList<>(); + for (String u : arr) { + urls.add(URL.valueOf(u)); + } + return urls; + } + } + return null; + } + + @Override + public List lookup(URL url) { + List result = new ArrayList<>(); + Map> notifiedUrls = getNotified().get(url); + if (CollectionUtils.isNotEmptyMap(notifiedUrls)) { + for (List urls : notifiedUrls.values()) { + for (URL u : urls) { + if (!EMPTY_PROTOCOL.equals(u.getProtocol())) { + result.add(u); + } + } + } + } else { + final AtomicReference> reference = new AtomicReference<>(); + NotifyListener listener = reference::set; + subscribe(url, listener); // Subscribe logic guarantees the first notify to return + List urls = reference.get(); + if (CollectionUtils.isNotEmpty(urls)) { + for (URL u : urls) { + if (!EMPTY_PROTOCOL.equals(u.getProtocol())) { + result.add(u); + } + } + } + } + return result; + } + + @Override + public void register(URL url) { + if (url == null) { + throw new IllegalArgumentException("register url == null"); + } + if (url.getPort() != 0) { + if (logger.isInfoEnabled()) { + logger.info("Register: " + url); + } + } + registered.add(url); + } + + @Override + public void unregister(URL url) { + if (url == null) { + throw new IllegalArgumentException("unregister url == null"); + } + if (url.getPort() != 0) { + if (logger.isInfoEnabled()) { + logger.info("Unregister: " + url); + } + } + registered.remove(url); + } + + @Override + public void subscribe(URL url, NotifyListener listener) { + if (url == null) { + throw new IllegalArgumentException("subscribe url == null"); + } + if (listener == null) { + throw new IllegalArgumentException("subscribe listener == null"); + } + if (logger.isInfoEnabled()) { + logger.info("Subscribe: " + url); + } + Set listeners = subscribed.computeIfAbsent(url, n -> new ConcurrentHashSet<>()); + listeners.add(listener); + } + + @Override + public void unsubscribe(URL url, NotifyListener listener) { + if (url == null) { + throw new IllegalArgumentException("unsubscribe url == null"); + } + if (listener == null) { + throw new IllegalArgumentException("unsubscribe listener == null"); + } + if (logger.isInfoEnabled()) { + logger.info("Unsubscribe: " + url); + } + Set listeners = subscribed.get(url); + if (listeners != null) { + listeners.remove(listener); + } + + // do not forget remove notified + notified.remove(url); + } + + protected void recover() throws Exception { + // register + Set recoverRegistered = new HashSet<>(getRegistered()); + if (!recoverRegistered.isEmpty()) { + if (logger.isInfoEnabled()) { + logger.info("Recover register url " + recoverRegistered); + } + for (URL url : recoverRegistered) { + register(url); + } + } + // subscribe + Map> recoverSubscribed = new HashMap<>(getSubscribed()); + if (!recoverSubscribed.isEmpty()) { + if (logger.isInfoEnabled()) { + logger.info("Recover subscribe url " + recoverSubscribed.keySet()); + } + for (Map.Entry> entry : recoverSubscribed.entrySet()) { + URL url = entry.getKey(); + for (NotifyListener listener : entry.getValue()) { + subscribe(url, listener); + } + } + } + } + + protected void notify(List urls) { + if (CollectionUtils.isEmpty(urls)) { + return; + } + + for (Map.Entry> entry : getSubscribed().entrySet()) { + URL url = entry.getKey(); + + if (!UrlUtils.isMatch(url, urls.get(0))) { + continue; + } + + Set listeners = entry.getValue(); + if (listeners != null) { + for (NotifyListener listener : listeners) { + try { + notify(url, listener, filterEmpty(url, urls)); + } catch (Throwable t) { + logger.error("Failed to notify registry event, urls: " + urls + ", cause: " + t.getMessage(), t); + } + } + } + } + } + + /** + * Notify changes from the Provider side. + * + * @param url consumer side url + * @param listener listener + * @param urls provider latest urls + */ + protected void notify(URL url, NotifyListener listener, List urls) { + if (url == null) { + throw new IllegalArgumentException("notify url == null"); + } + if (listener == null) { + throw new IllegalArgumentException("notify listener == null"); + } + if ((CollectionUtils.isEmpty(urls)) + && !ANY_VALUE.equals(url.getServiceInterface())) { + logger.warn("Ignore empty notify urls for subscribe url " + url); + return; + } + if (logger.isInfoEnabled()) { + logger.info("Notify urls for subscribe url " + url + ", url size: " + urls.size()); + } + // keep every provider's category. + Map> result = new HashMap<>(); + for (URL u : urls) { + if (UrlUtils.isMatch(url, u)) { + String category = u.getCategory(DEFAULT_CATEGORY); + List categoryList = result.computeIfAbsent(category, k -> new ArrayList<>()); + categoryList.add(u); + } + } + if (result.size() == 0) { + return; + } + Map> categoryNotified = notified.computeIfAbsent(url, u -> new ConcurrentHashMap<>()); + for (Map.Entry> entry : result.entrySet()) { + String category = entry.getKey(); + List categoryList = entry.getValue(); + categoryNotified.put(category, categoryList); + listener.notify(categoryList); + // We will update our cache file after each notification. + // When our Registry has a subscribe failure due to network jitter, we can return at least the existing cache URL. + if (localCacheEnabled) { + saveProperties(url); + } + } + } + + private void saveProperties(URL url) { + if (file == null) { + return; + } + + try { + StringBuilder buf = new StringBuilder(); + Map> categoryNotified = notified.get(url); + if (categoryNotified != null) { + for (List us : categoryNotified.values()) { + for (URL u : us) { + if (buf.length() > 0) { + buf.append(URL_SEPARATOR); + } + buf.append(u.toFullString()); + } + } + } + properties.setProperty(url.getServiceKey(), buf.toString()); + long version = lastCacheChanged.incrementAndGet(); + if (syncSaveFile) { + doSaveProperties(version); + } else { + registryCacheExecutor.execute(new SaveProperties(version)); + } + } catch (Throwable t) { + logger.warn(t.getMessage(), t); + } + } + + @Override + public void destroy() { + if (logger.isInfoEnabled()) { + logger.info("Destroy registry:" + getUrl()); + } + Set destroyRegistered = new HashSet<>(getRegistered()); + if (!destroyRegistered.isEmpty()) { + for (URL url : new HashSet<>(destroyRegistered)) { + if (url.getParameter(DYNAMIC_KEY, true)) { + try { + unregister(url); + if (logger.isInfoEnabled()) { + logger.info("Destroy unregister url " + url); + } + } catch (Throwable t) { + logger.warn("Failed to unregister url " + url + " to registry " + getUrl() + " on destroy, cause: " + t.getMessage(), t); + } + } + } + } + Map> destroySubscribed = new HashMap<>(getSubscribed()); + if (!destroySubscribed.isEmpty()) { + for (Map.Entry> entry : destroySubscribed.entrySet()) { + URL url = entry.getKey(); + for (NotifyListener listener : entry.getValue()) { + try { + unsubscribe(url, listener); + if (logger.isInfoEnabled()) { + logger.info("Destroy unsubscribe url " + url); + } + } catch (Throwable t) { + logger.warn("Failed to unsubscribe url " + url + " to registry " + getUrl() + " on destroy, cause: " + t.getMessage(), t); + } + } + } + } + AbstractRegistryFactory.removeDestroyedRegistry(this); + } + + protected boolean acceptable(URL urlToRegistry) { + String pattern = registryUrl.getParameter(ACCEPTS_KEY); + if (StringUtils.isEmpty(pattern)) { + return true; + } + + return Arrays.stream(COMMA_SPLIT_PATTERN.split(pattern)) + .anyMatch(p -> p.equalsIgnoreCase(urlToRegistry.getProtocol())); + } + + @Override + public String toString() { + return getUrl().toString(); + } + + private class SaveProperties implements Runnable { + private long version; + + private SaveProperties(long version) { + this.version = version; + } + + @Override + public void run() { + doSaveProperties(version); + } + } + +} diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/AbstractRegistryFactory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/AbstractRegistryFactory.java index c54eca43c5..bf696e4f54 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/AbstractRegistryFactory.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/AbstractRegistryFactory.java @@ -1,241 +1,241 @@ -/* - * 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.registry.support; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.URLBuilder; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.registry.NotifyListener; -import org.apache.dubbo.registry.Registry; -import org.apache.dubbo.registry.RegistryFactory; -import org.apache.dubbo.registry.RegistryService; -import org.apache.dubbo.registry.client.ServiceDiscovery; -import org.apache.dubbo.registry.client.ServiceDiscoveryRegistry; - -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.locks.ReentrantLock; -import java.util.stream.Collectors; - -import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.TIMESTAMP_KEY; -import static org.apache.dubbo.rpc.cluster.Constants.EXPORT_KEY; -import static org.apache.dubbo.rpc.cluster.Constants.REFER_KEY; - -/** - * AbstractRegistryFactory. (SPI, Singleton, ThreadSafe) - * - * @see org.apache.dubbo.registry.RegistryFactory - */ -public abstract class AbstractRegistryFactory implements RegistryFactory { - - // Log output - private static final Logger LOGGER = LoggerFactory.getLogger(AbstractRegistryFactory.class); - - // The lock for the acquisition process of the registry - protected static final ReentrantLock LOCK = new ReentrantLock(); - - // Registry Collection Map - protected static final Map REGISTRIES = new HashMap<>(); - - private static final AtomicBoolean destroyed = new AtomicBoolean(false); - - /** - * Get all registries - * - * @return all registries - */ - public static Collection getRegistries() { - return Collections.unmodifiableCollection(new LinkedList<>(REGISTRIES.values())); - } - - public static Registry getRegistry(String key) { - return REGISTRIES.get(key); - } - - public static List getServiceDiscoveries() { - return AbstractRegistryFactory.getRegistries() - .stream() - .filter(registry -> registry instanceof ServiceDiscoveryRegistry) - .map(registry -> (ServiceDiscoveryRegistry) registry) - .map(ServiceDiscoveryRegistry::getServiceDiscovery) - .collect(Collectors.toList()); - } - - /** - * Close all created registries - */ - public static void destroyAll() { - if (!destroyed.compareAndSet(false, true)) { - return; - } - - if (LOGGER.isInfoEnabled()) { - LOGGER.info("Close all registries " + getRegistries()); - } - // Lock up the registry shutdown process - LOCK.lock(); - try { - for (Registry registry : getRegistries()) { - try { - registry.destroy(); - } catch (Throwable e) { - LOGGER.error(e.getMessage(), e); - } - } - REGISTRIES.clear(); - } finally { - // Release the lock - LOCK.unlock(); - } - } - - /** - * Reset state of AbstractRegistryFactory - */ - public static void reset() { - destroyed.set(false); - REGISTRIES.clear(); - } - - private Registry getDefaultNopRegistryIfDestroyed() { - if (destroyed.get()) { - LOGGER.warn("All registry instances have been destroyed, failed to fetch any instance. " + - "Usually, this means no need to try to do unnecessary redundant resource clearance, all registries has been taken care of."); - return DEFAULT_NOP_REGISTRY; - } - return null; - } - - @Override - public Registry getRegistry(URL url) { - - Registry defaultNopRegistry = getDefaultNopRegistryIfDestroyed(); - if (null != defaultNopRegistry) { - return defaultNopRegistry; - } - - url = URLBuilder.from(url) - .setPath(RegistryService.class.getName()) - .addParameter(INTERFACE_KEY, RegistryService.class.getName()) - .removeParameters(EXPORT_KEY, REFER_KEY, TIMESTAMP_KEY) - .build(); - String key = createRegistryCacheKey(url); - // Lock the registry access process to ensure a single instance of the registry - LOCK.lock(); - try { - // double check - // fix https://github.com/apache/dubbo/issues/7265. - defaultNopRegistry = getDefaultNopRegistryIfDestroyed(); - if (null != defaultNopRegistry) { - return defaultNopRegistry; - } - - Registry registry = REGISTRIES.get(key); - if (registry != null) { - return registry; - } - //create registry by spi/ioc - registry = createRegistry(url); - if (registry == null) { - throw new IllegalStateException("Can not create registry " + url); - } - REGISTRIES.put(key, registry); - return registry; - } finally { - // Release the lock - LOCK.unlock(); - } - } - - /** - * Create the key for the registries cache. - * This method may be override by the sub-class. - * - * @param url the registration {@link URL url} - * @return non-null - */ - protected String createRegistryCacheKey(URL url) { - return url.toServiceStringWithoutResolving(); - } - - protected abstract Registry createRegistry(URL url); - - - private static Registry DEFAULT_NOP_REGISTRY = new Registry() { - @Override - public URL getUrl() { - return null; - } - - @Override - public boolean isAvailable() { - return false; - } - - @Override - public void destroy() { - - } - - @Override - public void register(URL url) { - - } - - @Override - public void unregister(URL url) { - - } - - @Override - public void subscribe(URL url, NotifyListener listener) { - - } - - @Override - public void unsubscribe(URL url, NotifyListener listener) { - - } - - @Override - public List lookup(URL url) { - return null; - } - }; - - public static void removeDestroyedRegistry(Registry toRm) { - LOCK.lock(); - try { - REGISTRIES.entrySet().removeIf(entry -> entry.getValue().equals(toRm)); - } finally { - LOCK.unlock(); - } - } - - // for unit test - public static void clearRegistryNotDestroy() { - REGISTRIES.clear(); - } - -} +/* + * 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.registry.support; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.URLBuilder; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.registry.NotifyListener; +import org.apache.dubbo.registry.Registry; +import org.apache.dubbo.registry.RegistryFactory; +import org.apache.dubbo.registry.RegistryService; +import org.apache.dubbo.registry.client.ServiceDiscovery; +import org.apache.dubbo.registry.client.ServiceDiscoveryRegistry; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.locks.ReentrantLock; +import java.util.stream.Collectors; + +import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.TIMESTAMP_KEY; +import static org.apache.dubbo.rpc.cluster.Constants.EXPORT_KEY; +import static org.apache.dubbo.rpc.cluster.Constants.REFER_KEY; + +/** + * AbstractRegistryFactory. (SPI, Singleton, ThreadSafe) + * + * @see org.apache.dubbo.registry.RegistryFactory + */ +public abstract class AbstractRegistryFactory implements RegistryFactory { + + // Log output + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractRegistryFactory.class); + + // The lock for the acquisition process of the registry + protected static final ReentrantLock LOCK = new ReentrantLock(); + + // Registry Collection Map + protected static final Map REGISTRIES = new HashMap<>(); + + private static final AtomicBoolean destroyed = new AtomicBoolean(false); + + /** + * Get all registries + * + * @return all registries + */ + public static Collection getRegistries() { + return Collections.unmodifiableCollection(new LinkedList<>(REGISTRIES.values())); + } + + public static Registry getRegistry(String key) { + return REGISTRIES.get(key); + } + + public static List getServiceDiscoveries() { + return AbstractRegistryFactory.getRegistries() + .stream() + .filter(registry -> registry instanceof ServiceDiscoveryRegistry) + .map(registry -> (ServiceDiscoveryRegistry) registry) + .map(ServiceDiscoveryRegistry::getServiceDiscovery) + .collect(Collectors.toList()); + } + + /** + * Close all created registries + */ + public static void destroyAll() { + if (!destroyed.compareAndSet(false, true)) { + return; + } + + if (LOGGER.isInfoEnabled()) { + LOGGER.info("Close all registries " + getRegistries()); + } + // Lock up the registry shutdown process + LOCK.lock(); + try { + for (Registry registry : getRegistries()) { + try { + registry.destroy(); + } catch (Throwable e) { + LOGGER.error(e.getMessage(), e); + } + } + REGISTRIES.clear(); + } finally { + // Release the lock + LOCK.unlock(); + } + } + + /** + * Reset state of AbstractRegistryFactory + */ + public static void reset() { + destroyed.set(false); + REGISTRIES.clear(); + } + + private Registry getDefaultNopRegistryIfDestroyed() { + if (destroyed.get()) { + LOGGER.warn("All registry instances have been destroyed, failed to fetch any instance. " + + "Usually, this means no need to try to do unnecessary redundant resource clearance, all registries has been taken care of."); + return DEFAULT_NOP_REGISTRY; + } + return null; + } + + @Override + public Registry getRegistry(URL url) { + + Registry defaultNopRegistry = getDefaultNopRegistryIfDestroyed(); + if (null != defaultNopRegistry) { + return defaultNopRegistry; + } + + url = URLBuilder.from(url) + .setPath(RegistryService.class.getName()) + .addParameter(INTERFACE_KEY, RegistryService.class.getName()) + .removeParameters(EXPORT_KEY, REFER_KEY, TIMESTAMP_KEY) + .build(); + String key = createRegistryCacheKey(url); + // Lock the registry access process to ensure a single instance of the registry + LOCK.lock(); + try { + // double check + // fix https://github.com/apache/dubbo/issues/7265. + defaultNopRegistry = getDefaultNopRegistryIfDestroyed(); + if (null != defaultNopRegistry) { + return defaultNopRegistry; + } + + Registry registry = REGISTRIES.get(key); + if (registry != null) { + return registry; + } + //create registry by spi/ioc + registry = createRegistry(url); + if (registry == null) { + throw new IllegalStateException("Can not create registry " + url); + } + REGISTRIES.put(key, registry); + return registry; + } finally { + // Release the lock + LOCK.unlock(); + } + } + + /** + * Create the key for the registries cache. + * This method may be override by the sub-class. + * + * @param url the registration {@link URL url} + * @return non-null + */ + protected String createRegistryCacheKey(URL url) { + return url.toServiceStringWithoutResolving(); + } + + protected abstract Registry createRegistry(URL url); + + + private static Registry DEFAULT_NOP_REGISTRY = new Registry() { + @Override + public URL getUrl() { + return null; + } + + @Override + public boolean isAvailable() { + return false; + } + + @Override + public void destroy() { + + } + + @Override + public void register(URL url) { + + } + + @Override + public void unregister(URL url) { + + } + + @Override + public void subscribe(URL url, NotifyListener listener) { + + } + + @Override + public void unsubscribe(URL url, NotifyListener listener) { + + } + + @Override + public List lookup(URL url) { + return null; + } + }; + + public static void removeDestroyedRegistry(Registry toRm) { + LOCK.lock(); + try { + REGISTRIES.entrySet().removeIf(entry -> entry.getValue().equals(toRm)); + } finally { + LOCK.unlock(); + } + } + + // for unit test + public static void clearRegistryNotDestroy() { + REGISTRIES.clear(); + } + +} diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/FailbackRegistry.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/FailbackRegistry.java index 0b5545f2c4..d0849b3cf4 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/FailbackRegistry.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/FailbackRegistry.java @@ -1,451 +1,451 @@ -/* - * 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.registry.support; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.timer.HashedWheelTimer; -import org.apache.dubbo.common.utils.CollectionUtils; -import org.apache.dubbo.common.utils.NamedThreadFactory; -import org.apache.dubbo.registry.NotifyListener; -import org.apache.dubbo.registry.retry.FailedRegisteredTask; -import org.apache.dubbo.registry.retry.FailedSubscribedTask; -import org.apache.dubbo.registry.retry.FailedUnregisteredTask; -import org.apache.dubbo.registry.retry.FailedUnsubscribedTask; -import org.apache.dubbo.remoting.Constants; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.TimeUnit; - -import static org.apache.dubbo.common.constants.CommonConstants.FILE_KEY; -import static org.apache.dubbo.registry.Constants.DEFAULT_REGISTRY_RETRY_PERIOD; -import static org.apache.dubbo.registry.Constants.REGISTRY_RETRY_PERIOD_KEY; - -/** - * FailbackRegistry. (SPI, Prototype, ThreadSafe) - */ -public abstract class FailbackRegistry extends AbstractRegistry { - - /* retry task map */ - - private final ConcurrentMap failedRegistered = new ConcurrentHashMap(); - - private final ConcurrentMap failedUnregistered = new ConcurrentHashMap(); - - private final ConcurrentMap failedSubscribed = new ConcurrentHashMap(); - - private final ConcurrentMap failedUnsubscribed = new ConcurrentHashMap(); - - /** - * The time in milliseconds the retryExecutor will wait - */ - private final int retryPeriod; - - // Timer for failure retry, regular check if there is a request for failure, and if there is, an unlimited retry - private final HashedWheelTimer retryTimer; - - public FailbackRegistry(URL url) { - super(url); - this.retryPeriod = url.getParameter(REGISTRY_RETRY_PERIOD_KEY, DEFAULT_REGISTRY_RETRY_PERIOD); - - // since the retry task will not be very much. 128 ticks is enough. - retryTimer = new HashedWheelTimer(new NamedThreadFactory("DubboRegistryRetryTimer", true), retryPeriod, TimeUnit.MILLISECONDS, 128); - } - - public void removeFailedRegisteredTask(URL url) { - failedRegistered.remove(url); - } - - public void removeFailedUnregisteredTask(URL url) { - failedUnregistered.remove(url); - } - - public void removeFailedSubscribedTask(URL url, NotifyListener listener) { - Holder h = new Holder(url, listener); - failedSubscribed.remove(h); - } - - public void removeFailedUnsubscribedTask(URL url, NotifyListener listener) { - Holder h = new Holder(url, listener); - failedUnsubscribed.remove(h); - } - - private void addFailedRegistered(URL url) { - FailedRegisteredTask oldOne = failedRegistered.get(url); - if (oldOne != null) { - return; - } - FailedRegisteredTask newTask = new FailedRegisteredTask(url, this); - oldOne = failedRegistered.putIfAbsent(url, newTask); - if (oldOne == null) { - // never has a retry task. then start a new task for retry. - retryTimer.newTimeout(newTask, retryPeriod, TimeUnit.MILLISECONDS); - } - } - - private void removeFailedRegistered(URL url) { - FailedRegisteredTask f = failedRegistered.remove(url); - if (f != null) { - f.cancel(); - } - } - - private void addFailedUnregistered(URL url) { - FailedUnregisteredTask oldOne = failedUnregistered.get(url); - if (oldOne != null) { - return; - } - FailedUnregisteredTask newTask = new FailedUnregisteredTask(url, this); - oldOne = failedUnregistered.putIfAbsent(url, newTask); - if (oldOne == null) { - // never has a retry task. then start a new task for retry. - retryTimer.newTimeout(newTask, retryPeriod, TimeUnit.MILLISECONDS); - } - } - - private void removeFailedUnregistered(URL url) { - FailedUnregisteredTask f = failedUnregistered.remove(url); - if (f != null) { - f.cancel(); - } - } - - protected void addFailedSubscribed(URL url, NotifyListener listener) { - Holder h = new Holder(url, listener); - FailedSubscribedTask oldOne = failedSubscribed.get(h); - if (oldOne != null) { - return; - } - FailedSubscribedTask newTask = new FailedSubscribedTask(url, this, listener); - oldOne = failedSubscribed.putIfAbsent(h, newTask); - if (oldOne == null) { - // never has a retry task. then start a new task for retry. - retryTimer.newTimeout(newTask, retryPeriod, TimeUnit.MILLISECONDS); - } - } - - public void removeFailedSubscribed(URL url, NotifyListener listener) { - Holder h = new Holder(url, listener); - FailedSubscribedTask f = failedSubscribed.remove(h); - if (f != null) { - f.cancel(); - } - removeFailedUnsubscribed(url, listener); - } - - private void addFailedUnsubscribed(URL url, NotifyListener listener) { - Holder h = new Holder(url, listener); - FailedUnsubscribedTask oldOne = failedUnsubscribed.get(h); - if (oldOne != null) { - return; - } - FailedUnsubscribedTask newTask = new FailedUnsubscribedTask(url, this, listener); - oldOne = failedUnsubscribed.putIfAbsent(h, newTask); - if (oldOne == null) { - // never has a retry task. then start a new task for retry. - retryTimer.newTimeout(newTask, retryPeriod, TimeUnit.MILLISECONDS); - } - } - - private void removeFailedUnsubscribed(URL url, NotifyListener listener) { - Holder h = new Holder(url, listener); - FailedUnsubscribedTask f = failedUnsubscribed.remove(h); - if (f != null) { - f.cancel(); - } - } - - ConcurrentMap getFailedRegistered() { - return failedRegistered; - } - - ConcurrentMap getFailedUnregistered() { - return failedUnregistered; - } - - ConcurrentMap getFailedSubscribed() { - return failedSubscribed; - } - - ConcurrentMap getFailedUnsubscribed() { - return failedUnsubscribed; - } - - - @Override - public void register(URL url) { - if (!acceptable(url)) { - logger.info("URL " + url + " will not be registered to Registry. Registry " + url + " does not accept service of this protocol type."); - return; - } - super.register(url); - removeFailedRegistered(url); - removeFailedUnregistered(url); - try { - // Sending a registration request to the server side - doRegister(url); - } catch (Exception e) { - Throwable t = e; - - // If the startup detection is opened, the Exception is thrown directly. - boolean check = getUrl().getParameter(Constants.CHECK_KEY, true) - && url.getParameter(Constants.CHECK_KEY, true) - && !(url.getPort() == 0); - boolean skipFailback = t instanceof SkipFailbackWrapperException; - if (check || skipFailback) { - if (skipFailback) { - t = t.getCause(); - } - throw new IllegalStateException("Failed to register " + url + " to registry " + getUrl().getAddress() + ", cause: " + t.getMessage(), t); - } else { - logger.error("Failed to register " + url + ", waiting for retry, cause: " + t.getMessage(), t); - } - - // Record a failed registration request to a failed list, retry regularly - addFailedRegistered(url); - } - } - - @Override - public void reExportRegister(URL url) { - if (!acceptable(url)) { - logger.info("URL " + url + " will not be registered to Registry. Registry " + url + " does not accept service of this protocol type."); - return; - } - super.register(url); - removeFailedRegistered(url); - removeFailedUnregistered(url); - try { - // Sending a registration request to the server side - doRegister(url); - } catch (Exception e) { - if (!(e instanceof SkipFailbackWrapperException)) { - throw new IllegalStateException("Failed to register (re-export) " + url + " to registry " + getUrl().getAddress() + ", cause: " + e.getMessage(), e); - } - } - } - - @Override - public void unregister(URL url) { - super.unregister(url); - removeFailedRegistered(url); - removeFailedUnregistered(url); - try { - // Sending a cancellation request to the server side - doUnregister(url); - } catch (Exception e) { - Throwable t = e; - - // If the startup detection is opened, the Exception is thrown directly. - boolean check = getUrl().getParameter(Constants.CHECK_KEY, true) - && url.getParameter(Constants.CHECK_KEY, true) - && !(url.getPort() == 0); - boolean skipFailback = t instanceof SkipFailbackWrapperException; - if (check || skipFailback) { - if (skipFailback) { - t = t.getCause(); - } - throw new IllegalStateException("Failed to unregister " + url + " to registry " + getUrl().getAddress() + ", cause: " + t.getMessage(), t); - } else { - logger.error("Failed to unregister " + url + ", waiting for retry, cause: " + t.getMessage(), t); - } - - // Record a failed registration request to a failed list, retry regularly - addFailedUnregistered(url); - } - } - - @Override - public void reExportUnregister(URL url) { - super.unregister(url); - removeFailedRegistered(url); - removeFailedUnregistered(url); - try { - // Sending a cancellation request to the server side - doUnregister(url); - } catch (Exception e) { - if (!(e instanceof SkipFailbackWrapperException)) { - throw new IllegalStateException("Failed to unregister(re-export) " + url + " to registry " + getUrl().getAddress() + ", cause: " + e.getMessage(), e); - } - } - } - - @Override - public void subscribe(URL url, NotifyListener listener) { - super.subscribe(url, listener); - removeFailedSubscribed(url, listener); - try { - // Sending a subscription request to the server side - doSubscribe(url, listener); - } catch (Exception e) { - Throwable t = e; - - List urls = getCacheUrls(url); - if (CollectionUtils.isNotEmpty(urls)) { - notify(url, listener, urls); - logger.error("Failed to subscribe " + url + ", Using cached list: " + urls + " from cache file: " + getUrl().getParameter(FILE_KEY, System.getProperty("user.home") + "/dubbo-registry-" + url.getHost() + ".cache") + ", cause: " + t.getMessage(), t); - } else { - // If the startup detection is opened, the Exception is thrown directly. - boolean check = getUrl().getParameter(Constants.CHECK_KEY, true) - && url.getParameter(Constants.CHECK_KEY, true); - boolean skipFailback = t instanceof SkipFailbackWrapperException; - if (check || skipFailback) { - if (skipFailback) { - t = t.getCause(); - } - throw new IllegalStateException("Failed to subscribe " + url + ", cause: " + t.getMessage(), t); - } else { - logger.error("Failed to subscribe " + url + ", waiting for retry, cause: " + t.getMessage(), t); - } - } - - // Record a failed registration request to a failed list, retry regularly - addFailedSubscribed(url, listener); - } - } - - @Override - public void unsubscribe(URL url, NotifyListener listener) { - super.unsubscribe(url, listener); - removeFailedSubscribed(url, listener); - try { - // Sending a canceling subscription request to the server side - doUnsubscribe(url, listener); - } catch (Exception e) { - Throwable t = e; - - // If the startup detection is opened, the Exception is thrown directly. - boolean check = getUrl().getParameter(Constants.CHECK_KEY, true) - && url.getParameter(Constants.CHECK_KEY, true); - boolean skipFailback = t instanceof SkipFailbackWrapperException; - if (check || skipFailback) { - if (skipFailback) { - t = t.getCause(); - } - throw new IllegalStateException("Failed to unsubscribe " + url + " to registry " + getUrl().getAddress() + ", cause: " + t.getMessage(), t); - } else { - logger.error("Failed to unsubscribe " + url + ", waiting for retry, cause: " + t.getMessage(), t); - } - - // Record a failed registration request to a failed list, retry regularly - addFailedUnsubscribed(url, listener); - } - } - - @Override - protected void notify(URL url, NotifyListener listener, List urls) { - if (url == null) { - throw new IllegalArgumentException("notify url == null"); - } - if (listener == null) { - throw new IllegalArgumentException("notify listener == null"); - } - try { - doNotify(url, listener, urls); - } catch (Exception t) { - // Record a failed registration request to a failed list - logger.error("Failed to notify addresses for subscribe " + url + ", cause: " + t.getMessage(), t); - } - } - - protected void doNotify(URL url, NotifyListener listener, List urls) { - super.notify(url, listener, urls); - } - - @Override - protected void recover() throws Exception { - // register - Set recoverRegistered = new HashSet(getRegistered()); - if (!recoverRegistered.isEmpty()) { - if (logger.isInfoEnabled()) { - logger.info("Recover register url " + recoverRegistered); - } - for (URL url : recoverRegistered) { - // remove fail registry or unRegistry task first. - removeFailedRegistered(url); - removeFailedUnregistered(url); - addFailedRegistered(url); - } - } - // subscribe - Map> recoverSubscribed = new HashMap>(getSubscribed()); - if (!recoverSubscribed.isEmpty()) { - if (logger.isInfoEnabled()) { - logger.info("Recover subscribe url " + recoverSubscribed.keySet()); - } - for (Map.Entry> entry : recoverSubscribed.entrySet()) { - URL url = entry.getKey(); - for (NotifyListener listener : entry.getValue()) { - // First remove other tasks to ensure that addFailedSubscribed can succeed. - removeFailedSubscribed(url, listener); - addFailedSubscribed(url, listener); - } - } - } - } - - @Override - public void destroy() { - super.destroy(); - retryTimer.stop(); - } - - // ==== Template method ==== - - public abstract void doRegister(URL url); - - public abstract void doUnregister(URL url); - - public abstract void doSubscribe(URL url, NotifyListener listener); - - public abstract void doUnsubscribe(URL url, NotifyListener listener); - - static class Holder { - - private final URL url; - - private final NotifyListener notifyListener; - - Holder(URL url, NotifyListener notifyListener) { - if (url == null || notifyListener == null) { - throw new IllegalArgumentException(); - } - this.url = url; - this.notifyListener = notifyListener; - } - - @Override - public int hashCode() { - return url.hashCode() + notifyListener.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof Holder) { - Holder h = (Holder) obj; - return this.url.equals(h.url) && this.notifyListener.equals(h.notifyListener); - } else { - return false; - } - } - } -} +/* + * 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.registry.support; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.timer.HashedWheelTimer; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.common.utils.NamedThreadFactory; +import org.apache.dubbo.registry.NotifyListener; +import org.apache.dubbo.registry.retry.FailedRegisteredTask; +import org.apache.dubbo.registry.retry.FailedSubscribedTask; +import org.apache.dubbo.registry.retry.FailedUnregisteredTask; +import org.apache.dubbo.registry.retry.FailedUnsubscribedTask; +import org.apache.dubbo.remoting.Constants; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.TimeUnit; + +import static org.apache.dubbo.common.constants.CommonConstants.FILE_KEY; +import static org.apache.dubbo.registry.Constants.DEFAULT_REGISTRY_RETRY_PERIOD; +import static org.apache.dubbo.registry.Constants.REGISTRY_RETRY_PERIOD_KEY; + +/** + * FailbackRegistry. (SPI, Prototype, ThreadSafe) + */ +public abstract class FailbackRegistry extends AbstractRegistry { + + /* retry task map */ + + private final ConcurrentMap failedRegistered = new ConcurrentHashMap(); + + private final ConcurrentMap failedUnregistered = new ConcurrentHashMap(); + + private final ConcurrentMap failedSubscribed = new ConcurrentHashMap(); + + private final ConcurrentMap failedUnsubscribed = new ConcurrentHashMap(); + + /** + * The time in milliseconds the retryExecutor will wait + */ + private final int retryPeriod; + + // Timer for failure retry, regular check if there is a request for failure, and if there is, an unlimited retry + private final HashedWheelTimer retryTimer; + + public FailbackRegistry(URL url) { + super(url); + this.retryPeriod = url.getParameter(REGISTRY_RETRY_PERIOD_KEY, DEFAULT_REGISTRY_RETRY_PERIOD); + + // since the retry task will not be very much. 128 ticks is enough. + retryTimer = new HashedWheelTimer(new NamedThreadFactory("DubboRegistryRetryTimer", true), retryPeriod, TimeUnit.MILLISECONDS, 128); + } + + public void removeFailedRegisteredTask(URL url) { + failedRegistered.remove(url); + } + + public void removeFailedUnregisteredTask(URL url) { + failedUnregistered.remove(url); + } + + public void removeFailedSubscribedTask(URL url, NotifyListener listener) { + Holder h = new Holder(url, listener); + failedSubscribed.remove(h); + } + + public void removeFailedUnsubscribedTask(URL url, NotifyListener listener) { + Holder h = new Holder(url, listener); + failedUnsubscribed.remove(h); + } + + private void addFailedRegistered(URL url) { + FailedRegisteredTask oldOne = failedRegistered.get(url); + if (oldOne != null) { + return; + } + FailedRegisteredTask newTask = new FailedRegisteredTask(url, this); + oldOne = failedRegistered.putIfAbsent(url, newTask); + if (oldOne == null) { + // never has a retry task. then start a new task for retry. + retryTimer.newTimeout(newTask, retryPeriod, TimeUnit.MILLISECONDS); + } + } + + private void removeFailedRegistered(URL url) { + FailedRegisteredTask f = failedRegistered.remove(url); + if (f != null) { + f.cancel(); + } + } + + private void addFailedUnregistered(URL url) { + FailedUnregisteredTask oldOne = failedUnregistered.get(url); + if (oldOne != null) { + return; + } + FailedUnregisteredTask newTask = new FailedUnregisteredTask(url, this); + oldOne = failedUnregistered.putIfAbsent(url, newTask); + if (oldOne == null) { + // never has a retry task. then start a new task for retry. + retryTimer.newTimeout(newTask, retryPeriod, TimeUnit.MILLISECONDS); + } + } + + private void removeFailedUnregistered(URL url) { + FailedUnregisteredTask f = failedUnregistered.remove(url); + if (f != null) { + f.cancel(); + } + } + + protected void addFailedSubscribed(URL url, NotifyListener listener) { + Holder h = new Holder(url, listener); + FailedSubscribedTask oldOne = failedSubscribed.get(h); + if (oldOne != null) { + return; + } + FailedSubscribedTask newTask = new FailedSubscribedTask(url, this, listener); + oldOne = failedSubscribed.putIfAbsent(h, newTask); + if (oldOne == null) { + // never has a retry task. then start a new task for retry. + retryTimer.newTimeout(newTask, retryPeriod, TimeUnit.MILLISECONDS); + } + } + + public void removeFailedSubscribed(URL url, NotifyListener listener) { + Holder h = new Holder(url, listener); + FailedSubscribedTask f = failedSubscribed.remove(h); + if (f != null) { + f.cancel(); + } + removeFailedUnsubscribed(url, listener); + } + + private void addFailedUnsubscribed(URL url, NotifyListener listener) { + Holder h = new Holder(url, listener); + FailedUnsubscribedTask oldOne = failedUnsubscribed.get(h); + if (oldOne != null) { + return; + } + FailedUnsubscribedTask newTask = new FailedUnsubscribedTask(url, this, listener); + oldOne = failedUnsubscribed.putIfAbsent(h, newTask); + if (oldOne == null) { + // never has a retry task. then start a new task for retry. + retryTimer.newTimeout(newTask, retryPeriod, TimeUnit.MILLISECONDS); + } + } + + private void removeFailedUnsubscribed(URL url, NotifyListener listener) { + Holder h = new Holder(url, listener); + FailedUnsubscribedTask f = failedUnsubscribed.remove(h); + if (f != null) { + f.cancel(); + } + } + + ConcurrentMap getFailedRegistered() { + return failedRegistered; + } + + ConcurrentMap getFailedUnregistered() { + return failedUnregistered; + } + + ConcurrentMap getFailedSubscribed() { + return failedSubscribed; + } + + ConcurrentMap getFailedUnsubscribed() { + return failedUnsubscribed; + } + + + @Override + public void register(URL url) { + if (!acceptable(url)) { + logger.info("URL " + url + " will not be registered to Registry. Registry " + url + " does not accept service of this protocol type."); + return; + } + super.register(url); + removeFailedRegistered(url); + removeFailedUnregistered(url); + try { + // Sending a registration request to the server side + doRegister(url); + } catch (Exception e) { + Throwable t = e; + + // If the startup detection is opened, the Exception is thrown directly. + boolean check = getUrl().getParameter(Constants.CHECK_KEY, true) + && url.getParameter(Constants.CHECK_KEY, true) + && !(url.getPort() == 0); + boolean skipFailback = t instanceof SkipFailbackWrapperException; + if (check || skipFailback) { + if (skipFailback) { + t = t.getCause(); + } + throw new IllegalStateException("Failed to register " + url + " to registry " + getUrl().getAddress() + ", cause: " + t.getMessage(), t); + } else { + logger.error("Failed to register " + url + ", waiting for retry, cause: " + t.getMessage(), t); + } + + // Record a failed registration request to a failed list, retry regularly + addFailedRegistered(url); + } + } + + @Override + public void reExportRegister(URL url) { + if (!acceptable(url)) { + logger.info("URL " + url + " will not be registered to Registry. Registry " + url + " does not accept service of this protocol type."); + return; + } + super.register(url); + removeFailedRegistered(url); + removeFailedUnregistered(url); + try { + // Sending a registration request to the server side + doRegister(url); + } catch (Exception e) { + if (!(e instanceof SkipFailbackWrapperException)) { + throw new IllegalStateException("Failed to register (re-export) " + url + " to registry " + getUrl().getAddress() + ", cause: " + e.getMessage(), e); + } + } + } + + @Override + public void unregister(URL url) { + super.unregister(url); + removeFailedRegistered(url); + removeFailedUnregistered(url); + try { + // Sending a cancellation request to the server side + doUnregister(url); + } catch (Exception e) { + Throwable t = e; + + // If the startup detection is opened, the Exception is thrown directly. + boolean check = getUrl().getParameter(Constants.CHECK_KEY, true) + && url.getParameter(Constants.CHECK_KEY, true) + && !(url.getPort() == 0); + boolean skipFailback = t instanceof SkipFailbackWrapperException; + if (check || skipFailback) { + if (skipFailback) { + t = t.getCause(); + } + throw new IllegalStateException("Failed to unregister " + url + " to registry " + getUrl().getAddress() + ", cause: " + t.getMessage(), t); + } else { + logger.error("Failed to unregister " + url + ", waiting for retry, cause: " + t.getMessage(), t); + } + + // Record a failed registration request to a failed list, retry regularly + addFailedUnregistered(url); + } + } + + @Override + public void reExportUnregister(URL url) { + super.unregister(url); + removeFailedRegistered(url); + removeFailedUnregistered(url); + try { + // Sending a cancellation request to the server side + doUnregister(url); + } catch (Exception e) { + if (!(e instanceof SkipFailbackWrapperException)) { + throw new IllegalStateException("Failed to unregister(re-export) " + url + " to registry " + getUrl().getAddress() + ", cause: " + e.getMessage(), e); + } + } + } + + @Override + public void subscribe(URL url, NotifyListener listener) { + super.subscribe(url, listener); + removeFailedSubscribed(url, listener); + try { + // Sending a subscription request to the server side + doSubscribe(url, listener); + } catch (Exception e) { + Throwable t = e; + + List urls = getCacheUrls(url); + if (CollectionUtils.isNotEmpty(urls)) { + notify(url, listener, urls); + logger.error("Failed to subscribe " + url + ", Using cached list: " + urls + " from cache file: " + getUrl().getParameter(FILE_KEY, System.getProperty("user.home") + "/dubbo-registry-" + url.getHost() + ".cache") + ", cause: " + t.getMessage(), t); + } else { + // If the startup detection is opened, the Exception is thrown directly. + boolean check = getUrl().getParameter(Constants.CHECK_KEY, true) + && url.getParameter(Constants.CHECK_KEY, true); + boolean skipFailback = t instanceof SkipFailbackWrapperException; + if (check || skipFailback) { + if (skipFailback) { + t = t.getCause(); + } + throw new IllegalStateException("Failed to subscribe " + url + ", cause: " + t.getMessage(), t); + } else { + logger.error("Failed to subscribe " + url + ", waiting for retry, cause: " + t.getMessage(), t); + } + } + + // Record a failed registration request to a failed list, retry regularly + addFailedSubscribed(url, listener); + } + } + + @Override + public void unsubscribe(URL url, NotifyListener listener) { + super.unsubscribe(url, listener); + removeFailedSubscribed(url, listener); + try { + // Sending a canceling subscription request to the server side + doUnsubscribe(url, listener); + } catch (Exception e) { + Throwable t = e; + + // If the startup detection is opened, the Exception is thrown directly. + boolean check = getUrl().getParameter(Constants.CHECK_KEY, true) + && url.getParameter(Constants.CHECK_KEY, true); + boolean skipFailback = t instanceof SkipFailbackWrapperException; + if (check || skipFailback) { + if (skipFailback) { + t = t.getCause(); + } + throw new IllegalStateException("Failed to unsubscribe " + url + " to registry " + getUrl().getAddress() + ", cause: " + t.getMessage(), t); + } else { + logger.error("Failed to unsubscribe " + url + ", waiting for retry, cause: " + t.getMessage(), t); + } + + // Record a failed registration request to a failed list, retry regularly + addFailedUnsubscribed(url, listener); + } + } + + @Override + protected void notify(URL url, NotifyListener listener, List urls) { + if (url == null) { + throw new IllegalArgumentException("notify url == null"); + } + if (listener == null) { + throw new IllegalArgumentException("notify listener == null"); + } + try { + doNotify(url, listener, urls); + } catch (Exception t) { + // Record a failed registration request to a failed list + logger.error("Failed to notify addresses for subscribe " + url + ", cause: " + t.getMessage(), t); + } + } + + protected void doNotify(URL url, NotifyListener listener, List urls) { + super.notify(url, listener, urls); + } + + @Override + protected void recover() throws Exception { + // register + Set recoverRegistered = new HashSet(getRegistered()); + if (!recoverRegistered.isEmpty()) { + if (logger.isInfoEnabled()) { + logger.info("Recover register url " + recoverRegistered); + } + for (URL url : recoverRegistered) { + // remove fail registry or unRegistry task first. + removeFailedRegistered(url); + removeFailedUnregistered(url); + addFailedRegistered(url); + } + } + // subscribe + Map> recoverSubscribed = new HashMap>(getSubscribed()); + if (!recoverSubscribed.isEmpty()) { + if (logger.isInfoEnabled()) { + logger.info("Recover subscribe url " + recoverSubscribed.keySet()); + } + for (Map.Entry> entry : recoverSubscribed.entrySet()) { + URL url = entry.getKey(); + for (NotifyListener listener : entry.getValue()) { + // First remove other tasks to ensure that addFailedSubscribed can succeed. + removeFailedSubscribed(url, listener); + addFailedSubscribed(url, listener); + } + } + } + } + + @Override + public void destroy() { + super.destroy(); + retryTimer.stop(); + } + + // ==== Template method ==== + + public abstract void doRegister(URL url); + + public abstract void doUnregister(URL url); + + public abstract void doSubscribe(URL url, NotifyListener listener); + + public abstract void doUnsubscribe(URL url, NotifyListener listener); + + static class Holder { + + private final URL url; + + private final NotifyListener notifyListener; + + Holder(URL url, NotifyListener notifyListener) { + if (url == null || notifyListener == null) { + throw new IllegalArgumentException(); + } + this.url = url; + this.notifyListener = notifyListener; + } + + @Override + public int hashCode() { + return url.hashCode() + notifyListener.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Holder) { + Holder h = (Holder) obj; + return this.url.equals(h.url) && this.notifyListener.equals(h.notifyListener); + } else { + return false; + } + } + } +} diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/PerformanceRegistryTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/PerformanceRegistryTest.java index 7d5b731638..ce8b8643b5 100644 --- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/PerformanceRegistryTest.java +++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/PerformanceRegistryTest.java @@ -1,67 +1,67 @@ -/* - * 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.registry; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.utils.NetUtils; - -import org.junit.jupiter.api.Test; - -/** - * RegistryPerformanceTest - * - */ -public class PerformanceRegistryTest { - - private static final Logger logger = LoggerFactory.getLogger(PerformanceRegistryTest.class); - - @Test - public void testRegistry() { - // read server info from property - if (PerformanceUtils.getProperty("server", null) == null) { - logger.warn("Please set -Dserver=127.0.0.1:9090"); - return; - } - final int base = PerformanceUtils.getIntProperty("base", 0); - final int concurrent = PerformanceUtils.getIntProperty("concurrent", 100); - int r = PerformanceUtils.getIntProperty("runs", 1000); - final int runs = r > 0 ? r : Integer.MAX_VALUE; - final Registry registry = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension().getRegistry(URL.valueOf("remote://admin:hello1234@" + PerformanceUtils.getProperty("server", "10.20.153.28:9090"))); - for (int i = 0; i < concurrent; i++) { - final int t = i; - new Thread(new Runnable() { - public void run() { - for (int j = 0; j < runs; j++) { - registry.register(URL.valueOf("remote://" + NetUtils.getLocalHost() + ":8080/demoService" + t + "_" + j + "?version=1.0.0&application=demo&dubbo=2.0&interface=" + "org.apache.dubbo.demo.DemoService" + (base + t) + "_" + (base + j))); - } - } - }).start(); - } - synchronized (PerformanceRegistryTest.class) { - while (true) { - try { - PerformanceRegistryTest.class.wait(); - } catch (InterruptedException e) { - } - } - } - } - -} \ No newline at end of file +/* + * 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.registry; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.NetUtils; + +import org.junit.jupiter.api.Test; + +/** + * RegistryPerformanceTest + * + */ +public class PerformanceRegistryTest { + + private static final Logger logger = LoggerFactory.getLogger(PerformanceRegistryTest.class); + + @Test + public void testRegistry() { + // read server info from property + if (PerformanceUtils.getProperty("server", null) == null) { + logger.warn("Please set -Dserver=127.0.0.1:9090"); + return; + } + final int base = PerformanceUtils.getIntProperty("base", 0); + final int concurrent = PerformanceUtils.getIntProperty("concurrent", 100); + int r = PerformanceUtils.getIntProperty("runs", 1000); + final int runs = r > 0 ? r : Integer.MAX_VALUE; + final Registry registry = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension().getRegistry(URL.valueOf("remote://admin:hello1234@" + PerformanceUtils.getProperty("server", "10.20.153.28:9090"))); + for (int i = 0; i < concurrent; i++) { + final int t = i; + new Thread(new Runnable() { + public void run() { + for (int j = 0; j < runs; j++) { + registry.register(URL.valueOf("remote://" + NetUtils.getLocalHost() + ":8080/demoService" + t + "_" + j + "?version=1.0.0&application=demo&dubbo=2.0&interface=" + "org.apache.dubbo.demo.DemoService" + (base + t) + "_" + (base + j))); + } + } + }).start(); + } + synchronized (PerformanceRegistryTest.class) { + while (true) { + try { + PerformanceRegistryTest.class.wait(); + } catch (InterruptedException e) { + } + } + } + } + +} diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/PerformanceUtils.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/PerformanceUtils.java index 84051db489..76cf7ca562 100644 --- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/PerformanceUtils.java +++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/PerformanceUtils.java @@ -1,127 +1,127 @@ -/* - * 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.registry; - -import java.net.NetworkInterface; -import java.net.SocketException; -import java.text.DecimalFormat; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.List; - -/** - * PerformanceUtils - * - */ -public class PerformanceUtils { - - private static final int WIDTH = 64; - - public static String getProperty(String key, String defaultValue) { - String value = System.getProperty(key); - if (value == null || value.trim().length() == 0 || value.startsWith("$")) { - return defaultValue; - } - return value.trim(); - } - - public static int getIntProperty(String key, int defaultValue) { - String value = System.getProperty(key); - if (value == null || value.trim().length() == 0 || value.startsWith("$")) { - return defaultValue; - } - return Integer.parseInt(value.trim()); - } - - public static boolean getBooleanProperty(String key, boolean defaultValue) { - String value = System.getProperty(key); - if (value == null || value.trim().length() == 0 || value.startsWith("$")) { - return defaultValue; - } - return Boolean.parseBoolean(value.trim()); - } - - public static List getEnvironment() { - List environment = new ArrayList(); - environment.add("OS: " + System.getProperty("os.name") + " " + System.getProperty("os.version") + " " + System.getProperty("os.arch", "")); - environment.add("CPU: " + Runtime.getRuntime().availableProcessors() + " cores"); - environment.add("JVM: " + System.getProperty("java.vm.name") + " " + System.getProperty("java.runtime.version")); - environment.add("Memory: " + DecimalFormat.getIntegerInstance().format(Runtime.getRuntime().totalMemory()) - + " bytes (Max: " + DecimalFormat.getIntegerInstance().format(Runtime.getRuntime().maxMemory()) + " bytes)"); - NetworkInterface ni = PerformanceUtils.getNetworkInterface(); - if (ni != null) { - environment.add("Network: " + ni.getDisplayName()); - } - return environment; - } - - public static void printSeparator() { - StringBuilder pad = new StringBuilder(); - for (int i = 0; i < WIDTH; i++) { - pad.append("-"); - } - System.out.println("+" + pad + "+"); - } - - public static void printBorder() { - StringBuilder pad = new StringBuilder(); - for (int i = 0; i < WIDTH; i++) { - pad.append("="); - } - System.out.println("+" + pad + "+"); - } - - public static void printBody(String msg) { - StringBuilder pad = new StringBuilder(); - int len = WIDTH - msg.length() - 1; - if (len > 0) { - for (int i = 0; i < len; i++) { - pad.append(" "); - } - } - System.out.println("| " + msg + pad + "|"); - } - - public static void printHeader(String msg) { - StringBuilder pad = new StringBuilder(); - int len = WIDTH - msg.length(); - if (len > 0) { - int half = len / 2; - for (int i = 0; i < half; i++) { - pad.append(" "); - } - } - System.out.println("|" + pad + msg + pad + ((len % 2 == 0) ? "" : " ") + "|"); - } - - public static NetworkInterface getNetworkInterface() { - try { - Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); - if (interfaces != null) { - while (interfaces.hasMoreElements()) { - try { - return interfaces.nextElement(); - } catch (Throwable e) { - } - } - } - } catch (SocketException e) { - } - return null; - } - -} \ No newline at end of file +/* + * 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.registry; + +import java.net.NetworkInterface; +import java.net.SocketException; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; + +/** + * PerformanceUtils + * + */ +public class PerformanceUtils { + + private static final int WIDTH = 64; + + public static String getProperty(String key, String defaultValue) { + String value = System.getProperty(key); + if (value == null || value.trim().length() == 0 || value.startsWith("$")) { + return defaultValue; + } + return value.trim(); + } + + public static int getIntProperty(String key, int defaultValue) { + String value = System.getProperty(key); + if (value == null || value.trim().length() == 0 || value.startsWith("$")) { + return defaultValue; + } + return Integer.parseInt(value.trim()); + } + + public static boolean getBooleanProperty(String key, boolean defaultValue) { + String value = System.getProperty(key); + if (value == null || value.trim().length() == 0 || value.startsWith("$")) { + return defaultValue; + } + return Boolean.parseBoolean(value.trim()); + } + + public static List getEnvironment() { + List environment = new ArrayList(); + environment.add("OS: " + System.getProperty("os.name") + " " + System.getProperty("os.version") + " " + System.getProperty("os.arch", "")); + environment.add("CPU: " + Runtime.getRuntime().availableProcessors() + " cores"); + environment.add("JVM: " + System.getProperty("java.vm.name") + " " + System.getProperty("java.runtime.version")); + environment.add("Memory: " + DecimalFormat.getIntegerInstance().format(Runtime.getRuntime().totalMemory()) + + " bytes (Max: " + DecimalFormat.getIntegerInstance().format(Runtime.getRuntime().maxMemory()) + " bytes)"); + NetworkInterface ni = PerformanceUtils.getNetworkInterface(); + if (ni != null) { + environment.add("Network: " + ni.getDisplayName()); + } + return environment; + } + + public static void printSeparator() { + StringBuilder pad = new StringBuilder(); + for (int i = 0; i < WIDTH; i++) { + pad.append("-"); + } + System.out.println("+" + pad + "+"); + } + + public static void printBorder() { + StringBuilder pad = new StringBuilder(); + for (int i = 0; i < WIDTH; i++) { + pad.append("="); + } + System.out.println("+" + pad + "+"); + } + + public static void printBody(String msg) { + StringBuilder pad = new StringBuilder(); + int len = WIDTH - msg.length() - 1; + if (len > 0) { + for (int i = 0; i < len; i++) { + pad.append(" "); + } + } + System.out.println("| " + msg + pad + "|"); + } + + public static void printHeader(String msg) { + StringBuilder pad = new StringBuilder(); + int len = WIDTH - msg.length(); + if (len > 0) { + int half = len / 2; + for (int i = 0; i < half; i++) { + pad.append(" "); + } + } + System.out.println("|" + pad + msg + pad + ((len % 2 == 0) ? "" : " ") + "|"); + } + + public static NetworkInterface getNetworkInterface() { + try { + Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); + if (interfaces != null) { + while (interfaces.hasMoreElements()) { + try { + return interfaces.nextElement(); + } catch (Throwable e) { + } + } + } + } catch (SocketException e) { + } + return null; + } + +} diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/ServiceDiscoveryTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/ServiceDiscoveryTest.java index e31e7d1f8e..c002c1af5c 100644 --- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/ServiceDiscoveryTest.java +++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/ServiceDiscoveryTest.java @@ -261,4 +261,4 @@ public class ServiceDiscoveryTest { public ServiceDiscovery getServiceDiscovery() { return serviceDiscovery; } -} \ No newline at end of file +} diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/support/AbstractRegistryFactoryTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/support/AbstractRegistryFactoryTest.java index a43583bdfb..69efa83c07 100644 --- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/support/AbstractRegistryFactoryTest.java +++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/support/AbstractRegistryFactoryTest.java @@ -1,126 +1,126 @@ -/* - * 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.registry.support; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.utils.NetUtils; -import org.apache.dubbo.registry.NotifyListener; -import org.apache.dubbo.registry.Registry; -import org.apache.dubbo.registry.RegistryFactory; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import java.util.Collection; -import java.util.List; - -/** - * AbstractRegistryFactoryTest - */ -public class AbstractRegistryFactoryTest { - - private RegistryFactory registryFactory = new AbstractRegistryFactory() { - - @Override - protected Registry createRegistry(final URL url) { - return new Registry() { - - public URL getUrl() { - return url; - } - - @Override - public boolean isAvailable() { - return false; - } - - @Override - public void destroy() { - } - - @Override - public void register(URL url) { - } - - @Override - public void unregister(URL url) { - } - - @Override - public void subscribe(URL url, NotifyListener listener) { - } - - @Override - public void unsubscribe(URL url, NotifyListener listener) { - } - - @Override - public List lookup(URL url) { - return null; - } - - }; - } - }; - - @Test - public void testRegistryFactoryCache() throws Exception { - URL url = URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostAddress() + ":2233"); - Registry registry1 = registryFactory.getRegistry(url); - Registry registry2 = registryFactory.getRegistry(url); - Assertions.assertEquals(registry1, registry2); - } - - /** - * Registration center address `dubbo` does not resolve - */ - // @Test - public void testRegistryFactoryIpCache() throws Exception { - Registry registry1 = registryFactory.getRegistry(URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostName() + ":2233")); - Registry registry2 = registryFactory.getRegistry(URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostAddress() + ":2233")); - Assertions.assertEquals(registry1, registry2); - } - - @Test - public void testRegistryFactoryGroupCache() throws Exception { - Registry registry1 = registryFactory.getRegistry(URL.valueOf("dubbo://" + NetUtils.getLocalHost() + ":2233?group=aaa")); - Registry registry2 = registryFactory.getRegistry(URL.valueOf("dubbo://" + NetUtils.getLocalHost() + ":2233?group=bbb")); - Assertions.assertNotSame(registry1, registry2); - } - - @Test - public void testDestroyAllRegistries() { - Registry registry1 = registryFactory.getRegistry(URL.valueOf("dubbo://" + NetUtils.getLocalHost() + ":8888?group=xxx")); - Registry registry2 = registryFactory.getRegistry(URL.valueOf("dubbo://" + NetUtils.getLocalHost() + ":9999?group=yyy")); - Registry registry3 = new AbstractRegistry(URL.valueOf("dubbo://" + NetUtils.getLocalHost() + ":2020?group=yyy")) { - @Override - public boolean isAvailable() { - return true; - } - }; - Collection registries = AbstractRegistryFactory.getRegistries(); - Assertions.assertTrue(registries.contains(registry1)); - Assertions.assertTrue(registries.contains(registry2)); - registry3.destroy(); - registries = AbstractRegistryFactory.getRegistries(); - Assertions.assertFalse(registries.contains(registry3)); - AbstractRegistryFactory.destroyAll(); - registries = AbstractRegistryFactory.getRegistries(); - Assertions.assertFalse(registries.contains(registry1)); - Assertions.assertFalse(registries.contains(registry2)); - } -} +/* + * 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.registry.support; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.utils.NetUtils; +import org.apache.dubbo.registry.NotifyListener; +import org.apache.dubbo.registry.Registry; +import org.apache.dubbo.registry.RegistryFactory; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.Collection; +import java.util.List; + +/** + * AbstractRegistryFactoryTest + */ +public class AbstractRegistryFactoryTest { + + private RegistryFactory registryFactory = new AbstractRegistryFactory() { + + @Override + protected Registry createRegistry(final URL url) { + return new Registry() { + + public URL getUrl() { + return url; + } + + @Override + public boolean isAvailable() { + return false; + } + + @Override + public void destroy() { + } + + @Override + public void register(URL url) { + } + + @Override + public void unregister(URL url) { + } + + @Override + public void subscribe(URL url, NotifyListener listener) { + } + + @Override + public void unsubscribe(URL url, NotifyListener listener) { + } + + @Override + public List lookup(URL url) { + return null; + } + + }; + } + }; + + @Test + public void testRegistryFactoryCache() throws Exception { + URL url = URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostAddress() + ":2233"); + Registry registry1 = registryFactory.getRegistry(url); + Registry registry2 = registryFactory.getRegistry(url); + Assertions.assertEquals(registry1, registry2); + } + + /** + * Registration center address `dubbo` does not resolve + */ + // @Test + public void testRegistryFactoryIpCache() throws Exception { + Registry registry1 = registryFactory.getRegistry(URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostName() + ":2233")); + Registry registry2 = registryFactory.getRegistry(URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostAddress() + ":2233")); + Assertions.assertEquals(registry1, registry2); + } + + @Test + public void testRegistryFactoryGroupCache() throws Exception { + Registry registry1 = registryFactory.getRegistry(URL.valueOf("dubbo://" + NetUtils.getLocalHost() + ":2233?group=aaa")); + Registry registry2 = registryFactory.getRegistry(URL.valueOf("dubbo://" + NetUtils.getLocalHost() + ":2233?group=bbb")); + Assertions.assertNotSame(registry1, registry2); + } + + @Test + public void testDestroyAllRegistries() { + Registry registry1 = registryFactory.getRegistry(URL.valueOf("dubbo://" + NetUtils.getLocalHost() + ":8888?group=xxx")); + Registry registry2 = registryFactory.getRegistry(URL.valueOf("dubbo://" + NetUtils.getLocalHost() + ":9999?group=yyy")); + Registry registry3 = new AbstractRegistry(URL.valueOf("dubbo://" + NetUtils.getLocalHost() + ":2020?group=yyy")) { + @Override + public boolean isAvailable() { + return true; + } + }; + Collection registries = AbstractRegistryFactory.getRegistries(); + Assertions.assertTrue(registries.contains(registry1)); + Assertions.assertTrue(registries.contains(registry2)); + registry3.destroy(); + registries = AbstractRegistryFactory.getRegistries(); + Assertions.assertFalse(registries.contains(registry3)); + AbstractRegistryFactory.destroyAll(); + registries = AbstractRegistryFactory.getRegistries(); + Assertions.assertFalse(registries.contains(registry1)); + Assertions.assertFalse(registries.contains(registry2)); + } +} diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/support/FailbackRegistryTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/support/FailbackRegistryTest.java index 94c44a056e..82c6444bc4 100644 --- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/support/FailbackRegistryTest.java +++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/support/FailbackRegistryTest.java @@ -1,243 +1,243 @@ -/* - * 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.registry.support; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.utils.CollectionUtils; -import org.apache.dubbo.registry.NotifyListener; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.atomic.AtomicReference; - -import static org.apache.dubbo.registry.Constants.CONSUMER_PROTOCOL; -import static org.apache.dubbo.registry.Constants.REGISTRY_RETRY_PERIOD_KEY; -import static org.junit.jupiter.api.Assertions.assertEquals; - -public class FailbackRegistryTest { - static String service; - static URL serviceUrl; - static URL registryUrl; - MockRegistry registry; - private int FAILED_PERIOD = 200; - private int sleeptime = 100; - private int trytimes = 5; - - /** - * @throws java.lang.Exception - */ - @BeforeEach - public void setUp() throws Exception { - service = "org.apache.dubbo.test.DemoService"; - serviceUrl = URL.valueOf("remote://127.0.0.1/demoservice?method=get"); - registryUrl = URL.valueOf("http://1.2.3.4:9090/registry?check=false&file=N/A").addParameter(REGISTRY_RETRY_PERIOD_KEY, String.valueOf(FAILED_PERIOD)); - } - - /** - * Test method for retry - * - * @throws Exception - */ - @Test - public void testDoRetry() throws Exception { - - final AtomicReference notified = new AtomicReference(false); - - // the latest latch just for 3. Because retry method has been removed. - final CountDownLatch latch = new CountDownLatch(2); - - NotifyListener listner = new NotifyListener() { - @Override - public void notify(List urls) { - notified.set(Boolean.TRUE); - } - }; - registry = new MockRegistry(registryUrl, latch); - registry.setBad(true); - registry.register(serviceUrl); - registry.unregister(serviceUrl); - registry.subscribe(serviceUrl.setProtocol(CONSUMER_PROTOCOL).addParameters(CollectionUtils.toStringMap("check", "false")), listner); - registry.unsubscribe(serviceUrl.setProtocol(CONSUMER_PROTOCOL).addParameters(CollectionUtils.toStringMap("check", "false")), listner); - - //Failure can not be called to listener. - assertEquals(false, notified.get()); - assertEquals(2, latch.getCount()); - - registry.setBad(false); - - for (int i = 0; i < trytimes; i++) { - System.out.println("failback registry retry ,times:" + i); - //System.out.println(latch.getCount()); - if (latch.getCount() == 0) - break; - Thread.sleep(sleeptime); - } -// Thread.sleep(100000);//for debug - assertEquals(0, latch.getCount()); - //The failedsubcribe corresponding key will be cleared when unsubscribing - assertEquals(false, notified.get()); - } - - @Test - public void testDoRetry_subscribe() throws Exception { - - final CountDownLatch latch = new CountDownLatch(1);//All of them are called 4 times. A successful attempt to lose 1. subscribe will not be done - - registry = new MockRegistry(registryUrl, latch); - registry.setBad(true); - registry.register(serviceUrl); - - registry.setBad(false); - - for (int i = 0; i < trytimes; i++) { - System.out.println("failback registry retry ,times:" + i); - if (latch.getCount() == 0) - break; - Thread.sleep(sleeptime); - } - assertEquals(0, latch.getCount()); - } - - @Test - public void testDoRetry_register() throws Exception { - - final AtomicReference notified = new AtomicReference(false); - final CountDownLatch latch = new CountDownLatch(1);//All of them are called 4 times. A successful attempt to lose 1. subscribe will not be done - - NotifyListener listner = new NotifyListener() { - @Override - public void notify(List urls) { - notified.set(Boolean.TRUE); - } - }; - registry = new MockRegistry(registryUrl, latch); - registry.setBad(true); - registry.subscribe(serviceUrl.setProtocol(CONSUMER_PROTOCOL).addParameters(CollectionUtils.toStringMap("check", "false")), listner); - - //Failure can not be called to listener. - assertEquals(false, notified.get()); - assertEquals(1, latch.getCount()); - - registry.setBad(false); - - for (int i = 0; i < trytimes; i++) { - System.out.println("failback registry retry ,times:" + i); - //System.out.println(latch.getCount()); - if (latch.getCount() == 0) - break; - Thread.sleep(sleeptime); - } -// Thread.sleep(100000); - assertEquals(0, latch.getCount()); - //The failedsubcribe corresponding key will be cleared when unsubscribing - assertEquals(true, notified.get()); - } - - @Test - public void testRecover() throws Exception { - CountDownLatch countDownLatch = new CountDownLatch(4); - final AtomicReference notified = new AtomicReference(false); - NotifyListener listener = new NotifyListener() { - @Override - public void notify(List urls) { - notified.set(Boolean.TRUE); - } - }; - - MockRegistry mockRegistry = new MockRegistry(registryUrl, countDownLatch); - mockRegistry.register(serviceUrl); - mockRegistry.subscribe(serviceUrl, listener); - Assertions.assertEquals(1, mockRegistry.getRegistered().size()); - Assertions.assertEquals(1, mockRegistry.getSubscribed().size()); - mockRegistry.recover(); - countDownLatch.await(); - Assertions.assertEquals(0, mockRegistry.getFailedRegistered().size()); - FailbackRegistry.Holder h = new FailbackRegistry.Holder(registryUrl, listener); - Assertions.assertNull(mockRegistry.getFailedSubscribed().get(h)); - Assertions.assertEquals(countDownLatch.getCount(), 0); - } - - private static class MockRegistry extends FailbackRegistry { - CountDownLatch latch; - private boolean bad = false; - - /** - * @param url - */ - public MockRegistry(URL url, CountDownLatch latch) { - super(url); - this.latch = latch; - } - - /** - * @param bad the bad to set - */ - public void setBad(boolean bad) { - this.bad = bad; - } - - @Override - public void doRegister(URL url) { - if (bad) { - throw new RuntimeException("can not invoke!"); - } - //System.out.println("do doRegister"); - latch.countDown(); - - } - - @Override - public void doUnregister(URL url) { - if (bad) { - throw new RuntimeException("can not invoke!"); - } - //System.out.println("do doUnregister"); - latch.countDown(); - - } - - @Override - public void doSubscribe(URL url, NotifyListener listener) { - if (bad) { - throw new RuntimeException("can not invoke!"); - } - //System.out.println("do doSubscribe"); - super.notify(url, listener, Arrays.asList(new URL[]{serviceUrl})); - latch.countDown(); - } - - @Override - public void doUnsubscribe(URL url, NotifyListener listener) { - if (bad) { - throw new RuntimeException("can not invoke!"); - } - //System.out.println("do doUnsubscribe"); - latch.countDown(); - } - - @Override - public boolean isAvailable() { - return true; - } - - } -} +/* + * 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.registry.support; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.registry.NotifyListener; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicReference; + +import static org.apache.dubbo.registry.Constants.CONSUMER_PROTOCOL; +import static org.apache.dubbo.registry.Constants.REGISTRY_RETRY_PERIOD_KEY; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class FailbackRegistryTest { + static String service; + static URL serviceUrl; + static URL registryUrl; + MockRegistry registry; + private int FAILED_PERIOD = 200; + private int sleeptime = 100; + private int trytimes = 5; + + /** + * @throws java.lang.Exception + */ + @BeforeEach + public void setUp() throws Exception { + service = "org.apache.dubbo.test.DemoService"; + serviceUrl = URL.valueOf("remote://127.0.0.1/demoservice?method=get"); + registryUrl = URL.valueOf("http://1.2.3.4:9090/registry?check=false&file=N/A").addParameter(REGISTRY_RETRY_PERIOD_KEY, String.valueOf(FAILED_PERIOD)); + } + + /** + * Test method for retry + * + * @throws Exception + */ + @Test + public void testDoRetry() throws Exception { + + final AtomicReference notified = new AtomicReference(false); + + // the latest latch just for 3. Because retry method has been removed. + final CountDownLatch latch = new CountDownLatch(2); + + NotifyListener listner = new NotifyListener() { + @Override + public void notify(List urls) { + notified.set(Boolean.TRUE); + } + }; + registry = new MockRegistry(registryUrl, latch); + registry.setBad(true); + registry.register(serviceUrl); + registry.unregister(serviceUrl); + registry.subscribe(serviceUrl.setProtocol(CONSUMER_PROTOCOL).addParameters(CollectionUtils.toStringMap("check", "false")), listner); + registry.unsubscribe(serviceUrl.setProtocol(CONSUMER_PROTOCOL).addParameters(CollectionUtils.toStringMap("check", "false")), listner); + + //Failure can not be called to listener. + assertEquals(false, notified.get()); + assertEquals(2, latch.getCount()); + + registry.setBad(false); + + for (int i = 0; i < trytimes; i++) { + System.out.println("failback registry retry ,times:" + i); + //System.out.println(latch.getCount()); + if (latch.getCount() == 0) + break; + Thread.sleep(sleeptime); + } +// Thread.sleep(100000);//for debug + assertEquals(0, latch.getCount()); + //The failedsubcribe corresponding key will be cleared when unsubscribing + assertEquals(false, notified.get()); + } + + @Test + public void testDoRetry_subscribe() throws Exception { + + final CountDownLatch latch = new CountDownLatch(1);//All of them are called 4 times. A successful attempt to lose 1. subscribe will not be done + + registry = new MockRegistry(registryUrl, latch); + registry.setBad(true); + registry.register(serviceUrl); + + registry.setBad(false); + + for (int i = 0; i < trytimes; i++) { + System.out.println("failback registry retry ,times:" + i); + if (latch.getCount() == 0) + break; + Thread.sleep(sleeptime); + } + assertEquals(0, latch.getCount()); + } + + @Test + public void testDoRetry_register() throws Exception { + + final AtomicReference notified = new AtomicReference(false); + final CountDownLatch latch = new CountDownLatch(1);//All of them are called 4 times. A successful attempt to lose 1. subscribe will not be done + + NotifyListener listner = new NotifyListener() { + @Override + public void notify(List urls) { + notified.set(Boolean.TRUE); + } + }; + registry = new MockRegistry(registryUrl, latch); + registry.setBad(true); + registry.subscribe(serviceUrl.setProtocol(CONSUMER_PROTOCOL).addParameters(CollectionUtils.toStringMap("check", "false")), listner); + + //Failure can not be called to listener. + assertEquals(false, notified.get()); + assertEquals(1, latch.getCount()); + + registry.setBad(false); + + for (int i = 0; i < trytimes; i++) { + System.out.println("failback registry retry ,times:" + i); + //System.out.println(latch.getCount()); + if (latch.getCount() == 0) + break; + Thread.sleep(sleeptime); + } +// Thread.sleep(100000); + assertEquals(0, latch.getCount()); + //The failedsubcribe corresponding key will be cleared when unsubscribing + assertEquals(true, notified.get()); + } + + @Test + public void testRecover() throws Exception { + CountDownLatch countDownLatch = new CountDownLatch(4); + final AtomicReference notified = new AtomicReference(false); + NotifyListener listener = new NotifyListener() { + @Override + public void notify(List urls) { + notified.set(Boolean.TRUE); + } + }; + + MockRegistry mockRegistry = new MockRegistry(registryUrl, countDownLatch); + mockRegistry.register(serviceUrl); + mockRegistry.subscribe(serviceUrl, listener); + Assertions.assertEquals(1, mockRegistry.getRegistered().size()); + Assertions.assertEquals(1, mockRegistry.getSubscribed().size()); + mockRegistry.recover(); + countDownLatch.await(); + Assertions.assertEquals(0, mockRegistry.getFailedRegistered().size()); + FailbackRegistry.Holder h = new FailbackRegistry.Holder(registryUrl, listener); + Assertions.assertNull(mockRegistry.getFailedSubscribed().get(h)); + Assertions.assertEquals(countDownLatch.getCount(), 0); + } + + private static class MockRegistry extends FailbackRegistry { + CountDownLatch latch; + private boolean bad = false; + + /** + * @param url + */ + public MockRegistry(URL url, CountDownLatch latch) { + super(url); + this.latch = latch; + } + + /** + * @param bad the bad to set + */ + public void setBad(boolean bad) { + this.bad = bad; + } + + @Override + public void doRegister(URL url) { + if (bad) { + throw new RuntimeException("can not invoke!"); + } + //System.out.println("do doRegister"); + latch.countDown(); + + } + + @Override + public void doUnregister(URL url) { + if (bad) { + throw new RuntimeException("can not invoke!"); + } + //System.out.println("do doUnregister"); + latch.countDown(); + + } + + @Override + public void doSubscribe(URL url, NotifyListener listener) { + if (bad) { + throw new RuntimeException("can not invoke!"); + } + //System.out.println("do doSubscribe"); + super.notify(url, listener, Arrays.asList(new URL[]{serviceUrl})); + latch.countDown(); + } + + @Override + public void doUnsubscribe(URL url, NotifyListener listener) { + if (bad) { + throw new RuntimeException("can not invoke!"); + } + //System.out.println("do doUnsubscribe"); + latch.countDown(); + } + + @Override + public boolean isAvailable() { + return true; + } + + } +} diff --git a/dubbo-registry/dubbo-registry-api/src/test/resources/log4j.xml b/dubbo-registry/dubbo-registry-api/src/test/resources/log4j.xml index f5c44f1f4e..de4c580e98 100644 --- a/dubbo-registry/dubbo-registry-api/src/test/resources/log4j.xml +++ b/dubbo-registry/dubbo-registry-api/src/test/resources/log4j.xml @@ -1,29 +1,29 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + \ No newline at end of file diff --git a/dubbo-registry/dubbo-registry-multicast/src/main/java/org/apache/dubbo/registry/multicast/MulticastRegistry.java b/dubbo-registry/dubbo-registry-multicast/src/main/java/org/apache/dubbo/registry/multicast/MulticastRegistry.java index 7807fecaf8..1c3bc50409 100644 --- a/dubbo-registry/dubbo-registry-multicast/src/main/java/org/apache/dubbo/registry/multicast/MulticastRegistry.java +++ b/dubbo-registry/dubbo-registry-multicast/src/main/java/org/apache/dubbo/registry/multicast/MulticastRegistry.java @@ -1,433 +1,433 @@ -/* - * 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.registry.multicast; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.utils.CollectionUtils; -import org.apache.dubbo.common.utils.ConcurrentHashSet; -import org.apache.dubbo.common.utils.ExecutorUtil; -import org.apache.dubbo.common.utils.NamedThreadFactory; -import org.apache.dubbo.common.utils.NetUtils; -import org.apache.dubbo.common.utils.UrlUtils; -import org.apache.dubbo.registry.NotifyListener; -import org.apache.dubbo.registry.support.FailbackRegistry; - -import java.io.IOException; -import java.net.DatagramPacket; -import java.net.Inet4Address; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.MulticastSocket; -import java.net.Socket; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; - -import static org.apache.dubbo.common.constants.CommonConstants.ANY_VALUE; -import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_TIMEOUT; -import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY; -import static org.apache.dubbo.common.constants.RegistryConstants.DYNAMIC_KEY; -import static org.apache.dubbo.common.constants.RegistryConstants.EMPTY_PROTOCOL; -import static org.apache.dubbo.common.constants.RegistryConstants.OVERRIDE_PROTOCOL; -import static org.apache.dubbo.common.constants.RegistryConstants.ROUTE_PROTOCOL; -import static org.apache.dubbo.registry.Constants.CONSUMER_PROTOCOL; -import static org.apache.dubbo.registry.Constants.DEFAULT_SESSION_TIMEOUT; -import static org.apache.dubbo.registry.Constants.REGISTER; -import static org.apache.dubbo.registry.Constants.REGISTER_KEY; -import static org.apache.dubbo.registry.Constants.SESSION_TIMEOUT_KEY; -import static org.apache.dubbo.registry.Constants.SUBSCRIBE; -import static org.apache.dubbo.registry.Constants.UNREGISTER; -import static org.apache.dubbo.registry.Constants.UNSUBSCRIBE; - -/** - * MulticastRegistry - */ -public class MulticastRegistry extends FailbackRegistry { - - // logging output - private static final Logger logger = LoggerFactory.getLogger(MulticastRegistry.class); - - private static final int DEFAULT_MULTICAST_PORT = 1234; - - private final InetAddress multicastAddress; - - private final MulticastSocket multicastSocket; - - private final int multicastPort; - - private final ConcurrentMap> received = new ConcurrentHashMap>(); - - private final ScheduledExecutorService cleanExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("DubboMulticastRegistryCleanTimer", true)); - - private final ScheduledFuture cleanFuture; - - private final int cleanPeriod; - - private volatile boolean admin = false; - - public MulticastRegistry(URL url) { - super(url); - if (url.isAnyHost()) { - throw new IllegalStateException("registry address == null"); - } - try { - multicastAddress = InetAddress.getByName(url.getHost()); - checkMulticastAddress(multicastAddress); - - multicastPort = url.getPort() <= 0 ? DEFAULT_MULTICAST_PORT : url.getPort(); - multicastSocket = new MulticastSocket(multicastPort); - NetUtils.joinMulticastGroup(multicastSocket, multicastAddress); - Thread thread = new Thread(new Runnable() { - @Override - public void run() { - byte[] buf = new byte[2048]; - DatagramPacket recv = new DatagramPacket(buf, buf.length); - while (!multicastSocket.isClosed()) { - try { - multicastSocket.receive(recv); - String msg = new String(recv.getData()).trim(); - int i = msg.indexOf('\n'); - if (i > 0) { - msg = msg.substring(0, i).trim(); - } - MulticastRegistry.this.receive(msg, (InetSocketAddress) recv.getSocketAddress()); - Arrays.fill(buf, (byte) 0); - } catch (Throwable e) { - if (!multicastSocket.isClosed()) { - logger.error(e.getMessage(), e); - } - } - } - } - }, "DubboMulticastRegistryReceiver"); - thread.setDaemon(true); - thread.start(); - } catch (IOException e) { - throw new IllegalStateException(e.getMessage(), e); - } - this.cleanPeriod = url.getParameter(SESSION_TIMEOUT_KEY, DEFAULT_SESSION_TIMEOUT); - if (url.getParameter("clean", true)) { - this.cleanFuture = cleanExecutor.scheduleWithFixedDelay(new Runnable() { - @Override - public void run() { - try { - clean(); // Remove the expired - } catch (Throwable t) { // Defensive fault tolerance - logger.error("Unexpected exception occur at clean expired provider, cause: " + t.getMessage(), t); - } - } - }, cleanPeriod, cleanPeriod, TimeUnit.MILLISECONDS); - } else { - this.cleanFuture = null; - } - } - - private void checkMulticastAddress(InetAddress multicastAddress) { - if (!multicastAddress.isMulticastAddress()) { - String message = "Invalid multicast address " + multicastAddress; - if (multicastAddress instanceof Inet4Address) { - throw new IllegalArgumentException(message + ", " + - "ipv4 multicast address scope: 224.0.0.0 - 239.255.255.255."); - } else { - throw new IllegalArgumentException(message + ", " + "ipv6 multicast address must start with ff, " + - "for example: ff01::1"); - } - } - } - - /** - * Remove the expired providers, only when "clean" parameter is true. - */ - private void clean() { - if (admin) { - for (Set providers : new HashSet>(received.values())) { - for (URL url : new HashSet(providers)) { - if (isExpired(url)) { - if (logger.isWarnEnabled()) { - logger.warn("Clean expired provider " + url); - } - doUnregister(url); - } - } - } - } - } - - private boolean isExpired(URL url) { - if (!url.getParameter(DYNAMIC_KEY, true) || url.getPort() <= 0 || CONSUMER_PROTOCOL.equals(url.getProtocol()) || ROUTE_PROTOCOL.equals(url.getProtocol()) || OVERRIDE_PROTOCOL.equals(url.getProtocol())) { - return false; - } - try (Socket socket = new Socket(url.getHost(), url.getPort())) { - } catch (Throwable e) { - try { - Thread.sleep(100); - } catch (Throwable e2) { - } - try (Socket socket2 = new Socket(url.getHost(), url.getPort())) { - } catch (Throwable e2) { - return true; - } - } - return false; - } - - private void receive(String msg, InetSocketAddress remoteAddress) { - if (logger.isInfoEnabled()) { - logger.info("Receive multicast message: " + msg + " from " + remoteAddress); - } - if (msg.startsWith(REGISTER)) { - URL url = URL.valueOf(msg.substring(REGISTER.length()).trim()); - registered(url); - } else if (msg.startsWith(UNREGISTER)) { - URL url = URL.valueOf(msg.substring(UNREGISTER.length()).trim()); - unregistered(url); - } else if (msg.startsWith(SUBSCRIBE)) { - URL url = URL.valueOf(msg.substring(SUBSCRIBE.length()).trim()); - Set urls = getRegistered(); - if (CollectionUtils.isNotEmpty(urls)) { - for (URL u : urls) { - if (UrlUtils.isMatch(url, u)) { - String host = remoteAddress != null && remoteAddress.getAddress() != null ? remoteAddress.getAddress().getHostAddress() : url.getIp(); - if (url.getParameter("unicast", true) // Whether the consumer's machine has only one process - && !NetUtils.getLocalHost().equals(host)) { // Multiple processes in the same machine cannot be unicast with unicast or there will be only one process receiving information - unicast(REGISTER + " " + u.toFullString(), host); - } else { - multicast(REGISTER + " " + u.toFullString()); - } - } - } - } - }/* else if (msg.startsWith(UNSUBSCRIBE)) { - }*/ - } - - private void multicast(String msg) { - if (logger.isInfoEnabled()) { - logger.info("Send multicast message: " + msg + " to " + multicastAddress + ":" + multicastPort); - } - try { - byte[] data = (msg + "\n").getBytes(); - DatagramPacket hi = new DatagramPacket(data, data.length, multicastAddress, multicastPort); - multicastSocket.send(hi); - } catch (Exception e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - - private void unicast(String msg, String host) { - if (logger.isInfoEnabled()) { - logger.info("Send unicast message: " + msg + " to " + host + ":" + multicastPort); - } - try { - byte[] data = (msg + "\n").getBytes(); - DatagramPacket hi = new DatagramPacket(data, data.length, InetAddress.getByName(host), multicastPort); - multicastSocket.send(hi); - } catch (Exception e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - - @Override - public void doRegister(URL url) { - multicast(REGISTER + " " + url.toFullString()); - } - - @Override - public void doUnregister(URL url) { - multicast(UNREGISTER + " " + url.toFullString()); - } - - @Override - public void doSubscribe(URL url, final NotifyListener listener) { - if (ANY_VALUE.equals(url.getServiceInterface())) { - admin = true; - } - multicast(SUBSCRIBE + " " + url.toFullString()); - synchronized (listener) { - try { - listener.wait(url.getParameter(TIMEOUT_KEY, DEFAULT_TIMEOUT)); - } catch (InterruptedException e) { - } - } - } - - @Override - public void doUnsubscribe(URL url, NotifyListener listener) { - if (!ANY_VALUE.equals(url.getServiceInterface()) && url.getParameter(REGISTER_KEY, true)) { - unregister(url); - } - multicast(UNSUBSCRIBE + " " + url.toFullString()); - } - - @Override - public boolean isAvailable() { - try { - return multicastSocket != null; - } catch (Throwable t) { - return false; - } - } - - /** - * Remove the expired providers(if clean is true), leave the multicast group and close the multicast socket. - */ - @Override - public void destroy() { - super.destroy(); - try { - ExecutorUtil.cancelScheduledFuture(cleanFuture); - } catch (Throwable t) { - logger.warn(t.getMessage(), t); - } - try { - multicastSocket.leaveGroup(multicastAddress); - multicastSocket.close(); - } catch (Throwable t) { - logger.warn(t.getMessage(), t); - } - ExecutorUtil.gracefulShutdown(cleanExecutor, cleanPeriod); - } - - protected void registered(URL url) { - for (Map.Entry> entry : getSubscribed().entrySet()) { - URL key = entry.getKey(); - if (UrlUtils.isMatch(key, url)) { - Set urls = received.computeIfAbsent(key, k -> new ConcurrentHashSet<>()); - urls.add(url); - List list = toList(urls); - for (final NotifyListener listener : entry.getValue()) { - notify(key, listener, list); - synchronized (listener) { - listener.notify(); - } - } - } - } - } - - protected void unregistered(URL url) { - for (Map.Entry> entry : getSubscribed().entrySet()) { - URL key = entry.getKey(); - if (UrlUtils.isMatch(key, url)) { - Set urls = received.get(key); - if (urls != null) { - urls.remove(url); - } - if (urls == null || urls.isEmpty()) { - if (urls == null) { - urls = new ConcurrentHashSet(); - } - URL empty = url.setProtocol(EMPTY_PROTOCOL); - urls.add(empty); - } - List list = toList(urls); - for (NotifyListener listener : entry.getValue()) { - notify(key, listener, list); - } - } - } - } - - protected void subscribed(URL url, NotifyListener listener) { - List urls = lookup(url); - notify(url, listener, urls); - } - - private List toList(Set urls) { - List list = new ArrayList(); - if (CollectionUtils.isNotEmpty(urls)) { - list.addAll(urls); - } - return list; - } - - @Override - public void register(URL url) { - super.register(url); - registered(url); - } - - @Override - public void unregister(URL url) { - super.unregister(url); - unregistered(url); - } - - @Override - public void subscribe(URL url, NotifyListener listener) { - super.subscribe(url, listener); - subscribed(url, listener); - } - - @Override - public void unsubscribe(URL url, NotifyListener listener) { - super.unsubscribe(url, listener); - received.remove(url); - } - - @Override - public List lookup(URL url) { - List urls = new ArrayList<>(); - Map> notifiedUrls = getNotified().get(url); - if (notifiedUrls != null && notifiedUrls.size() > 0) { - for (List values : notifiedUrls.values()) { - urls.addAll(values); - } - } - if (urls.isEmpty()) { - List cacheUrls = getCacheUrls(url); - if (CollectionUtils.isNotEmpty(cacheUrls)) { - urls.addAll(cacheUrls); - } - } - if (urls.isEmpty()) { - for (URL u : getRegistered()) { - if (UrlUtils.isMatch(url, u)) { - urls.add(u); - } - } - } - if (ANY_VALUE.equals(url.getServiceInterface())) { - for (URL u : getSubscribed().keySet()) { - if (UrlUtils.isMatch(url, u)) { - urls.add(u); - } - } - } - return urls; - } - - public MulticastSocket getMulticastSocket() { - return multicastSocket; - } - - public Map> getReceived() { - return received; - } - -} +/* + * 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.registry.multicast; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.common.utils.ConcurrentHashSet; +import org.apache.dubbo.common.utils.ExecutorUtil; +import org.apache.dubbo.common.utils.NamedThreadFactory; +import org.apache.dubbo.common.utils.NetUtils; +import org.apache.dubbo.common.utils.UrlUtils; +import org.apache.dubbo.registry.NotifyListener; +import org.apache.dubbo.registry.support.FailbackRegistry; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.Inet4Address; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.MulticastSocket; +import java.net.Socket; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import static org.apache.dubbo.common.constants.CommonConstants.ANY_VALUE; +import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_TIMEOUT; +import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY; +import static org.apache.dubbo.common.constants.RegistryConstants.DYNAMIC_KEY; +import static org.apache.dubbo.common.constants.RegistryConstants.EMPTY_PROTOCOL; +import static org.apache.dubbo.common.constants.RegistryConstants.OVERRIDE_PROTOCOL; +import static org.apache.dubbo.common.constants.RegistryConstants.ROUTE_PROTOCOL; +import static org.apache.dubbo.registry.Constants.CONSUMER_PROTOCOL; +import static org.apache.dubbo.registry.Constants.DEFAULT_SESSION_TIMEOUT; +import static org.apache.dubbo.registry.Constants.REGISTER; +import static org.apache.dubbo.registry.Constants.REGISTER_KEY; +import static org.apache.dubbo.registry.Constants.SESSION_TIMEOUT_KEY; +import static org.apache.dubbo.registry.Constants.SUBSCRIBE; +import static org.apache.dubbo.registry.Constants.UNREGISTER; +import static org.apache.dubbo.registry.Constants.UNSUBSCRIBE; + +/** + * MulticastRegistry + */ +public class MulticastRegistry extends FailbackRegistry { + + // logging output + private static final Logger logger = LoggerFactory.getLogger(MulticastRegistry.class); + + private static final int DEFAULT_MULTICAST_PORT = 1234; + + private final InetAddress multicastAddress; + + private final MulticastSocket multicastSocket; + + private final int multicastPort; + + private final ConcurrentMap> received = new ConcurrentHashMap>(); + + private final ScheduledExecutorService cleanExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("DubboMulticastRegistryCleanTimer", true)); + + private final ScheduledFuture cleanFuture; + + private final int cleanPeriod; + + private volatile boolean admin = false; + + public MulticastRegistry(URL url) { + super(url); + if (url.isAnyHost()) { + throw new IllegalStateException("registry address == null"); + } + try { + multicastAddress = InetAddress.getByName(url.getHost()); + checkMulticastAddress(multicastAddress); + + multicastPort = url.getPort() <= 0 ? DEFAULT_MULTICAST_PORT : url.getPort(); + multicastSocket = new MulticastSocket(multicastPort); + NetUtils.joinMulticastGroup(multicastSocket, multicastAddress); + Thread thread = new Thread(new Runnable() { + @Override + public void run() { + byte[] buf = new byte[2048]; + DatagramPacket recv = new DatagramPacket(buf, buf.length); + while (!multicastSocket.isClosed()) { + try { + multicastSocket.receive(recv); + String msg = new String(recv.getData()).trim(); + int i = msg.indexOf('\n'); + if (i > 0) { + msg = msg.substring(0, i).trim(); + } + MulticastRegistry.this.receive(msg, (InetSocketAddress) recv.getSocketAddress()); + Arrays.fill(buf, (byte) 0); + } catch (Throwable e) { + if (!multicastSocket.isClosed()) { + logger.error(e.getMessage(), e); + } + } + } + } + }, "DubboMulticastRegistryReceiver"); + thread.setDaemon(true); + thread.start(); + } catch (IOException e) { + throw new IllegalStateException(e.getMessage(), e); + } + this.cleanPeriod = url.getParameter(SESSION_TIMEOUT_KEY, DEFAULT_SESSION_TIMEOUT); + if (url.getParameter("clean", true)) { + this.cleanFuture = cleanExecutor.scheduleWithFixedDelay(new Runnable() { + @Override + public void run() { + try { + clean(); // Remove the expired + } catch (Throwable t) { // Defensive fault tolerance + logger.error("Unexpected exception occur at clean expired provider, cause: " + t.getMessage(), t); + } + } + }, cleanPeriod, cleanPeriod, TimeUnit.MILLISECONDS); + } else { + this.cleanFuture = null; + } + } + + private void checkMulticastAddress(InetAddress multicastAddress) { + if (!multicastAddress.isMulticastAddress()) { + String message = "Invalid multicast address " + multicastAddress; + if (multicastAddress instanceof Inet4Address) { + throw new IllegalArgumentException(message + ", " + + "ipv4 multicast address scope: 224.0.0.0 - 239.255.255.255."); + } else { + throw new IllegalArgumentException(message + ", " + "ipv6 multicast address must start with ff, " + + "for example: ff01::1"); + } + } + } + + /** + * Remove the expired providers, only when "clean" parameter is true. + */ + private void clean() { + if (admin) { + for (Set providers : new HashSet>(received.values())) { + for (URL url : new HashSet(providers)) { + if (isExpired(url)) { + if (logger.isWarnEnabled()) { + logger.warn("Clean expired provider " + url); + } + doUnregister(url); + } + } + } + } + } + + private boolean isExpired(URL url) { + if (!url.getParameter(DYNAMIC_KEY, true) || url.getPort() <= 0 || CONSUMER_PROTOCOL.equals(url.getProtocol()) || ROUTE_PROTOCOL.equals(url.getProtocol()) || OVERRIDE_PROTOCOL.equals(url.getProtocol())) { + return false; + } + try (Socket socket = new Socket(url.getHost(), url.getPort())) { + } catch (Throwable e) { + try { + Thread.sleep(100); + } catch (Throwable e2) { + } + try (Socket socket2 = new Socket(url.getHost(), url.getPort())) { + } catch (Throwable e2) { + return true; + } + } + return false; + } + + private void receive(String msg, InetSocketAddress remoteAddress) { + if (logger.isInfoEnabled()) { + logger.info("Receive multicast message: " + msg + " from " + remoteAddress); + } + if (msg.startsWith(REGISTER)) { + URL url = URL.valueOf(msg.substring(REGISTER.length()).trim()); + registered(url); + } else if (msg.startsWith(UNREGISTER)) { + URL url = URL.valueOf(msg.substring(UNREGISTER.length()).trim()); + unregistered(url); + } else if (msg.startsWith(SUBSCRIBE)) { + URL url = URL.valueOf(msg.substring(SUBSCRIBE.length()).trim()); + Set urls = getRegistered(); + if (CollectionUtils.isNotEmpty(urls)) { + for (URL u : urls) { + if (UrlUtils.isMatch(url, u)) { + String host = remoteAddress != null && remoteAddress.getAddress() != null ? remoteAddress.getAddress().getHostAddress() : url.getIp(); + if (url.getParameter("unicast", true) // Whether the consumer's machine has only one process + && !NetUtils.getLocalHost().equals(host)) { // Multiple processes in the same machine cannot be unicast with unicast or there will be only one process receiving information + unicast(REGISTER + " " + u.toFullString(), host); + } else { + multicast(REGISTER + " " + u.toFullString()); + } + } + } + } + }/* else if (msg.startsWith(UNSUBSCRIBE)) { + }*/ + } + + private void multicast(String msg) { + if (logger.isInfoEnabled()) { + logger.info("Send multicast message: " + msg + " to " + multicastAddress + ":" + multicastPort); + } + try { + byte[] data = (msg + "\n").getBytes(); + DatagramPacket hi = new DatagramPacket(data, data.length, multicastAddress, multicastPort); + multicastSocket.send(hi); + } catch (Exception e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + private void unicast(String msg, String host) { + if (logger.isInfoEnabled()) { + logger.info("Send unicast message: " + msg + " to " + host + ":" + multicastPort); + } + try { + byte[] data = (msg + "\n").getBytes(); + DatagramPacket hi = new DatagramPacket(data, data.length, InetAddress.getByName(host), multicastPort); + multicastSocket.send(hi); + } catch (Exception e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + @Override + public void doRegister(URL url) { + multicast(REGISTER + " " + url.toFullString()); + } + + @Override + public void doUnregister(URL url) { + multicast(UNREGISTER + " " + url.toFullString()); + } + + @Override + public void doSubscribe(URL url, final NotifyListener listener) { + if (ANY_VALUE.equals(url.getServiceInterface())) { + admin = true; + } + multicast(SUBSCRIBE + " " + url.toFullString()); + synchronized (listener) { + try { + listener.wait(url.getParameter(TIMEOUT_KEY, DEFAULT_TIMEOUT)); + } catch (InterruptedException e) { + } + } + } + + @Override + public void doUnsubscribe(URL url, NotifyListener listener) { + if (!ANY_VALUE.equals(url.getServiceInterface()) && url.getParameter(REGISTER_KEY, true)) { + unregister(url); + } + multicast(UNSUBSCRIBE + " " + url.toFullString()); + } + + @Override + public boolean isAvailable() { + try { + return multicastSocket != null; + } catch (Throwable t) { + return false; + } + } + + /** + * Remove the expired providers(if clean is true), leave the multicast group and close the multicast socket. + */ + @Override + public void destroy() { + super.destroy(); + try { + ExecutorUtil.cancelScheduledFuture(cleanFuture); + } catch (Throwable t) { + logger.warn(t.getMessage(), t); + } + try { + multicastSocket.leaveGroup(multicastAddress); + multicastSocket.close(); + } catch (Throwable t) { + logger.warn(t.getMessage(), t); + } + ExecutorUtil.gracefulShutdown(cleanExecutor, cleanPeriod); + } + + protected void registered(URL url) { + for (Map.Entry> entry : getSubscribed().entrySet()) { + URL key = entry.getKey(); + if (UrlUtils.isMatch(key, url)) { + Set urls = received.computeIfAbsent(key, k -> new ConcurrentHashSet<>()); + urls.add(url); + List list = toList(urls); + for (final NotifyListener listener : entry.getValue()) { + notify(key, listener, list); + synchronized (listener) { + listener.notify(); + } + } + } + } + } + + protected void unregistered(URL url) { + for (Map.Entry> entry : getSubscribed().entrySet()) { + URL key = entry.getKey(); + if (UrlUtils.isMatch(key, url)) { + Set urls = received.get(key); + if (urls != null) { + urls.remove(url); + } + if (urls == null || urls.isEmpty()) { + if (urls == null) { + urls = new ConcurrentHashSet(); + } + URL empty = url.setProtocol(EMPTY_PROTOCOL); + urls.add(empty); + } + List list = toList(urls); + for (NotifyListener listener : entry.getValue()) { + notify(key, listener, list); + } + } + } + } + + protected void subscribed(URL url, NotifyListener listener) { + List urls = lookup(url); + notify(url, listener, urls); + } + + private List toList(Set urls) { + List list = new ArrayList(); + if (CollectionUtils.isNotEmpty(urls)) { + list.addAll(urls); + } + return list; + } + + @Override + public void register(URL url) { + super.register(url); + registered(url); + } + + @Override + public void unregister(URL url) { + super.unregister(url); + unregistered(url); + } + + @Override + public void subscribe(URL url, NotifyListener listener) { + super.subscribe(url, listener); + subscribed(url, listener); + } + + @Override + public void unsubscribe(URL url, NotifyListener listener) { + super.unsubscribe(url, listener); + received.remove(url); + } + + @Override + public List lookup(URL url) { + List urls = new ArrayList<>(); + Map> notifiedUrls = getNotified().get(url); + if (notifiedUrls != null && notifiedUrls.size() > 0) { + for (List values : notifiedUrls.values()) { + urls.addAll(values); + } + } + if (urls.isEmpty()) { + List cacheUrls = getCacheUrls(url); + if (CollectionUtils.isNotEmpty(cacheUrls)) { + urls.addAll(cacheUrls); + } + } + if (urls.isEmpty()) { + for (URL u : getRegistered()) { + if (UrlUtils.isMatch(url, u)) { + urls.add(u); + } + } + } + if (ANY_VALUE.equals(url.getServiceInterface())) { + for (URL u : getSubscribed().keySet()) { + if (UrlUtils.isMatch(url, u)) { + urls.add(u); + } + } + } + return urls; + } + + public MulticastSocket getMulticastSocket() { + return multicastSocket; + } + + public Map> getReceived() { + return received; + } + +} diff --git a/dubbo-registry/dubbo-registry-multicast/src/main/java/org/apache/dubbo/registry/multicast/MulticastRegistryFactory.java b/dubbo-registry/dubbo-registry-multicast/src/main/java/org/apache/dubbo/registry/multicast/MulticastRegistryFactory.java index c7006baae7..88e96e609d 100644 --- a/dubbo-registry/dubbo-registry-multicast/src/main/java/org/apache/dubbo/registry/multicast/MulticastRegistryFactory.java +++ b/dubbo-registry/dubbo-registry-multicast/src/main/java/org/apache/dubbo/registry/multicast/MulticastRegistryFactory.java @@ -1,34 +1,34 @@ -/* - * 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.registry.multicast; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.registry.Registry; -import org.apache.dubbo.registry.support.AbstractRegistryFactory; - -/** - * MulticastRegistryLocator - * - */ -public class MulticastRegistryFactory extends AbstractRegistryFactory { - - @Override - public Registry createRegistry(URL url) { - return new MulticastRegistry(url); - } - -} +/* + * 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.registry.multicast; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.registry.Registry; +import org.apache.dubbo.registry.support.AbstractRegistryFactory; + +/** + * MulticastRegistryLocator + * + */ +public class MulticastRegistryFactory extends AbstractRegistryFactory { + + @Override + public Registry createRegistry(URL url) { + return new MulticastRegistry(url); + } + +} diff --git a/dubbo-registry/dubbo-registry-multicast/src/test/java/org/apache/dubbo/registry/multicast/MulticastRegistryFactoryTest.java b/dubbo-registry/dubbo-registry-multicast/src/test/java/org/apache/dubbo/registry/multicast/MulticastRegistryFactoryTest.java index 2ee7a896b8..3999cdcff6 100644 --- a/dubbo-registry/dubbo-registry-multicast/src/test/java/org/apache/dubbo/registry/multicast/MulticastRegistryFactoryTest.java +++ b/dubbo-registry/dubbo-registry-multicast/src/test/java/org/apache/dubbo/registry/multicast/MulticastRegistryFactoryTest.java @@ -32,4 +32,4 @@ public class MulticastRegistryFactoryTest { assertThat(registry, not(nullValue())); assertThat(registry.isAvailable(), is(true)); } -} \ No newline at end of file +} diff --git a/dubbo-registry/dubbo-registry-multicast/src/test/java/org/apache/dubbo/registry/multicast/MulticastRegistryTest.java b/dubbo-registry/dubbo-registry-multicast/src/test/java/org/apache/dubbo/registry/multicast/MulticastRegistryTest.java index 32e71d0555..0da009c4a4 100644 --- a/dubbo-registry/dubbo-registry-multicast/src/test/java/org/apache/dubbo/registry/multicast/MulticastRegistryTest.java +++ b/dubbo-registry/dubbo-registry-multicast/src/test/java/org/apache/dubbo/registry/multicast/MulticastRegistryTest.java @@ -1,275 +1,275 @@ -/* - * 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.registry.multicast; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.utils.NetUtils; -import org.apache.dubbo.registry.NotifyListener; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.net.InetAddress; -import java.net.MulticastSocket; -import java.net.UnknownHostException; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.Set; - -import static org.apache.dubbo.common.constants.RegistryConstants.EMPTY_PROTOCOL; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -public class MulticastRegistryTest { - - private String service = "org.apache.dubbo.test.injvmServie"; - private URL registryUrl = URL.valueOf("multicast://239.239.239.239/"); - private URL serviceUrl = URL.valueOf("dubbo://" + NetUtils.getLocalHost() + "/" + service - + "?methods=test1,test2"); - private URL adminUrl = URL.valueOf("dubbo://" + NetUtils.getLocalHost() + "/*"); - private URL consumerUrl = URL.valueOf("subscribe://" + NetUtils.getLocalHost() + "/" + service + "?arg1=1&arg2=2"); - private MulticastRegistry registry = new MulticastRegistry(registryUrl); - - @BeforeEach - public void setUp() { - registry.register(serviceUrl); - } - - /** - * Test method for {@link org.apache.dubbo.registry.multicast.MulticastRegistry#MulticastRegistry(URL)}. - */ - @Test - public void testUrlError() { - Assertions.assertThrows(UnknownHostException.class, () -> { - try { - URL errorUrl = URL.valueOf("multicast://mullticast.local/"); - new MulticastRegistry(errorUrl); - } catch (IllegalStateException e) { - throw e.getCause(); - } - }); - } - - /** - * Test method for {@link org.apache.dubbo.registry.multicast.MulticastRegistry#MulticastRegistry(URL)}. - */ - @Test - public void testAnyHost() { - Assertions.assertThrows(IllegalStateException.class, () -> { - URL errorUrl = URL.valueOf("multicast://0.0.0.0/"); - new MulticastRegistry(errorUrl); - }); - } - - /** - * Test method for {@link org.apache.dubbo.registry.multicast.MulticastRegistry#MulticastRegistry(URL)}. - */ - @Test - public void testGetCustomPort() { - int port = NetUtils.getAvailablePort(20880 + new Random().nextInt(10000)); - URL customPortUrl = URL.valueOf("multicast://239.239.239.239:" + port); - MulticastRegistry multicastRegistry = new MulticastRegistry(customPortUrl); - assertThat(multicastRegistry.getUrl().getPort(), is(port)); - } - - /** - * Test method for {@link org.apache.dubbo.registry.multicast.MulticastRegistry#getRegistered()}. - */ - @Test - public void testRegister() { - Set registered; - // clear first - registered = registry.getRegistered(); - for (URL url : registered) { - registry.unregister(url); - } - - for (int i = 0; i < 2; i++) { - registry.register(serviceUrl); - registered = registry.getRegistered(); - assertTrue(registered.contains(serviceUrl)); - } - // confirm only 1 register success - registered = registry.getRegistered(); - assertEquals(1, registered.size()); - } - - /** - * Test method for {@link org.apache.dubbo.registry.multicast.MulticastRegistry#unregister(URL)}. - */ - @Test - public void testUnregister() { - Set registered; - - // register first - registry.register(serviceUrl); - registered = registry.getRegistered(); - assertTrue(registered.contains(serviceUrl)); - - // then unregister - registered = registry.getRegistered(); - registry.unregister(serviceUrl); - assertFalse(registered.contains(serviceUrl)); - } - - /** - * Test method for - * {@link org.apache.dubbo.registry.multicast.MulticastRegistry#subscribe(URL url, org.apache.dubbo.registry.NotifyListener)} - * . - */ - @Test - public void testSubscribe() { - // verify listener - final URL[] notifyUrl = new URL[1]; - for (int i = 0; i < 10; i++) { - registry.register(serviceUrl); - registry.subscribe(consumerUrl, urls -> { - notifyUrl[0] = urls.get(0); - - Map> subscribed = registry.getSubscribed(); - assertEquals(consumerUrl, subscribed.keySet().iterator().next()); - }); - if (!EMPTY_PROTOCOL.equalsIgnoreCase(notifyUrl[0].getProtocol())) { - break; - } - } - assertEquals(serviceUrl.toFullString(), notifyUrl[0].toFullString()); - } - - /** - * Test method for {@link org.apache.dubbo.registry.multicast.MulticastRegistry#unsubscribe(URL, NotifyListener)} - */ - @Test - public void testUnsubscribe() { - // subscribe first - registry.subscribe(consumerUrl, new NotifyListener() { - @Override - public void notify(List urls) { - // do nothing - } - }); - - // then unsubscribe - registry.unsubscribe(consumerUrl, new NotifyListener() { - @Override - public void notify(List urls) { - Map> subscribed = registry.getSubscribed(); - Set listeners = subscribed.get(consumerUrl); - assertTrue(listeners.isEmpty()); - - Map> received = registry.getReceived(); - assertTrue(received.get(consumerUrl).isEmpty()); - } - }); - } - - /** - * Test method for {@link MulticastRegistry#isAvailable()} - */ - @Test - public void testAvailability() { - int port = NetUtils.getAvailablePort(20880 + new Random().nextInt(10000)); - MulticastRegistry registry = new MulticastRegistry(URL.valueOf("multicast://224.5.6.8:" + port)); - assertTrue(registry.isAvailable()); - } - - /** - * Test method for {@link MulticastRegistry#destroy()} - */ - @Test - public void testDestroy() { - MulticastSocket socket = registry.getMulticastSocket(); - assertFalse(socket.isClosed()); - - // then destroy, the multicast socket will be closed - registry.destroy(); - socket = registry.getMulticastSocket(); - assertTrue(socket.isClosed()); - } - - /** - * Test method for {@link org.apache.dubbo.registry.multicast.MulticastRegistry#MulticastRegistry(URL)} - */ - @Test - public void testDefaultPort() { - MulticastRegistry multicastRegistry = new MulticastRegistry(URL.valueOf("multicast://224.5.6.7")); - try { - MulticastSocket multicastSocket = multicastRegistry.getMulticastSocket(); - Assertions.assertEquals(1234, multicastSocket.getLocalPort()); - } finally { - multicastRegistry.destroy(); - } - } - - /** - * Test method for {@link org.apache.dubbo.registry.multicast.MulticastRegistry#MulticastRegistry(URL)} - */ - @Test - public void testCustomedPort() { - int port = NetUtils.getAvailablePort(20880 + new Random().nextInt(10000)); - MulticastRegistry multicastRegistry = new MulticastRegistry(URL.valueOf("multicast://224.5.6.7:" + port)); - try { - MulticastSocket multicastSocket = multicastRegistry.getMulticastSocket(); - assertEquals(port, multicastSocket.getLocalPort()); - } finally { - multicastRegistry.destroy(); - } - } - - @Test - public void testMulticastAddress() { - InetAddress multicastAddress = null; - MulticastSocket multicastSocket = null; - try { - // ipv4 multicast address - multicastAddress = InetAddress.getByName("224.55.66.77"); - multicastSocket = new MulticastSocket(2345); - multicastSocket.setLoopbackMode(false); - NetUtils.setInterface(multicastSocket, false); - multicastSocket.joinGroup(multicastAddress); - } catch (Exception e) { - Assertions.fail(e); - } finally { - if (multicastSocket != null) { - multicastSocket.close(); - } - } - - // multicast ipv6 address, - try { - multicastAddress = InetAddress.getByName("ff01::1"); - - multicastSocket = new MulticastSocket(); - multicastSocket.setLoopbackMode(false); - NetUtils.setInterface(multicastSocket, true); - multicastSocket.joinGroup(multicastAddress); - } catch (Throwable t) { - t.printStackTrace(); - } finally { - if (multicastSocket != null) { - multicastSocket.close(); - } - } - - } - -} +/* + * 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.registry.multicast; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.utils.NetUtils; +import org.apache.dubbo.registry.NotifyListener; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.net.InetAddress; +import java.net.MulticastSocket; +import java.net.UnknownHostException; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Set; + +import static org.apache.dubbo.common.constants.RegistryConstants.EMPTY_PROTOCOL; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class MulticastRegistryTest { + + private String service = "org.apache.dubbo.test.injvmServie"; + private URL registryUrl = URL.valueOf("multicast://239.239.239.239/"); + private URL serviceUrl = URL.valueOf("dubbo://" + NetUtils.getLocalHost() + "/" + service + + "?methods=test1,test2"); + private URL adminUrl = URL.valueOf("dubbo://" + NetUtils.getLocalHost() + "/*"); + private URL consumerUrl = URL.valueOf("subscribe://" + NetUtils.getLocalHost() + "/" + service + "?arg1=1&arg2=2"); + private MulticastRegistry registry = new MulticastRegistry(registryUrl); + + @BeforeEach + public void setUp() { + registry.register(serviceUrl); + } + + /** + * Test method for {@link org.apache.dubbo.registry.multicast.MulticastRegistry#MulticastRegistry(URL)}. + */ + @Test + public void testUrlError() { + Assertions.assertThrows(UnknownHostException.class, () -> { + try { + URL errorUrl = URL.valueOf("multicast://mullticast.local/"); + new MulticastRegistry(errorUrl); + } catch (IllegalStateException e) { + throw e.getCause(); + } + }); + } + + /** + * Test method for {@link org.apache.dubbo.registry.multicast.MulticastRegistry#MulticastRegistry(URL)}. + */ + @Test + public void testAnyHost() { + Assertions.assertThrows(IllegalStateException.class, () -> { + URL errorUrl = URL.valueOf("multicast://0.0.0.0/"); + new MulticastRegistry(errorUrl); + }); + } + + /** + * Test method for {@link org.apache.dubbo.registry.multicast.MulticastRegistry#MulticastRegistry(URL)}. + */ + @Test + public void testGetCustomPort() { + int port = NetUtils.getAvailablePort(20880 + new Random().nextInt(10000)); + URL customPortUrl = URL.valueOf("multicast://239.239.239.239:" + port); + MulticastRegistry multicastRegistry = new MulticastRegistry(customPortUrl); + assertThat(multicastRegistry.getUrl().getPort(), is(port)); + } + + /** + * Test method for {@link org.apache.dubbo.registry.multicast.MulticastRegistry#getRegistered()}. + */ + @Test + public void testRegister() { + Set registered; + // clear first + registered = registry.getRegistered(); + for (URL url : registered) { + registry.unregister(url); + } + + for (int i = 0; i < 2; i++) { + registry.register(serviceUrl); + registered = registry.getRegistered(); + assertTrue(registered.contains(serviceUrl)); + } + // confirm only 1 register success + registered = registry.getRegistered(); + assertEquals(1, registered.size()); + } + + /** + * Test method for {@link org.apache.dubbo.registry.multicast.MulticastRegistry#unregister(URL)}. + */ + @Test + public void testUnregister() { + Set registered; + + // register first + registry.register(serviceUrl); + registered = registry.getRegistered(); + assertTrue(registered.contains(serviceUrl)); + + // then unregister + registered = registry.getRegistered(); + registry.unregister(serviceUrl); + assertFalse(registered.contains(serviceUrl)); + } + + /** + * Test method for + * {@link org.apache.dubbo.registry.multicast.MulticastRegistry#subscribe(URL url, org.apache.dubbo.registry.NotifyListener)} + * . + */ + @Test + public void testSubscribe() { + // verify listener + final URL[] notifyUrl = new URL[1]; + for (int i = 0; i < 10; i++) { + registry.register(serviceUrl); + registry.subscribe(consumerUrl, urls -> { + notifyUrl[0] = urls.get(0); + + Map> subscribed = registry.getSubscribed(); + assertEquals(consumerUrl, subscribed.keySet().iterator().next()); + }); + if (!EMPTY_PROTOCOL.equalsIgnoreCase(notifyUrl[0].getProtocol())) { + break; + } + } + assertEquals(serviceUrl.toFullString(), notifyUrl[0].toFullString()); + } + + /** + * Test method for {@link org.apache.dubbo.registry.multicast.MulticastRegistry#unsubscribe(URL, NotifyListener)} + */ + @Test + public void testUnsubscribe() { + // subscribe first + registry.subscribe(consumerUrl, new NotifyListener() { + @Override + public void notify(List urls) { + // do nothing + } + }); + + // then unsubscribe + registry.unsubscribe(consumerUrl, new NotifyListener() { + @Override + public void notify(List urls) { + Map> subscribed = registry.getSubscribed(); + Set listeners = subscribed.get(consumerUrl); + assertTrue(listeners.isEmpty()); + + Map> received = registry.getReceived(); + assertTrue(received.get(consumerUrl).isEmpty()); + } + }); + } + + /** + * Test method for {@link MulticastRegistry#isAvailable()} + */ + @Test + public void testAvailability() { + int port = NetUtils.getAvailablePort(20880 + new Random().nextInt(10000)); + MulticastRegistry registry = new MulticastRegistry(URL.valueOf("multicast://224.5.6.8:" + port)); + assertTrue(registry.isAvailable()); + } + + /** + * Test method for {@link MulticastRegistry#destroy()} + */ + @Test + public void testDestroy() { + MulticastSocket socket = registry.getMulticastSocket(); + assertFalse(socket.isClosed()); + + // then destroy, the multicast socket will be closed + registry.destroy(); + socket = registry.getMulticastSocket(); + assertTrue(socket.isClosed()); + } + + /** + * Test method for {@link org.apache.dubbo.registry.multicast.MulticastRegistry#MulticastRegistry(URL)} + */ + @Test + public void testDefaultPort() { + MulticastRegistry multicastRegistry = new MulticastRegistry(URL.valueOf("multicast://224.5.6.7")); + try { + MulticastSocket multicastSocket = multicastRegistry.getMulticastSocket(); + Assertions.assertEquals(1234, multicastSocket.getLocalPort()); + } finally { + multicastRegistry.destroy(); + } + } + + /** + * Test method for {@link org.apache.dubbo.registry.multicast.MulticastRegistry#MulticastRegistry(URL)} + */ + @Test + public void testCustomedPort() { + int port = NetUtils.getAvailablePort(20880 + new Random().nextInt(10000)); + MulticastRegistry multicastRegistry = new MulticastRegistry(URL.valueOf("multicast://224.5.6.7:" + port)); + try { + MulticastSocket multicastSocket = multicastRegistry.getMulticastSocket(); + assertEquals(port, multicastSocket.getLocalPort()); + } finally { + multicastRegistry.destroy(); + } + } + + @Test + public void testMulticastAddress() { + InetAddress multicastAddress = null; + MulticastSocket multicastSocket = null; + try { + // ipv4 multicast address + multicastAddress = InetAddress.getByName("224.55.66.77"); + multicastSocket = new MulticastSocket(2345); + multicastSocket.setLoopbackMode(false); + NetUtils.setInterface(multicastSocket, false); + multicastSocket.joinGroup(multicastAddress); + } catch (Exception e) { + Assertions.fail(e); + } finally { + if (multicastSocket != null) { + multicastSocket.close(); + } + } + + // multicast ipv6 address, + try { + multicastAddress = InetAddress.getByName("ff01::1"); + + multicastSocket = new MulticastSocket(); + multicastSocket.setLoopbackMode(false); + NetUtils.setInterface(multicastSocket, true); + multicastSocket.joinGroup(multicastAddress); + } catch (Throwable t) { + t.printStackTrace(); + } finally { + if (multicastSocket != null) { + multicastSocket.close(); + } + } + + } + +} diff --git a/dubbo-registry/dubbo-registry-multiple/src/main/java/org/apache/dubbo/registry/multiple/MultipleServiceDiscovery.java b/dubbo-registry/dubbo-registry-multiple/src/main/java/org/apache/dubbo/registry/multiple/MultipleServiceDiscovery.java index 8f5338f2eb..068b6d3d42 100644 --- a/dubbo-registry/dubbo-registry-multiple/src/main/java/org/apache/dubbo/registry/multiple/MultipleServiceDiscovery.java +++ b/dubbo-registry/dubbo-registry-multiple/src/main/java/org/apache/dubbo/registry/multiple/MultipleServiceDiscovery.java @@ -187,4 +187,4 @@ public class MultipleServiceDiscovery implements ServiceDiscovery { } } } -} \ No newline at end of file +} diff --git a/dubbo-registry/dubbo-registry-multiple/src/main/java/org/apache/dubbo/registry/multiple/MultipleServiceDiscoveryFactory.java b/dubbo-registry/dubbo-registry-multiple/src/main/java/org/apache/dubbo/registry/multiple/MultipleServiceDiscoveryFactory.java index 9de8d3da9c..1eb4dc8a59 100644 --- a/dubbo-registry/dubbo-registry-multiple/src/main/java/org/apache/dubbo/registry/multiple/MultipleServiceDiscoveryFactory.java +++ b/dubbo-registry/dubbo-registry-multiple/src/main/java/org/apache/dubbo/registry/multiple/MultipleServiceDiscoveryFactory.java @@ -25,4 +25,4 @@ public class MultipleServiceDiscoveryFactory extends AbstractServiceDiscoveryFac protected ServiceDiscovery createDiscovery(URL registryURL) { return new MultipleServiceDiscovery(); } -} \ No newline at end of file +} diff --git a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosRegistry.java b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosRegistry.java index b0c2113b60..261a38c4d7 100644 --- a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosRegistry.java +++ b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosRegistry.java @@ -641,4 +641,4 @@ public class NacosRegistry extends FailbackRegistry { } } -} \ No newline at end of file +} diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperRegistry.java b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperRegistry.java index 09464b7108..3da0d145d6 100644 --- a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperRegistry.java +++ b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperRegistry.java @@ -1,345 +1,345 @@ -/* - * 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.registry.zookeeper; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.utils.CollectionUtils; -import org.apache.dubbo.common.utils.ConcurrentHashSet; -import org.apache.dubbo.common.utils.UrlUtils; -import org.apache.dubbo.registry.NotifyListener; -import org.apache.dubbo.registry.RegistryNotifier; -import org.apache.dubbo.registry.support.CacheableFailbackRegistry; -import org.apache.dubbo.remoting.Constants; -import org.apache.dubbo.remoting.zookeeper.ChildListener; -import org.apache.dubbo.remoting.zookeeper.StateListener; -import org.apache.dubbo.remoting.zookeeper.ZookeeperClient; -import org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter; -import org.apache.dubbo.rpc.RpcException; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.CountDownLatch; - -import static org.apache.dubbo.common.constants.CommonConstants.ANY_VALUE; -import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.PATH_SEPARATOR; -import static org.apache.dubbo.common.constants.RegistryConstants.CONFIGURATORS_CATEGORY; -import static org.apache.dubbo.common.constants.RegistryConstants.CONSUMERS_CATEGORY; -import static org.apache.dubbo.common.constants.RegistryConstants.DEFAULT_CATEGORY; -import static org.apache.dubbo.common.constants.RegistryConstants.DYNAMIC_KEY; -import static org.apache.dubbo.common.constants.RegistryConstants.PROVIDERS_CATEGORY; -import static org.apache.dubbo.common.constants.RegistryConstants.ROUTERS_CATEGORY; - -/** - * ZookeeperRegistry - */ -public class ZookeeperRegistry extends CacheableFailbackRegistry { - - private final static Logger logger = LoggerFactory.getLogger(ZookeeperRegistry.class); - - private final static String DEFAULT_ROOT = "dubbo"; - - private final String root; - - private final Set anyServices = new ConcurrentHashSet<>(); - - private final ConcurrentMap> zkListeners = new ConcurrentHashMap<>(); - - private final ZookeeperClient zkClient; - - public ZookeeperRegistry(URL url, ZookeeperTransporter zookeeperTransporter) { - super(url); - if (url.isAnyHost()) { - throw new IllegalStateException("registry address == null"); - } - String group = url.getGroup(DEFAULT_ROOT); - if (!group.startsWith(PATH_SEPARATOR)) { - group = PATH_SEPARATOR + group; - } - this.root = group; - zkClient = zookeeperTransporter.connect(url); - zkClient.addStateListener((state) -> { - if (state == StateListener.RECONNECTED) { - logger.warn("Trying to fetch the latest urls, in case there're provider changes during connection loss.\n" + - " Since ephemeral ZNode will not get deleted for a connection lose, " + - "there's no need to re-register url of this instance."); - ZookeeperRegistry.this.fetchLatestAddresses(); - } else if (state == StateListener.NEW_SESSION_CREATED) { - logger.warn("Trying to re-register urls and re-subscribe listeners of this instance to registry..."); - try { - ZookeeperRegistry.this.recover(); - } catch (Exception e) { - logger.error(e.getMessage(), e); - } - } else if (state == StateListener.SESSION_LOST) { - logger.warn("Url of this instance will be deleted from registry soon. " + - "Dubbo client will try to re-register once a new session is created."); - } else if (state == StateListener.SUSPENDED) { - - } else if (state == StateListener.CONNECTED) { - - } - }); - } - - @Override - public boolean isAvailable() { - return zkClient.isConnected(); - } - - @Override - public void destroy() { - super.destroy(); - try { - zkClient.close(); - } catch (Exception e) { - logger.warn("Failed to close zookeeper client " + getUrl() + ", cause: " + e.getMessage(), e); - } - } - - @Override - public void doRegister(URL url) { - try { - zkClient.create(toUrlPath(url), url.getParameter(DYNAMIC_KEY, true)); - } catch (Throwable e) { - throw new RpcException("Failed to register " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e); - } - } - - @Override - public void doUnregister(URL url) { - try { - zkClient.delete(toUrlPath(url)); - } catch (Throwable e) { - throw new RpcException("Failed to unregister " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e); - } - } - - @Override - public void doSubscribe(final URL url, final NotifyListener listener) { - try { - if (ANY_VALUE.equals(url.getServiceInterface())) { - String root = toRootPath(); - ConcurrentMap listeners = zkListeners.computeIfAbsent(url, k -> new ConcurrentHashMap<>()); - ChildListener zkListener = listeners.computeIfAbsent(listener, k -> (parentPath, currentChilds) -> { - for (String child : currentChilds) { - child = URL.decode(child); - if (!anyServices.contains(child)) { - anyServices.add(child); - subscribe(url.setPath(child).addParameters(INTERFACE_KEY, child, - Constants.CHECK_KEY, String.valueOf(false)), k); - } - } - }); - zkClient.create(root, false); - List services = zkClient.addChildListener(root, zkListener); - if (CollectionUtils.isNotEmpty(services)) { - for (String service : services) { - service = URL.decode(service); - anyServices.add(service); - subscribe(url.setPath(service).addParameters(INTERFACE_KEY, service, - Constants.CHECK_KEY, String.valueOf(false)), listener); - } - } - } else { - CountDownLatch latch = new CountDownLatch(1); - List urls = new ArrayList<>(); - for (String path : toCategoriesPath(url)) { - ConcurrentMap listeners = zkListeners.computeIfAbsent(url, k -> new ConcurrentHashMap<>()); - ChildListener zkListener = listeners.computeIfAbsent(listener, k -> new RegistryChildListenerImpl(url, path, k, latch)); - if (zkListener instanceof RegistryChildListenerImpl) { - ((RegistryChildListenerImpl) zkListener).setLatch(latch); - } - zkClient.create(path, false); - List children = zkClient.addChildListener(path, zkListener); - if (children != null) { - urls.addAll(toUrlsWithEmpty(url, path, children)); - } - } - notify(url, listener, urls); - // tells the listener to run only after the sync notification of main thread finishes. - latch.countDown(); - } - } catch (Throwable e) { - throw new RpcException("Failed to subscribe " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e); - } - } - - @Override - public void doUnsubscribe(URL url, NotifyListener listener) { - ConcurrentMap listeners = zkListeners.get(url); - if (listeners != null) { - ChildListener zkListener = listeners.remove(listener); - if (zkListener != null) { - if (ANY_VALUE.equals(url.getServiceInterface())) { - String root = toRootPath(); - zkClient.removeChildListener(root, zkListener); - } else { - for (String path : toCategoriesPath(url)) { - zkClient.removeChildListener(path, zkListener); - } - } - } - - if(listeners.isEmpty()){ - zkListeners.remove(url); - } - } - } - - @Override - public List lookup(URL url) { - if (url == null) { - throw new IllegalArgumentException("lookup url == null"); - } - try { - List providers = new ArrayList<>(); - for (String path : toCategoriesPath(url)) { - List children = zkClient.getChildren(path); - if (children != null) { - providers.addAll(children); - } - } - return toUrlsWithoutEmpty(url, providers); - } catch (Throwable e) { - throw new RpcException("Failed to lookup " + url + " from zookeeper " + getUrl() + ", cause: " + e.getMessage(), e); - } - } - - private String toRootDir() { - if (root.equals(PATH_SEPARATOR)) { - return root; - } - return root + PATH_SEPARATOR; - } - - private String toRootPath() { - return root; - } - - private String toServicePath(URL url) { - String name = url.getServiceInterface(); - if (ANY_VALUE.equals(name)) { - return toRootPath(); - } - return toRootDir() + URL.encode(name); - } - - private String[] toCategoriesPath(URL url) { - String[] categories; - if (ANY_VALUE.equals(url.getCategory())) { - categories = new String[]{PROVIDERS_CATEGORY, CONSUMERS_CATEGORY, ROUTERS_CATEGORY, CONFIGURATORS_CATEGORY}; - } else { - categories = url.getCategory(new String[]{DEFAULT_CATEGORY}); - } - String[] paths = new String[categories.length]; - for (int i = 0; i < categories.length; i++) { - paths[i] = toServicePath(url) + PATH_SEPARATOR + categories[i]; - } - return paths; - } - - private String toCategoryPath(URL url) { - return toServicePath(url) + PATH_SEPARATOR + url.getCategory(DEFAULT_CATEGORY); - } - - private String toUrlPath(URL url) { - return toCategoryPath(url) + PATH_SEPARATOR + URL.encode(url.toFullString()); - } - - /** - * When zookeeper connection recovered from a connection loss, it need to fetch the latest provider list. - * re-register watcher is only a side effect and is not mandate. - */ - private void fetchLatestAddresses() { - // subscribe - Map> recoverSubscribed = new HashMap>(getSubscribed()); - if (!recoverSubscribed.isEmpty()) { - if (logger.isInfoEnabled()) { - logger.info("Fetching the latest urls of " + recoverSubscribed.keySet()); - } - for (Map.Entry> entry : recoverSubscribed.entrySet()) { - URL url = entry.getKey(); - for (NotifyListener listener : entry.getValue()) { - removeFailedSubscribed(url, listener); - addFailedSubscribed(url, listener); - } - } - } - } - - @Override - protected boolean isMatch(URL subscribeUrl, URL providerUrl) { - return UrlUtils.isMatch(subscribeUrl, providerUrl); - } - - private class RegistryChildListenerImpl implements ChildListener { - private RegistryNotifier notifier; - private long lastExecuteTime; - private volatile CountDownLatch latch; - - public RegistryChildListenerImpl(URL consumerUrl, String path, NotifyListener listener, CountDownLatch latch) { - this.latch = latch; - notifier = new RegistryNotifier(ZookeeperRegistry.this.getDelay()) { - @Override - public void notify(Object rawAddresses) { - long delayTime = getDelayTime(); - if (delayTime <= 0) { - this.doNotify(rawAddresses); - } else { - long interval = delayTime - (System.currentTimeMillis() - lastExecuteTime); - if (interval > 0) { - try { - Thread.sleep(interval); - } catch (InterruptedException e) { - // ignore - } - } - lastExecuteTime = System.currentTimeMillis(); - this.doNotify(rawAddresses); - } - } - - @Override - protected void doNotify(Object rawAddresses) { - ZookeeperRegistry.this.notify(consumerUrl, listener, ZookeeperRegistry.this.toUrlsWithEmpty(consumerUrl, path, (List) rawAddresses)); - } - }; - } - - public void setLatch(CountDownLatch latch) { - this.latch = latch; - } - - @Override - public void childChanged(String path, List children) { - try { - latch.await(); - } catch (InterruptedException e) { - logger.warn("Zookeeper children listener thread was interrupted unexpectedly, may cause race condition with the main thread."); - } - notifier.notify(children); - } - } -} +/* + * 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.registry.zookeeper; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.common.utils.ConcurrentHashSet; +import org.apache.dubbo.common.utils.UrlUtils; +import org.apache.dubbo.registry.NotifyListener; +import org.apache.dubbo.registry.RegistryNotifier; +import org.apache.dubbo.registry.support.CacheableFailbackRegistry; +import org.apache.dubbo.remoting.Constants; +import org.apache.dubbo.remoting.zookeeper.ChildListener; +import org.apache.dubbo.remoting.zookeeper.StateListener; +import org.apache.dubbo.remoting.zookeeper.ZookeeperClient; +import org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter; +import org.apache.dubbo.rpc.RpcException; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.CountDownLatch; + +import static org.apache.dubbo.common.constants.CommonConstants.ANY_VALUE; +import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.PATH_SEPARATOR; +import static org.apache.dubbo.common.constants.RegistryConstants.CONFIGURATORS_CATEGORY; +import static org.apache.dubbo.common.constants.RegistryConstants.CONSUMERS_CATEGORY; +import static org.apache.dubbo.common.constants.RegistryConstants.DEFAULT_CATEGORY; +import static org.apache.dubbo.common.constants.RegistryConstants.DYNAMIC_KEY; +import static org.apache.dubbo.common.constants.RegistryConstants.PROVIDERS_CATEGORY; +import static org.apache.dubbo.common.constants.RegistryConstants.ROUTERS_CATEGORY; + +/** + * ZookeeperRegistry + */ +public class ZookeeperRegistry extends CacheableFailbackRegistry { + + private final static Logger logger = LoggerFactory.getLogger(ZookeeperRegistry.class); + + private final static String DEFAULT_ROOT = "dubbo"; + + private final String root; + + private final Set anyServices = new ConcurrentHashSet<>(); + + private final ConcurrentMap> zkListeners = new ConcurrentHashMap<>(); + + private final ZookeeperClient zkClient; + + public ZookeeperRegistry(URL url, ZookeeperTransporter zookeeperTransporter) { + super(url); + if (url.isAnyHost()) { + throw new IllegalStateException("registry address == null"); + } + String group = url.getGroup(DEFAULT_ROOT); + if (!group.startsWith(PATH_SEPARATOR)) { + group = PATH_SEPARATOR + group; + } + this.root = group; + zkClient = zookeeperTransporter.connect(url); + zkClient.addStateListener((state) -> { + if (state == StateListener.RECONNECTED) { + logger.warn("Trying to fetch the latest urls, in case there're provider changes during connection loss.\n" + + " Since ephemeral ZNode will not get deleted for a connection lose, " + + "there's no need to re-register url of this instance."); + ZookeeperRegistry.this.fetchLatestAddresses(); + } else if (state == StateListener.NEW_SESSION_CREATED) { + logger.warn("Trying to re-register urls and re-subscribe listeners of this instance to registry..."); + try { + ZookeeperRegistry.this.recover(); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + } else if (state == StateListener.SESSION_LOST) { + logger.warn("Url of this instance will be deleted from registry soon. " + + "Dubbo client will try to re-register once a new session is created."); + } else if (state == StateListener.SUSPENDED) { + + } else if (state == StateListener.CONNECTED) { + + } + }); + } + + @Override + public boolean isAvailable() { + return zkClient.isConnected(); + } + + @Override + public void destroy() { + super.destroy(); + try { + zkClient.close(); + } catch (Exception e) { + logger.warn("Failed to close zookeeper client " + getUrl() + ", cause: " + e.getMessage(), e); + } + } + + @Override + public void doRegister(URL url) { + try { + zkClient.create(toUrlPath(url), url.getParameter(DYNAMIC_KEY, true)); + } catch (Throwable e) { + throw new RpcException("Failed to register " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e); + } + } + + @Override + public void doUnregister(URL url) { + try { + zkClient.delete(toUrlPath(url)); + } catch (Throwable e) { + throw new RpcException("Failed to unregister " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e); + } + } + + @Override + public void doSubscribe(final URL url, final NotifyListener listener) { + try { + if (ANY_VALUE.equals(url.getServiceInterface())) { + String root = toRootPath(); + ConcurrentMap listeners = zkListeners.computeIfAbsent(url, k -> new ConcurrentHashMap<>()); + ChildListener zkListener = listeners.computeIfAbsent(listener, k -> (parentPath, currentChilds) -> { + for (String child : currentChilds) { + child = URL.decode(child); + if (!anyServices.contains(child)) { + anyServices.add(child); + subscribe(url.setPath(child).addParameters(INTERFACE_KEY, child, + Constants.CHECK_KEY, String.valueOf(false)), k); + } + } + }); + zkClient.create(root, false); + List services = zkClient.addChildListener(root, zkListener); + if (CollectionUtils.isNotEmpty(services)) { + for (String service : services) { + service = URL.decode(service); + anyServices.add(service); + subscribe(url.setPath(service).addParameters(INTERFACE_KEY, service, + Constants.CHECK_KEY, String.valueOf(false)), listener); + } + } + } else { + CountDownLatch latch = new CountDownLatch(1); + List urls = new ArrayList<>(); + for (String path : toCategoriesPath(url)) { + ConcurrentMap listeners = zkListeners.computeIfAbsent(url, k -> new ConcurrentHashMap<>()); + ChildListener zkListener = listeners.computeIfAbsent(listener, k -> new RegistryChildListenerImpl(url, path, k, latch)); + if (zkListener instanceof RegistryChildListenerImpl) { + ((RegistryChildListenerImpl) zkListener).setLatch(latch); + } + zkClient.create(path, false); + List children = zkClient.addChildListener(path, zkListener); + if (children != null) { + urls.addAll(toUrlsWithEmpty(url, path, children)); + } + } + notify(url, listener, urls); + // tells the listener to run only after the sync notification of main thread finishes. + latch.countDown(); + } + } catch (Throwable e) { + throw new RpcException("Failed to subscribe " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e); + } + } + + @Override + public void doUnsubscribe(URL url, NotifyListener listener) { + ConcurrentMap listeners = zkListeners.get(url); + if (listeners != null) { + ChildListener zkListener = listeners.remove(listener); + if (zkListener != null) { + if (ANY_VALUE.equals(url.getServiceInterface())) { + String root = toRootPath(); + zkClient.removeChildListener(root, zkListener); + } else { + for (String path : toCategoriesPath(url)) { + zkClient.removeChildListener(path, zkListener); + } + } + } + + if(listeners.isEmpty()){ + zkListeners.remove(url); + } + } + } + + @Override + public List lookup(URL url) { + if (url == null) { + throw new IllegalArgumentException("lookup url == null"); + } + try { + List providers = new ArrayList<>(); + for (String path : toCategoriesPath(url)) { + List children = zkClient.getChildren(path); + if (children != null) { + providers.addAll(children); + } + } + return toUrlsWithoutEmpty(url, providers); + } catch (Throwable e) { + throw new RpcException("Failed to lookup " + url + " from zookeeper " + getUrl() + ", cause: " + e.getMessage(), e); + } + } + + private String toRootDir() { + if (root.equals(PATH_SEPARATOR)) { + return root; + } + return root + PATH_SEPARATOR; + } + + private String toRootPath() { + return root; + } + + private String toServicePath(URL url) { + String name = url.getServiceInterface(); + if (ANY_VALUE.equals(name)) { + return toRootPath(); + } + return toRootDir() + URL.encode(name); + } + + private String[] toCategoriesPath(URL url) { + String[] categories; + if (ANY_VALUE.equals(url.getCategory())) { + categories = new String[]{PROVIDERS_CATEGORY, CONSUMERS_CATEGORY, ROUTERS_CATEGORY, CONFIGURATORS_CATEGORY}; + } else { + categories = url.getCategory(new String[]{DEFAULT_CATEGORY}); + } + String[] paths = new String[categories.length]; + for (int i = 0; i < categories.length; i++) { + paths[i] = toServicePath(url) + PATH_SEPARATOR + categories[i]; + } + return paths; + } + + private String toCategoryPath(URL url) { + return toServicePath(url) + PATH_SEPARATOR + url.getCategory(DEFAULT_CATEGORY); + } + + private String toUrlPath(URL url) { + return toCategoryPath(url) + PATH_SEPARATOR + URL.encode(url.toFullString()); + } + + /** + * When zookeeper connection recovered from a connection loss, it need to fetch the latest provider list. + * re-register watcher is only a side effect and is not mandate. + */ + private void fetchLatestAddresses() { + // subscribe + Map> recoverSubscribed = new HashMap>(getSubscribed()); + if (!recoverSubscribed.isEmpty()) { + if (logger.isInfoEnabled()) { + logger.info("Fetching the latest urls of " + recoverSubscribed.keySet()); + } + for (Map.Entry> entry : recoverSubscribed.entrySet()) { + URL url = entry.getKey(); + for (NotifyListener listener : entry.getValue()) { + removeFailedSubscribed(url, listener); + addFailedSubscribed(url, listener); + } + } + } + } + + @Override + protected boolean isMatch(URL subscribeUrl, URL providerUrl) { + return UrlUtils.isMatch(subscribeUrl, providerUrl); + } + + private class RegistryChildListenerImpl implements ChildListener { + private RegistryNotifier notifier; + private long lastExecuteTime; + private volatile CountDownLatch latch; + + public RegistryChildListenerImpl(URL consumerUrl, String path, NotifyListener listener, CountDownLatch latch) { + this.latch = latch; + notifier = new RegistryNotifier(ZookeeperRegistry.this.getDelay()) { + @Override + public void notify(Object rawAddresses) { + long delayTime = getDelayTime(); + if (delayTime <= 0) { + this.doNotify(rawAddresses); + } else { + long interval = delayTime - (System.currentTimeMillis() - lastExecuteTime); + if (interval > 0) { + try { + Thread.sleep(interval); + } catch (InterruptedException e) { + // ignore + } + } + lastExecuteTime = System.currentTimeMillis(); + this.doNotify(rawAddresses); + } + } + + @Override + protected void doNotify(Object rawAddresses) { + ZookeeperRegistry.this.notify(consumerUrl, listener, ZookeeperRegistry.this.toUrlsWithEmpty(consumerUrl, path, (List) rawAddresses)); + } + }; + } + + public void setLatch(CountDownLatch latch) { + this.latch = latch; + } + + @Override + public void childChanged(String path, List children) { + try { + latch.await(); + } catch (InterruptedException e) { + logger.warn("Zookeeper children listener thread was interrupted unexpectedly, may cause race condition with the main thread."); + } + notifier.notify(children); + } + } +} diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperRegistryFactory.java b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperRegistryFactory.java index d702d0184c..d393830c87 100644 --- a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperRegistryFactory.java +++ b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperRegistryFactory.java @@ -1,45 +1,45 @@ -/* - * 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.registry.zookeeper; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.registry.Registry; -import org.apache.dubbo.registry.support.AbstractRegistryFactory; -import org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter; - -/** - * ZookeeperRegistryFactory. - * - */ -public class ZookeeperRegistryFactory extends AbstractRegistryFactory { - - private ZookeeperTransporter zookeeperTransporter; - - /** - * Invisible injection of zookeeper client via IOC/SPI - * @param zookeeperTransporter - */ - public void setZookeeperTransporter(ZookeeperTransporter zookeeperTransporter) { - this.zookeeperTransporter = zookeeperTransporter; - } - - @Override - public Registry createRegistry(URL url) { - return new ZookeeperRegistry(url, zookeeperTransporter); - } - -} +/* + * 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.registry.zookeeper; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.registry.Registry; +import org.apache.dubbo.registry.support.AbstractRegistryFactory; +import org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter; + +/** + * ZookeeperRegistryFactory. + * + */ +public class ZookeeperRegistryFactory extends AbstractRegistryFactory { + + private ZookeeperTransporter zookeeperTransporter; + + /** + * Invisible injection of zookeeper client via IOC/SPI + * @param zookeeperTransporter + */ + public void setZookeeperTransporter(ZookeeperTransporter zookeeperTransporter) { + this.zookeeperTransporter = zookeeperTransporter; + } + + @Override + public Registry createRegistry(URL url) { + return new ZookeeperRegistry(url, zookeeperTransporter); + } + +} diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/test/java/org/apache/dubbo/registry/zookeeper/ZookeeperRegistryTest.java b/dubbo-registry/dubbo-registry-zookeeper/src/test/java/org/apache/dubbo/registry/zookeeper/ZookeeperRegistryTest.java index d0b10f690d..60d79c8e4d 100644 --- a/dubbo-registry/dubbo-registry-zookeeper/src/test/java/org/apache/dubbo/registry/zookeeper/ZookeeperRegistryTest.java +++ b/dubbo-registry/dubbo-registry-zookeeper/src/test/java/org/apache/dubbo/registry/zookeeper/ZookeeperRegistryTest.java @@ -1,157 +1,157 @@ -/* - * 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.registry.zookeeper; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.status.Status; -import org.apache.dubbo.common.utils.NetUtils; -import org.apache.dubbo.registry.NotifyListener; -import org.apache.dubbo.registry.Registry; -import org.apache.dubbo.registry.status.RegistryStatusChecker; -import org.apache.dubbo.remoting.zookeeper.curator.CuratorZookeeperTransporter; - -import org.apache.curator.test.TestingServer; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CountDownLatch; - -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.not; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.mockito.Mockito.mock; - -public class ZookeeperRegistryTest { - private TestingServer zkServer; - private ZookeeperRegistry zookeeperRegistry; - private String service = "org.apache.dubbo.test.injvmServie"; - private URL serviceUrl = URL.valueOf("zookeeper://zookeeper/" + service + "?notify=false&methods=test1,test2"); - private URL anyUrl = URL.valueOf("zookeeper://zookeeper/*"); - private URL registryUrl; - private ZookeeperRegistryFactory zookeeperRegistryFactory; - - @BeforeEach - public void setUp() throws Exception { - int zkServerPort = NetUtils.getAvailablePort(); - this.zkServer = new TestingServer(zkServerPort, true); - this.zkServer.start(); - - this.registryUrl = URL.valueOf("zookeeper://localhost:" + zkServerPort); - zookeeperRegistryFactory = new ZookeeperRegistryFactory(); - zookeeperRegistryFactory.setZookeeperTransporter(new CuratorZookeeperTransporter()); - this.zookeeperRegistry = (ZookeeperRegistry) zookeeperRegistryFactory.createRegistry(registryUrl); - } - - @AfterEach - public void tearDown() throws Exception { - zkServer.stop(); - } - - @Test - public void testAnyHost() { - Assertions.assertThrows(IllegalStateException.class, () -> { - URL errorUrl = URL.valueOf("multicast://0.0.0.0/"); - new ZookeeperRegistryFactory().createRegistry(errorUrl); - }); - } - - @Test - public void testRegister() { - Set registered; - - for (int i = 0; i < 2; i++) { - zookeeperRegistry.register(serviceUrl); - registered = zookeeperRegistry.getRegistered(); - assertThat(registered.contains(serviceUrl), is(true)); - } - - registered = zookeeperRegistry.getRegistered(); - assertThat(registered.size(), is(1)); - } - - @Test - public void testSubscribe() { - NotifyListener listener = mock(NotifyListener.class); - zookeeperRegistry.subscribe(serviceUrl, listener); - - Map> subscribed = zookeeperRegistry.getSubscribed(); - assertThat(subscribed.size(), is(1)); - assertThat(subscribed.get(serviceUrl).size(), is(1)); - - zookeeperRegistry.unsubscribe(serviceUrl, listener); - subscribed = zookeeperRegistry.getSubscribed(); - assertThat(subscribed.size(), is(1)); - assertThat(subscribed.get(serviceUrl).size(), is(0)); - } - - @Test - public void testAvailable() { - zookeeperRegistry.register(serviceUrl); - assertThat(zookeeperRegistry.isAvailable(), is(true)); - - zookeeperRegistry.destroy(); - assertThat(zookeeperRegistry.isAvailable(), is(false)); - } - - @Test - public void testLookup() { - List lookup = zookeeperRegistry.lookup(serviceUrl); - assertThat(lookup.size(), is(0)); - - zookeeperRegistry.register(serviceUrl); - lookup = zookeeperRegistry.lookup(serviceUrl); - assertThat(lookup.size(), is(1)); - } - - @Disabled - @Test - /* - This UT is unstable, consider remove it later. - @see https://github.com/apache/dubbo/issues/1787 - */ - public void testStatusChecker() { - RegistryStatusChecker registryStatusChecker = new RegistryStatusChecker(); - Status status = registryStatusChecker.check(); - assertThat(status.getLevel(), is(Status.Level.UNKNOWN)); - - Registry registry = zookeeperRegistryFactory.getRegistry(registryUrl); - assertThat(registry, not(nullValue())); - - status = registryStatusChecker.check(); - assertThat(status.getLevel(), is(Status.Level.ERROR)); - - registry.register(serviceUrl); - status = registryStatusChecker.check(); - assertThat(status.getLevel(), is(Status.Level.OK)); - } - - @Test - public void testSubscribeAnyValue() throws InterruptedException { - final CountDownLatch latch = new CountDownLatch(1); - zookeeperRegistry.register(serviceUrl); - zookeeperRegistry.subscribe(anyUrl, urls -> latch.countDown()); - zookeeperRegistry.register(serviceUrl); - latch.await(); - } -} +/* + * 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.registry.zookeeper; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.status.Status; +import org.apache.dubbo.common.utils.NetUtils; +import org.apache.dubbo.registry.NotifyListener; +import org.apache.dubbo.registry.Registry; +import org.apache.dubbo.registry.status.RegistryStatusChecker; +import org.apache.dubbo.remoting.zookeeper.curator.CuratorZookeeperTransporter; + +import org.apache.curator.test.TestingServer; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CountDownLatch; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.mockito.Mockito.mock; + +public class ZookeeperRegistryTest { + private TestingServer zkServer; + private ZookeeperRegistry zookeeperRegistry; + private String service = "org.apache.dubbo.test.injvmServie"; + private URL serviceUrl = URL.valueOf("zookeeper://zookeeper/" + service + "?notify=false&methods=test1,test2"); + private URL anyUrl = URL.valueOf("zookeeper://zookeeper/*"); + private URL registryUrl; + private ZookeeperRegistryFactory zookeeperRegistryFactory; + + @BeforeEach + public void setUp() throws Exception { + int zkServerPort = NetUtils.getAvailablePort(); + this.zkServer = new TestingServer(zkServerPort, true); + this.zkServer.start(); + + this.registryUrl = URL.valueOf("zookeeper://localhost:" + zkServerPort); + zookeeperRegistryFactory = new ZookeeperRegistryFactory(); + zookeeperRegistryFactory.setZookeeperTransporter(new CuratorZookeeperTransporter()); + this.zookeeperRegistry = (ZookeeperRegistry) zookeeperRegistryFactory.createRegistry(registryUrl); + } + + @AfterEach + public void tearDown() throws Exception { + zkServer.stop(); + } + + @Test + public void testAnyHost() { + Assertions.assertThrows(IllegalStateException.class, () -> { + URL errorUrl = URL.valueOf("multicast://0.0.0.0/"); + new ZookeeperRegistryFactory().createRegistry(errorUrl); + }); + } + + @Test + public void testRegister() { + Set registered; + + for (int i = 0; i < 2; i++) { + zookeeperRegistry.register(serviceUrl); + registered = zookeeperRegistry.getRegistered(); + assertThat(registered.contains(serviceUrl), is(true)); + } + + registered = zookeeperRegistry.getRegistered(); + assertThat(registered.size(), is(1)); + } + + @Test + public void testSubscribe() { + NotifyListener listener = mock(NotifyListener.class); + zookeeperRegistry.subscribe(serviceUrl, listener); + + Map> subscribed = zookeeperRegistry.getSubscribed(); + assertThat(subscribed.size(), is(1)); + assertThat(subscribed.get(serviceUrl).size(), is(1)); + + zookeeperRegistry.unsubscribe(serviceUrl, listener); + subscribed = zookeeperRegistry.getSubscribed(); + assertThat(subscribed.size(), is(1)); + assertThat(subscribed.get(serviceUrl).size(), is(0)); + } + + @Test + public void testAvailable() { + zookeeperRegistry.register(serviceUrl); + assertThat(zookeeperRegistry.isAvailable(), is(true)); + + zookeeperRegistry.destroy(); + assertThat(zookeeperRegistry.isAvailable(), is(false)); + } + + @Test + public void testLookup() { + List lookup = zookeeperRegistry.lookup(serviceUrl); + assertThat(lookup.size(), is(0)); + + zookeeperRegistry.register(serviceUrl); + lookup = zookeeperRegistry.lookup(serviceUrl); + assertThat(lookup.size(), is(1)); + } + + @Disabled + @Test + /* + This UT is unstable, consider remove it later. + @see https://github.com/apache/dubbo/issues/1787 + */ + public void testStatusChecker() { + RegistryStatusChecker registryStatusChecker = new RegistryStatusChecker(); + Status status = registryStatusChecker.check(); + assertThat(status.getLevel(), is(Status.Level.UNKNOWN)); + + Registry registry = zookeeperRegistryFactory.getRegistry(registryUrl); + assertThat(registry, not(nullValue())); + + status = registryStatusChecker.check(); + assertThat(status.getLevel(), is(Status.Level.ERROR)); + + registry.register(serviceUrl); + status = registryStatusChecker.check(); + assertThat(status.getLevel(), is(Status.Level.OK)); + } + + @Test + public void testSubscribeAnyValue() throws InterruptedException { + final CountDownLatch latch = new CountDownLatch(1); + zookeeperRegistry.register(serviceUrl); + zookeeperRegistry.subscribe(anyUrl, urls -> latch.countDown()); + zookeeperRegistry.register(serviceUrl); + latch.await(); + } +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Channel.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Channel.java index c88cb4f061..b10837f5fc 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Channel.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Channel.java @@ -71,4 +71,4 @@ public interface Channel extends Endpoint { * @param key key. */ void removeAttribute(String key); -} \ No newline at end of file +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/ChannelHandler.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/ChannelHandler.java index 832e481191..b1fb112d6a 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/ChannelHandler.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/ChannelHandler.java @@ -66,4 +66,4 @@ public interface ChannelHandler { */ void caught(Channel channel, Throwable exception) throws RemotingException; -} \ No newline at end of file +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Client.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Client.java index 7f15535353..1e3f87a91f 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Client.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Client.java @@ -1,38 +1,38 @@ -/* - * 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.remoting; - -import org.apache.dubbo.common.Resetable; - -/** - * Remoting Client. (API/SPI, Prototype, ThreadSafe) - *

- * Client/Server - * - * @see org.apache.dubbo.remoting.Transporter#connect(org.apache.dubbo.common.URL, ChannelHandler) - */ -public interface Client extends Endpoint, Channel, Resetable, IdleSensible { - - /** - * reconnect. - */ - void reconnect() throws RemotingException; - - @Deprecated - void reset(org.apache.dubbo.common.Parameters parameters); - -} +/* + * 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.remoting; + +import org.apache.dubbo.common.Resetable; + +/** + * Remoting Client. (API/SPI, Prototype, ThreadSafe) + *

+ * Client/Server + * + * @see org.apache.dubbo.remoting.Transporter#connect(org.apache.dubbo.common.URL, ChannelHandler) + */ +public interface Client extends Endpoint, Channel, Resetable, IdleSensible { + + /** + * reconnect. + */ + void reconnect() throws RemotingException; + + @Deprecated + void reset(org.apache.dubbo.common.Parameters parameters); + +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Constants.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Constants.java index 56e1845f79..f44b80b602 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Constants.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Constants.java @@ -135,4 +135,4 @@ public interface Constants { String CONNECTIONS_KEY = "connections"; int DEFAULT_BACKLOG = 1024; -} \ No newline at end of file +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Endpoint.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Endpoint.java index caafa9e98b..2a20f7c379 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Endpoint.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Endpoint.java @@ -1,89 +1,89 @@ -/* - * 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.remoting; - -import org.apache.dubbo.common.URL; - -import java.net.InetSocketAddress; - -/** - * Endpoint. (API/SPI, Prototype, ThreadSafe) - * - * - * @see org.apache.dubbo.remoting.Channel - * @see org.apache.dubbo.remoting.Client - * @see RemotingServer - */ -public interface Endpoint { - - /** - * get url. - * - * @return url - */ - URL getUrl(); - - /** - * get channel handler. - * - * @return channel handler - */ - ChannelHandler getChannelHandler(); - - /** - * get local address. - * - * @return local address. - */ - InetSocketAddress getLocalAddress(); - - /** - * send message. - * - * @param message - * @throws RemotingException - */ - void send(Object message) throws RemotingException; - - /** - * send message. - * - * @param message - * @param sent already sent to socket? - */ - void send(Object message, boolean sent) throws RemotingException; - - /** - * close the channel. - */ - void close(); - - /** - * Graceful close the channel. - */ - void close(int timeout); - - void startClose(); - - /** - * is closed. - * - * @return closed - */ - boolean isClosed(); - -} \ No newline at end of file +/* + * 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.remoting; + +import org.apache.dubbo.common.URL; + +import java.net.InetSocketAddress; + +/** + * Endpoint. (API/SPI, Prototype, ThreadSafe) + * + * + * @see org.apache.dubbo.remoting.Channel + * @see org.apache.dubbo.remoting.Client + * @see RemotingServer + */ +public interface Endpoint { + + /** + * get url. + * + * @return url + */ + URL getUrl(); + + /** + * get channel handler. + * + * @return channel handler + */ + ChannelHandler getChannelHandler(); + + /** + * get local address. + * + * @return local address. + */ + InetSocketAddress getLocalAddress(); + + /** + * send message. + * + * @param message + * @throws RemotingException + */ + void send(Object message) throws RemotingException; + + /** + * send message. + * + * @param message + * @param sent already sent to socket? + */ + void send(Object message, boolean sent) throws RemotingException; + + /** + * close the channel. + */ + void close(); + + /** + * Graceful close the channel. + */ + void close(int timeout); + + void startClose(); + + /** + * is closed. + * + * @return closed + */ + boolean isClosed(); + +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/ExecutionException.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/ExecutionException.java index 48286ef30b..97783c158b 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/ExecutionException.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/ExecutionException.java @@ -1,68 +1,68 @@ -/* - * 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.remoting; - -import java.net.InetSocketAddress; - -/** - * ReceiveException - * - * @export - */ -public class ExecutionException extends RemotingException { - - private static final long serialVersionUID = -2531085236111056860L; - - private final Object request; - - public ExecutionException(Object request, Channel channel, String message, Throwable cause) { - super(channel, message, cause); - this.request = request; - } - - public ExecutionException(Object request, Channel channel, String msg) { - super(channel, msg); - this.request = request; - } - - public ExecutionException(Object request, Channel channel, Throwable cause) { - super(channel, cause); - this.request = request; - } - - public ExecutionException(Object request, InetSocketAddress localAddress, InetSocketAddress remoteAddress, String message, - Throwable cause) { - super(localAddress, remoteAddress, message, cause); - this.request = request; - } - - public ExecutionException(Object request, InetSocketAddress localAddress, InetSocketAddress remoteAddress, String message) { - super(localAddress, remoteAddress, message); - this.request = request; - } - - public ExecutionException(Object request, InetSocketAddress localAddress, InetSocketAddress remoteAddress, Throwable cause) { - super(localAddress, remoteAddress, cause); - this.request = request; - } - - - public Object getRequest() { - return request; - } - -} \ No newline at end of file +/* + * 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.remoting; + +import java.net.InetSocketAddress; + +/** + * ReceiveException + * + * @export + */ +public class ExecutionException extends RemotingException { + + private static final long serialVersionUID = -2531085236111056860L; + + private final Object request; + + public ExecutionException(Object request, Channel channel, String message, Throwable cause) { + super(channel, message, cause); + this.request = request; + } + + public ExecutionException(Object request, Channel channel, String msg) { + super(channel, msg); + this.request = request; + } + + public ExecutionException(Object request, Channel channel, Throwable cause) { + super(channel, cause); + this.request = request; + } + + public ExecutionException(Object request, InetSocketAddress localAddress, InetSocketAddress remoteAddress, String message, + Throwable cause) { + super(localAddress, remoteAddress, message, cause); + this.request = request; + } + + public ExecutionException(Object request, InetSocketAddress localAddress, InetSocketAddress remoteAddress, String message) { + super(localAddress, remoteAddress, message); + this.request = request; + } + + public ExecutionException(Object request, InetSocketAddress localAddress, InetSocketAddress remoteAddress, Throwable cause) { + super(localAddress, remoteAddress, cause); + this.request = request; + } + + + public Object getRequest() { + return request; + } + +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/RemotingException.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/RemotingException.java index 1bbd4c2547..32abe4eaf1 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/RemotingException.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/RemotingException.java @@ -81,4 +81,4 @@ public class RemotingException extends Exception { public InetSocketAddress getRemoteAddress() { return remoteAddress; } -} \ No newline at end of file +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/TimeoutException.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/TimeoutException.java index a14371645f..9ecb8e4e4e 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/TimeoutException.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/TimeoutException.java @@ -54,4 +54,4 @@ public class TimeoutException extends RemotingException { return phase == 0; } -} \ No newline at end of file +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Transporters.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Transporters.java index bd64854275..5856ba8df4 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Transporters.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Transporters.java @@ -1,82 +1,82 @@ -/* - * 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.remoting; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.Version; -import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.remoting.transport.ChannelHandlerAdapter; -import org.apache.dubbo.remoting.transport.ChannelHandlerDispatcher; - -/** - * Transporter facade. (API, Static, ThreadSafe) - */ -public class Transporters { - - static { - // check duplicate jar package - Version.checkDuplicate(Transporters.class); - Version.checkDuplicate(RemotingException.class); - } - - private Transporters() { - } - - public static RemotingServer bind(String url, ChannelHandler... handler) throws RemotingException { - return bind(URL.valueOf(url), handler); - } - - public static RemotingServer bind(URL url, ChannelHandler... handlers) throws RemotingException { - if (url == null) { - throw new IllegalArgumentException("url == null"); - } - if (handlers == null || handlers.length == 0) { - throw new IllegalArgumentException("handlers == null"); - } - ChannelHandler handler; - if (handlers.length == 1) { - handler = handlers[0]; - } else { - handler = new ChannelHandlerDispatcher(handlers); - } - return getTransporter().bind(url, handler); - } - - public static Client connect(String url, ChannelHandler... handler) throws RemotingException { - return connect(URL.valueOf(url), handler); - } - - public static Client connect(URL url, ChannelHandler... handlers) throws RemotingException { - if (url == null) { - throw new IllegalArgumentException("url == null"); - } - ChannelHandler handler; - if (handlers == null || handlers.length == 0) { - handler = new ChannelHandlerAdapter(); - } else if (handlers.length == 1) { - handler = handlers[0]; - } else { - handler = new ChannelHandlerDispatcher(handlers); - } - return getTransporter().connect(url, handler); - } - - public static Transporter getTransporter() { - return ExtensionLoader.getExtensionLoader(Transporter.class).getAdaptiveExtension(); - } - -} \ No newline at end of file +/* + * 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.remoting; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.Version; +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.remoting.transport.ChannelHandlerAdapter; +import org.apache.dubbo.remoting.transport.ChannelHandlerDispatcher; + +/** + * Transporter facade. (API, Static, ThreadSafe) + */ +public class Transporters { + + static { + // check duplicate jar package + Version.checkDuplicate(Transporters.class); + Version.checkDuplicate(RemotingException.class); + } + + private Transporters() { + } + + public static RemotingServer bind(String url, ChannelHandler... handler) throws RemotingException { + return bind(URL.valueOf(url), handler); + } + + public static RemotingServer bind(URL url, ChannelHandler... handlers) throws RemotingException { + if (url == null) { + throw new IllegalArgumentException("url == null"); + } + if (handlers == null || handlers.length == 0) { + throw new IllegalArgumentException("handlers == null"); + } + ChannelHandler handler; + if (handlers.length == 1) { + handler = handlers[0]; + } else { + handler = new ChannelHandlerDispatcher(handlers); + } + return getTransporter().bind(url, handler); + } + + public static Client connect(String url, ChannelHandler... handler) throws RemotingException { + return connect(URL.valueOf(url), handler); + } + + public static Client connect(URL url, ChannelHandler... handlers) throws RemotingException { + if (url == null) { + throw new IllegalArgumentException("url == null"); + } + ChannelHandler handler; + if (handlers == null || handlers.length == 0) { + handler = new ChannelHandlerAdapter(); + } else if (handlers.length == 1) { + handler = handlers[0]; + } else { + handler = new ChannelHandlerDispatcher(handlers); + } + return getTransporter().connect(url, handler); + } + + public static Transporter getTransporter() { + return ExtensionLoader.getExtensionLoader(Transporter.class).getAdaptiveExtension(); + } + +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/ConnectionHandler.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/ConnectionHandler.java index bdb27b7839..cad5a87760 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/ConnectionHandler.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/ConnectionHandler.java @@ -89,4 +89,4 @@ public class ConnectionHandler extends ChannelInboundHandlerAdapter { eventLoop.schedule(connection::connect, 1, TimeUnit.SECONDS); } -} \ No newline at end of file +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/ConnectionManager.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/ConnectionManager.java index 2c2bc59164..4143c9d1ce 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/ConnectionManager.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/ConnectionManager.java @@ -29,4 +29,4 @@ public interface ConnectionManager { void forEachConnection(Consumer connectionConsumer); -} \ No newline at end of file +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/ExchangeChannel.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/ExchangeChannel.java index c0cf131d8e..6f50739b44 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/ExchangeChannel.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/ExchangeChannel.java @@ -1,84 +1,84 @@ -/* - * 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.remoting.exchange; - -import org.apache.dubbo.remoting.Channel; -import org.apache.dubbo.remoting.RemotingException; - -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; - -/** - * ExchangeChannel. (API/SPI, Prototype, ThreadSafe) - */ -public interface ExchangeChannel extends Channel { - - /** - * send request. - * - * @param request - * @return response future - * @throws RemotingException - */ - @Deprecated - CompletableFuture request(Object request) throws RemotingException; - - /** - * send request. - * - * @param request - * @param timeout - * @return response future - * @throws RemotingException - */ - @Deprecated - CompletableFuture request(Object request, int timeout) throws RemotingException; - - /** - * send request. - * - * @param request - * @return response future - * @throws RemotingException - */ - CompletableFuture request(Object request, ExecutorService executor) throws RemotingException; - - /** - * send request. - * - * @param request - * @param timeout - * @return response future - * @throws RemotingException - */ - CompletableFuture request(Object request, int timeout, ExecutorService executor) throws RemotingException; - - /** - * get message handler. - * - * @return message handler - */ - ExchangeHandler getExchangeHandler(); - - /** - * graceful close. - * - * @param timeout - */ - @Override - void close(int timeout); -} +/* + * 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.remoting.exchange; + +import org.apache.dubbo.remoting.Channel; +import org.apache.dubbo.remoting.RemotingException; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; + +/** + * ExchangeChannel. (API/SPI, Prototype, ThreadSafe) + */ +public interface ExchangeChannel extends Channel { + + /** + * send request. + * + * @param request + * @return response future + * @throws RemotingException + */ + @Deprecated + CompletableFuture request(Object request) throws RemotingException; + + /** + * send request. + * + * @param request + * @param timeout + * @return response future + * @throws RemotingException + */ + @Deprecated + CompletableFuture request(Object request, int timeout) throws RemotingException; + + /** + * send request. + * + * @param request + * @return response future + * @throws RemotingException + */ + CompletableFuture request(Object request, ExecutorService executor) throws RemotingException; + + /** + * send request. + * + * @param request + * @param timeout + * @return response future + * @throws RemotingException + */ + CompletableFuture request(Object request, int timeout, ExecutorService executor) throws RemotingException; + + /** + * get message handler. + * + * @return message handler + */ + ExchangeHandler getExchangeHandler(); + + /** + * graceful close. + * + * @param timeout + */ + @Override + void close(int timeout); +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/ExchangeClient.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/ExchangeClient.java index 89846cb58c..8ce3fac479 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/ExchangeClient.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/ExchangeClient.java @@ -1,28 +1,28 @@ -/* - * 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.remoting.exchange; - -import org.apache.dubbo.remoting.Client; - -/** - * ExchangeClient. (API/SPI, Prototype, ThreadSafe) - * - * - */ -public interface ExchangeClient extends Client, ExchangeChannel { - -} \ No newline at end of file +/* + * 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.remoting.exchange; + +import org.apache.dubbo.remoting.Client; + +/** + * ExchangeClient. (API/SPI, Prototype, ThreadSafe) + * + * + */ +public interface ExchangeClient extends Client, ExchangeChannel { + +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/ExchangeHandler.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/ExchangeHandler.java index 6073b55443..118c932805 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/ExchangeHandler.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/ExchangeHandler.java @@ -1,40 +1,40 @@ -/* - * 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.remoting.exchange; - -import org.apache.dubbo.remoting.ChannelHandler; -import org.apache.dubbo.remoting.RemotingException; -import org.apache.dubbo.remoting.telnet.TelnetHandler; - -import java.util.concurrent.CompletableFuture; - -/** - * ExchangeHandler. (API, Prototype, ThreadSafe) - */ -public interface ExchangeHandler extends ChannelHandler, TelnetHandler { - - /** - * reply. - * - * @param channel - * @param request - * @return response - * @throws RemotingException - */ - CompletableFuture reply(ExchangeChannel channel, Object request) throws RemotingException; - -} \ No newline at end of file +/* + * 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.remoting.exchange; + +import org.apache.dubbo.remoting.ChannelHandler; +import org.apache.dubbo.remoting.RemotingException; +import org.apache.dubbo.remoting.telnet.TelnetHandler; + +import java.util.concurrent.CompletableFuture; + +/** + * ExchangeHandler. (API, Prototype, ThreadSafe) + */ +public interface ExchangeHandler extends ChannelHandler, TelnetHandler { + + /** + * reply. + * + * @param channel + * @param request + * @return response + * @throws RemotingException + */ + CompletableFuture reply(ExchangeChannel channel, Object request) throws RemotingException; + +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/ExchangeServer.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/ExchangeServer.java index 8c52f470db..f8565c4125 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/ExchangeServer.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/ExchangeServer.java @@ -1,44 +1,44 @@ -/* - * 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.remoting.exchange; - -import org.apache.dubbo.remoting.RemotingServer; - -import java.net.InetSocketAddress; -import java.util.Collection; - -/** - * ExchangeServer. (API/SPI, Prototype, ThreadSafe) - */ -public interface ExchangeServer extends RemotingServer { - - /** - * get channels. - * - * @return channels - */ - Collection getExchangeChannels(); - - /** - * get channel. - * - * @param remoteAddress - * @return channel - */ - ExchangeChannel getExchangeChannel(InetSocketAddress remoteAddress); - -} \ No newline at end of file +/* + * 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.remoting.exchange; + +import org.apache.dubbo.remoting.RemotingServer; + +import java.net.InetSocketAddress; +import java.util.Collection; + +/** + * ExchangeServer. (API/SPI, Prototype, ThreadSafe) + */ +public interface ExchangeServer extends RemotingServer { + + /** + * get channels. + * + * @return channels + */ + Collection getExchangeChannels(); + + /** + * get channel. + * + * @param remoteAddress + * @return channel + */ + ExchangeChannel getExchangeChannel(InetSocketAddress remoteAddress); + +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/Exchanger.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/Exchanger.java index d524961a0d..d7c321d454 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/Exchanger.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/Exchanger.java @@ -1,55 +1,55 @@ -/* - * 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.remoting.exchange; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.extension.Adaptive; -import org.apache.dubbo.common.extension.SPI; -import org.apache.dubbo.remoting.Constants; -import org.apache.dubbo.remoting.RemotingException; -import org.apache.dubbo.remoting.exchange.support.header.HeaderExchanger; - -/** - * Exchanger. (SPI, Singleton, ThreadSafe) - *

- * Message Exchange Pattern - * Request-Response - */ -@SPI(HeaderExchanger.NAME) -public interface Exchanger { - - /** - * bind. - * - * @param url - * @param handler - * @return message server - */ - @Adaptive({Constants.EXCHANGER_KEY}) - ExchangeServer bind(URL url, ExchangeHandler handler) throws RemotingException; - - /** - * connect. - * - * @param url - * @param handler - * @return message channel - */ - @Adaptive({Constants.EXCHANGER_KEY}) - ExchangeClient connect(URL url, ExchangeHandler handler) throws RemotingException; - -} +/* + * 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.remoting.exchange; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.Adaptive; +import org.apache.dubbo.common.extension.SPI; +import org.apache.dubbo.remoting.Constants; +import org.apache.dubbo.remoting.RemotingException; +import org.apache.dubbo.remoting.exchange.support.header.HeaderExchanger; + +/** + * Exchanger. (SPI, Singleton, ThreadSafe) + *

+ * Message Exchange Pattern + * Request-Response + */ +@SPI(HeaderExchanger.NAME) +public interface Exchanger { + + /** + * bind. + * + * @param url + * @param handler + * @return message server + */ + @Adaptive({Constants.EXCHANGER_KEY}) + ExchangeServer bind(URL url, ExchangeHandler handler) throws RemotingException; + + /** + * connect. + * + * @param url + * @param handler + * @return message channel + */ + @Adaptive({Constants.EXCHANGER_KEY}) + ExchangeClient connect(URL url, ExchangeHandler handler) throws RemotingException; + +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/Exchangers.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/Exchangers.java index 1e3b2786c0..f3aadd204e 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/Exchangers.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/Exchangers.java @@ -1,121 +1,121 @@ -/* - * 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.remoting.exchange; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.Version; -import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.remoting.ChannelHandler; -import org.apache.dubbo.remoting.Constants; -import org.apache.dubbo.remoting.RemotingException; -import org.apache.dubbo.remoting.exchange.support.ExchangeHandlerDispatcher; -import org.apache.dubbo.remoting.exchange.support.Replier; -import org.apache.dubbo.remoting.transport.ChannelHandlerAdapter; - -/** - * Exchanger facade. (API, Static, ThreadSafe) - */ -public class Exchangers { - - static { - // check duplicate jar package - Version.checkDuplicate(Exchangers.class); - } - - private Exchangers() { - } - - public static ExchangeServer bind(String url, Replier replier) throws RemotingException { - return bind(URL.valueOf(url), replier); - } - - public static ExchangeServer bind(URL url, Replier replier) throws RemotingException { - return bind(url, new ChannelHandlerAdapter(), replier); - } - - public static ExchangeServer bind(String url, ChannelHandler handler, Replier replier) throws RemotingException { - return bind(URL.valueOf(url), handler, replier); - } - - public static ExchangeServer bind(URL url, ChannelHandler handler, Replier replier) throws RemotingException { - return bind(url, new ExchangeHandlerDispatcher(replier, handler)); - } - - public static ExchangeServer bind(String url, ExchangeHandler handler) throws RemotingException { - return bind(URL.valueOf(url), handler); - } - - public static ExchangeServer bind(URL url, ExchangeHandler handler) throws RemotingException { - if (url == null) { - throw new IllegalArgumentException("url == null"); - } - if (handler == null) { - throw new IllegalArgumentException("handler == null"); - } - url = url.addParameterIfAbsent(Constants.CODEC_KEY, "exchange"); - return getExchanger(url).bind(url, handler); - } - - public static ExchangeClient connect(String url) throws RemotingException { - return connect(URL.valueOf(url)); - } - - public static ExchangeClient connect(URL url) throws RemotingException { - return connect(url, new ChannelHandlerAdapter(), null); - } - - public static ExchangeClient connect(String url, Replier replier) throws RemotingException { - return connect(URL.valueOf(url), new ChannelHandlerAdapter(), replier); - } - - public static ExchangeClient connect(URL url, Replier replier) throws RemotingException { - return connect(url, new ChannelHandlerAdapter(), replier); - } - - public static ExchangeClient connect(String url, ChannelHandler handler, Replier replier) throws RemotingException { - return connect(URL.valueOf(url), handler, replier); - } - - public static ExchangeClient connect(URL url, ChannelHandler handler, Replier replier) throws RemotingException { - return connect(url, new ExchangeHandlerDispatcher(replier, handler)); - } - - public static ExchangeClient connect(String url, ExchangeHandler handler) throws RemotingException { - return connect(URL.valueOf(url), handler); - } - - public static ExchangeClient connect(URL url, ExchangeHandler handler) throws RemotingException { - if (url == null) { - throw new IllegalArgumentException("url == null"); - } - if (handler == null) { - throw new IllegalArgumentException("handler == null"); - } -// url = url.addParameterIfAbsent(Constants.CODEC_KEY, "exchange"); - return getExchanger(url).connect(url, handler); - } - - public static Exchanger getExchanger(URL url) { - String type = url.getParameter(Constants.EXCHANGER_KEY, Constants.DEFAULT_EXCHANGER); - return getExchanger(type); - } - - public static Exchanger getExchanger(String type) { - return ExtensionLoader.getExtensionLoader(Exchanger.class).getExtension(type); - } - -} +/* + * 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.remoting.exchange; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.Version; +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.remoting.ChannelHandler; +import org.apache.dubbo.remoting.Constants; +import org.apache.dubbo.remoting.RemotingException; +import org.apache.dubbo.remoting.exchange.support.ExchangeHandlerDispatcher; +import org.apache.dubbo.remoting.exchange.support.Replier; +import org.apache.dubbo.remoting.transport.ChannelHandlerAdapter; + +/** + * Exchanger facade. (API, Static, ThreadSafe) + */ +public class Exchangers { + + static { + // check duplicate jar package + Version.checkDuplicate(Exchangers.class); + } + + private Exchangers() { + } + + public static ExchangeServer bind(String url, Replier replier) throws RemotingException { + return bind(URL.valueOf(url), replier); + } + + public static ExchangeServer bind(URL url, Replier replier) throws RemotingException { + return bind(url, new ChannelHandlerAdapter(), replier); + } + + public static ExchangeServer bind(String url, ChannelHandler handler, Replier replier) throws RemotingException { + return bind(URL.valueOf(url), handler, replier); + } + + public static ExchangeServer bind(URL url, ChannelHandler handler, Replier replier) throws RemotingException { + return bind(url, new ExchangeHandlerDispatcher(replier, handler)); + } + + public static ExchangeServer bind(String url, ExchangeHandler handler) throws RemotingException { + return bind(URL.valueOf(url), handler); + } + + public static ExchangeServer bind(URL url, ExchangeHandler handler) throws RemotingException { + if (url == null) { + throw new IllegalArgumentException("url == null"); + } + if (handler == null) { + throw new IllegalArgumentException("handler == null"); + } + url = url.addParameterIfAbsent(Constants.CODEC_KEY, "exchange"); + return getExchanger(url).bind(url, handler); + } + + public static ExchangeClient connect(String url) throws RemotingException { + return connect(URL.valueOf(url)); + } + + public static ExchangeClient connect(URL url) throws RemotingException { + return connect(url, new ChannelHandlerAdapter(), null); + } + + public static ExchangeClient connect(String url, Replier replier) throws RemotingException { + return connect(URL.valueOf(url), new ChannelHandlerAdapter(), replier); + } + + public static ExchangeClient connect(URL url, Replier replier) throws RemotingException { + return connect(url, new ChannelHandlerAdapter(), replier); + } + + public static ExchangeClient connect(String url, ChannelHandler handler, Replier replier) throws RemotingException { + return connect(URL.valueOf(url), handler, replier); + } + + public static ExchangeClient connect(URL url, ChannelHandler handler, Replier replier) throws RemotingException { + return connect(url, new ExchangeHandlerDispatcher(replier, handler)); + } + + public static ExchangeClient connect(String url, ExchangeHandler handler) throws RemotingException { + return connect(URL.valueOf(url), handler); + } + + public static ExchangeClient connect(URL url, ExchangeHandler handler) throws RemotingException { + if (url == null) { + throw new IllegalArgumentException("url == null"); + } + if (handler == null) { + throw new IllegalArgumentException("handler == null"); + } +// url = url.addParameterIfAbsent(Constants.CODEC_KEY, "exchange"); + return getExchanger(url).connect(url, handler); + } + + public static Exchanger getExchanger(URL url) { + String type = url.getParameter(Constants.EXCHANGER_KEY, Constants.DEFAULT_EXCHANGER); + return getExchanger(type); + } + + public static Exchanger getExchanger(String type) { + return ExtensionLoader.getExtensionLoader(Exchanger.class).getExtension(type); + } + +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/Response.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/Response.java index 0faf00e08d..923ace1f93 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/Response.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/Response.java @@ -1,174 +1,174 @@ -/* - * 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.remoting.exchange; - -import static org.apache.dubbo.common.constants.CommonConstants.HEARTBEAT_EVENT; - -/** - * Response - */ -public class Response { - - /** - * ok. - */ - public static final byte OK = 20; - - /** - * client side timeout. - */ - public static final byte CLIENT_TIMEOUT = 30; - - /** - * server side timeout. - */ - public static final byte SERVER_TIMEOUT = 31; - - /** - * channel inactive, directly return the unfinished requests. - */ - public static final byte CHANNEL_INACTIVE = 35; - - /** - * request format error. - */ - public static final byte BAD_REQUEST = 40; - - /** - * response format error. - */ - public static final byte BAD_RESPONSE = 50; - - /** - * service not found. - */ - public static final byte SERVICE_NOT_FOUND = 60; - - /** - * service error. - */ - public static final byte SERVICE_ERROR = 70; - - /** - * internal server error. - */ - public static final byte SERVER_ERROR = 80; - - /** - * internal server error. - */ - public static final byte CLIENT_ERROR = 90; - - /** - * server side threadpool exhausted and quick return. - */ - public static final byte SERVER_THREADPOOL_EXHAUSTED_ERROR = 100; - - private long mId = 0; - - private String mVersion; - - private byte mStatus = OK; - - private boolean mEvent = false; - - private String mErrorMsg; - - private Object mResult; - - public Response() { - } - - public Response(long id) { - mId = id; - } - - public Response(long id, String version) { - mId = id; - mVersion = version; - } - - public long getId() { - return mId; - } - - public void setId(long id) { - mId = id; - } - - public String getVersion() { - return mVersion; - } - - public void setVersion(String version) { - mVersion = version; - } - - public byte getStatus() { - return mStatus; - } - - public void setStatus(byte status) { - mStatus = status; - } - - public boolean isEvent() { - return mEvent; - } - - public void setEvent(String event) { - mEvent = true; - mResult = event; - } - - public void setEvent(boolean mEvent) { - this.mEvent = mEvent; - } - - public boolean isHeartbeat() { - return mEvent && HEARTBEAT_EVENT == mResult; - } - - @Deprecated - public void setHeartbeat(boolean isHeartbeat) { - if (isHeartbeat) { - setEvent(HEARTBEAT_EVENT); - } - } - - public Object getResult() { - return mResult; - } - - public void setResult(Object msg) { - mResult = msg; - } - - public String getErrorMessage() { - return mErrorMsg; - } - - public void setErrorMessage(String msg) { - mErrorMsg = msg; - } - - @Override - public String toString() { - return "Response [id=" + mId + ", version=" + mVersion + ", status=" + mStatus + ", event=" + mEvent - + ", error=" + mErrorMsg + ", result=" + (mResult == this ? "this" : mResult) + "]"; - } -} \ No newline at end of file +/* + * 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.remoting.exchange; + +import static org.apache.dubbo.common.constants.CommonConstants.HEARTBEAT_EVENT; + +/** + * Response + */ +public class Response { + + /** + * ok. + */ + public static final byte OK = 20; + + /** + * client side timeout. + */ + public static final byte CLIENT_TIMEOUT = 30; + + /** + * server side timeout. + */ + public static final byte SERVER_TIMEOUT = 31; + + /** + * channel inactive, directly return the unfinished requests. + */ + public static final byte CHANNEL_INACTIVE = 35; + + /** + * request format error. + */ + public static final byte BAD_REQUEST = 40; + + /** + * response format error. + */ + public static final byte BAD_RESPONSE = 50; + + /** + * service not found. + */ + public static final byte SERVICE_NOT_FOUND = 60; + + /** + * service error. + */ + public static final byte SERVICE_ERROR = 70; + + /** + * internal server error. + */ + public static final byte SERVER_ERROR = 80; + + /** + * internal server error. + */ + public static final byte CLIENT_ERROR = 90; + + /** + * server side threadpool exhausted and quick return. + */ + public static final byte SERVER_THREADPOOL_EXHAUSTED_ERROR = 100; + + private long mId = 0; + + private String mVersion; + + private byte mStatus = OK; + + private boolean mEvent = false; + + private String mErrorMsg; + + private Object mResult; + + public Response() { + } + + public Response(long id) { + mId = id; + } + + public Response(long id, String version) { + mId = id; + mVersion = version; + } + + public long getId() { + return mId; + } + + public void setId(long id) { + mId = id; + } + + public String getVersion() { + return mVersion; + } + + public void setVersion(String version) { + mVersion = version; + } + + public byte getStatus() { + return mStatus; + } + + public void setStatus(byte status) { + mStatus = status; + } + + public boolean isEvent() { + return mEvent; + } + + public void setEvent(String event) { + mEvent = true; + mResult = event; + } + + public void setEvent(boolean mEvent) { + this.mEvent = mEvent; + } + + public boolean isHeartbeat() { + return mEvent && HEARTBEAT_EVENT == mResult; + } + + @Deprecated + public void setHeartbeat(boolean isHeartbeat) { + if (isHeartbeat) { + setEvent(HEARTBEAT_EVENT); + } + } + + public Object getResult() { + return mResult; + } + + public void setResult(Object msg) { + mResult = msg; + } + + public String getErrorMessage() { + return mErrorMsg; + } + + public void setErrorMessage(String msg) { + mErrorMsg = msg; + } + + @Override + public String toString() { + return "Response [id=" + mId + ", version=" + mVersion + ", status=" + mStatus + ", event=" + mEvent + + ", error=" + mErrorMsg + ", result=" + (mResult == this ? "this" : mResult) + "]"; + } +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/codec/ExchangeCodec.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/codec/ExchangeCodec.java index 246bbb2ef8..552c61bf46 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/codec/ExchangeCodec.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/codec/ExchangeCodec.java @@ -1,507 +1,507 @@ -/* - * 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.remoting.exchange.codec; - -import org.apache.dubbo.common.Version; -import org.apache.dubbo.common.config.ConfigurationUtils; -import org.apache.dubbo.common.io.Bytes; -import org.apache.dubbo.common.io.StreamUtils; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.serialize.Cleanable; -import org.apache.dubbo.common.serialize.ObjectInput; -import org.apache.dubbo.common.serialize.ObjectOutput; -import org.apache.dubbo.common.serialize.Serialization; -import org.apache.dubbo.common.utils.StringUtils; -import org.apache.dubbo.remoting.Channel; -import org.apache.dubbo.remoting.RemotingException; -import org.apache.dubbo.remoting.buffer.ChannelBuffer; -import org.apache.dubbo.remoting.buffer.ChannelBufferInputStream; -import org.apache.dubbo.remoting.buffer.ChannelBufferOutputStream; -import org.apache.dubbo.remoting.exchange.Request; -import org.apache.dubbo.remoting.exchange.Response; -import org.apache.dubbo.remoting.exchange.support.DefaultFuture; -import org.apache.dubbo.remoting.telnet.codec.TelnetCodec; -import org.apache.dubbo.remoting.transport.CodecSupport; -import org.apache.dubbo.remoting.transport.ExceedPayloadLimitException; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; - -/** - * ExchangeCodec. - */ -public class ExchangeCodec extends TelnetCodec { - - // header length. - protected static final int HEADER_LENGTH = 16; - // magic header. - protected static final short MAGIC = (short) 0xdabb; - protected static final byte MAGIC_HIGH = Bytes.short2bytes(MAGIC)[0]; - protected static final byte MAGIC_LOW = Bytes.short2bytes(MAGIC)[1]; - // message flag. - protected static final byte FLAG_REQUEST = (byte) 0x80; - protected static final byte FLAG_TWOWAY = (byte) 0x40; - protected static final byte FLAG_EVENT = (byte) 0x20; - protected static final int SERIALIZATION_MASK = 0x1f; - private static final Logger logger = LoggerFactory.getLogger(ExchangeCodec.class); - - public Short getMagicCode() { - return MAGIC; - } - - @Override - public void encode(Channel channel, ChannelBuffer buffer, Object msg) throws IOException { - if (msg instanceof Request) { - encodeRequest(channel, buffer, (Request) msg); - } else if (msg instanceof Response) { - encodeResponse(channel, buffer, (Response) msg); - } else { - super.encode(channel, buffer, msg); - } - } - - @Override - public Object decode(Channel channel, ChannelBuffer buffer) throws IOException { - int readable = buffer.readableBytes(); - byte[] header = new byte[Math.min(readable, HEADER_LENGTH)]; - buffer.readBytes(header); - return decode(channel, buffer, readable, header); - } - - @Override - protected Object decode(Channel channel, ChannelBuffer buffer, int readable, byte[] header) throws IOException { - // check magic number. - if (readable > 0 && header[0] != MAGIC_HIGH - || readable > 1 && header[1] != MAGIC_LOW) { - int length = header.length; - if (header.length < readable) { - header = Bytes.copyOf(header, readable); - buffer.readBytes(header, length, readable - length); - } - for (int i = 1; i < header.length - 1; i++) { - if (header[i] == MAGIC_HIGH && header[i + 1] == MAGIC_LOW) { - buffer.readerIndex(buffer.readerIndex() - header.length + i); - header = Bytes.copyOf(header, i); - break; - } - } - return super.decode(channel, buffer, readable, header); - } - // check length. - if (readable < HEADER_LENGTH) { - return DecodeResult.NEED_MORE_INPUT; - } - - // get data length. - int len = Bytes.bytes2int(header, 12); - - // When receiving response, how to exceed the length, then directly construct a response to the client. - // see more detail from https://github.com/apache/dubbo/issues/7021. - Object obj = finishRespWhenOverPayload(channel, len, header); - if (null != obj) { - return obj; - } - - checkPayload(channel, len); - - int tt = len + HEADER_LENGTH; - if (readable < tt) { - return DecodeResult.NEED_MORE_INPUT; - } - - // limit input stream. - ChannelBufferInputStream is = new ChannelBufferInputStream(buffer, len); - - try { - return decodeBody(channel, is, header); - } finally { - if (is.available() > 0) { - try { - if (logger.isWarnEnabled()) { - logger.warn("Skip input stream " + is.available()); - } - StreamUtils.skipUnusedStream(is); - } catch (IOException e) { - logger.warn(e.getMessage(), e); - } - } - } - } - - protected Object decodeBody(Channel channel, InputStream is, byte[] header) throws IOException { - byte flag = header[2], proto = (byte) (flag & SERIALIZATION_MASK); - // get request id. - long id = Bytes.bytes2long(header, 4); - if ((flag & FLAG_REQUEST) == 0) { - // decode response. - Response res = new Response(id); - if ((flag & FLAG_EVENT) != 0) { - res.setEvent(true); - } - // get status. - byte status = header[3]; - res.setStatus(status); - try { - if (status == Response.OK) { - Object data; - if (res.isEvent()) { - byte[] eventPayload = CodecSupport.getPayload(is); - if (CodecSupport.isHeartBeat(eventPayload, proto)) { - // heart beat response data is always null; - data = null; - } else { - data = decodeEventData(channel, CodecSupport.deserialize(channel.getUrl(), new ByteArrayInputStream(eventPayload), proto), eventPayload); - } - } else { - data = decodeResponseData(channel, CodecSupport.deserialize(channel.getUrl(), is, proto), getRequestData(id)); - } - res.setResult(data); - } else { - res.setErrorMessage(CodecSupport.deserialize(channel.getUrl(), is, proto).readUTF()); - } - } catch (Throwable t) { - res.setStatus(Response.CLIENT_ERROR); - res.setErrorMessage(StringUtils.toString(t)); - } - return res; - } else { - // decode request. - Request req = new Request(id); - req.setVersion(Version.getProtocolVersion()); - req.setTwoWay((flag & FLAG_TWOWAY) != 0); - if ((flag & FLAG_EVENT) != 0) { - req.setEvent(true); - } - try { - Object data; - if (req.isEvent()) { - byte[] eventPayload = CodecSupport.getPayload(is); - if (CodecSupport.isHeartBeat(eventPayload, proto)) { - // heart beat response data is always null; - data = null; - } else { - data = decodeEventData(channel, CodecSupport.deserialize(channel.getUrl(), new ByteArrayInputStream(eventPayload), proto), eventPayload); - } - } else { - data = decodeRequestData(channel, CodecSupport.deserialize(channel.getUrl(), is, proto)); - } - req.setData(data); - } catch (Throwable t) { - // bad request - req.setBroken(true); - req.setData(t); - } - return req; - } - } - - protected Object getRequestData(long id) { - DefaultFuture future = DefaultFuture.getFuture(id); - if (future == null) { - return null; - } - Request req = future.getRequest(); - if (req == null) { - return null; - } - return req.getData(); - } - - protected void encodeRequest(Channel channel, ChannelBuffer buffer, Request req) throws IOException { - Serialization serialization = getSerialization(channel, req); - // header. - byte[] header = new byte[HEADER_LENGTH]; - // set magic number. - Bytes.short2bytes(MAGIC, header); - - // set request and serialization flag. - header[2] = (byte) (FLAG_REQUEST | serialization.getContentTypeId()); - - if (req.isTwoWay()) { - header[2] |= FLAG_TWOWAY; - } - if (req.isEvent()) { - header[2] |= FLAG_EVENT; - } - - // set request id. - Bytes.long2bytes(req.getId(), header, 4); - - // encode request data. - int savedWriteIndex = buffer.writerIndex(); - buffer.writerIndex(savedWriteIndex + HEADER_LENGTH); - ChannelBufferOutputStream bos = new ChannelBufferOutputStream(buffer); - - if (req.isHeartbeat()) { - // heartbeat request data is always null - bos.write(CodecSupport.getNullBytesOf(serialization)); - } else { - ObjectOutput out = serialization.serialize(channel.getUrl(), bos); - if (req.isEvent()) { - encodeEventData(channel, out, req.getData()); - } else { - encodeRequestData(channel, out, req.getData(), req.getVersion()); - } - out.flushBuffer(); - if (out instanceof Cleanable) { - ((Cleanable) out).cleanup(); - } - } - - bos.flush(); - bos.close(); - int len = bos.writtenBytes(); - checkPayload(channel, len); - Bytes.int2bytes(len, header, 12); - - // write - buffer.writerIndex(savedWriteIndex); - buffer.writeBytes(header); // write header. - buffer.writerIndex(savedWriteIndex + HEADER_LENGTH + len); - } - - protected void encodeResponse(Channel channel, ChannelBuffer buffer, Response res) throws IOException { - int savedWriteIndex = buffer.writerIndex(); - try { - Serialization serialization = getSerialization(channel, res); - // header. - byte[] header = new byte[HEADER_LENGTH]; - // set magic number. - Bytes.short2bytes(MAGIC, header); - // set request and serialization flag. - header[2] = serialization.getContentTypeId(); - if (res.isHeartbeat()) { - header[2] |= FLAG_EVENT; - } - // set response status. - byte status = res.getStatus(); - header[3] = status; - // set request id. - Bytes.long2bytes(res.getId(), header, 4); - - buffer.writerIndex(savedWriteIndex + HEADER_LENGTH); - ChannelBufferOutputStream bos = new ChannelBufferOutputStream(buffer); - - // encode response data or error message. - if (status == Response.OK) { - if(res.isHeartbeat()){ - // heartbeat response data is always null - bos.write(CodecSupport.getNullBytesOf(serialization)); - }else { - ObjectOutput out = serialization.serialize(channel.getUrl(), bos); - if (res.isEvent()) { - encodeEventData(channel, out, res.getResult()); - } else { - encodeResponseData(channel, out, res.getResult(), res.getVersion()); - } - out.flushBuffer(); - if (out instanceof Cleanable) { - ((Cleanable) out).cleanup(); - } - } - } else { - ObjectOutput out = serialization.serialize(channel.getUrl(), bos); - out.writeUTF(res.getErrorMessage()); - out.flushBuffer(); - if (out instanceof Cleanable) { - ((Cleanable) out).cleanup(); - } - } - - bos.flush(); - bos.close(); - - int len = bos.writtenBytes(); - checkPayload(channel, len); - Bytes.int2bytes(len, header, 12); - // write - buffer.writerIndex(savedWriteIndex); - buffer.writeBytes(header); // write header. - buffer.writerIndex(savedWriteIndex + HEADER_LENGTH + len); - } catch (Throwable t) { - // clear buffer - buffer.writerIndex(savedWriteIndex); - // send error message to Consumer, otherwise, Consumer will wait till timeout. - if (!res.isEvent() && res.getStatus() != Response.BAD_RESPONSE) { - Response r = new Response(res.getId(), res.getVersion()); - r.setStatus(Response.BAD_RESPONSE); - - if (t instanceof ExceedPayloadLimitException) { - logger.warn(t.getMessage(), t); - try { - r.setErrorMessage(t.getMessage()); - channel.send(r); - return; - } catch (RemotingException e) { - logger.warn("Failed to send bad_response info back: " + t.getMessage() + ", cause: " + e.getMessage(), e); - } - } else { - // FIXME log error message in Codec and handle in caught() of IoHanndler? - logger.warn("Fail to encode response: " + res + ", send bad_response info instead, cause: " + t.getMessage(), t); - try { - r.setErrorMessage("Failed to send response: " + res + ", cause: " + StringUtils.toString(t)); - channel.send(r); - return; - } catch (RemotingException e) { - logger.warn("Failed to send bad_response info back: " + res + ", cause: " + e.getMessage(), e); - } - } - } - - // Rethrow exception - if (t instanceof IOException) { - throw (IOException) t; - } else if (t instanceof RuntimeException) { - throw (RuntimeException) t; - } else if (t instanceof Error) { - throw (Error) t; - } else { - throw new RuntimeException(t.getMessage(), t); - } - } - } - - @Override - protected Object decodeData(ObjectInput in) throws IOException { - return decodeRequestData(in); - } - - protected Object decodeRequestData(ObjectInput in) throws IOException { - try { - return in.readObject(); - } catch (ClassNotFoundException e) { - throw new IOException(StringUtils.toString("Read object failed.", e)); - } - } - - protected Object decodeResponseData(ObjectInput in) throws IOException { - try { - return in.readObject(); - } catch (ClassNotFoundException e) { - throw new IOException(StringUtils.toString("Read object failed.", e)); - } - } - - @Override - protected void encodeData(ObjectOutput out, Object data) throws IOException { - encodeRequestData(out, data); - } - - private void encodeEventData(ObjectOutput out, Object data) throws IOException { - out.writeEvent(data); - } - - @Deprecated - protected void encodeHeartbeatData(ObjectOutput out, Object data) throws IOException { - encodeEventData(out, data); - } - - protected void encodeRequestData(ObjectOutput out, Object data) throws IOException { - out.writeObject(data); - } - - protected void encodeResponseData(ObjectOutput out, Object data) throws IOException { - out.writeObject(data); - } - - @Override - protected Object decodeData(Channel channel, ObjectInput in) throws IOException { - return decodeRequestData(channel, in); - } - - protected Object decodeEventData(Channel channel, ObjectInput in, byte[] eventBytes) throws IOException { - try { - if (eventBytes != null) { - int dataLen = eventBytes.length; - int threshold = ConfigurationUtils.getSystemConfiguration().getInt("deserialization.event.size", 50); - if (dataLen > threshold) { - throw new IllegalArgumentException("Event data too long, actual size " + threshold + ", threshold " + threshold + " rejected for security consideration."); - } - } - return in.readEvent(); - } catch (IOException | ClassNotFoundException e) { - throw new IOException(StringUtils.toString("Decode dubbo protocol event failed.", e)); - } - } - - protected Object decodeRequestData(Channel channel, ObjectInput in) throws IOException { - return decodeRequestData(in); - } - - protected Object decodeResponseData(Channel channel, ObjectInput in) throws IOException { - return decodeResponseData(in); - } - - protected Object decodeResponseData(Channel channel, ObjectInput in, Object requestData) throws IOException { - return decodeResponseData(channel, in); - } - - @Override - protected void encodeData(Channel channel, ObjectOutput out, Object data) throws IOException { - encodeRequestData(channel, out, data); - } - - private void encodeEventData(Channel channel, ObjectOutput out, Object data) throws IOException { - encodeEventData(out, data); - } - - @Deprecated - protected void encodeHeartbeatData(Channel channel, ObjectOutput out, Object data) throws IOException { - encodeHeartbeatData(out, data); - } - - protected void encodeRequestData(Channel channel, ObjectOutput out, Object data) throws IOException { - encodeRequestData(out, data); - } - - protected void encodeResponseData(Channel channel, ObjectOutput out, Object data) throws IOException { - encodeResponseData(out, data); - } - - protected void encodeRequestData(Channel channel, ObjectOutput out, Object data, String version) throws IOException { - encodeRequestData(out, data); - } - - protected void encodeResponseData(Channel channel, ObjectOutput out, Object data, String version) throws IOException { - encodeResponseData(out, data); - } - - private Object finishRespWhenOverPayload(Channel channel, long size, byte[] header) { - int payload = getPayload(channel); - boolean overPayload = isOverPayload(payload, size); - if (overPayload) { - long reqId = Bytes.bytes2long(header, 4); - byte flag = header[2]; - if ((flag & FLAG_REQUEST) == 0) { - Response res = new Response(reqId); - if ((flag & FLAG_EVENT) != 0) { - res.setEvent(true); - } - // get status. - byte status = header[3]; - res.setStatus(Response.CLIENT_ERROR); - String errorMsg = "Data length too large: " + size + ", max payload: " + payload + ", channel: " + channel; - logger.error(errorMsg); - res.setErrorMessage(errorMsg); - return res; - } - } - return null; - } -} +/* + * 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.remoting.exchange.codec; + +import org.apache.dubbo.common.Version; +import org.apache.dubbo.common.config.ConfigurationUtils; +import org.apache.dubbo.common.io.Bytes; +import org.apache.dubbo.common.io.StreamUtils; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.serialize.Cleanable; +import org.apache.dubbo.common.serialize.ObjectInput; +import org.apache.dubbo.common.serialize.ObjectOutput; +import org.apache.dubbo.common.serialize.Serialization; +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.remoting.Channel; +import org.apache.dubbo.remoting.RemotingException; +import org.apache.dubbo.remoting.buffer.ChannelBuffer; +import org.apache.dubbo.remoting.buffer.ChannelBufferInputStream; +import org.apache.dubbo.remoting.buffer.ChannelBufferOutputStream; +import org.apache.dubbo.remoting.exchange.Request; +import org.apache.dubbo.remoting.exchange.Response; +import org.apache.dubbo.remoting.exchange.support.DefaultFuture; +import org.apache.dubbo.remoting.telnet.codec.TelnetCodec; +import org.apache.dubbo.remoting.transport.CodecSupport; +import org.apache.dubbo.remoting.transport.ExceedPayloadLimitException; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * ExchangeCodec. + */ +public class ExchangeCodec extends TelnetCodec { + + // header length. + protected static final int HEADER_LENGTH = 16; + // magic header. + protected static final short MAGIC = (short) 0xdabb; + protected static final byte MAGIC_HIGH = Bytes.short2bytes(MAGIC)[0]; + protected static final byte MAGIC_LOW = Bytes.short2bytes(MAGIC)[1]; + // message flag. + protected static final byte FLAG_REQUEST = (byte) 0x80; + protected static final byte FLAG_TWOWAY = (byte) 0x40; + protected static final byte FLAG_EVENT = (byte) 0x20; + protected static final int SERIALIZATION_MASK = 0x1f; + private static final Logger logger = LoggerFactory.getLogger(ExchangeCodec.class); + + public Short getMagicCode() { + return MAGIC; + } + + @Override + public void encode(Channel channel, ChannelBuffer buffer, Object msg) throws IOException { + if (msg instanceof Request) { + encodeRequest(channel, buffer, (Request) msg); + } else if (msg instanceof Response) { + encodeResponse(channel, buffer, (Response) msg); + } else { + super.encode(channel, buffer, msg); + } + } + + @Override + public Object decode(Channel channel, ChannelBuffer buffer) throws IOException { + int readable = buffer.readableBytes(); + byte[] header = new byte[Math.min(readable, HEADER_LENGTH)]; + buffer.readBytes(header); + return decode(channel, buffer, readable, header); + } + + @Override + protected Object decode(Channel channel, ChannelBuffer buffer, int readable, byte[] header) throws IOException { + // check magic number. + if (readable > 0 && header[0] != MAGIC_HIGH + || readable > 1 && header[1] != MAGIC_LOW) { + int length = header.length; + if (header.length < readable) { + header = Bytes.copyOf(header, readable); + buffer.readBytes(header, length, readable - length); + } + for (int i = 1; i < header.length - 1; i++) { + if (header[i] == MAGIC_HIGH && header[i + 1] == MAGIC_LOW) { + buffer.readerIndex(buffer.readerIndex() - header.length + i); + header = Bytes.copyOf(header, i); + break; + } + } + return super.decode(channel, buffer, readable, header); + } + // check length. + if (readable < HEADER_LENGTH) { + return DecodeResult.NEED_MORE_INPUT; + } + + // get data length. + int len = Bytes.bytes2int(header, 12); + + // When receiving response, how to exceed the length, then directly construct a response to the client. + // see more detail from https://github.com/apache/dubbo/issues/7021. + Object obj = finishRespWhenOverPayload(channel, len, header); + if (null != obj) { + return obj; + } + + checkPayload(channel, len); + + int tt = len + HEADER_LENGTH; + if (readable < tt) { + return DecodeResult.NEED_MORE_INPUT; + } + + // limit input stream. + ChannelBufferInputStream is = new ChannelBufferInputStream(buffer, len); + + try { + return decodeBody(channel, is, header); + } finally { + if (is.available() > 0) { + try { + if (logger.isWarnEnabled()) { + logger.warn("Skip input stream " + is.available()); + } + StreamUtils.skipUnusedStream(is); + } catch (IOException e) { + logger.warn(e.getMessage(), e); + } + } + } + } + + protected Object decodeBody(Channel channel, InputStream is, byte[] header) throws IOException { + byte flag = header[2], proto = (byte) (flag & SERIALIZATION_MASK); + // get request id. + long id = Bytes.bytes2long(header, 4); + if ((flag & FLAG_REQUEST) == 0) { + // decode response. + Response res = new Response(id); + if ((flag & FLAG_EVENT) != 0) { + res.setEvent(true); + } + // get status. + byte status = header[3]; + res.setStatus(status); + try { + if (status == Response.OK) { + Object data; + if (res.isEvent()) { + byte[] eventPayload = CodecSupport.getPayload(is); + if (CodecSupport.isHeartBeat(eventPayload, proto)) { + // heart beat response data is always null; + data = null; + } else { + data = decodeEventData(channel, CodecSupport.deserialize(channel.getUrl(), new ByteArrayInputStream(eventPayload), proto), eventPayload); + } + } else { + data = decodeResponseData(channel, CodecSupport.deserialize(channel.getUrl(), is, proto), getRequestData(id)); + } + res.setResult(data); + } else { + res.setErrorMessage(CodecSupport.deserialize(channel.getUrl(), is, proto).readUTF()); + } + } catch (Throwable t) { + res.setStatus(Response.CLIENT_ERROR); + res.setErrorMessage(StringUtils.toString(t)); + } + return res; + } else { + // decode request. + Request req = new Request(id); + req.setVersion(Version.getProtocolVersion()); + req.setTwoWay((flag & FLAG_TWOWAY) != 0); + if ((flag & FLAG_EVENT) != 0) { + req.setEvent(true); + } + try { + Object data; + if (req.isEvent()) { + byte[] eventPayload = CodecSupport.getPayload(is); + if (CodecSupport.isHeartBeat(eventPayload, proto)) { + // heart beat response data is always null; + data = null; + } else { + data = decodeEventData(channel, CodecSupport.deserialize(channel.getUrl(), new ByteArrayInputStream(eventPayload), proto), eventPayload); + } + } else { + data = decodeRequestData(channel, CodecSupport.deserialize(channel.getUrl(), is, proto)); + } + req.setData(data); + } catch (Throwable t) { + // bad request + req.setBroken(true); + req.setData(t); + } + return req; + } + } + + protected Object getRequestData(long id) { + DefaultFuture future = DefaultFuture.getFuture(id); + if (future == null) { + return null; + } + Request req = future.getRequest(); + if (req == null) { + return null; + } + return req.getData(); + } + + protected void encodeRequest(Channel channel, ChannelBuffer buffer, Request req) throws IOException { + Serialization serialization = getSerialization(channel, req); + // header. + byte[] header = new byte[HEADER_LENGTH]; + // set magic number. + Bytes.short2bytes(MAGIC, header); + + // set request and serialization flag. + header[2] = (byte) (FLAG_REQUEST | serialization.getContentTypeId()); + + if (req.isTwoWay()) { + header[2] |= FLAG_TWOWAY; + } + if (req.isEvent()) { + header[2] |= FLAG_EVENT; + } + + // set request id. + Bytes.long2bytes(req.getId(), header, 4); + + // encode request data. + int savedWriteIndex = buffer.writerIndex(); + buffer.writerIndex(savedWriteIndex + HEADER_LENGTH); + ChannelBufferOutputStream bos = new ChannelBufferOutputStream(buffer); + + if (req.isHeartbeat()) { + // heartbeat request data is always null + bos.write(CodecSupport.getNullBytesOf(serialization)); + } else { + ObjectOutput out = serialization.serialize(channel.getUrl(), bos); + if (req.isEvent()) { + encodeEventData(channel, out, req.getData()); + } else { + encodeRequestData(channel, out, req.getData(), req.getVersion()); + } + out.flushBuffer(); + if (out instanceof Cleanable) { + ((Cleanable) out).cleanup(); + } + } + + bos.flush(); + bos.close(); + int len = bos.writtenBytes(); + checkPayload(channel, len); + Bytes.int2bytes(len, header, 12); + + // write + buffer.writerIndex(savedWriteIndex); + buffer.writeBytes(header); // write header. + buffer.writerIndex(savedWriteIndex + HEADER_LENGTH + len); + } + + protected void encodeResponse(Channel channel, ChannelBuffer buffer, Response res) throws IOException { + int savedWriteIndex = buffer.writerIndex(); + try { + Serialization serialization = getSerialization(channel, res); + // header. + byte[] header = new byte[HEADER_LENGTH]; + // set magic number. + Bytes.short2bytes(MAGIC, header); + // set request and serialization flag. + header[2] = serialization.getContentTypeId(); + if (res.isHeartbeat()) { + header[2] |= FLAG_EVENT; + } + // set response status. + byte status = res.getStatus(); + header[3] = status; + // set request id. + Bytes.long2bytes(res.getId(), header, 4); + + buffer.writerIndex(savedWriteIndex + HEADER_LENGTH); + ChannelBufferOutputStream bos = new ChannelBufferOutputStream(buffer); + + // encode response data or error message. + if (status == Response.OK) { + if(res.isHeartbeat()){ + // heartbeat response data is always null + bos.write(CodecSupport.getNullBytesOf(serialization)); + }else { + ObjectOutput out = serialization.serialize(channel.getUrl(), bos); + if (res.isEvent()) { + encodeEventData(channel, out, res.getResult()); + } else { + encodeResponseData(channel, out, res.getResult(), res.getVersion()); + } + out.flushBuffer(); + if (out instanceof Cleanable) { + ((Cleanable) out).cleanup(); + } + } + } else { + ObjectOutput out = serialization.serialize(channel.getUrl(), bos); + out.writeUTF(res.getErrorMessage()); + out.flushBuffer(); + if (out instanceof Cleanable) { + ((Cleanable) out).cleanup(); + } + } + + bos.flush(); + bos.close(); + + int len = bos.writtenBytes(); + checkPayload(channel, len); + Bytes.int2bytes(len, header, 12); + // write + buffer.writerIndex(savedWriteIndex); + buffer.writeBytes(header); // write header. + buffer.writerIndex(savedWriteIndex + HEADER_LENGTH + len); + } catch (Throwable t) { + // clear buffer + buffer.writerIndex(savedWriteIndex); + // send error message to Consumer, otherwise, Consumer will wait till timeout. + if (!res.isEvent() && res.getStatus() != Response.BAD_RESPONSE) { + Response r = new Response(res.getId(), res.getVersion()); + r.setStatus(Response.BAD_RESPONSE); + + if (t instanceof ExceedPayloadLimitException) { + logger.warn(t.getMessage(), t); + try { + r.setErrorMessage(t.getMessage()); + channel.send(r); + return; + } catch (RemotingException e) { + logger.warn("Failed to send bad_response info back: " + t.getMessage() + ", cause: " + e.getMessage(), e); + } + } else { + // FIXME log error message in Codec and handle in caught() of IoHanndler? + logger.warn("Fail to encode response: " + res + ", send bad_response info instead, cause: " + t.getMessage(), t); + try { + r.setErrorMessage("Failed to send response: " + res + ", cause: " + StringUtils.toString(t)); + channel.send(r); + return; + } catch (RemotingException e) { + logger.warn("Failed to send bad_response info back: " + res + ", cause: " + e.getMessage(), e); + } + } + } + + // Rethrow exception + if (t instanceof IOException) { + throw (IOException) t; + } else if (t instanceof RuntimeException) { + throw (RuntimeException) t; + } else if (t instanceof Error) { + throw (Error) t; + } else { + throw new RuntimeException(t.getMessage(), t); + } + } + } + + @Override + protected Object decodeData(ObjectInput in) throws IOException { + return decodeRequestData(in); + } + + protected Object decodeRequestData(ObjectInput in) throws IOException { + try { + return in.readObject(); + } catch (ClassNotFoundException e) { + throw new IOException(StringUtils.toString("Read object failed.", e)); + } + } + + protected Object decodeResponseData(ObjectInput in) throws IOException { + try { + return in.readObject(); + } catch (ClassNotFoundException e) { + throw new IOException(StringUtils.toString("Read object failed.", e)); + } + } + + @Override + protected void encodeData(ObjectOutput out, Object data) throws IOException { + encodeRequestData(out, data); + } + + private void encodeEventData(ObjectOutput out, Object data) throws IOException { + out.writeEvent(data); + } + + @Deprecated + protected void encodeHeartbeatData(ObjectOutput out, Object data) throws IOException { + encodeEventData(out, data); + } + + protected void encodeRequestData(ObjectOutput out, Object data) throws IOException { + out.writeObject(data); + } + + protected void encodeResponseData(ObjectOutput out, Object data) throws IOException { + out.writeObject(data); + } + + @Override + protected Object decodeData(Channel channel, ObjectInput in) throws IOException { + return decodeRequestData(channel, in); + } + + protected Object decodeEventData(Channel channel, ObjectInput in, byte[] eventBytes) throws IOException { + try { + if (eventBytes != null) { + int dataLen = eventBytes.length; + int threshold = ConfigurationUtils.getSystemConfiguration().getInt("deserialization.event.size", 50); + if (dataLen > threshold) { + throw new IllegalArgumentException("Event data too long, actual size " + threshold + ", threshold " + threshold + " rejected for security consideration."); + } + } + return in.readEvent(); + } catch (IOException | ClassNotFoundException e) { + throw new IOException(StringUtils.toString("Decode dubbo protocol event failed.", e)); + } + } + + protected Object decodeRequestData(Channel channel, ObjectInput in) throws IOException { + return decodeRequestData(in); + } + + protected Object decodeResponseData(Channel channel, ObjectInput in) throws IOException { + return decodeResponseData(in); + } + + protected Object decodeResponseData(Channel channel, ObjectInput in, Object requestData) throws IOException { + return decodeResponseData(channel, in); + } + + @Override + protected void encodeData(Channel channel, ObjectOutput out, Object data) throws IOException { + encodeRequestData(channel, out, data); + } + + private void encodeEventData(Channel channel, ObjectOutput out, Object data) throws IOException { + encodeEventData(out, data); + } + + @Deprecated + protected void encodeHeartbeatData(Channel channel, ObjectOutput out, Object data) throws IOException { + encodeHeartbeatData(out, data); + } + + protected void encodeRequestData(Channel channel, ObjectOutput out, Object data) throws IOException { + encodeRequestData(out, data); + } + + protected void encodeResponseData(Channel channel, ObjectOutput out, Object data) throws IOException { + encodeResponseData(out, data); + } + + protected void encodeRequestData(Channel channel, ObjectOutput out, Object data, String version) throws IOException { + encodeRequestData(out, data); + } + + protected void encodeResponseData(Channel channel, ObjectOutput out, Object data, String version) throws IOException { + encodeResponseData(out, data); + } + + private Object finishRespWhenOverPayload(Channel channel, long size, byte[] header) { + int payload = getPayload(channel); + boolean overPayload = isOverPayload(payload, size); + if (overPayload) { + long reqId = Bytes.bytes2long(header, 4); + byte flag = header[2]; + if ((flag & FLAG_REQUEST) == 0) { + Response res = new Response(reqId); + if ((flag & FLAG_EVENT) != 0) { + res.setEvent(true); + } + // get status. + byte status = header[3]; + res.setStatus(Response.CLIENT_ERROR); + String errorMsg = "Data length too large: " + size + ", max payload: " + payload + ", channel: " + channel; + logger.error(errorMsg); + res.setErrorMessage(errorMsg); + return res; + } + } + return null; + } +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/ExchangeHandlerAdapter.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/ExchangeHandlerAdapter.java index e2f0f42c8b..bc3e33ae5e 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/ExchangeHandlerAdapter.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/ExchangeHandlerAdapter.java @@ -1,36 +1,36 @@ -/* - * 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.remoting.exchange.support; - -import org.apache.dubbo.remoting.RemotingException; -import org.apache.dubbo.remoting.exchange.ExchangeChannel; -import org.apache.dubbo.remoting.exchange.ExchangeHandler; -import org.apache.dubbo.remoting.telnet.support.TelnetHandlerAdapter; - -import java.util.concurrent.CompletableFuture; - -/** - * ExchangeHandlerAdapter - */ -public abstract class ExchangeHandlerAdapter extends TelnetHandlerAdapter implements ExchangeHandler { - - @Override - public CompletableFuture reply(ExchangeChannel channel, Object msg) throws RemotingException { - return null; - } - -} \ No newline at end of file +/* + * 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.remoting.exchange.support; + +import org.apache.dubbo.remoting.RemotingException; +import org.apache.dubbo.remoting.exchange.ExchangeChannel; +import org.apache.dubbo.remoting.exchange.ExchangeHandler; +import org.apache.dubbo.remoting.telnet.support.TelnetHandlerAdapter; + +import java.util.concurrent.CompletableFuture; + +/** + * ExchangeHandlerAdapter + */ +public abstract class ExchangeHandlerAdapter extends TelnetHandlerAdapter implements ExchangeHandler { + + @Override + public CompletableFuture reply(ExchangeChannel channel, Object msg) throws RemotingException { + return null; + } + +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/ExchangeHandlerDispatcher.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/ExchangeHandlerDispatcher.java index 873e2ee67b..f3a833700f 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/ExchangeHandlerDispatcher.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/ExchangeHandlerDispatcher.java @@ -1,121 +1,121 @@ -/* - * 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.remoting.exchange.support; - -import org.apache.dubbo.remoting.Channel; -import org.apache.dubbo.remoting.ChannelHandler; -import org.apache.dubbo.remoting.RemotingException; -import org.apache.dubbo.remoting.exchange.ExchangeChannel; -import org.apache.dubbo.remoting.exchange.ExchangeHandler; -import org.apache.dubbo.remoting.telnet.TelnetHandler; -import org.apache.dubbo.remoting.telnet.support.TelnetHandlerAdapter; -import org.apache.dubbo.remoting.transport.ChannelHandlerDispatcher; - -import java.util.concurrent.CompletableFuture; - -/** - * ExchangeHandlerDispatcher - */ -public class ExchangeHandlerDispatcher implements ExchangeHandler { - - private final ReplierDispatcher replierDispatcher; - - private final ChannelHandlerDispatcher handlerDispatcher; - - private final TelnetHandler telnetHandler; - - public ExchangeHandlerDispatcher() { - replierDispatcher = new ReplierDispatcher(); - handlerDispatcher = new ChannelHandlerDispatcher(); - telnetHandler = new TelnetHandlerAdapter(); - } - - public ExchangeHandlerDispatcher(Replier replier) { - replierDispatcher = new ReplierDispatcher(replier); - handlerDispatcher = new ChannelHandlerDispatcher(); - telnetHandler = new TelnetHandlerAdapter(); - } - - public ExchangeHandlerDispatcher(ChannelHandler... handlers) { - replierDispatcher = new ReplierDispatcher(); - handlerDispatcher = new ChannelHandlerDispatcher(handlers); - telnetHandler = new TelnetHandlerAdapter(); - } - - public ExchangeHandlerDispatcher(Replier replier, ChannelHandler... handlers) { - replierDispatcher = new ReplierDispatcher(replier); - handlerDispatcher = new ChannelHandlerDispatcher(handlers); - telnetHandler = new TelnetHandlerAdapter(); - } - - public ExchangeHandlerDispatcher addChannelHandler(ChannelHandler handler) { - handlerDispatcher.addChannelHandler(handler); - return this; - } - - public ExchangeHandlerDispatcher removeChannelHandler(ChannelHandler handler) { - handlerDispatcher.removeChannelHandler(handler); - return this; - } - - public ExchangeHandlerDispatcher addReplier(Class type, Replier replier) { - replierDispatcher.addReplier(type, replier); - return this; - } - - public ExchangeHandlerDispatcher removeReplier(Class type) { - replierDispatcher.removeReplier(type); - return this; - } - - @Override - @SuppressWarnings({"unchecked", "rawtypes"}) - public CompletableFuture reply(ExchangeChannel channel, Object request) throws RemotingException { - return CompletableFuture.completedFuture(((Replier) replierDispatcher).reply(channel, request)); - } - - @Override - public void connected(Channel channel) { - handlerDispatcher.connected(channel); - } - - @Override - public void disconnected(Channel channel) { - handlerDispatcher.disconnected(channel); - } - - @Override - public void sent(Channel channel, Object message) { - handlerDispatcher.sent(channel, message); - } - - @Override - public void received(Channel channel, Object message) { - handlerDispatcher.received(channel, message); - } - - @Override - public void caught(Channel channel, Throwable exception) { - handlerDispatcher.caught(channel, exception); - } - - @Override - public String telnet(Channel channel, String message) throws RemotingException { - return telnetHandler.telnet(channel, message); - } - -} +/* + * 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.remoting.exchange.support; + +import org.apache.dubbo.remoting.Channel; +import org.apache.dubbo.remoting.ChannelHandler; +import org.apache.dubbo.remoting.RemotingException; +import org.apache.dubbo.remoting.exchange.ExchangeChannel; +import org.apache.dubbo.remoting.exchange.ExchangeHandler; +import org.apache.dubbo.remoting.telnet.TelnetHandler; +import org.apache.dubbo.remoting.telnet.support.TelnetHandlerAdapter; +import org.apache.dubbo.remoting.transport.ChannelHandlerDispatcher; + +import java.util.concurrent.CompletableFuture; + +/** + * ExchangeHandlerDispatcher + */ +public class ExchangeHandlerDispatcher implements ExchangeHandler { + + private final ReplierDispatcher replierDispatcher; + + private final ChannelHandlerDispatcher handlerDispatcher; + + private final TelnetHandler telnetHandler; + + public ExchangeHandlerDispatcher() { + replierDispatcher = new ReplierDispatcher(); + handlerDispatcher = new ChannelHandlerDispatcher(); + telnetHandler = new TelnetHandlerAdapter(); + } + + public ExchangeHandlerDispatcher(Replier replier) { + replierDispatcher = new ReplierDispatcher(replier); + handlerDispatcher = new ChannelHandlerDispatcher(); + telnetHandler = new TelnetHandlerAdapter(); + } + + public ExchangeHandlerDispatcher(ChannelHandler... handlers) { + replierDispatcher = new ReplierDispatcher(); + handlerDispatcher = new ChannelHandlerDispatcher(handlers); + telnetHandler = new TelnetHandlerAdapter(); + } + + public ExchangeHandlerDispatcher(Replier replier, ChannelHandler... handlers) { + replierDispatcher = new ReplierDispatcher(replier); + handlerDispatcher = new ChannelHandlerDispatcher(handlers); + telnetHandler = new TelnetHandlerAdapter(); + } + + public ExchangeHandlerDispatcher addChannelHandler(ChannelHandler handler) { + handlerDispatcher.addChannelHandler(handler); + return this; + } + + public ExchangeHandlerDispatcher removeChannelHandler(ChannelHandler handler) { + handlerDispatcher.removeChannelHandler(handler); + return this; + } + + public ExchangeHandlerDispatcher addReplier(Class type, Replier replier) { + replierDispatcher.addReplier(type, replier); + return this; + } + + public ExchangeHandlerDispatcher removeReplier(Class type) { + replierDispatcher.removeReplier(type); + return this; + } + + @Override + @SuppressWarnings({"unchecked", "rawtypes"}) + public CompletableFuture reply(ExchangeChannel channel, Object request) throws RemotingException { + return CompletableFuture.completedFuture(((Replier) replierDispatcher).reply(channel, request)); + } + + @Override + public void connected(Channel channel) { + handlerDispatcher.connected(channel); + } + + @Override + public void disconnected(Channel channel) { + handlerDispatcher.disconnected(channel); + } + + @Override + public void sent(Channel channel, Object message) { + handlerDispatcher.sent(channel, message); + } + + @Override + public void received(Channel channel, Object message) { + handlerDispatcher.received(channel, message); + } + + @Override + public void caught(Channel channel, Throwable exception) { + handlerDispatcher.caught(channel, exception); + } + + @Override + public String telnet(Channel channel, String message) throws RemotingException { + return telnetHandler.telnet(channel, message); + } + +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/ExchangeServerDelegate.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/ExchangeServerDelegate.java index 89c41c7cf2..8fdc4289b5 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/ExchangeServerDelegate.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/ExchangeServerDelegate.java @@ -1,132 +1,132 @@ -/* - * 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.remoting.exchange.support; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.remoting.Channel; -import org.apache.dubbo.remoting.ChannelHandler; -import org.apache.dubbo.remoting.RemotingException; -import org.apache.dubbo.remoting.exchange.ExchangeChannel; -import org.apache.dubbo.remoting.exchange.ExchangeServer; - -import java.net.InetSocketAddress; -import java.util.Collection; - -/** - * ExchangeServerDelegate - */ -public class ExchangeServerDelegate implements ExchangeServer { - - private transient ExchangeServer server; - - public ExchangeServerDelegate() { - } - - public ExchangeServerDelegate(ExchangeServer server) { - setServer(server); - } - - public ExchangeServer getServer() { - return server; - } - - public void setServer(ExchangeServer server) { - this.server = server; - } - - @Override - public boolean isBound() { - return server.isBound(); - } - - @Override - public void reset(URL url) { - server.reset(url); - } - - @Override - @Deprecated - public void reset(org.apache.dubbo.common.Parameters parameters) { - reset(getUrl().addParameters(parameters.getParameters())); - } - - @Override - public Collection getChannels() { - return server.getChannels(); - } - - @Override - public Channel getChannel(InetSocketAddress remoteAddress) { - return server.getChannel(remoteAddress); - } - - @Override - public URL getUrl() { - return server.getUrl(); - } - - @Override - public ChannelHandler getChannelHandler() { - return server.getChannelHandler(); - } - - @Override - public InetSocketAddress getLocalAddress() { - return server.getLocalAddress(); - } - - @Override - public void send(Object message) throws RemotingException { - server.send(message); - } - - @Override - public void send(Object message, boolean sent) throws RemotingException { - server.send(message, sent); - } - - @Override - public void close() { - server.close(); - } - - @Override - public boolean isClosed() { - return server.isClosed(); - } - - @Override - public Collection getExchangeChannels() { - return server.getExchangeChannels(); - } - - @Override - public ExchangeChannel getExchangeChannel(InetSocketAddress remoteAddress) { - return server.getExchangeChannel(remoteAddress); - } - - @Override - public void close(int timeout) { - server.close(timeout); - } - - @Override - public void startClose() { - server.startClose(); - } - -} +/* + * 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.remoting.exchange.support; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.remoting.Channel; +import org.apache.dubbo.remoting.ChannelHandler; +import org.apache.dubbo.remoting.RemotingException; +import org.apache.dubbo.remoting.exchange.ExchangeChannel; +import org.apache.dubbo.remoting.exchange.ExchangeServer; + +import java.net.InetSocketAddress; +import java.util.Collection; + +/** + * ExchangeServerDelegate + */ +public class ExchangeServerDelegate implements ExchangeServer { + + private transient ExchangeServer server; + + public ExchangeServerDelegate() { + } + + public ExchangeServerDelegate(ExchangeServer server) { + setServer(server); + } + + public ExchangeServer getServer() { + return server; + } + + public void setServer(ExchangeServer server) { + this.server = server; + } + + @Override + public boolean isBound() { + return server.isBound(); + } + + @Override + public void reset(URL url) { + server.reset(url); + } + + @Override + @Deprecated + public void reset(org.apache.dubbo.common.Parameters parameters) { + reset(getUrl().addParameters(parameters.getParameters())); + } + + @Override + public Collection getChannels() { + return server.getChannels(); + } + + @Override + public Channel getChannel(InetSocketAddress remoteAddress) { + return server.getChannel(remoteAddress); + } + + @Override + public URL getUrl() { + return server.getUrl(); + } + + @Override + public ChannelHandler getChannelHandler() { + return server.getChannelHandler(); + } + + @Override + public InetSocketAddress getLocalAddress() { + return server.getLocalAddress(); + } + + @Override + public void send(Object message) throws RemotingException { + server.send(message); + } + + @Override + public void send(Object message, boolean sent) throws RemotingException { + server.send(message, sent); + } + + @Override + public void close() { + server.close(); + } + + @Override + public boolean isClosed() { + return server.isClosed(); + } + + @Override + public Collection getExchangeChannels() { + return server.getExchangeChannels(); + } + + @Override + public ExchangeChannel getExchangeChannel(InetSocketAddress remoteAddress) { + return server.getExchangeChannel(remoteAddress); + } + + @Override + public void close(int timeout) { + server.close(timeout); + } + + @Override + public void startClose() { + server.startClose(); + } + +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/Replier.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/Replier.java index f7605f9ef4..1be0c1cb1c 100755 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/Replier.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/Replier.java @@ -1,37 +1,37 @@ -/* - * 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.remoting.exchange.support; - -import org.apache.dubbo.remoting.RemotingException; -import org.apache.dubbo.remoting.exchange.ExchangeChannel; - -/** - * Replier. (API, Prototype, ThreadSafe) - */ -public interface Replier { - - /** - * reply. - * - * @param channel - * @param request - * @return response - * @throws RemotingException - */ - Object reply(ExchangeChannel channel, T request) throws RemotingException; - -} \ No newline at end of file +/* + * 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.remoting.exchange.support; + +import org.apache.dubbo.remoting.RemotingException; +import org.apache.dubbo.remoting.exchange.ExchangeChannel; + +/** + * Replier. (API, Prototype, ThreadSafe) + */ +public interface Replier { + + /** + * reply. + * + * @param channel + * @param request + * @return response + * @throws RemotingException + */ + Object reply(ExchangeChannel channel, T request) throws RemotingException; + +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/ReplierDispatcher.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/ReplierDispatcher.java index 43bf8f88ea..4cd8eb411d 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/ReplierDispatcher.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/ReplierDispatcher.java @@ -1,77 +1,77 @@ -/* - * 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.remoting.exchange.support; - -import org.apache.dubbo.remoting.RemotingException; -import org.apache.dubbo.remoting.exchange.ExchangeChannel; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * ReplierDispatcher - */ -public class ReplierDispatcher implements Replier { - - private final Replier defaultReplier; - - private final Map, Replier> repliers = new ConcurrentHashMap, Replier>(); - - public ReplierDispatcher() { - this(null, null); - } - - public ReplierDispatcher(Replier defaultReplier) { - this(defaultReplier, null); - } - - public ReplierDispatcher(Replier defaultReplier, Map, Replier> repliers) { - this.defaultReplier = defaultReplier; - if (repliers != null && repliers.size() > 0) { - this.repliers.putAll(repliers); - } - } - - public ReplierDispatcher addReplier(Class type, Replier replier) { - repliers.put(type, replier); - return this; - } - - public ReplierDispatcher removeReplier(Class type) { - repliers.remove(type); - return this; - } - - private Replier getReplier(Class type) { - for (Map.Entry, Replier> entry : repliers.entrySet()) { - if (entry.getKey().isAssignableFrom(type)) { - return entry.getValue(); - } - } - if (defaultReplier != null) { - return defaultReplier; - } - throw new IllegalStateException("Replier not found, Unsupported message object: " + type); - } - - @Override - @SuppressWarnings({"unchecked", "rawtypes"}) - public Object reply(ExchangeChannel channel, Object request) throws RemotingException { - return ((Replier) getReplier(request.getClass())).reply(channel, request); - } - -} +/* + * 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.remoting.exchange.support; + +import org.apache.dubbo.remoting.RemotingException; +import org.apache.dubbo.remoting.exchange.ExchangeChannel; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * ReplierDispatcher + */ +public class ReplierDispatcher implements Replier { + + private final Replier defaultReplier; + + private final Map, Replier> repliers = new ConcurrentHashMap, Replier>(); + + public ReplierDispatcher() { + this(null, null); + } + + public ReplierDispatcher(Replier defaultReplier) { + this(defaultReplier, null); + } + + public ReplierDispatcher(Replier defaultReplier, Map, Replier> repliers) { + this.defaultReplier = defaultReplier; + if (repliers != null && repliers.size() > 0) { + this.repliers.putAll(repliers); + } + } + + public ReplierDispatcher addReplier(Class type, Replier replier) { + repliers.put(type, replier); + return this; + } + + public ReplierDispatcher removeReplier(Class type) { + repliers.remove(type); + return this; + } + + private Replier getReplier(Class type) { + for (Map.Entry, Replier> entry : repliers.entrySet()) { + if (entry.getKey().isAssignableFrom(type)) { + return entry.getValue(); + } + } + if (defaultReplier != null) { + return defaultReplier; + } + throw new IllegalStateException("Replier not found, Unsupported message object: " + type); + } + + @Override + @SuppressWarnings({"unchecked", "rawtypes"}) + public Object reply(ExchangeChannel channel, Object request) throws RemotingException { + return ((Replier) getReplier(request.getClass())).reply(channel, request); + } + +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeChannel.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeChannel.java index a1c7b2596f..387900e403 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeChannel.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeChannel.java @@ -1,270 +1,270 @@ -/* - * 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.remoting.exchange.support.header; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.Version; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.remoting.Channel; -import org.apache.dubbo.remoting.ChannelHandler; -import org.apache.dubbo.remoting.RemotingException; -import org.apache.dubbo.remoting.exchange.ExchangeChannel; -import org.apache.dubbo.remoting.exchange.ExchangeHandler; -import org.apache.dubbo.remoting.exchange.Request; -import org.apache.dubbo.remoting.exchange.Response; -import org.apache.dubbo.remoting.exchange.support.DefaultFuture; - -import java.net.InetSocketAddress; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; - -import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_TIMEOUT; -import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY; - -/** - * ExchangeReceiver - */ -final class HeaderExchangeChannel implements ExchangeChannel { - - private static final Logger logger = LoggerFactory.getLogger(HeaderExchangeChannel.class); - - private static final String CHANNEL_KEY = HeaderExchangeChannel.class.getName() + ".CHANNEL"; - - private final Channel channel; - - private volatile boolean closed = false; - - HeaderExchangeChannel(Channel channel) { - if (channel == null) { - throw new IllegalArgumentException("channel == null"); - } - this.channel = channel; - } - - static HeaderExchangeChannel getOrAddChannel(Channel ch) { - if (ch == null) { - return null; - } - HeaderExchangeChannel ret = (HeaderExchangeChannel) ch.getAttribute(CHANNEL_KEY); - if (ret == null) { - ret = new HeaderExchangeChannel(ch); - if (ch.isConnected()) { - ch.setAttribute(CHANNEL_KEY, ret); - } - } - return ret; - } - - static void removeChannelIfDisconnected(Channel ch) { - if (ch != null && !ch.isConnected()) { - ch.removeAttribute(CHANNEL_KEY); - } - } - - static void removeChannel(Channel ch) { - if (ch != null) { - ch.removeAttribute(CHANNEL_KEY); - } - } - - @Override - public void send(Object message) throws RemotingException { - send(message, false); - } - - @Override - public void send(Object message, boolean sent) throws RemotingException { - if (closed) { - throw new RemotingException(this.getLocalAddress(), null, "Failed to send message " + message + ", cause: The channel " + this + " is closed!"); - } - if (message instanceof Request - || message instanceof Response - || message instanceof String) { - channel.send(message, sent); - } else { - Request request = new Request(); - request.setVersion(Version.getProtocolVersion()); - request.setTwoWay(false); - request.setData(message); - channel.send(request, sent); - } - } - - @Override - public CompletableFuture request(Object request) throws RemotingException { - return request(request, null); - } - - @Override - public CompletableFuture request(Object request, int timeout) throws RemotingException { - return request(request, timeout, null); - } - - @Override - public CompletableFuture request(Object request, ExecutorService executor) throws RemotingException { - return request(request, channel.getUrl().getPositiveParameter(TIMEOUT_KEY, DEFAULT_TIMEOUT), executor); - } - - @Override - public CompletableFuture request(Object request, int timeout, ExecutorService executor) throws RemotingException { - if (closed) { - throw new RemotingException(this.getLocalAddress(), null, "Failed to send request " + request + ", cause: The channel " + this + " is closed!"); - } - // create request. - Request req = new Request(); - req.setVersion(Version.getProtocolVersion()); - req.setTwoWay(true); - req.setData(request); - DefaultFuture future = DefaultFuture.newFuture(channel, req, timeout, executor); - try { - channel.send(req); - } catch (RemotingException e) { - future.cancel(); - throw e; - } - return future; - } - - @Override - public boolean isClosed() { - return closed; - } - - @Override - public void close() { - try { - // graceful close - DefaultFuture.closeChannel(channel); - channel.close(); - } catch (Throwable e) { - logger.warn(e.getMessage(), e); - } - } - - // graceful close - @Override - public void close(int timeout) { - if (closed) { - return; - } - closed = true; - if (timeout > 0) { - long start = System.currentTimeMillis(); - while (DefaultFuture.hasFuture(channel) - && System.currentTimeMillis() - start < timeout) { - try { - Thread.sleep(10); - } catch (InterruptedException e) { - logger.warn(e.getMessage(), e); - } - } - } - close(); - } - - @Override - public void startClose() { - channel.startClose(); - } - - @Override - public InetSocketAddress getLocalAddress() { - return channel.getLocalAddress(); - } - - @Override - public InetSocketAddress getRemoteAddress() { - return channel.getRemoteAddress(); - } - - @Override - public URL getUrl() { - return channel.getUrl(); - } - - @Override - public boolean isConnected() { - return channel.isConnected(); - } - - @Override - public ChannelHandler getChannelHandler() { - return channel.getChannelHandler(); - } - - @Override - public ExchangeHandler getExchangeHandler() { - return (ExchangeHandler) channel.getChannelHandler(); - } - - @Override - public Object getAttribute(String key) { - return channel.getAttribute(key); - } - - @Override - public void setAttribute(String key, Object value) { - channel.setAttribute(key, value); - } - - @Override - public void removeAttribute(String key) { - channel.removeAttribute(key); - } - - @Override - public boolean hasAttribute(String key) { - return channel.hasAttribute(key); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((channel == null) ? 0 : channel.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - HeaderExchangeChannel other = (HeaderExchangeChannel) obj; - if (channel == null) { - if (other.channel != null) { - return false; - } - } else if (!channel.equals(other.channel)) { - return false; - } - return true; - } - - @Override - public String toString() { - return channel.toString(); - } - -} +/* + * 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.remoting.exchange.support.header; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.Version; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.remoting.Channel; +import org.apache.dubbo.remoting.ChannelHandler; +import org.apache.dubbo.remoting.RemotingException; +import org.apache.dubbo.remoting.exchange.ExchangeChannel; +import org.apache.dubbo.remoting.exchange.ExchangeHandler; +import org.apache.dubbo.remoting.exchange.Request; +import org.apache.dubbo.remoting.exchange.Response; +import org.apache.dubbo.remoting.exchange.support.DefaultFuture; + +import java.net.InetSocketAddress; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; + +import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_TIMEOUT; +import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY; + +/** + * ExchangeReceiver + */ +final class HeaderExchangeChannel implements ExchangeChannel { + + private static final Logger logger = LoggerFactory.getLogger(HeaderExchangeChannel.class); + + private static final String CHANNEL_KEY = HeaderExchangeChannel.class.getName() + ".CHANNEL"; + + private final Channel channel; + + private volatile boolean closed = false; + + HeaderExchangeChannel(Channel channel) { + if (channel == null) { + throw new IllegalArgumentException("channel == null"); + } + this.channel = channel; + } + + static HeaderExchangeChannel getOrAddChannel(Channel ch) { + if (ch == null) { + return null; + } + HeaderExchangeChannel ret = (HeaderExchangeChannel) ch.getAttribute(CHANNEL_KEY); + if (ret == null) { + ret = new HeaderExchangeChannel(ch); + if (ch.isConnected()) { + ch.setAttribute(CHANNEL_KEY, ret); + } + } + return ret; + } + + static void removeChannelIfDisconnected(Channel ch) { + if (ch != null && !ch.isConnected()) { + ch.removeAttribute(CHANNEL_KEY); + } + } + + static void removeChannel(Channel ch) { + if (ch != null) { + ch.removeAttribute(CHANNEL_KEY); + } + } + + @Override + public void send(Object message) throws RemotingException { + send(message, false); + } + + @Override + public void send(Object message, boolean sent) throws RemotingException { + if (closed) { + throw new RemotingException(this.getLocalAddress(), null, "Failed to send message " + message + ", cause: The channel " + this + " is closed!"); + } + if (message instanceof Request + || message instanceof Response + || message instanceof String) { + channel.send(message, sent); + } else { + Request request = new Request(); + request.setVersion(Version.getProtocolVersion()); + request.setTwoWay(false); + request.setData(message); + channel.send(request, sent); + } + } + + @Override + public CompletableFuture request(Object request) throws RemotingException { + return request(request, null); + } + + @Override + public CompletableFuture request(Object request, int timeout) throws RemotingException { + return request(request, timeout, null); + } + + @Override + public CompletableFuture request(Object request, ExecutorService executor) throws RemotingException { + return request(request, channel.getUrl().getPositiveParameter(TIMEOUT_KEY, DEFAULT_TIMEOUT), executor); + } + + @Override + public CompletableFuture request(Object request, int timeout, ExecutorService executor) throws RemotingException { + if (closed) { + throw new RemotingException(this.getLocalAddress(), null, "Failed to send request " + request + ", cause: The channel " + this + " is closed!"); + } + // create request. + Request req = new Request(); + req.setVersion(Version.getProtocolVersion()); + req.setTwoWay(true); + req.setData(request); + DefaultFuture future = DefaultFuture.newFuture(channel, req, timeout, executor); + try { + channel.send(req); + } catch (RemotingException e) { + future.cancel(); + throw e; + } + return future; + } + + @Override + public boolean isClosed() { + return closed; + } + + @Override + public void close() { + try { + // graceful close + DefaultFuture.closeChannel(channel); + channel.close(); + } catch (Throwable e) { + logger.warn(e.getMessage(), e); + } + } + + // graceful close + @Override + public void close(int timeout) { + if (closed) { + return; + } + closed = true; + if (timeout > 0) { + long start = System.currentTimeMillis(); + while (DefaultFuture.hasFuture(channel) + && System.currentTimeMillis() - start < timeout) { + try { + Thread.sleep(10); + } catch (InterruptedException e) { + logger.warn(e.getMessage(), e); + } + } + } + close(); + } + + @Override + public void startClose() { + channel.startClose(); + } + + @Override + public InetSocketAddress getLocalAddress() { + return channel.getLocalAddress(); + } + + @Override + public InetSocketAddress getRemoteAddress() { + return channel.getRemoteAddress(); + } + + @Override + public URL getUrl() { + return channel.getUrl(); + } + + @Override + public boolean isConnected() { + return channel.isConnected(); + } + + @Override + public ChannelHandler getChannelHandler() { + return channel.getChannelHandler(); + } + + @Override + public ExchangeHandler getExchangeHandler() { + return (ExchangeHandler) channel.getChannelHandler(); + } + + @Override + public Object getAttribute(String key) { + return channel.getAttribute(key); + } + + @Override + public void setAttribute(String key, Object value) { + channel.setAttribute(key, value); + } + + @Override + public void removeAttribute(String key) { + channel.removeAttribute(key); + } + + @Override + public boolean hasAttribute(String key) { + return channel.hasAttribute(key); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((channel == null) ? 0 : channel.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + HeaderExchangeChannel other = (HeaderExchangeChannel) obj; + if (channel == null) { + if (other.channel != null) { + return false; + } + } else if (!channel.equals(other.channel)) { + return false; + } + return true; + } + + @Override + public String toString() { + return channel.toString(); + } + +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeClient.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeClient.java index bb5bef456c..ced7dbab94 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeClient.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeClient.java @@ -1,238 +1,238 @@ -/* - * 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.remoting.exchange.support.header; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.timer.HashedWheelTimer; -import org.apache.dubbo.common.utils.Assert; -import org.apache.dubbo.common.utils.NamedThreadFactory; -import org.apache.dubbo.remoting.ChannelHandler; -import org.apache.dubbo.remoting.Client; -import org.apache.dubbo.remoting.Constants; -import org.apache.dubbo.remoting.RemotingException; -import org.apache.dubbo.remoting.exchange.ExchangeChannel; -import org.apache.dubbo.remoting.exchange.ExchangeClient; -import org.apache.dubbo.remoting.exchange.ExchangeHandler; - -import java.net.InetSocketAddress; -import java.util.Collections; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.TimeUnit; - -import static org.apache.dubbo.remoting.Constants.HEARTBEAT_CHECK_TICK; -import static org.apache.dubbo.remoting.Constants.LEAST_HEARTBEAT_DURATION; -import static org.apache.dubbo.remoting.Constants.TICKS_PER_WHEEL; -import static org.apache.dubbo.remoting.utils.UrlUtils.getHeartbeat; -import static org.apache.dubbo.remoting.utils.UrlUtils.getIdleTimeout; - -/** - * DefaultMessageClient - */ -public class HeaderExchangeClient implements ExchangeClient { - - private final Client client; - private final ExchangeChannel channel; - - private static final HashedWheelTimer IDLE_CHECK_TIMER = new HashedWheelTimer( - new NamedThreadFactory("dubbo-client-idleCheck", true), 1, TimeUnit.SECONDS, TICKS_PER_WHEEL); - private HeartbeatTimerTask heartBeatTimerTask; - private ReconnectTimerTask reconnectTimerTask; - - public HeaderExchangeClient(Client client, boolean startTimer) { - Assert.notNull(client, "Client can't be null"); - this.client = client; - this.channel = new HeaderExchangeChannel(client); - - if (startTimer) { - URL url = client.getUrl(); - startReconnectTask(url); - startHeartBeatTask(url); - } - } - - @Override - public CompletableFuture request(Object request) throws RemotingException { - return channel.request(request); - } - - @Override - public URL getUrl() { - return channel.getUrl(); - } - - @Override - public InetSocketAddress getRemoteAddress() { - return channel.getRemoteAddress(); - } - - @Override - public CompletableFuture request(Object request, int timeout) throws RemotingException { - return channel.request(request, timeout); - } - - @Override - public CompletableFuture request(Object request, ExecutorService executor) throws RemotingException { - return channel.request(request, executor); - } - - @Override - public CompletableFuture request(Object request, int timeout, ExecutorService executor) throws RemotingException { - return channel.request(request, timeout, executor); - } - - @Override - public ChannelHandler getChannelHandler() { - return channel.getChannelHandler(); - } - - @Override - public boolean isConnected() { - return channel.isConnected(); - } - - @Override - public InetSocketAddress getLocalAddress() { - return channel.getLocalAddress(); - } - - @Override - public ExchangeHandler getExchangeHandler() { - return channel.getExchangeHandler(); - } - - @Override - public void send(Object message) throws RemotingException { - channel.send(message); - } - - @Override - public void send(Object message, boolean sent) throws RemotingException { - channel.send(message, sent); - } - - @Override - public boolean isClosed() { - return channel.isClosed(); - } - - @Override - public void close() { - doClose(); - channel.close(); - } - - @Override - public void close(int timeout) { - // Mark the client into the closure process - startClose(); - doClose(); - channel.close(timeout); - } - - @Override - public void startClose() { - channel.startClose(); - } - - @Override - public void reset(URL url) { - client.reset(url); - // FIXME, should cancel and restart timer tasks if parameters in the new URL are different? - } - - @Override - @Deprecated - public void reset(org.apache.dubbo.common.Parameters parameters) { - reset(getUrl().addParameters(parameters.getParameters())); - } - - @Override - public void reconnect() throws RemotingException { - client.reconnect(); - } - - @Override - public Object getAttribute(String key) { - return channel.getAttribute(key); - } - - @Override - public void setAttribute(String key, Object value) { - channel.setAttribute(key, value); - } - - @Override - public void removeAttribute(String key) { - channel.removeAttribute(key); - } - - @Override - public boolean hasAttribute(String key) { - return channel.hasAttribute(key); - } - - private void startHeartBeatTask(URL url) { - if (!client.canHandleIdle()) { - AbstractTimerTask.ChannelProvider cp = () -> Collections.singletonList(HeaderExchangeClient.this); - int heartbeat = getHeartbeat(url); - long heartbeatTick = calculateLeastDuration(heartbeat); - this.heartBeatTimerTask = new HeartbeatTimerTask(cp, heartbeatTick, heartbeat); - IDLE_CHECK_TIMER.newTimeout(heartBeatTimerTask, heartbeatTick, TimeUnit.MILLISECONDS); - } - } - - private void startReconnectTask(URL url) { - if (shouldReconnect(url)) { - AbstractTimerTask.ChannelProvider cp = () -> Collections.singletonList(HeaderExchangeClient.this); - int idleTimeout = getIdleTimeout(url); - long heartbeatTimeoutTick = calculateLeastDuration(idleTimeout); - this.reconnectTimerTask = new ReconnectTimerTask(cp, heartbeatTimeoutTick, idleTimeout); - IDLE_CHECK_TIMER.newTimeout(reconnectTimerTask, heartbeatTimeoutTick, TimeUnit.MILLISECONDS); - } - } - - private void doClose() { - if (heartBeatTimerTask != null) { - heartBeatTimerTask.cancel(); - } - - if (reconnectTimerTask != null) { - reconnectTimerTask.cancel(); - } - } - - /** - * Each interval cannot be less than 1000ms. - */ - private long calculateLeastDuration(int time) { - if (time / HEARTBEAT_CHECK_TICK <= 0) { - return LEAST_HEARTBEAT_DURATION; - } else { - return time / HEARTBEAT_CHECK_TICK; - } - } - - private boolean shouldReconnect(URL url) { - return url.getParameter(Constants.RECONNECT_KEY, true); - } - - @Override - public String toString() { - return "HeaderExchangeClient [channel=" + channel + "]"; - } -} +/* + * 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.remoting.exchange.support.header; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.timer.HashedWheelTimer; +import org.apache.dubbo.common.utils.Assert; +import org.apache.dubbo.common.utils.NamedThreadFactory; +import org.apache.dubbo.remoting.ChannelHandler; +import org.apache.dubbo.remoting.Client; +import org.apache.dubbo.remoting.Constants; +import org.apache.dubbo.remoting.RemotingException; +import org.apache.dubbo.remoting.exchange.ExchangeChannel; +import org.apache.dubbo.remoting.exchange.ExchangeClient; +import org.apache.dubbo.remoting.exchange.ExchangeHandler; + +import java.net.InetSocketAddress; +import java.util.Collections; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeUnit; + +import static org.apache.dubbo.remoting.Constants.HEARTBEAT_CHECK_TICK; +import static org.apache.dubbo.remoting.Constants.LEAST_HEARTBEAT_DURATION; +import static org.apache.dubbo.remoting.Constants.TICKS_PER_WHEEL; +import static org.apache.dubbo.remoting.utils.UrlUtils.getHeartbeat; +import static org.apache.dubbo.remoting.utils.UrlUtils.getIdleTimeout; + +/** + * DefaultMessageClient + */ +public class HeaderExchangeClient implements ExchangeClient { + + private final Client client; + private final ExchangeChannel channel; + + private static final HashedWheelTimer IDLE_CHECK_TIMER = new HashedWheelTimer( + new NamedThreadFactory("dubbo-client-idleCheck", true), 1, TimeUnit.SECONDS, TICKS_PER_WHEEL); + private HeartbeatTimerTask heartBeatTimerTask; + private ReconnectTimerTask reconnectTimerTask; + + public HeaderExchangeClient(Client client, boolean startTimer) { + Assert.notNull(client, "Client can't be null"); + this.client = client; + this.channel = new HeaderExchangeChannel(client); + + if (startTimer) { + URL url = client.getUrl(); + startReconnectTask(url); + startHeartBeatTask(url); + } + } + + @Override + public CompletableFuture request(Object request) throws RemotingException { + return channel.request(request); + } + + @Override + public URL getUrl() { + return channel.getUrl(); + } + + @Override + public InetSocketAddress getRemoteAddress() { + return channel.getRemoteAddress(); + } + + @Override + public CompletableFuture request(Object request, int timeout) throws RemotingException { + return channel.request(request, timeout); + } + + @Override + public CompletableFuture request(Object request, ExecutorService executor) throws RemotingException { + return channel.request(request, executor); + } + + @Override + public CompletableFuture request(Object request, int timeout, ExecutorService executor) throws RemotingException { + return channel.request(request, timeout, executor); + } + + @Override + public ChannelHandler getChannelHandler() { + return channel.getChannelHandler(); + } + + @Override + public boolean isConnected() { + return channel.isConnected(); + } + + @Override + public InetSocketAddress getLocalAddress() { + return channel.getLocalAddress(); + } + + @Override + public ExchangeHandler getExchangeHandler() { + return channel.getExchangeHandler(); + } + + @Override + public void send(Object message) throws RemotingException { + channel.send(message); + } + + @Override + public void send(Object message, boolean sent) throws RemotingException { + channel.send(message, sent); + } + + @Override + public boolean isClosed() { + return channel.isClosed(); + } + + @Override + public void close() { + doClose(); + channel.close(); + } + + @Override + public void close(int timeout) { + // Mark the client into the closure process + startClose(); + doClose(); + channel.close(timeout); + } + + @Override + public void startClose() { + channel.startClose(); + } + + @Override + public void reset(URL url) { + client.reset(url); + // FIXME, should cancel and restart timer tasks if parameters in the new URL are different? + } + + @Override + @Deprecated + public void reset(org.apache.dubbo.common.Parameters parameters) { + reset(getUrl().addParameters(parameters.getParameters())); + } + + @Override + public void reconnect() throws RemotingException { + client.reconnect(); + } + + @Override + public Object getAttribute(String key) { + return channel.getAttribute(key); + } + + @Override + public void setAttribute(String key, Object value) { + channel.setAttribute(key, value); + } + + @Override + public void removeAttribute(String key) { + channel.removeAttribute(key); + } + + @Override + public boolean hasAttribute(String key) { + return channel.hasAttribute(key); + } + + private void startHeartBeatTask(URL url) { + if (!client.canHandleIdle()) { + AbstractTimerTask.ChannelProvider cp = () -> Collections.singletonList(HeaderExchangeClient.this); + int heartbeat = getHeartbeat(url); + long heartbeatTick = calculateLeastDuration(heartbeat); + this.heartBeatTimerTask = new HeartbeatTimerTask(cp, heartbeatTick, heartbeat); + IDLE_CHECK_TIMER.newTimeout(heartBeatTimerTask, heartbeatTick, TimeUnit.MILLISECONDS); + } + } + + private void startReconnectTask(URL url) { + if (shouldReconnect(url)) { + AbstractTimerTask.ChannelProvider cp = () -> Collections.singletonList(HeaderExchangeClient.this); + int idleTimeout = getIdleTimeout(url); + long heartbeatTimeoutTick = calculateLeastDuration(idleTimeout); + this.reconnectTimerTask = new ReconnectTimerTask(cp, heartbeatTimeoutTick, idleTimeout); + IDLE_CHECK_TIMER.newTimeout(reconnectTimerTask, heartbeatTimeoutTick, TimeUnit.MILLISECONDS); + } + } + + private void doClose() { + if (heartBeatTimerTask != null) { + heartBeatTimerTask.cancel(); + } + + if (reconnectTimerTask != null) { + reconnectTimerTask.cancel(); + } + } + + /** + * Each interval cannot be less than 1000ms. + */ + private long calculateLeastDuration(int time) { + if (time / HEARTBEAT_CHECK_TICK <= 0) { + return LEAST_HEARTBEAT_DURATION; + } else { + return time / HEARTBEAT_CHECK_TICK; + } + } + + private boolean shouldReconnect(URL url) { + return url.getParameter(Constants.RECONNECT_KEY, true); + } + + @Override + public String toString() { + return "HeaderExchangeClient [channel=" + channel + "]"; + } +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeHandler.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeHandler.java index 447c84fcf5..5f03b50eaf 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeHandler.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeHandler.java @@ -1,229 +1,229 @@ -/* - * 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.remoting.exchange.support.header; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.utils.NetUtils; -import org.apache.dubbo.common.utils.StringUtils; -import org.apache.dubbo.remoting.Channel; -import org.apache.dubbo.remoting.ChannelHandler; -import org.apache.dubbo.remoting.Constants; -import org.apache.dubbo.remoting.ExecutionException; -import org.apache.dubbo.remoting.RemotingException; -import org.apache.dubbo.remoting.exchange.ExchangeChannel; -import org.apache.dubbo.remoting.exchange.ExchangeHandler; -import org.apache.dubbo.remoting.exchange.Request; -import org.apache.dubbo.remoting.exchange.Response; -import org.apache.dubbo.remoting.exchange.support.DefaultFuture; -import org.apache.dubbo.remoting.transport.ChannelHandlerDelegate; - -import java.net.InetSocketAddress; -import java.util.concurrent.CompletionStage; - -import static org.apache.dubbo.common.constants.CommonConstants.READONLY_EVENT; - - -/** - * ExchangeReceiver - */ -public class HeaderExchangeHandler implements ChannelHandlerDelegate { - - protected static final Logger logger = LoggerFactory.getLogger(HeaderExchangeHandler.class); - - private final ExchangeHandler handler; - - public HeaderExchangeHandler(ExchangeHandler handler) { - if (handler == null) { - throw new IllegalArgumentException("handler == null"); - } - this.handler = handler; - } - - static void handleResponse(Channel channel, Response response) throws RemotingException { - if (response != null && !response.isHeartbeat()) { - DefaultFuture.received(channel, response); - } - } - - private static boolean isClientSide(Channel channel) { - InetSocketAddress address = channel.getRemoteAddress(); - URL url = channel.getUrl(); - return url.getPort() == address.getPort() && - NetUtils.filterLocalHost(url.getIp()) - .equals(NetUtils.filterLocalHost(address.getAddress().getHostAddress())); - } - - void handlerEvent(Channel channel, Request req) throws RemotingException { - if (req.getData() != null && req.getData().equals(READONLY_EVENT)) { - channel.setAttribute(Constants.CHANNEL_ATTRIBUTE_READONLY_KEY, Boolean.TRUE); - } - } - - void handleRequest(final ExchangeChannel channel, Request req) throws RemotingException { - Response res = new Response(req.getId(), req.getVersion()); - if (req.isBroken()) { - Object data = req.getData(); - - String msg; - if (data == null) { - msg = null; - } else if (data instanceof Throwable) { - msg = StringUtils.toString((Throwable) data); - } else { - msg = data.toString(); - } - res.setErrorMessage("Fail to decode request due to: " + msg); - res.setStatus(Response.BAD_REQUEST); - - channel.send(res); - return; - } - // find handler by message class. - Object msg = req.getData(); - try { - CompletionStage future = handler.reply(channel, msg); - future.whenComplete((appResult, t) -> { - try { - if (t == null) { - res.setStatus(Response.OK); - res.setResult(appResult); - } else { - res.setStatus(Response.SERVICE_ERROR); - res.setErrorMessage(StringUtils.toString(t)); - } - channel.send(res); - } catch (RemotingException e) { - logger.warn("Send result to consumer failed, channel is " + channel + ", msg is " + e); - } - }); - } catch (Throwable e) { - res.setStatus(Response.SERVICE_ERROR); - res.setErrorMessage(StringUtils.toString(e)); - channel.send(res); - } - } - - @Override - public void connected(Channel channel) throws RemotingException { - ExchangeChannel exchangeChannel = HeaderExchangeChannel.getOrAddChannel(channel); - handler.connected(exchangeChannel); - } - - @Override - public void disconnected(Channel channel) throws RemotingException { - ExchangeChannel exchangeChannel = HeaderExchangeChannel.getOrAddChannel(channel); - try { - handler.disconnected(exchangeChannel); - } finally { - DefaultFuture.closeChannel(channel); - HeaderExchangeChannel.removeChannel(channel); - } - } - - @Override - public void sent(Channel channel, Object message) throws RemotingException { - Throwable exception = null; - try { - ExchangeChannel exchangeChannel = HeaderExchangeChannel.getOrAddChannel(channel); - handler.sent(exchangeChannel, message); - } catch (Throwable t) { - exception = t; - HeaderExchangeChannel.removeChannelIfDisconnected(channel); - } - if (message instanceof Request) { - Request request = (Request) message; - DefaultFuture.sent(channel, request); - } - if (exception != null) { - if (exception instanceof RuntimeException) { - throw (RuntimeException) exception; - } else if (exception instanceof RemotingException) { - throw (RemotingException) exception; - } else { - throw new RemotingException(channel.getLocalAddress(), channel.getRemoteAddress(), - exception.getMessage(), exception); - } - } - } - - @Override - public void received(Channel channel, Object message) throws RemotingException { - final ExchangeChannel exchangeChannel = HeaderExchangeChannel.getOrAddChannel(channel); - if (message instanceof Request) { - // handle request. - Request request = (Request) message; - if (request.isEvent()) { - handlerEvent(channel, request); - } else { - if (request.isTwoWay()) { - handleRequest(exchangeChannel, request); - } else { - handler.received(exchangeChannel, request.getData()); - } - } - } else if (message instanceof Response) { - handleResponse(channel, (Response) message); - } else if (message instanceof String) { - if (isClientSide(channel)) { - Exception e = new Exception("Dubbo client can not supported string message: " + message + " in channel: " + channel + ", url: " + channel.getUrl()); - logger.error(e.getMessage(), e); - } else { - String echo = handler.telnet(channel, (String) message); - if (echo != null && echo.length() > 0) { - channel.send(echo); - } - } - } else { - handler.received(exchangeChannel, message); - } - } - - @Override - public void caught(Channel channel, Throwable exception) throws RemotingException { - if (exception instanceof ExecutionException) { - ExecutionException e = (ExecutionException) exception; - Object msg = e.getRequest(); - if (msg instanceof Request) { - Request req = (Request) msg; - if (req.isTwoWay() && !req.isHeartbeat()) { - Response res = new Response(req.getId(), req.getVersion()); - res.setStatus(Response.SERVER_ERROR); - res.setErrorMessage(StringUtils.toString(e)); - channel.send(res); - return; - } - } - } - ExchangeChannel exchangeChannel = HeaderExchangeChannel.getOrAddChannel(channel); - try { - handler.caught(exchangeChannel, exception); - } finally { - HeaderExchangeChannel.removeChannelIfDisconnected(channel); - } - } - - @Override - public ChannelHandler getHandler() { - if (handler instanceof ChannelHandlerDelegate) { - return ((ChannelHandlerDelegate) handler).getHandler(); - } else { - return handler; - } - } -} +/* + * 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.remoting.exchange.support.header; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.NetUtils; +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.remoting.Channel; +import org.apache.dubbo.remoting.ChannelHandler; +import org.apache.dubbo.remoting.Constants; +import org.apache.dubbo.remoting.ExecutionException; +import org.apache.dubbo.remoting.RemotingException; +import org.apache.dubbo.remoting.exchange.ExchangeChannel; +import org.apache.dubbo.remoting.exchange.ExchangeHandler; +import org.apache.dubbo.remoting.exchange.Request; +import org.apache.dubbo.remoting.exchange.Response; +import org.apache.dubbo.remoting.exchange.support.DefaultFuture; +import org.apache.dubbo.remoting.transport.ChannelHandlerDelegate; + +import java.net.InetSocketAddress; +import java.util.concurrent.CompletionStage; + +import static org.apache.dubbo.common.constants.CommonConstants.READONLY_EVENT; + + +/** + * ExchangeReceiver + */ +public class HeaderExchangeHandler implements ChannelHandlerDelegate { + + protected static final Logger logger = LoggerFactory.getLogger(HeaderExchangeHandler.class); + + private final ExchangeHandler handler; + + public HeaderExchangeHandler(ExchangeHandler handler) { + if (handler == null) { + throw new IllegalArgumentException("handler == null"); + } + this.handler = handler; + } + + static void handleResponse(Channel channel, Response response) throws RemotingException { + if (response != null && !response.isHeartbeat()) { + DefaultFuture.received(channel, response); + } + } + + private static boolean isClientSide(Channel channel) { + InetSocketAddress address = channel.getRemoteAddress(); + URL url = channel.getUrl(); + return url.getPort() == address.getPort() && + NetUtils.filterLocalHost(url.getIp()) + .equals(NetUtils.filterLocalHost(address.getAddress().getHostAddress())); + } + + void handlerEvent(Channel channel, Request req) throws RemotingException { + if (req.getData() != null && req.getData().equals(READONLY_EVENT)) { + channel.setAttribute(Constants.CHANNEL_ATTRIBUTE_READONLY_KEY, Boolean.TRUE); + } + } + + void handleRequest(final ExchangeChannel channel, Request req) throws RemotingException { + Response res = new Response(req.getId(), req.getVersion()); + if (req.isBroken()) { + Object data = req.getData(); + + String msg; + if (data == null) { + msg = null; + } else if (data instanceof Throwable) { + msg = StringUtils.toString((Throwable) data); + } else { + msg = data.toString(); + } + res.setErrorMessage("Fail to decode request due to: " + msg); + res.setStatus(Response.BAD_REQUEST); + + channel.send(res); + return; + } + // find handler by message class. + Object msg = req.getData(); + try { + CompletionStage future = handler.reply(channel, msg); + future.whenComplete((appResult, t) -> { + try { + if (t == null) { + res.setStatus(Response.OK); + res.setResult(appResult); + } else { + res.setStatus(Response.SERVICE_ERROR); + res.setErrorMessage(StringUtils.toString(t)); + } + channel.send(res); + } catch (RemotingException e) { + logger.warn("Send result to consumer failed, channel is " + channel + ", msg is " + e); + } + }); + } catch (Throwable e) { + res.setStatus(Response.SERVICE_ERROR); + res.setErrorMessage(StringUtils.toString(e)); + channel.send(res); + } + } + + @Override + public void connected(Channel channel) throws RemotingException { + ExchangeChannel exchangeChannel = HeaderExchangeChannel.getOrAddChannel(channel); + handler.connected(exchangeChannel); + } + + @Override + public void disconnected(Channel channel) throws RemotingException { + ExchangeChannel exchangeChannel = HeaderExchangeChannel.getOrAddChannel(channel); + try { + handler.disconnected(exchangeChannel); + } finally { + DefaultFuture.closeChannel(channel); + HeaderExchangeChannel.removeChannel(channel); + } + } + + @Override + public void sent(Channel channel, Object message) throws RemotingException { + Throwable exception = null; + try { + ExchangeChannel exchangeChannel = HeaderExchangeChannel.getOrAddChannel(channel); + handler.sent(exchangeChannel, message); + } catch (Throwable t) { + exception = t; + HeaderExchangeChannel.removeChannelIfDisconnected(channel); + } + if (message instanceof Request) { + Request request = (Request) message; + DefaultFuture.sent(channel, request); + } + if (exception != null) { + if (exception instanceof RuntimeException) { + throw (RuntimeException) exception; + } else if (exception instanceof RemotingException) { + throw (RemotingException) exception; + } else { + throw new RemotingException(channel.getLocalAddress(), channel.getRemoteAddress(), + exception.getMessage(), exception); + } + } + } + + @Override + public void received(Channel channel, Object message) throws RemotingException { + final ExchangeChannel exchangeChannel = HeaderExchangeChannel.getOrAddChannel(channel); + if (message instanceof Request) { + // handle request. + Request request = (Request) message; + if (request.isEvent()) { + handlerEvent(channel, request); + } else { + if (request.isTwoWay()) { + handleRequest(exchangeChannel, request); + } else { + handler.received(exchangeChannel, request.getData()); + } + } + } else if (message instanceof Response) { + handleResponse(channel, (Response) message); + } else if (message instanceof String) { + if (isClientSide(channel)) { + Exception e = new Exception("Dubbo client can not supported string message: " + message + " in channel: " + channel + ", url: " + channel.getUrl()); + logger.error(e.getMessage(), e); + } else { + String echo = handler.telnet(channel, (String) message); + if (echo != null && echo.length() > 0) { + channel.send(echo); + } + } + } else { + handler.received(exchangeChannel, message); + } + } + + @Override + public void caught(Channel channel, Throwable exception) throws RemotingException { + if (exception instanceof ExecutionException) { + ExecutionException e = (ExecutionException) exception; + Object msg = e.getRequest(); + if (msg instanceof Request) { + Request req = (Request) msg; + if (req.isTwoWay() && !req.isHeartbeat()) { + Response res = new Response(req.getId(), req.getVersion()); + res.setStatus(Response.SERVER_ERROR); + res.setErrorMessage(StringUtils.toString(e)); + channel.send(res); + return; + } + } + } + ExchangeChannel exchangeChannel = HeaderExchangeChannel.getOrAddChannel(channel); + try { + handler.caught(exchangeChannel, exception); + } finally { + HeaderExchangeChannel.removeChannelIfDisconnected(channel); + } + } + + @Override + public ChannelHandler getHandler() { + if (handler instanceof ChannelHandlerDelegate) { + return ((ChannelHandlerDelegate) handler).getHandler(); + } else { + return handler; + } + } +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeServer.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeServer.java index 67c2592608..569688a696 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeServer.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeServer.java @@ -1,273 +1,273 @@ -/* - * 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.remoting.exchange.support.header; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.Version; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.timer.HashedWheelTimer; -import org.apache.dubbo.common.utils.Assert; -import org.apache.dubbo.common.utils.CollectionUtils; -import org.apache.dubbo.common.utils.NamedThreadFactory; -import org.apache.dubbo.remoting.Channel; -import org.apache.dubbo.remoting.ChannelHandler; -import org.apache.dubbo.remoting.Constants; -import org.apache.dubbo.remoting.RemotingException; -import org.apache.dubbo.remoting.RemotingServer; -import org.apache.dubbo.remoting.exchange.ExchangeChannel; -import org.apache.dubbo.remoting.exchange.ExchangeServer; -import org.apache.dubbo.remoting.exchange.Request; - -import java.net.InetSocketAddress; -import java.util.ArrayList; -import java.util.Collection; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -import static java.util.Collections.unmodifiableCollection; -import static org.apache.dubbo.common.constants.CommonConstants.READONLY_EVENT; -import static org.apache.dubbo.remoting.Constants.HEARTBEAT_CHECK_TICK; -import static org.apache.dubbo.remoting.Constants.LEAST_HEARTBEAT_DURATION; -import static org.apache.dubbo.remoting.Constants.TICKS_PER_WHEEL; -import static org.apache.dubbo.remoting.utils.UrlUtils.getHeartbeat; -import static org.apache.dubbo.remoting.utils.UrlUtils.getIdleTimeout; - -/** - * ExchangeServerImpl - */ -public class HeaderExchangeServer implements ExchangeServer { - - protected final Logger logger = LoggerFactory.getLogger(getClass()); - - private final RemotingServer server; - private AtomicBoolean closed = new AtomicBoolean(false); - - private static final HashedWheelTimer IDLE_CHECK_TIMER = new HashedWheelTimer(new NamedThreadFactory("dubbo-server-idleCheck", true), 1, - TimeUnit.SECONDS, TICKS_PER_WHEEL); - - private CloseTimerTask closeTimerTask; - - public HeaderExchangeServer(RemotingServer server) { - Assert.notNull(server, "server == null"); - this.server = server; - startIdleCheckTask(getUrl()); - } - - public RemotingServer getServer() { - return server; - } - - @Override - public boolean isClosed() { - return server.isClosed(); - } - - private boolean isRunning() { - Collection channels = getChannels(); - for (Channel channel : channels) { - - /** - * If there are any client connections, - * our server should be running. - */ - - if (channel.isConnected()) { - return true; - } - } - return false; - } - - @Override - public void close() { - doClose(); - server.close(); - } - - @Override - public void close(final int timeout) { - startClose(); - if (timeout > 0) { - final long max = (long) timeout; - final long start = System.currentTimeMillis(); - if (getUrl().getParameter(Constants.CHANNEL_SEND_READONLYEVENT_KEY, true)) { - sendChannelReadOnlyEvent(); - } - while (HeaderExchangeServer.this.isRunning() - && System.currentTimeMillis() - start < max) { - try { - Thread.sleep(10); - } catch (InterruptedException e) { - logger.warn(e.getMessage(), e); - } - } - } - doClose(); - server.close(timeout); - } - - @Override - public void startClose() { - server.startClose(); - } - - private void sendChannelReadOnlyEvent() { - Request request = new Request(); - request.setEvent(READONLY_EVENT); - request.setTwoWay(false); - request.setVersion(Version.getProtocolVersion()); - - Collection channels = getChannels(); - for (Channel channel : channels) { - try { - if (channel.isConnected()) { - channel.send(request, getUrl().getParameter(Constants.CHANNEL_READONLYEVENT_SENT_KEY, true)); - } - } catch (RemotingException e) { - logger.warn("send cannot write message error.", e); - } - } - } - - private void doClose() { - if (!closed.compareAndSet(false, true)) { - return; - } - cancelCloseTask(); - } - - private void cancelCloseTask() { - if (closeTimerTask != null) { - closeTimerTask.cancel(); - } - } - - @Override - public Collection getExchangeChannels() { - Collection exchangeChannels = new ArrayList(); - Collection channels = server.getChannels(); - if (CollectionUtils.isNotEmpty(channels)) { - for (Channel channel : channels) { - exchangeChannels.add(HeaderExchangeChannel.getOrAddChannel(channel)); - } - } - return exchangeChannels; - } - - @Override - public ExchangeChannel getExchangeChannel(InetSocketAddress remoteAddress) { - Channel channel = server.getChannel(remoteAddress); - return HeaderExchangeChannel.getOrAddChannel(channel); - } - - @Override - @SuppressWarnings({"unchecked", "rawtypes"}) - public Collection getChannels() { - return (Collection) getExchangeChannels(); - } - - @Override - public Channel getChannel(InetSocketAddress remoteAddress) { - return getExchangeChannel(remoteAddress); - } - - @Override - public boolean isBound() { - return server.isBound(); - } - - @Override - public InetSocketAddress getLocalAddress() { - return server.getLocalAddress(); - } - - @Override - public URL getUrl() { - return server.getUrl(); - } - - @Override - public ChannelHandler getChannelHandler() { - return server.getChannelHandler(); - } - - @Override - public void reset(URL url) { - server.reset(url); - try { - int currHeartbeat = getHeartbeat(getUrl()); - int currIdleTimeout = getIdleTimeout(getUrl()); - int heartbeat = getHeartbeat(url); - int idleTimeout = getIdleTimeout(url); - if (currHeartbeat != heartbeat || currIdleTimeout != idleTimeout) { - cancelCloseTask(); - startIdleCheckTask(url); - } - } catch (Throwable t) { - logger.error(t.getMessage(), t); - } - } - - @Override - @Deprecated - public void reset(org.apache.dubbo.common.Parameters parameters) { - reset(getUrl().addParameters(parameters.getParameters())); - } - - @Override - public void send(Object message) throws RemotingException { - if (closed.get()) { - throw new RemotingException(this.getLocalAddress(), null, "Failed to send message " + message - + ", cause: The server " + getLocalAddress() + " is closed!"); - } - server.send(message); - } - - @Override - public void send(Object message, boolean sent) throws RemotingException { - if (closed.get()) { - throw new RemotingException(this.getLocalAddress(), null, "Failed to send message " + message - + ", cause: The server " + getLocalAddress() + " is closed!"); - } - server.send(message, sent); - } - - /** - * Each interval cannot be less than 1000ms. - */ - private long calculateLeastDuration(int time) { - if (time / HEARTBEAT_CHECK_TICK <= 0) { - return LEAST_HEARTBEAT_DURATION; - } else { - return time / HEARTBEAT_CHECK_TICK; - } - } - - private void startIdleCheckTask(URL url) { - if (!server.canHandleIdle()) { - AbstractTimerTask.ChannelProvider cp = () -> unmodifiableCollection(HeaderExchangeServer.this.getChannels()); - int idleTimeout = getIdleTimeout(url); - long idleTimeoutTick = calculateLeastDuration(idleTimeout); - CloseTimerTask closeTimerTask = new CloseTimerTask(cp, idleTimeoutTick, idleTimeout); - this.closeTimerTask = closeTimerTask; - - // init task and start timer. - IDLE_CHECK_TIMER.newTimeout(closeTimerTask, idleTimeoutTick, TimeUnit.MILLISECONDS); - } - } -} +/* + * 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.remoting.exchange.support.header; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.Version; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.timer.HashedWheelTimer; +import org.apache.dubbo.common.utils.Assert; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.common.utils.NamedThreadFactory; +import org.apache.dubbo.remoting.Channel; +import org.apache.dubbo.remoting.ChannelHandler; +import org.apache.dubbo.remoting.Constants; +import org.apache.dubbo.remoting.RemotingException; +import org.apache.dubbo.remoting.RemotingServer; +import org.apache.dubbo.remoting.exchange.ExchangeChannel; +import org.apache.dubbo.remoting.exchange.ExchangeServer; +import org.apache.dubbo.remoting.exchange.Request; + +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.Collection; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +import static java.util.Collections.unmodifiableCollection; +import static org.apache.dubbo.common.constants.CommonConstants.READONLY_EVENT; +import static org.apache.dubbo.remoting.Constants.HEARTBEAT_CHECK_TICK; +import static org.apache.dubbo.remoting.Constants.LEAST_HEARTBEAT_DURATION; +import static org.apache.dubbo.remoting.Constants.TICKS_PER_WHEEL; +import static org.apache.dubbo.remoting.utils.UrlUtils.getHeartbeat; +import static org.apache.dubbo.remoting.utils.UrlUtils.getIdleTimeout; + +/** + * ExchangeServerImpl + */ +public class HeaderExchangeServer implements ExchangeServer { + + protected final Logger logger = LoggerFactory.getLogger(getClass()); + + private final RemotingServer server; + private AtomicBoolean closed = new AtomicBoolean(false); + + private static final HashedWheelTimer IDLE_CHECK_TIMER = new HashedWheelTimer(new NamedThreadFactory("dubbo-server-idleCheck", true), 1, + TimeUnit.SECONDS, TICKS_PER_WHEEL); + + private CloseTimerTask closeTimerTask; + + public HeaderExchangeServer(RemotingServer server) { + Assert.notNull(server, "server == null"); + this.server = server; + startIdleCheckTask(getUrl()); + } + + public RemotingServer getServer() { + return server; + } + + @Override + public boolean isClosed() { + return server.isClosed(); + } + + private boolean isRunning() { + Collection channels = getChannels(); + for (Channel channel : channels) { + + /** + * If there are any client connections, + * our server should be running. + */ + + if (channel.isConnected()) { + return true; + } + } + return false; + } + + @Override + public void close() { + doClose(); + server.close(); + } + + @Override + public void close(final int timeout) { + startClose(); + if (timeout > 0) { + final long max = (long) timeout; + final long start = System.currentTimeMillis(); + if (getUrl().getParameter(Constants.CHANNEL_SEND_READONLYEVENT_KEY, true)) { + sendChannelReadOnlyEvent(); + } + while (HeaderExchangeServer.this.isRunning() + && System.currentTimeMillis() - start < max) { + try { + Thread.sleep(10); + } catch (InterruptedException e) { + logger.warn(e.getMessage(), e); + } + } + } + doClose(); + server.close(timeout); + } + + @Override + public void startClose() { + server.startClose(); + } + + private void sendChannelReadOnlyEvent() { + Request request = new Request(); + request.setEvent(READONLY_EVENT); + request.setTwoWay(false); + request.setVersion(Version.getProtocolVersion()); + + Collection channels = getChannels(); + for (Channel channel : channels) { + try { + if (channel.isConnected()) { + channel.send(request, getUrl().getParameter(Constants.CHANNEL_READONLYEVENT_SENT_KEY, true)); + } + } catch (RemotingException e) { + logger.warn("send cannot write message error.", e); + } + } + } + + private void doClose() { + if (!closed.compareAndSet(false, true)) { + return; + } + cancelCloseTask(); + } + + private void cancelCloseTask() { + if (closeTimerTask != null) { + closeTimerTask.cancel(); + } + } + + @Override + public Collection getExchangeChannels() { + Collection exchangeChannels = new ArrayList(); + Collection channels = server.getChannels(); + if (CollectionUtils.isNotEmpty(channels)) { + for (Channel channel : channels) { + exchangeChannels.add(HeaderExchangeChannel.getOrAddChannel(channel)); + } + } + return exchangeChannels; + } + + @Override + public ExchangeChannel getExchangeChannel(InetSocketAddress remoteAddress) { + Channel channel = server.getChannel(remoteAddress); + return HeaderExchangeChannel.getOrAddChannel(channel); + } + + @Override + @SuppressWarnings({"unchecked", "rawtypes"}) + public Collection getChannels() { + return (Collection) getExchangeChannels(); + } + + @Override + public Channel getChannel(InetSocketAddress remoteAddress) { + return getExchangeChannel(remoteAddress); + } + + @Override + public boolean isBound() { + return server.isBound(); + } + + @Override + public InetSocketAddress getLocalAddress() { + return server.getLocalAddress(); + } + + @Override + public URL getUrl() { + return server.getUrl(); + } + + @Override + public ChannelHandler getChannelHandler() { + return server.getChannelHandler(); + } + + @Override + public void reset(URL url) { + server.reset(url); + try { + int currHeartbeat = getHeartbeat(getUrl()); + int currIdleTimeout = getIdleTimeout(getUrl()); + int heartbeat = getHeartbeat(url); + int idleTimeout = getIdleTimeout(url); + if (currHeartbeat != heartbeat || currIdleTimeout != idleTimeout) { + cancelCloseTask(); + startIdleCheckTask(url); + } + } catch (Throwable t) { + logger.error(t.getMessage(), t); + } + } + + @Override + @Deprecated + public void reset(org.apache.dubbo.common.Parameters parameters) { + reset(getUrl().addParameters(parameters.getParameters())); + } + + @Override + public void send(Object message) throws RemotingException { + if (closed.get()) { + throw new RemotingException(this.getLocalAddress(), null, "Failed to send message " + message + + ", cause: The server " + getLocalAddress() + " is closed!"); + } + server.send(message); + } + + @Override + public void send(Object message, boolean sent) throws RemotingException { + if (closed.get()) { + throw new RemotingException(this.getLocalAddress(), null, "Failed to send message " + message + + ", cause: The server " + getLocalAddress() + " is closed!"); + } + server.send(message, sent); + } + + /** + * Each interval cannot be less than 1000ms. + */ + private long calculateLeastDuration(int time) { + if (time / HEARTBEAT_CHECK_TICK <= 0) { + return LEAST_HEARTBEAT_DURATION; + } else { + return time / HEARTBEAT_CHECK_TICK; + } + } + + private void startIdleCheckTask(URL url) { + if (!server.canHandleIdle()) { + AbstractTimerTask.ChannelProvider cp = () -> unmodifiableCollection(HeaderExchangeServer.this.getChannels()); + int idleTimeout = getIdleTimeout(url); + long idleTimeoutTick = calculateLeastDuration(idleTimeout); + CloseTimerTask closeTimerTask = new CloseTimerTask(cp, idleTimeoutTick, idleTimeout); + this.closeTimerTask = closeTimerTask; + + // init task and start timer. + IDLE_CHECK_TIMER.newTimeout(closeTimerTask, idleTimeoutTick, TimeUnit.MILLISECONDS); + } + } +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchanger.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchanger.java index e2e8f1b1c9..90f7c9830d 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchanger.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchanger.java @@ -1,47 +1,47 @@ -/* - * 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.remoting.exchange.support.header; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.remoting.RemotingException; -import org.apache.dubbo.remoting.Transporters; -import org.apache.dubbo.remoting.exchange.ExchangeClient; -import org.apache.dubbo.remoting.exchange.ExchangeHandler; -import org.apache.dubbo.remoting.exchange.ExchangeServer; -import org.apache.dubbo.remoting.exchange.Exchanger; -import org.apache.dubbo.remoting.transport.DecodeHandler; - -/** - * DefaultMessenger - * - * - */ -public class HeaderExchanger implements Exchanger { - - public static final String NAME = "header"; - - @Override - public ExchangeClient connect(URL url, ExchangeHandler handler) throws RemotingException { - return new HeaderExchangeClient(Transporters.connect(url, new DecodeHandler(new HeaderExchangeHandler(handler))), true); - } - - @Override - public ExchangeServer bind(URL url, ExchangeHandler handler) throws RemotingException { - return new HeaderExchangeServer(Transporters.bind(url, new DecodeHandler(new HeaderExchangeHandler(handler)))); - } - -} +/* + * 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.remoting.exchange.support.header; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.remoting.RemotingException; +import org.apache.dubbo.remoting.Transporters; +import org.apache.dubbo.remoting.exchange.ExchangeClient; +import org.apache.dubbo.remoting.exchange.ExchangeHandler; +import org.apache.dubbo.remoting.exchange.ExchangeServer; +import org.apache.dubbo.remoting.exchange.Exchanger; +import org.apache.dubbo.remoting.transport.DecodeHandler; + +/** + * DefaultMessenger + * + * + */ +public class HeaderExchanger implements Exchanger { + + public static final String NAME = "header"; + + @Override + public ExchangeClient connect(URL url, ExchangeHandler handler) throws RemotingException { + return new HeaderExchangeClient(Transporters.connect(url, new DecodeHandler(new HeaderExchangeHandler(handler))), true); + } + + @Override + public ExchangeServer bind(URL url, ExchangeHandler handler) throws RemotingException { + return new HeaderExchangeServer(Transporters.bind(url, new DecodeHandler(new HeaderExchangeHandler(handler)))); + } + +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/TelnetHandler.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/TelnetHandler.java index 12e2c98980..8bfc7fd56a 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/TelnetHandler.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/TelnetHandler.java @@ -1,37 +1,37 @@ -/* - * 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.remoting.telnet; - -import org.apache.dubbo.common.extension.SPI; -import org.apache.dubbo.remoting.Channel; -import org.apache.dubbo.remoting.RemotingException; - -/** - * TelnetHandler - */ -@SPI -public interface TelnetHandler { - - /** - * telnet. - * - * @param channel - * @param message - */ - String telnet(Channel channel, String message) throws RemotingException; - -} \ No newline at end of file +/* + * 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.remoting.telnet; + +import org.apache.dubbo.common.extension.SPI; +import org.apache.dubbo.remoting.Channel; +import org.apache.dubbo.remoting.RemotingException; + +/** + * TelnetHandler + */ +@SPI +public interface TelnetHandler { + + /** + * telnet. + * + * @param channel + * @param message + */ + String telnet(Channel channel, String message) throws RemotingException; + +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/codec/TelnetCodec.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/codec/TelnetCodec.java index 3ac276bf19..a5cfe86c34 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/codec/TelnetCodec.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/codec/TelnetCodec.java @@ -1,298 +1,298 @@ -/* - * 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.remoting.telnet.codec; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.utils.CollectionUtils; -import org.apache.dubbo.common.utils.StringUtils; -import org.apache.dubbo.remoting.Channel; -import org.apache.dubbo.remoting.RemotingException; -import org.apache.dubbo.remoting.buffer.ChannelBuffer; -import org.apache.dubbo.remoting.transport.codec.TransportCodec; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.nio.charset.Charset; -import java.util.Arrays; -import java.util.LinkedList; -import java.util.List; - -import static org.apache.dubbo.remoting.Constants.CHARSET_KEY; -import static org.apache.dubbo.remoting.Constants.DEFAULT_CHARSET; - -/** - * TelnetCodec - */ -public class TelnetCodec extends TransportCodec { - - private static final Logger logger = LoggerFactory.getLogger(TelnetCodec.class); - - private static final String HISTORY_LIST_KEY = "telnet.history.list"; - - private static final String HISTORY_INDEX_KEY = "telnet.history.index"; - - private static final byte[] UP = new byte[]{27, 91, 65}; - - private static final byte[] DOWN = new byte[]{27, 91, 66}; - - private static final List ENTER = Arrays.asList( - new byte[]{'\r', '\n'} /* Windows Enter */, - new byte[]{'\n'} /* Linux Enter */); - - private static final List EXIT = Arrays.asList( - new byte[]{3} /* Windows Ctrl+C */, - new byte[]{-1, -12, -1, -3, 6} /* Linux Ctrl+C */, - new byte[]{-1, -19, -1, -3, 6} /* Linux Pause */); - - private static Charset getCharset(Channel channel) { - if (channel != null) { - Object attribute = channel.getAttribute(CHARSET_KEY); - if (attribute instanceof String) { - try { - return Charset.forName((String) attribute); - } catch (Throwable t) { - logger.warn(t.getMessage(), t); - } - } else if (attribute instanceof Charset) { - return (Charset) attribute; - } - URL url = channel.getUrl(); - if (url != null) { - String parameter = url.getParameter(CHARSET_KEY); - if (StringUtils.isNotEmpty(parameter)) { - try { - return Charset.forName(parameter); - } catch (Throwable t) { - logger.warn(t.getMessage(), t); - } - } - } - } - try { - return Charset.forName(DEFAULT_CHARSET); - } catch (Throwable t) { - logger.warn(t.getMessage(), t); - } - return Charset.defaultCharset(); - } - - private static String toString(byte[] message, Charset charset) throws UnsupportedEncodingException { - byte[] copy = new byte[message.length]; - int index = 0; - for (int i = 0; i < message.length; i++) { - byte b = message[i]; - if (b == '\b') { // backspace - if (index > 0) { - index--; - } - if (i > 2 && message[i - 2] < 0) { // double byte char - if (index > 0) { - index--; - } - } - } else if (b == 27) { // escape - if (i < message.length - 4 && message[i + 4] == 126) { - i = i + 4; - } else if (i < message.length - 3 && message[i + 3] == 126) { - i = i + 3; - } else if (i < message.length - 2) { - i = i + 2; - } - } else if (b == -1 && i < message.length - 2 - && (message[i + 1] == -3 || message[i + 1] == -5)) { // handshake - i = i + 2; - } else { - copy[index++] = message[i]; - } - } - if (index == 0) { - return ""; - } - return new String(copy, 0, index, charset.name()).trim(); - } - - private static boolean isEquals(byte[] message, byte[] command) throws IOException { - return message.length == command.length && endsWith(message, command); - } - - private static boolean endsWith(byte[] message, byte[] command) throws IOException { - if (message.length < command.length) { - return false; - } - int offset = message.length - command.length; - for (int i = command.length - 1; i >= 0; i--) { - if (message[offset + i] != command[i]) { - return false; - } - } - return true; - } - - @Override - public void encode(Channel channel, ChannelBuffer buffer, Object message) throws IOException { - if (message instanceof String) { - if (isClientSide(channel)) { - message = message + "\r\n"; - } - byte[] msgData = ((String) message).getBytes(getCharset(channel).name()); - buffer.writeBytes(msgData); - } else { - super.encode(channel, buffer, message); - } - } - - @Override - public Object decode(Channel channel, ChannelBuffer buffer) throws IOException { - int readable = buffer.readableBytes(); - byte[] message = new byte[readable]; - buffer.readBytes(message); - return decode(channel, buffer, readable, message); - } - - @SuppressWarnings("unchecked") - protected Object decode(Channel channel, ChannelBuffer buffer, int readable, byte[] message) throws IOException { - if (isClientSide(channel)) { - return toString(message, getCharset(channel)); - } - checkPayload(channel, readable); - if (message == null || message.length == 0) { - return DecodeResult.NEED_MORE_INPUT; - } - - if (message[message.length - 1] == '\b') { // Windows backspace echo - try { - boolean doublechar = message.length >= 3 && message[message.length - 3] < 0; // double byte char - channel.send(new String(doublechar ? new byte[]{32, 32, 8, 8} : new byte[]{32, 8}, getCharset(channel).name())); - } catch (RemotingException e) { - throw new IOException(StringUtils.toString(e)); - } - return DecodeResult.NEED_MORE_INPUT; - } - - for (Object command : EXIT) { - if (isEquals(message, (byte[]) command)) { - if (logger.isInfoEnabled()) { - logger.info(new Exception("Close channel " + channel + " on exit command: " + Arrays.toString((byte[]) command))); - } - channel.close(); - return null; - } - } - - boolean up = endsWith(message, UP); - boolean down = endsWith(message, DOWN); - if (up || down) { - LinkedList history = (LinkedList) channel.getAttribute(HISTORY_LIST_KEY); - if (CollectionUtils.isEmpty(history)) { - return DecodeResult.NEED_MORE_INPUT; - } - Integer index = (Integer) channel.getAttribute(HISTORY_INDEX_KEY); - Integer old = index; - if (index == null) { - index = history.size() - 1; - } else { - if (up) { - index = index - 1; - if (index < 0) { - index = history.size() - 1; - } - } else { - index = index + 1; - if (index > history.size() - 1) { - index = 0; - } - } - } - if (old == null || !old.equals(index)) { - channel.setAttribute(HISTORY_INDEX_KEY, index); - String value = history.get(index); - if (old != null && old >= 0 && old < history.size()) { - String ov = history.get(old); - StringBuilder buf = new StringBuilder(); - for (int i = 0; i < ov.length(); i++) { - buf.append("\b"); - } - for (int i = 0; i < ov.length(); i++) { - buf.append(" "); - } - for (int i = 0; i < ov.length(); i++) { - buf.append("\b"); - } - value = buf.toString() + value; - } - try { - channel.send(value); - } catch (RemotingException e) { - throw new IOException(StringUtils.toString(e)); - } - } - return DecodeResult.NEED_MORE_INPUT; - } - for (Object command : EXIT) { - if (isEquals(message, (byte[]) command)) { - if (logger.isInfoEnabled()) { - logger.info(new Exception("Close channel " + channel + " on exit command " + command)); - } - channel.close(); - return null; - } - } - byte[] enter = null; - for (Object command : ENTER) { - if (endsWith(message, (byte[]) command)) { - enter = (byte[]) command; - break; - } - } - if (enter == null) { - return DecodeResult.NEED_MORE_INPUT; - } - LinkedList history = (LinkedList) channel.getAttribute(HISTORY_LIST_KEY); - Integer index = (Integer) channel.getAttribute(HISTORY_INDEX_KEY); - channel.removeAttribute(HISTORY_INDEX_KEY); - if (CollectionUtils.isNotEmpty(history) && index != null && index >= 0 && index < history.size()) { - String value = history.get(index); - if (value != null) { - byte[] b1 = value.getBytes(); - byte[] b2 = new byte[b1.length + message.length]; - System.arraycopy(b1, 0, b2, 0, b1.length); - System.arraycopy(message, 0, b2, b1.length, message.length); - message = b2; - } - } - String result = toString(message, getCharset(channel)); - if (result.trim().length() > 0) { - if (history == null) { - history = new LinkedList(); - channel.setAttribute(HISTORY_LIST_KEY, history); - } - if (history.isEmpty()) { - history.addLast(result); - } else if (!result.equals(history.getLast())) { - history.remove(result); - history.addLast(result); - if (history.size() > 10) { - history.removeFirst(); - } - } - } - return result; - } - -} +/* + * 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.remoting.telnet.codec; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.remoting.Channel; +import org.apache.dubbo.remoting.RemotingException; +import org.apache.dubbo.remoting.buffer.ChannelBuffer; +import org.apache.dubbo.remoting.transport.codec.TransportCodec; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +import static org.apache.dubbo.remoting.Constants.CHARSET_KEY; +import static org.apache.dubbo.remoting.Constants.DEFAULT_CHARSET; + +/** + * TelnetCodec + */ +public class TelnetCodec extends TransportCodec { + + private static final Logger logger = LoggerFactory.getLogger(TelnetCodec.class); + + private static final String HISTORY_LIST_KEY = "telnet.history.list"; + + private static final String HISTORY_INDEX_KEY = "telnet.history.index"; + + private static final byte[] UP = new byte[]{27, 91, 65}; + + private static final byte[] DOWN = new byte[]{27, 91, 66}; + + private static final List ENTER = Arrays.asList( + new byte[]{'\r', '\n'} /* Windows Enter */, + new byte[]{'\n'} /* Linux Enter */); + + private static final List EXIT = Arrays.asList( + new byte[]{3} /* Windows Ctrl+C */, + new byte[]{-1, -12, -1, -3, 6} /* Linux Ctrl+C */, + new byte[]{-1, -19, -1, -3, 6} /* Linux Pause */); + + private static Charset getCharset(Channel channel) { + if (channel != null) { + Object attribute = channel.getAttribute(CHARSET_KEY); + if (attribute instanceof String) { + try { + return Charset.forName((String) attribute); + } catch (Throwable t) { + logger.warn(t.getMessage(), t); + } + } else if (attribute instanceof Charset) { + return (Charset) attribute; + } + URL url = channel.getUrl(); + if (url != null) { + String parameter = url.getParameter(CHARSET_KEY); + if (StringUtils.isNotEmpty(parameter)) { + try { + return Charset.forName(parameter); + } catch (Throwable t) { + logger.warn(t.getMessage(), t); + } + } + } + } + try { + return Charset.forName(DEFAULT_CHARSET); + } catch (Throwable t) { + logger.warn(t.getMessage(), t); + } + return Charset.defaultCharset(); + } + + private static String toString(byte[] message, Charset charset) throws UnsupportedEncodingException { + byte[] copy = new byte[message.length]; + int index = 0; + for (int i = 0; i < message.length; i++) { + byte b = message[i]; + if (b == '\b') { // backspace + if (index > 0) { + index--; + } + if (i > 2 && message[i - 2] < 0) { // double byte char + if (index > 0) { + index--; + } + } + } else if (b == 27) { // escape + if (i < message.length - 4 && message[i + 4] == 126) { + i = i + 4; + } else if (i < message.length - 3 && message[i + 3] == 126) { + i = i + 3; + } else if (i < message.length - 2) { + i = i + 2; + } + } else if (b == -1 && i < message.length - 2 + && (message[i + 1] == -3 || message[i + 1] == -5)) { // handshake + i = i + 2; + } else { + copy[index++] = message[i]; + } + } + if (index == 0) { + return ""; + } + return new String(copy, 0, index, charset.name()).trim(); + } + + private static boolean isEquals(byte[] message, byte[] command) throws IOException { + return message.length == command.length && endsWith(message, command); + } + + private static boolean endsWith(byte[] message, byte[] command) throws IOException { + if (message.length < command.length) { + return false; + } + int offset = message.length - command.length; + for (int i = command.length - 1; i >= 0; i--) { + if (message[offset + i] != command[i]) { + return false; + } + } + return true; + } + + @Override + public void encode(Channel channel, ChannelBuffer buffer, Object message) throws IOException { + if (message instanceof String) { + if (isClientSide(channel)) { + message = message + "\r\n"; + } + byte[] msgData = ((String) message).getBytes(getCharset(channel).name()); + buffer.writeBytes(msgData); + } else { + super.encode(channel, buffer, message); + } + } + + @Override + public Object decode(Channel channel, ChannelBuffer buffer) throws IOException { + int readable = buffer.readableBytes(); + byte[] message = new byte[readable]; + buffer.readBytes(message); + return decode(channel, buffer, readable, message); + } + + @SuppressWarnings("unchecked") + protected Object decode(Channel channel, ChannelBuffer buffer, int readable, byte[] message) throws IOException { + if (isClientSide(channel)) { + return toString(message, getCharset(channel)); + } + checkPayload(channel, readable); + if (message == null || message.length == 0) { + return DecodeResult.NEED_MORE_INPUT; + } + + if (message[message.length - 1] == '\b') { // Windows backspace echo + try { + boolean doublechar = message.length >= 3 && message[message.length - 3] < 0; // double byte char + channel.send(new String(doublechar ? new byte[]{32, 32, 8, 8} : new byte[]{32, 8}, getCharset(channel).name())); + } catch (RemotingException e) { + throw new IOException(StringUtils.toString(e)); + } + return DecodeResult.NEED_MORE_INPUT; + } + + for (Object command : EXIT) { + if (isEquals(message, (byte[]) command)) { + if (logger.isInfoEnabled()) { + logger.info(new Exception("Close channel " + channel + " on exit command: " + Arrays.toString((byte[]) command))); + } + channel.close(); + return null; + } + } + + boolean up = endsWith(message, UP); + boolean down = endsWith(message, DOWN); + if (up || down) { + LinkedList history = (LinkedList) channel.getAttribute(HISTORY_LIST_KEY); + if (CollectionUtils.isEmpty(history)) { + return DecodeResult.NEED_MORE_INPUT; + } + Integer index = (Integer) channel.getAttribute(HISTORY_INDEX_KEY); + Integer old = index; + if (index == null) { + index = history.size() - 1; + } else { + if (up) { + index = index - 1; + if (index < 0) { + index = history.size() - 1; + } + } else { + index = index + 1; + if (index > history.size() - 1) { + index = 0; + } + } + } + if (old == null || !old.equals(index)) { + channel.setAttribute(HISTORY_INDEX_KEY, index); + String value = history.get(index); + if (old != null && old >= 0 && old < history.size()) { + String ov = history.get(old); + StringBuilder buf = new StringBuilder(); + for (int i = 0; i < ov.length(); i++) { + buf.append("\b"); + } + for (int i = 0; i < ov.length(); i++) { + buf.append(" "); + } + for (int i = 0; i < ov.length(); i++) { + buf.append("\b"); + } + value = buf.toString() + value; + } + try { + channel.send(value); + } catch (RemotingException e) { + throw new IOException(StringUtils.toString(e)); + } + } + return DecodeResult.NEED_MORE_INPUT; + } + for (Object command : EXIT) { + if (isEquals(message, (byte[]) command)) { + if (logger.isInfoEnabled()) { + logger.info(new Exception("Close channel " + channel + " on exit command " + command)); + } + channel.close(); + return null; + } + } + byte[] enter = null; + for (Object command : ENTER) { + if (endsWith(message, (byte[]) command)) { + enter = (byte[]) command; + break; + } + } + if (enter == null) { + return DecodeResult.NEED_MORE_INPUT; + } + LinkedList history = (LinkedList) channel.getAttribute(HISTORY_LIST_KEY); + Integer index = (Integer) channel.getAttribute(HISTORY_INDEX_KEY); + channel.removeAttribute(HISTORY_INDEX_KEY); + if (CollectionUtils.isNotEmpty(history) && index != null && index >= 0 && index < history.size()) { + String value = history.get(index); + if (value != null) { + byte[] b1 = value.getBytes(); + byte[] b2 = new byte[b1.length + message.length]; + System.arraycopy(b1, 0, b2, 0, b1.length); + System.arraycopy(message, 0, b2, b1.length, message.length); + message = b2; + } + } + String result = toString(message, getCharset(channel)); + if (result.trim().length() > 0) { + if (history == null) { + history = new LinkedList(); + channel.setAttribute(HISTORY_LIST_KEY, history); + } + if (history.isEmpty()) { + history.addLast(result); + } else if (!result.equals(history.getLast())) { + history.remove(result); + history.addLast(result); + if (history.size() > 10) { + history.removeFirst(); + } + } + } + return result; + } + +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/Help.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/Help.java index fc68e119d5..cc8f2ba98a 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/Help.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/Help.java @@ -1,39 +1,39 @@ -/* - * 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.remoting.telnet.support; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Help - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) -public @interface Help { - - String parameter() default ""; - - String summary(); - - String detail() default ""; - -} \ No newline at end of file +/* + * 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.remoting.telnet.support; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Help + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +public @interface Help { + + String parameter() default ""; + + String summary(); + + String detail() default ""; + +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/TelnetHandlerAdapter.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/TelnetHandlerAdapter.java index 95eb57540e..d25ba8c131 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/TelnetHandlerAdapter.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/TelnetHandlerAdapter.java @@ -1,100 +1,100 @@ -/* - * 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.remoting.telnet.support; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.common.utils.StringUtils; -import org.apache.dubbo.remoting.Channel; -import org.apache.dubbo.remoting.Constants; -import org.apache.dubbo.remoting.RemotingException; -import org.apache.dubbo.remoting.telnet.TelnetHandler; -import org.apache.dubbo.remoting.transport.ChannelHandlerAdapter; - -import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN; -import static org.apache.dubbo.remoting.Constants.TELNET; - -public class TelnetHandlerAdapter extends ChannelHandlerAdapter implements TelnetHandler { - - private final ExtensionLoader extensionLoader = ExtensionLoader.getExtensionLoader(TelnetHandler.class); - - @Override - public String telnet(Channel channel, String message) throws RemotingException { - String prompt = channel.getUrl().getParameterAndDecoded(Constants.PROMPT_KEY, Constants.DEFAULT_PROMPT); - boolean noprompt = message.contains("--no-prompt"); - message = message.replace("--no-prompt", ""); - StringBuilder buf = new StringBuilder(); - message = message.trim(); - String command; - if (message.length() > 0) { - int i = message.indexOf(' '); - if (i > 0) { - command = message.substring(0, i).trim(); - message = message.substring(i + 1).trim(); - } else { - command = message; - message = ""; - } - } else { - command = ""; - } - if (command.length() > 0) { - if (extensionLoader.hasExtension(command)) { - if (commandEnabled(channel.getUrl(), command)) { - try { - String result = extensionLoader.getExtension(command).telnet(channel, message); - if (result == null) { - return null; - } - buf.append(result); - } catch (Throwable t) { - buf.append(t.getMessage()); - } - } else { - buf.append("Command: "); - buf.append(command); - buf.append(" disabled"); - } - } else { - buf.append("Unsupported command: "); - buf.append(command); - } - } - if (buf.length() > 0) { - buf.append("\r\n"); - } - if (StringUtils.isNotEmpty(prompt) && !noprompt) { - buf.append(prompt); - } - return buf.toString(); - } - - private boolean commandEnabled(URL url, String command) { - String supportCommands = url.getParameter(TELNET); - if (StringUtils.isEmpty(supportCommands)) { - return true; - } - String[] commands = COMMA_SPLIT_PATTERN.split(supportCommands); - for (String c : commands) { - if (command.equals(c)) { - return true; - } - } - return false; - } - -} +/* + * 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.remoting.telnet.support; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.remoting.Channel; +import org.apache.dubbo.remoting.Constants; +import org.apache.dubbo.remoting.RemotingException; +import org.apache.dubbo.remoting.telnet.TelnetHandler; +import org.apache.dubbo.remoting.transport.ChannelHandlerAdapter; + +import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN; +import static org.apache.dubbo.remoting.Constants.TELNET; + +public class TelnetHandlerAdapter extends ChannelHandlerAdapter implements TelnetHandler { + + private final ExtensionLoader extensionLoader = ExtensionLoader.getExtensionLoader(TelnetHandler.class); + + @Override + public String telnet(Channel channel, String message) throws RemotingException { + String prompt = channel.getUrl().getParameterAndDecoded(Constants.PROMPT_KEY, Constants.DEFAULT_PROMPT); + boolean noprompt = message.contains("--no-prompt"); + message = message.replace("--no-prompt", ""); + StringBuilder buf = new StringBuilder(); + message = message.trim(); + String command; + if (message.length() > 0) { + int i = message.indexOf(' '); + if (i > 0) { + command = message.substring(0, i).trim(); + message = message.substring(i + 1).trim(); + } else { + command = message; + message = ""; + } + } else { + command = ""; + } + if (command.length() > 0) { + if (extensionLoader.hasExtension(command)) { + if (commandEnabled(channel.getUrl(), command)) { + try { + String result = extensionLoader.getExtension(command).telnet(channel, message); + if (result == null) { + return null; + } + buf.append(result); + } catch (Throwable t) { + buf.append(t.getMessage()); + } + } else { + buf.append("Command: "); + buf.append(command); + buf.append(" disabled"); + } + } else { + buf.append("Unsupported command: "); + buf.append(command); + } + } + if (buf.length() > 0) { + buf.append("\r\n"); + } + if (StringUtils.isNotEmpty(prompt) && !noprompt) { + buf.append(prompt); + } + return buf.toString(); + } + + private boolean commandEnabled(URL url, String command) { + String supportCommands = url.getParameter(TELNET); + if (StringUtils.isEmpty(supportCommands)) { + return true; + } + String[] commands = COMMA_SPLIT_PATTERN.split(supportCommands); + for (String c : commands) { + if (command.equals(c)) { + return true; + } + } + return false; + } + +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/TelnetUtils.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/TelnetUtils.java index 219ca04802..ab7f3b1f24 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/TelnetUtils.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/TelnetUtils.java @@ -1,159 +1,159 @@ -/* - * 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.remoting.telnet.support; - -import java.util.Arrays; -import java.util.List; - -/** - * TelnetUtils - */ -public class TelnetUtils { - - public static String toList(List> table) { - int[] widths = new int[table.get(0).size()]; - for (int j = 0; j < widths.length; j++) { - for (List row : table) { - widths[j] = Math.max(widths[j], row.get(j).length()); - } - } - StringBuilder buf = new StringBuilder(); - for (List row : table) { - if (buf.length() > 0) { - buf.append("\r\n"); - } - for (int j = 0; j < widths.length; j++) { - if (j > 0) { - buf.append(" - "); - } - String value = row.get(j); - buf.append(value); - if (j < widths.length - 1) { - int pad = widths[j] - value.length(); - if (pad > 0) { - for (int k = 0; k < pad; k++) { - buf.append(" "); - } - } - } - } - } - return buf.toString(); - } - - public static String toTable(String[] header, List> table) { - return toTable(Arrays.asList(header), table); - } - - public static String toTable(List header, List> table) { - int totalWidth = 0; - int[] widths = new int[header.size()]; - int maxwidth = 70; - int maxcountbefore = 0; - for (int j = 0; j < widths.length; j++) { - widths[j] = Math.max(widths[j], header.get(j).length()); - } - for (List row : table) { - int countbefore = 0; - for (int j = 0; j < widths.length; j++) { - widths[j] = Math.max(widths[j], row.get(j).length()); - totalWidth = (totalWidth + widths[j]) > maxwidth ? maxwidth : (totalWidth + widths[j]); - if (j < widths.length - 1) { - countbefore = countbefore + widths[j]; - } - } - maxcountbefore = Math.max(countbefore, maxcountbefore); - } - widths[widths.length - 1] = Math.min(widths[widths.length - 1], maxwidth - maxcountbefore); - StringBuilder buf = new StringBuilder(); - //line - buf.append("+"); - for (int j = 0; j < widths.length; j++) { - for (int k = 0; k < widths[j] + 2; k++) { - buf.append("-"); - } - buf.append("+"); - } - buf.append("\r\n"); - //header - buf.append("|"); - for (int j = 0; j < widths.length; j++) { - String cell = header.get(j); - buf.append(" "); - buf.append(cell); - int pad = widths[j] - cell.length(); - if (pad > 0) { - for (int k = 0; k < pad; k++) { - buf.append(" "); - } - } - buf.append(" |"); - } - buf.append("\r\n"); - //line - buf.append("+"); - for (int j = 0; j < widths.length; j++) { - for (int k = 0; k < widths[j] + 2; k++) { - buf.append("-"); - } - buf.append("+"); - } - buf.append("\r\n"); - //content - for (List row : table) { - StringBuilder rowbuf = new StringBuilder(); - rowbuf.append("|"); - for (int j = 0; j < widths.length; j++) { - String cell = row.get(j); - rowbuf.append(" "); - int remaing = cell.length(); - while (remaing > 0) { - - if (rowbuf.length() >= totalWidth) { - buf.append(rowbuf.toString()); - rowbuf = new StringBuilder(); -// for(int m = 0;m < maxcountbefore && maxcountbefore < totalWidth ; m++){ -// rowbuf.append(" "); -// } - } - - rowbuf.append(cell, cell.length() - remaing, cell.length() - remaing + 1); - remaing--; - } - int pad = widths[j] - cell.length(); - if (pad > 0) { - for (int k = 0; k < pad; k++) { - rowbuf.append(" "); - } - } - rowbuf.append(" |"); - } - buf.append(rowbuf).append("\r\n"); - } - //line - buf.append("+"); - for (int j = 0; j < widths.length; j++) { - for (int k = 0; k < widths[j] + 2; k++) { - buf.append("-"); - } - buf.append("+"); - } - buf.append("\r\n"); - return buf.toString(); - } - -} \ No newline at end of file +/* + * 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.remoting.telnet.support; + +import java.util.Arrays; +import java.util.List; + +/** + * TelnetUtils + */ +public class TelnetUtils { + + public static String toList(List> table) { + int[] widths = new int[table.get(0).size()]; + for (int j = 0; j < widths.length; j++) { + for (List row : table) { + widths[j] = Math.max(widths[j], row.get(j).length()); + } + } + StringBuilder buf = new StringBuilder(); + for (List row : table) { + if (buf.length() > 0) { + buf.append("\r\n"); + } + for (int j = 0; j < widths.length; j++) { + if (j > 0) { + buf.append(" - "); + } + String value = row.get(j); + buf.append(value); + if (j < widths.length - 1) { + int pad = widths[j] - value.length(); + if (pad > 0) { + for (int k = 0; k < pad; k++) { + buf.append(" "); + } + } + } + } + } + return buf.toString(); + } + + public static String toTable(String[] header, List> table) { + return toTable(Arrays.asList(header), table); + } + + public static String toTable(List header, List> table) { + int totalWidth = 0; + int[] widths = new int[header.size()]; + int maxwidth = 70; + int maxcountbefore = 0; + for (int j = 0; j < widths.length; j++) { + widths[j] = Math.max(widths[j], header.get(j).length()); + } + for (List row : table) { + int countbefore = 0; + for (int j = 0; j < widths.length; j++) { + widths[j] = Math.max(widths[j], row.get(j).length()); + totalWidth = (totalWidth + widths[j]) > maxwidth ? maxwidth : (totalWidth + widths[j]); + if (j < widths.length - 1) { + countbefore = countbefore + widths[j]; + } + } + maxcountbefore = Math.max(countbefore, maxcountbefore); + } + widths[widths.length - 1] = Math.min(widths[widths.length - 1], maxwidth - maxcountbefore); + StringBuilder buf = new StringBuilder(); + //line + buf.append("+"); + for (int j = 0; j < widths.length; j++) { + for (int k = 0; k < widths[j] + 2; k++) { + buf.append("-"); + } + buf.append("+"); + } + buf.append("\r\n"); + //header + buf.append("|"); + for (int j = 0; j < widths.length; j++) { + String cell = header.get(j); + buf.append(" "); + buf.append(cell); + int pad = widths[j] - cell.length(); + if (pad > 0) { + for (int k = 0; k < pad; k++) { + buf.append(" "); + } + } + buf.append(" |"); + } + buf.append("\r\n"); + //line + buf.append("+"); + for (int j = 0; j < widths.length; j++) { + for (int k = 0; k < widths[j] + 2; k++) { + buf.append("-"); + } + buf.append("+"); + } + buf.append("\r\n"); + //content + for (List row : table) { + StringBuilder rowbuf = new StringBuilder(); + rowbuf.append("|"); + for (int j = 0; j < widths.length; j++) { + String cell = row.get(j); + rowbuf.append(" "); + int remaing = cell.length(); + while (remaing > 0) { + + if (rowbuf.length() >= totalWidth) { + buf.append(rowbuf.toString()); + rowbuf = new StringBuilder(); +// for(int m = 0;m < maxcountbefore && maxcountbefore < totalWidth ; m++){ +// rowbuf.append(" "); +// } + } + + rowbuf.append(cell, cell.length() - remaing, cell.length() - remaing + 1); + remaing--; + } + int pad = widths[j] - cell.length(); + if (pad > 0) { + for (int k = 0; k < pad; k++) { + rowbuf.append(" "); + } + } + rowbuf.append(" |"); + } + buf.append(rowbuf).append("\r\n"); + } + //line + buf.append("+"); + for (int j = 0; j < widths.length; j++) { + for (int k = 0; k < widths[j] + 2; k++) { + buf.append("-"); + } + buf.append("+"); + } + buf.append("\r\n"); + return buf.toString(); + } + +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/command/ClearTelnetHandler.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/command/ClearTelnetHandler.java index 7fc6afb825..84b78c19c6 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/command/ClearTelnetHandler.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/command/ClearTelnetHandler.java @@ -1,48 +1,48 @@ -/* - * 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.remoting.telnet.support.command; - -import org.apache.dubbo.common.extension.Activate; -import org.apache.dubbo.common.utils.StringUtils; -import org.apache.dubbo.remoting.Channel; -import org.apache.dubbo.remoting.telnet.TelnetHandler; -import org.apache.dubbo.remoting.telnet.support.Help; - -/** - * ClearTelnetHandler - */ -@Activate -@Help(parameter = "[lines]", summary = "Clear screen.", detail = "Clear screen.") -public class ClearTelnetHandler implements TelnetHandler { - - @Override - public String telnet(Channel channel, String message) { - int lines = 100; - if (message.length() > 0) { - if (!StringUtils.isInteger(message)) { - return "Illegal lines " + message + ", must be integer."; - } - lines = Integer.parseInt(message); - } - StringBuilder buf = new StringBuilder(); - for (int i = 0; i < lines; i++) { - buf.append("\r\n"); - } - return buf.toString(); - } - -} +/* + * 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.remoting.telnet.support.command; + +import org.apache.dubbo.common.extension.Activate; +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.remoting.Channel; +import org.apache.dubbo.remoting.telnet.TelnetHandler; +import org.apache.dubbo.remoting.telnet.support.Help; + +/** + * ClearTelnetHandler + */ +@Activate +@Help(parameter = "[lines]", summary = "Clear screen.", detail = "Clear screen.") +public class ClearTelnetHandler implements TelnetHandler { + + @Override + public String telnet(Channel channel, String message) { + int lines = 100; + if (message.length() > 0) { + if (!StringUtils.isInteger(message)) { + return "Illegal lines " + message + ", must be integer."; + } + lines = Integer.parseInt(message); + } + StringBuilder buf = new StringBuilder(); + for (int i = 0; i < lines; i++) { + buf.append("\r\n"); + } + return buf.toString(); + } + +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/command/ExitTelnetHandler.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/command/ExitTelnetHandler.java index 1634eb7d01..9f176aaae0 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/command/ExitTelnetHandler.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/command/ExitTelnetHandler.java @@ -1,37 +1,37 @@ -/* - * 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.remoting.telnet.support.command; - -import org.apache.dubbo.common.extension.Activate; -import org.apache.dubbo.remoting.Channel; -import org.apache.dubbo.remoting.telnet.TelnetHandler; -import org.apache.dubbo.remoting.telnet.support.Help; - -/** - * ExitTelnetHandler - */ -@Activate -@Help(parameter = "", summary = "Exit the telnet.", detail = "Exit the telnet.") -public class ExitTelnetHandler implements TelnetHandler { - - @Override - public String telnet(Channel channel, String message) { - channel.close(); - return null; - } - -} +/* + * 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.remoting.telnet.support.command; + +import org.apache.dubbo.common.extension.Activate; +import org.apache.dubbo.remoting.Channel; +import org.apache.dubbo.remoting.telnet.TelnetHandler; +import org.apache.dubbo.remoting.telnet.support.Help; + +/** + * ExitTelnetHandler + */ +@Activate +@Help(parameter = "", summary = "Exit the telnet.", detail = "Exit the telnet.") +public class ExitTelnetHandler implements TelnetHandler { + + @Override + public String telnet(Channel channel, String message) { + channel.close(); + return null; + } + +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/command/HelpTelnetHandler.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/command/HelpTelnetHandler.java index b22cd1ac66..7da05de306 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/command/HelpTelnetHandler.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/command/HelpTelnetHandler.java @@ -1,73 +1,73 @@ -/* - * 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.remoting.telnet.support.command; - -import org.apache.dubbo.common.extension.Activate; -import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.common.utils.CollectionUtils; -import org.apache.dubbo.remoting.Channel; -import org.apache.dubbo.remoting.telnet.TelnetHandler; -import org.apache.dubbo.remoting.telnet.support.Help; -import org.apache.dubbo.remoting.telnet.support.TelnetUtils; - -import java.util.ArrayList; -import java.util.List; - -/** - * HelpTelnetHandler - */ -@Activate -@Help(parameter = "[command]", summary = "Show help.", detail = "Show help.") -public class HelpTelnetHandler implements TelnetHandler { - - private final ExtensionLoader extensionLoader = ExtensionLoader.getExtensionLoader(TelnetHandler.class); - - @Override - public String telnet(Channel channel, String message) { - if (message.length() > 0) { - if (!extensionLoader.hasExtension(message)) { - return "No such command " + message; - } - TelnetHandler handler = extensionLoader.getExtension(message); - Help help = handler.getClass().getAnnotation(Help.class); - StringBuilder buf = new StringBuilder(); - buf.append("Command:\r\n "); - buf.append(message + " " + help.parameter().replace("\r\n", " ").replace("\n", " ")); - buf.append("\r\nSummary:\r\n "); - buf.append(help.summary().replace("\r\n", " ").replace("\n", " ")); - buf.append("\r\nDetail:\r\n "); - buf.append(help.detail().replace("\r\n", " \r\n").replace("\n", " \n")); - return buf.toString(); - } else { - List> table = new ArrayList>(); - List handlers = extensionLoader.getActivateExtension(channel.getUrl(), "telnet"); - if (CollectionUtils.isNotEmpty(handlers)) { - for (TelnetHandler handler : handlers) { - Help help = handler.getClass().getAnnotation(Help.class); - List row = new ArrayList(); - String parameter = " " + extensionLoader.getExtensionName(handler) + " " + (help != null ? help.parameter().replace("\r\n", " ").replace("\n", " ") : ""); - row.add(parameter.length() > 55 ? parameter.substring(0, 55) + "..." : parameter); - String summary = help != null ? help.summary().replace("\r\n", " ").replace("\n", " ") : ""; - row.add(summary.length() > 55 ? summary.substring(0, 55) + "..." : summary); - table.add(row); - } - } - return "Please input \"help [command]\" show detail.\r\n" + TelnetUtils.toList(table); - } - } - -} +/* + * 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.remoting.telnet.support.command; + +import org.apache.dubbo.common.extension.Activate; +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.remoting.Channel; +import org.apache.dubbo.remoting.telnet.TelnetHandler; +import org.apache.dubbo.remoting.telnet.support.Help; +import org.apache.dubbo.remoting.telnet.support.TelnetUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + * HelpTelnetHandler + */ +@Activate +@Help(parameter = "[command]", summary = "Show help.", detail = "Show help.") +public class HelpTelnetHandler implements TelnetHandler { + + private final ExtensionLoader extensionLoader = ExtensionLoader.getExtensionLoader(TelnetHandler.class); + + @Override + public String telnet(Channel channel, String message) { + if (message.length() > 0) { + if (!extensionLoader.hasExtension(message)) { + return "No such command " + message; + } + TelnetHandler handler = extensionLoader.getExtension(message); + Help help = handler.getClass().getAnnotation(Help.class); + StringBuilder buf = new StringBuilder(); + buf.append("Command:\r\n "); + buf.append(message + " " + help.parameter().replace("\r\n", " ").replace("\n", " ")); + buf.append("\r\nSummary:\r\n "); + buf.append(help.summary().replace("\r\n", " ").replace("\n", " ")); + buf.append("\r\nDetail:\r\n "); + buf.append(help.detail().replace("\r\n", " \r\n").replace("\n", " \n")); + return buf.toString(); + } else { + List> table = new ArrayList>(); + List handlers = extensionLoader.getActivateExtension(channel.getUrl(), "telnet"); + if (CollectionUtils.isNotEmpty(handlers)) { + for (TelnetHandler handler : handlers) { + Help help = handler.getClass().getAnnotation(Help.class); + List row = new ArrayList(); + String parameter = " " + extensionLoader.getExtensionName(handler) + " " + (help != null ? help.parameter().replace("\r\n", " ").replace("\n", " ") : ""); + row.add(parameter.length() > 55 ? parameter.substring(0, 55) + "..." : parameter); + String summary = help != null ? help.summary().replace("\r\n", " ").replace("\n", " ") : ""; + row.add(summary.length() > 55 ? summary.substring(0, 55) + "..." : summary); + table.add(row); + } + } + return "Please input \"help [command]\" show detail.\r\n" + TelnetUtils.toList(table); + } + } + +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/command/StatusTelnetHandler.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/command/StatusTelnetHandler.java index b64e708765..acb2a50212 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/command/StatusTelnetHandler.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/command/StatusTelnetHandler.java @@ -1,101 +1,101 @@ -/* - * 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.remoting.telnet.support.command; - -import org.apache.dubbo.common.extension.Activate; -import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.common.status.Status; -import org.apache.dubbo.common.status.StatusChecker; -import org.apache.dubbo.common.status.support.StatusUtils; -import org.apache.dubbo.common.utils.CollectionUtils; -import org.apache.dubbo.common.utils.StringUtils; -import org.apache.dubbo.remoting.Channel; -import org.apache.dubbo.remoting.telnet.TelnetHandler; -import org.apache.dubbo.remoting.telnet.support.Help; -import org.apache.dubbo.remoting.telnet.support.TelnetUtils; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN; - -/** - * StatusTelnetHandler - */ -@Activate -@Help(parameter = "[-l]", summary = "Show status.", detail = "Show status.") -public class StatusTelnetHandler implements TelnetHandler { - - private final ExtensionLoader extensionLoader = ExtensionLoader.getExtensionLoader(StatusChecker.class); - - @Override - public String telnet(Channel channel, String message) { - if ("-l".equals(message)) { - List checkers = extensionLoader.getActivateExtension(channel.getUrl(), "status"); - String[] header = new String[]{"resource", "status", "message"}; - List> table = new ArrayList>(); - Map statuses = new HashMap(); - if (CollectionUtils.isNotEmpty(checkers)) { - for (StatusChecker checker : checkers) { - String name = extensionLoader.getExtensionName(checker); - Status stat; - try { - stat = checker.check(); - } catch (Throwable t) { - stat = new Status(Status.Level.ERROR, t.getMessage()); - } - statuses.put(name, stat); - if (stat.getLevel() != null && stat.getLevel() != Status.Level.UNKNOWN) { - List row = new ArrayList(); - row.add(name); - row.add(String.valueOf(stat.getLevel())); - row.add(stat.getMessage() == null ? "" : stat.getMessage()); - table.add(row); - } - } - } - Status stat = StatusUtils.getSummaryStatus(statuses); - List row = new ArrayList(); - row.add("summary"); - row.add(String.valueOf(stat.getLevel())); - row.add(stat.getMessage()); - table.add(row); - return TelnetUtils.toTable(header, table); - } else if (message.length() > 0) { - return "Unsupported parameter " + message + " for status."; - } - String status = channel.getUrl().getParameter("status"); - Map statuses = new HashMap(); - if (StringUtils.isNotEmpty(status)) { - String[] ss = COMMA_SPLIT_PATTERN.split(status); - for (String s : ss) { - StatusChecker handler = extensionLoader.getExtension(s); - Status stat; - try { - stat = handler.check(); - } catch (Throwable t) { - stat = new Status(Status.Level.ERROR, t.getMessage()); - } - statuses.put(s, stat); - } - } - Status stat = StatusUtils.getSummaryStatus(statuses); - return String.valueOf(stat.getLevel()); - } -} +/* + * 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.remoting.telnet.support.command; + +import org.apache.dubbo.common.extension.Activate; +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.common.status.Status; +import org.apache.dubbo.common.status.StatusChecker; +import org.apache.dubbo.common.status.support.StatusUtils; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.remoting.Channel; +import org.apache.dubbo.remoting.telnet.TelnetHandler; +import org.apache.dubbo.remoting.telnet.support.Help; +import org.apache.dubbo.remoting.telnet.support.TelnetUtils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN; + +/** + * StatusTelnetHandler + */ +@Activate +@Help(parameter = "[-l]", summary = "Show status.", detail = "Show status.") +public class StatusTelnetHandler implements TelnetHandler { + + private final ExtensionLoader extensionLoader = ExtensionLoader.getExtensionLoader(StatusChecker.class); + + @Override + public String telnet(Channel channel, String message) { + if ("-l".equals(message)) { + List checkers = extensionLoader.getActivateExtension(channel.getUrl(), "status"); + String[] header = new String[]{"resource", "status", "message"}; + List> table = new ArrayList>(); + Map statuses = new HashMap(); + if (CollectionUtils.isNotEmpty(checkers)) { + for (StatusChecker checker : checkers) { + String name = extensionLoader.getExtensionName(checker); + Status stat; + try { + stat = checker.check(); + } catch (Throwable t) { + stat = new Status(Status.Level.ERROR, t.getMessage()); + } + statuses.put(name, stat); + if (stat.getLevel() != null && stat.getLevel() != Status.Level.UNKNOWN) { + List row = new ArrayList(); + row.add(name); + row.add(String.valueOf(stat.getLevel())); + row.add(stat.getMessage() == null ? "" : stat.getMessage()); + table.add(row); + } + } + } + Status stat = StatusUtils.getSummaryStatus(statuses); + List row = new ArrayList(); + row.add("summary"); + row.add(String.valueOf(stat.getLevel())); + row.add(stat.getMessage()); + table.add(row); + return TelnetUtils.toTable(header, table); + } else if (message.length() > 0) { + return "Unsupported parameter " + message + " for status."; + } + String status = channel.getUrl().getParameter("status"); + Map statuses = new HashMap(); + if (StringUtils.isNotEmpty(status)) { + String[] ss = COMMA_SPLIT_PATTERN.split(status); + for (String s : ss) { + StatusChecker handler = extensionLoader.getExtension(s); + Status stat; + try { + stat = handler.check(); + } catch (Throwable t) { + stat = new Status(Status.Level.ERROR, t.getMessage()); + } + statuses.put(s, stat); + } + } + Status stat = StatusUtils.getSummaryStatus(statuses); + return String.valueOf(stat.getLevel()); + } +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/AbstractChannel.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/AbstractChannel.java index c993eec9d7..dee60daae4 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/AbstractChannel.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/AbstractChannel.java @@ -1,47 +1,47 @@ -/* - * 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.remoting.transport; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.remoting.Channel; -import org.apache.dubbo.remoting.ChannelHandler; -import org.apache.dubbo.remoting.RemotingException; -import org.apache.dubbo.remoting.utils.PayloadDropper; - -/** - * AbstractChannel - */ -public abstract class AbstractChannel extends AbstractPeer implements Channel { - - public AbstractChannel(URL url, ChannelHandler handler) { - super(url, handler); - } - - @Override - public void send(Object message, boolean sent) throws RemotingException { - if (isClosed()) { - throw new RemotingException(this, "Failed to send message " - + (message == null ? "" : message.getClass().getName()) + ":" + PayloadDropper.getRequestWithoutData(message) - + ", cause: Channel closed. channel: " + getLocalAddress() + " -> " + getRemoteAddress()); - } - } - - @Override - public String toString() { - return getLocalAddress() + " -> " + getRemoteAddress(); - } -} +/* + * 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.remoting.transport; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.remoting.Channel; +import org.apache.dubbo.remoting.ChannelHandler; +import org.apache.dubbo.remoting.RemotingException; +import org.apache.dubbo.remoting.utils.PayloadDropper; + +/** + * AbstractChannel + */ +public abstract class AbstractChannel extends AbstractPeer implements Channel { + + public AbstractChannel(URL url, ChannelHandler handler) { + super(url, handler); + } + + @Override + public void send(Object message, boolean sent) throws RemotingException { + if (isClosed()) { + throw new RemotingException(this, "Failed to send message " + + (message == null ? "" : message.getClass().getName()) + ":" + PayloadDropper.getRequestWithoutData(message) + + ", cause: Channel closed. channel: " + getLocalAddress() + " -> " + getRemoteAddress()); + } + } + + @Override + public String toString() { + return getLocalAddress() + " -> " + getRemoteAddress(); + } +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/AbstractPeer.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/AbstractPeer.java index ecad2365e8..9ded5052ad 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/AbstractPeer.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/AbstractPeer.java @@ -1,154 +1,154 @@ -/* - * 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.remoting.transport; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.remoting.Channel; -import org.apache.dubbo.remoting.ChannelHandler; -import org.apache.dubbo.remoting.Constants; -import org.apache.dubbo.remoting.Endpoint; -import org.apache.dubbo.remoting.RemotingException; - -/** - * AbstractPeer - */ -public abstract class AbstractPeer implements Endpoint, ChannelHandler { - - private final ChannelHandler handler; - - private volatile URL url; - - // closing closed means the process is being closed and close is finished - private volatile boolean closing; - - private volatile boolean closed; - - public AbstractPeer(URL url, ChannelHandler handler) { - if (url == null) { - throw new IllegalArgumentException("url == null"); - } - if (handler == null) { - throw new IllegalArgumentException("handler == null"); - } - this.url = url; - this.handler = handler; - } - - @Override - public void send(Object message) throws RemotingException { - send(message, url.getParameter(Constants.SENT_KEY, false)); - } - - @Override - public void close() { - closed = true; - } - - @Override - public void close(int timeout) { - close(); - } - - @Override - public void startClose() { - if (isClosed()) { - return; - } - closing = true; - } - - @Override - public URL getUrl() { - return url; - } - - protected void setUrl(URL url) { - if (url == null) { - throw new IllegalArgumentException("url == null"); - } - this.url = url; - } - - @Override - public ChannelHandler getChannelHandler() { - if (handler instanceof ChannelHandlerDelegate) { - return ((ChannelHandlerDelegate) handler).getHandler(); - } else { - return handler; - } - } - - /** - * @return ChannelHandler - */ - @Deprecated - public ChannelHandler getHandler() { - return getDelegateHandler(); - } - - /** - * Return the final handler (which may have been wrapped). This method should be distinguished with getChannelHandler() method - * - * @return ChannelHandler - */ - public ChannelHandler getDelegateHandler() { - return handler; - } - - @Override - public boolean isClosed() { - return closed; - } - - public boolean isClosing() { - return closing && !closed; - } - - @Override - public void connected(Channel ch) throws RemotingException { - if (closed) { - return; - } - handler.connected(ch); - } - - @Override - public void disconnected(Channel ch) throws RemotingException { - handler.disconnected(ch); - } - - @Override - public void sent(Channel ch, Object msg) throws RemotingException { - if (closed) { - return; - } - handler.sent(ch, msg); - } - - @Override - public void received(Channel ch, Object msg) throws RemotingException { - if (closed) { - return; - } - handler.received(ch, msg); - } - - @Override - public void caught(Channel ch, Throwable ex) throws RemotingException { - handler.caught(ch, ex); - } -} +/* + * 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.remoting.transport; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.remoting.Channel; +import org.apache.dubbo.remoting.ChannelHandler; +import org.apache.dubbo.remoting.Constants; +import org.apache.dubbo.remoting.Endpoint; +import org.apache.dubbo.remoting.RemotingException; + +/** + * AbstractPeer + */ +public abstract class AbstractPeer implements Endpoint, ChannelHandler { + + private final ChannelHandler handler; + + private volatile URL url; + + // closing closed means the process is being closed and close is finished + private volatile boolean closing; + + private volatile boolean closed; + + public AbstractPeer(URL url, ChannelHandler handler) { + if (url == null) { + throw new IllegalArgumentException("url == null"); + } + if (handler == null) { + throw new IllegalArgumentException("handler == null"); + } + this.url = url; + this.handler = handler; + } + + @Override + public void send(Object message) throws RemotingException { + send(message, url.getParameter(Constants.SENT_KEY, false)); + } + + @Override + public void close() { + closed = true; + } + + @Override + public void close(int timeout) { + close(); + } + + @Override + public void startClose() { + if (isClosed()) { + return; + } + closing = true; + } + + @Override + public URL getUrl() { + return url; + } + + protected void setUrl(URL url) { + if (url == null) { + throw new IllegalArgumentException("url == null"); + } + this.url = url; + } + + @Override + public ChannelHandler getChannelHandler() { + if (handler instanceof ChannelHandlerDelegate) { + return ((ChannelHandlerDelegate) handler).getHandler(); + } else { + return handler; + } + } + + /** + * @return ChannelHandler + */ + @Deprecated + public ChannelHandler getHandler() { + return getDelegateHandler(); + } + + /** + * Return the final handler (which may have been wrapped). This method should be distinguished with getChannelHandler() method + * + * @return ChannelHandler + */ + public ChannelHandler getDelegateHandler() { + return handler; + } + + @Override + public boolean isClosed() { + return closed; + } + + public boolean isClosing() { + return closing && !closed; + } + + @Override + public void connected(Channel ch) throws RemotingException { + if (closed) { + return; + } + handler.connected(ch); + } + + @Override + public void disconnected(Channel ch) throws RemotingException { + handler.disconnected(ch); + } + + @Override + public void sent(Channel ch, Object msg) throws RemotingException { + if (closed) { + return; + } + handler.sent(ch, msg); + } + + @Override + public void received(Channel ch, Object msg) throws RemotingException { + if (closed) { + return; + } + handler.received(ch, msg); + } + + @Override + public void caught(Channel ch, Throwable ex) throws RemotingException { + handler.caught(ch, ex); + } +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/ChannelDelegate.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/ChannelDelegate.java index fb64a77620..eb4ce77a03 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/ChannelDelegate.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/ChannelDelegate.java @@ -1,126 +1,126 @@ -/* - * 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.remoting.transport; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.remoting.Channel; -import org.apache.dubbo.remoting.ChannelHandler; -import org.apache.dubbo.remoting.RemotingException; - -import java.net.InetSocketAddress; - -/** - * ChannelDelegate - */ -public class ChannelDelegate implements Channel { - - private transient Channel channel; - - public ChannelDelegate() { - } - - public ChannelDelegate(Channel channel) { - setChannel(channel); - } - - public Channel getChannel() { - return channel; - } - - public void setChannel(Channel channel) { - if (channel == null) { - throw new IllegalArgumentException("channel == null"); - } - this.channel = channel; - } - - @Override - public URL getUrl() { - return channel.getUrl(); - } - - @Override - public InetSocketAddress getRemoteAddress() { - return channel.getRemoteAddress(); - } - - @Override - public ChannelHandler getChannelHandler() { - return channel.getChannelHandler(); - } - - @Override - public boolean isConnected() { - return channel.isConnected(); - } - - @Override - public InetSocketAddress getLocalAddress() { - return channel.getLocalAddress(); - } - - @Override - public boolean hasAttribute(String key) { - return channel.hasAttribute(key); - } - - @Override - public void send(Object message) throws RemotingException { - channel.send(message); - } - - @Override - public Object getAttribute(String key) { - return channel.getAttribute(key); - } - - @Override - public void setAttribute(String key, Object value) { - channel.setAttribute(key, value); - } - - @Override - public void send(Object message, boolean sent) throws RemotingException { - channel.send(message, sent); - } - - @Override - public void removeAttribute(String key) { - channel.removeAttribute(key); - } - - @Override - public void close() { - channel.close(); - } - - @Override - public void close(int timeout) { - channel.close(timeout); - } - - @Override - public void startClose() { - channel.startClose(); - } - - @Override - public boolean isClosed() { - return channel.isClosed(); - } - -} +/* + * 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.remoting.transport; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.remoting.Channel; +import org.apache.dubbo.remoting.ChannelHandler; +import org.apache.dubbo.remoting.RemotingException; + +import java.net.InetSocketAddress; + +/** + * ChannelDelegate + */ +public class ChannelDelegate implements Channel { + + private transient Channel channel; + + public ChannelDelegate() { + } + + public ChannelDelegate(Channel channel) { + setChannel(channel); + } + + public Channel getChannel() { + return channel; + } + + public void setChannel(Channel channel) { + if (channel == null) { + throw new IllegalArgumentException("channel == null"); + } + this.channel = channel; + } + + @Override + public URL getUrl() { + return channel.getUrl(); + } + + @Override + public InetSocketAddress getRemoteAddress() { + return channel.getRemoteAddress(); + } + + @Override + public ChannelHandler getChannelHandler() { + return channel.getChannelHandler(); + } + + @Override + public boolean isConnected() { + return channel.isConnected(); + } + + @Override + public InetSocketAddress getLocalAddress() { + return channel.getLocalAddress(); + } + + @Override + public boolean hasAttribute(String key) { + return channel.hasAttribute(key); + } + + @Override + public void send(Object message) throws RemotingException { + channel.send(message); + } + + @Override + public Object getAttribute(String key) { + return channel.getAttribute(key); + } + + @Override + public void setAttribute(String key, Object value) { + channel.setAttribute(key, value); + } + + @Override + public void send(Object message, boolean sent) throws RemotingException { + channel.send(message, sent); + } + + @Override + public void removeAttribute(String key) { + channel.removeAttribute(key); + } + + @Override + public void close() { + channel.close(); + } + + @Override + public void close(int timeout) { + channel.close(timeout); + } + + @Override + public void startClose() { + channel.startClose(); + } + + @Override + public boolean isClosed() { + return channel.isClosed(); + } + +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/ChannelHandlerDelegate.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/ChannelHandlerDelegate.java index bab09bdbce..5429a2a442 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/ChannelHandlerDelegate.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/ChannelHandlerDelegate.java @@ -1,23 +1,23 @@ -/* - * 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.remoting.transport; - -import org.apache.dubbo.remoting.ChannelHandler; - -public interface ChannelHandlerDelegate extends ChannelHandler { - ChannelHandler getHandler(); -} +/* + * 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.remoting.transport; + +import org.apache.dubbo.remoting.ChannelHandler; + +public interface ChannelHandlerDelegate extends ChannelHandler { + ChannelHandler getHandler(); +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/ChannelHandlerDispatcher.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/ChannelHandlerDispatcher.java index 783741b78e..3ef2415783 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/ChannelHandlerDispatcher.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/ChannelHandlerDispatcher.java @@ -1,120 +1,120 @@ -/* - * 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.remoting.transport; - -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.utils.CollectionUtils; -import org.apache.dubbo.remoting.Channel; -import org.apache.dubbo.remoting.ChannelHandler; - -import java.util.Arrays; -import java.util.Collection; -import java.util.concurrent.CopyOnWriteArraySet; - -/** - * ChannelListenerDispatcher - */ -public class ChannelHandlerDispatcher implements ChannelHandler { - - private static final Logger logger = LoggerFactory.getLogger(ChannelHandlerDispatcher.class); - - private final Collection channelHandlers = new CopyOnWriteArraySet(); - - public ChannelHandlerDispatcher() { - } - - public ChannelHandlerDispatcher(ChannelHandler... handlers) { - this(handlers == null ? null : Arrays.asList(handlers)); - } - - public ChannelHandlerDispatcher(Collection handlers) { - if (CollectionUtils.isNotEmpty(handlers)) { - this.channelHandlers.addAll(handlers); - } - } - - public Collection getChannelHandlers() { - return channelHandlers; - } - - public ChannelHandlerDispatcher addChannelHandler(ChannelHandler handler) { - this.channelHandlers.add(handler); - return this; - } - - public ChannelHandlerDispatcher removeChannelHandler(ChannelHandler handler) { - this.channelHandlers.remove(handler); - return this; - } - - @Override - public void connected(Channel channel) { - for (ChannelHandler listener : channelHandlers) { - try { - listener.connected(channel); - } catch (Throwable t) { - logger.error(t.getMessage(), t); - } - } - } - - @Override - public void disconnected(Channel channel) { - for (ChannelHandler listener : channelHandlers) { - try { - listener.disconnected(channel); - } catch (Throwable t) { - logger.error(t.getMessage(), t); - } - } - } - - @Override - public void sent(Channel channel, Object message) { - for (ChannelHandler listener : channelHandlers) { - try { - listener.sent(channel, message); - } catch (Throwable t) { - logger.error(t.getMessage(), t); - } - } - } - - @Override - public void received(Channel channel, Object message) { - for (ChannelHandler listener : channelHandlers) { - try { - listener.received(channel, message); - } catch (Throwable t) { - logger.error(t.getMessage(), t); - } - } - } - - @Override - public void caught(Channel channel, Throwable exception) { - for (ChannelHandler listener : channelHandlers) { - try { - listener.caught(channel, exception); - } catch (Throwable t) { - logger.error(t.getMessage(), t); - } - } - } - -} +/* + * 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.remoting.transport; + +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.remoting.Channel; +import org.apache.dubbo.remoting.ChannelHandler; + +import java.util.Arrays; +import java.util.Collection; +import java.util.concurrent.CopyOnWriteArraySet; + +/** + * ChannelListenerDispatcher + */ +public class ChannelHandlerDispatcher implements ChannelHandler { + + private static final Logger logger = LoggerFactory.getLogger(ChannelHandlerDispatcher.class); + + private final Collection channelHandlers = new CopyOnWriteArraySet(); + + public ChannelHandlerDispatcher() { + } + + public ChannelHandlerDispatcher(ChannelHandler... handlers) { + this(handlers == null ? null : Arrays.asList(handlers)); + } + + public ChannelHandlerDispatcher(Collection handlers) { + if (CollectionUtils.isNotEmpty(handlers)) { + this.channelHandlers.addAll(handlers); + } + } + + public Collection getChannelHandlers() { + return channelHandlers; + } + + public ChannelHandlerDispatcher addChannelHandler(ChannelHandler handler) { + this.channelHandlers.add(handler); + return this; + } + + public ChannelHandlerDispatcher removeChannelHandler(ChannelHandler handler) { + this.channelHandlers.remove(handler); + return this; + } + + @Override + public void connected(Channel channel) { + for (ChannelHandler listener : channelHandlers) { + try { + listener.connected(channel); + } catch (Throwable t) { + logger.error(t.getMessage(), t); + } + } + } + + @Override + public void disconnected(Channel channel) { + for (ChannelHandler listener : channelHandlers) { + try { + listener.disconnected(channel); + } catch (Throwable t) { + logger.error(t.getMessage(), t); + } + } + } + + @Override + public void sent(Channel channel, Object message) { + for (ChannelHandler listener : channelHandlers) { + try { + listener.sent(channel, message); + } catch (Throwable t) { + logger.error(t.getMessage(), t); + } + } + } + + @Override + public void received(Channel channel, Object message) { + for (ChannelHandler listener : channelHandlers) { + try { + listener.received(channel, message); + } catch (Throwable t) { + logger.error(t.getMessage(), t); + } + } + } + + @Override + public void caught(Channel channel, Throwable exception) { + for (ChannelHandler listener : channelHandlers) { + try { + listener.caught(channel, exception); + } catch (Throwable t) { + logger.error(t.getMessage(), t); + } + } + } + +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/ClientDelegate.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/ClientDelegate.java index b3b60819bc..d2a7673d0e 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/ClientDelegate.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/ClientDelegate.java @@ -1,142 +1,142 @@ -/* - * 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.remoting.transport; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.remoting.ChannelHandler; -import org.apache.dubbo.remoting.Client; -import org.apache.dubbo.remoting.RemotingException; - -import java.net.InetSocketAddress; - -/** - * ClientDelegate - */ -public class ClientDelegate implements Client { - - private transient Client client; - - public ClientDelegate() { - } - - public ClientDelegate(Client client) { - setClient(client); - } - - public Client getClient() { - return client; - } - - public void setClient(Client client) { - if (client == null) { - throw new IllegalArgumentException("client == null"); - } - this.client = client; - } - - @Override - public void reset(URL url) { - client.reset(url); - } - - @Override - @Deprecated - public void reset(org.apache.dubbo.common.Parameters parameters) { - reset(getUrl().addParameters(parameters.getParameters())); - } - - @Override - public URL getUrl() { - return client.getUrl(); - } - - @Override - public InetSocketAddress getRemoteAddress() { - return client.getRemoteAddress(); - } - - @Override - public void reconnect() throws RemotingException { - client.reconnect(); - } - - @Override - public ChannelHandler getChannelHandler() { - return client.getChannelHandler(); - } - - @Override - public boolean isConnected() { - return client.isConnected(); - } - - @Override - public InetSocketAddress getLocalAddress() { - return client.getLocalAddress(); - } - - @Override - public boolean hasAttribute(String key) { - return client.hasAttribute(key); - } - - @Override - public void send(Object message) throws RemotingException { - client.send(message); - } - - @Override - public Object getAttribute(String key) { - return client.getAttribute(key); - } - - @Override - public void setAttribute(String key, Object value) { - client.setAttribute(key, value); - } - - @Override - public void send(Object message, boolean sent) throws RemotingException { - client.send(message, sent); - } - - @Override - public void removeAttribute(String key) { - client.removeAttribute(key); - } - - @Override - public void close() { - client.close(); - } - - @Override - public void close(int timeout) { - client.close(timeout); - } - - @Override - public void startClose() { - client.startClose(); - } - - @Override - public boolean isClosed() { - return client.isClosed(); - } - -} +/* + * 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.remoting.transport; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.remoting.ChannelHandler; +import org.apache.dubbo.remoting.Client; +import org.apache.dubbo.remoting.RemotingException; + +import java.net.InetSocketAddress; + +/** + * ClientDelegate + */ +public class ClientDelegate implements Client { + + private transient Client client; + + public ClientDelegate() { + } + + public ClientDelegate(Client client) { + setClient(client); + } + + public Client getClient() { + return client; + } + + public void setClient(Client client) { + if (client == null) { + throw new IllegalArgumentException("client == null"); + } + this.client = client; + } + + @Override + public void reset(URL url) { + client.reset(url); + } + + @Override + @Deprecated + public void reset(org.apache.dubbo.common.Parameters parameters) { + reset(getUrl().addParameters(parameters.getParameters())); + } + + @Override + public URL getUrl() { + return client.getUrl(); + } + + @Override + public InetSocketAddress getRemoteAddress() { + return client.getRemoteAddress(); + } + + @Override + public void reconnect() throws RemotingException { + client.reconnect(); + } + + @Override + public ChannelHandler getChannelHandler() { + return client.getChannelHandler(); + } + + @Override + public boolean isConnected() { + return client.isConnected(); + } + + @Override + public InetSocketAddress getLocalAddress() { + return client.getLocalAddress(); + } + + @Override + public boolean hasAttribute(String key) { + return client.hasAttribute(key); + } + + @Override + public void send(Object message) throws RemotingException { + client.send(message); + } + + @Override + public Object getAttribute(String key) { + return client.getAttribute(key); + } + + @Override + public void setAttribute(String key, Object value) { + client.setAttribute(key, value); + } + + @Override + public void send(Object message, boolean sent) throws RemotingException { + client.send(message, sent); + } + + @Override + public void removeAttribute(String key) { + client.removeAttribute(key); + } + + @Override + public void close() { + client.close(); + } + + @Override + public void close(int timeout) { + client.close(timeout); + } + + @Override + public void startClose() { + client.startClose(); + } + + @Override + public boolean isClosed() { + return client.isClosed(); + } + +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/ServerDelegate.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/ServerDelegate.java index 49b508ab19..0aa39495ce 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/ServerDelegate.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/ServerDelegate.java @@ -1,122 +1,122 @@ -/* - * 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.remoting.transport; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.remoting.Channel; -import org.apache.dubbo.remoting.ChannelHandler; -import org.apache.dubbo.remoting.RemotingException; -import org.apache.dubbo.remoting.RemotingServer; - -import java.net.InetSocketAddress; -import java.util.Collection; - -/** - * ServerDelegate - * - * - */ -public class ServerDelegate implements RemotingServer { - - private transient RemotingServer server; - - public ServerDelegate() { - } - - public ServerDelegate(RemotingServer server) { - setServer(server); - } - - public RemotingServer getServer() { - return server; - } - - public void setServer(RemotingServer server) { - this.server = server; - } - - @Override - public boolean isBound() { - return server.isBound(); - } - - @Override - public void reset(URL url) { - server.reset(url); - } - - @Override - @Deprecated - public void reset(org.apache.dubbo.common.Parameters parameters) { - reset(getUrl().addParameters(parameters.getParameters())); - } - - @Override - public Collection getChannels() { - return server.getChannels(); - } - - @Override - public Channel getChannel(InetSocketAddress remoteAddress) { - return server.getChannel(remoteAddress); - } - - @Override - public URL getUrl() { - return server.getUrl(); - } - - @Override - public ChannelHandler getChannelHandler() { - return server.getChannelHandler(); - } - - @Override - public InetSocketAddress getLocalAddress() { - return server.getLocalAddress(); - } - - @Override - public void send(Object message) throws RemotingException { - server.send(message); - } - - @Override - public void send(Object message, boolean sent) throws RemotingException { - server.send(message, sent); - } - - @Override - public void close() { - server.close(); - } - - @Override - public void close(int timeout) { - server.close(timeout); - } - - @Override - public void startClose() { - server.startClose(); - } - - @Override - public boolean isClosed() { - return server.isClosed(); - } -} +/* + * 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.remoting.transport; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.remoting.Channel; +import org.apache.dubbo.remoting.ChannelHandler; +import org.apache.dubbo.remoting.RemotingException; +import org.apache.dubbo.remoting.RemotingServer; + +import java.net.InetSocketAddress; +import java.util.Collection; + +/** + * ServerDelegate + * + * + */ +public class ServerDelegate implements RemotingServer { + + private transient RemotingServer server; + + public ServerDelegate() { + } + + public ServerDelegate(RemotingServer server) { + setServer(server); + } + + public RemotingServer getServer() { + return server; + } + + public void setServer(RemotingServer server) { + this.server = server; + } + + @Override + public boolean isBound() { + return server.isBound(); + } + + @Override + public void reset(URL url) { + server.reset(url); + } + + @Override + @Deprecated + public void reset(org.apache.dubbo.common.Parameters parameters) { + reset(getUrl().addParameters(parameters.getParameters())); + } + + @Override + public Collection getChannels() { + return server.getChannels(); + } + + @Override + public Channel getChannel(InetSocketAddress remoteAddress) { + return server.getChannel(remoteAddress); + } + + @Override + public URL getUrl() { + return server.getUrl(); + } + + @Override + public ChannelHandler getChannelHandler() { + return server.getChannelHandler(); + } + + @Override + public InetSocketAddress getLocalAddress() { + return server.getLocalAddress(); + } + + @Override + public void send(Object message) throws RemotingException { + server.send(message); + } + + @Override + public void send(Object message, boolean sent) throws RemotingException { + server.send(message, sent); + } + + @Override + public void close() { + server.close(); + } + + @Override + public void close(int timeout) { + server.close(timeout); + } + + @Override + public void startClose() { + server.startClose(); + } + + @Override + public boolean isClosed() { + return server.isClosed(); + } +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/codec/TransportCodec.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/codec/TransportCodec.java index 5a4d26470e..49d1e292d0 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/codec/TransportCodec.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/codec/TransportCodec.java @@ -1,81 +1,81 @@ -/* - * 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.remoting.transport.codec; - -import org.apache.dubbo.common.serialize.Cleanable; -import org.apache.dubbo.common.serialize.ObjectInput; -import org.apache.dubbo.common.serialize.ObjectOutput; -import org.apache.dubbo.common.utils.StringUtils; -import org.apache.dubbo.remoting.Channel; -import org.apache.dubbo.remoting.buffer.ChannelBuffer; -import org.apache.dubbo.remoting.buffer.ChannelBufferInputStream; -import org.apache.dubbo.remoting.buffer.ChannelBufferOutputStream; -import org.apache.dubbo.remoting.transport.AbstractCodec; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -/** - * Subclasses {@link org.apache.dubbo.remoting.telnet.codec.TelnetCodec} and {@link org.apache.dubbo.remoting.exchange.codec.ExchangeCodec} - * both override all the methods declared in this class. - */ -@Deprecated -public class TransportCodec extends AbstractCodec { - - @Override - public void encode(Channel channel, ChannelBuffer buffer, Object message) throws IOException { - OutputStream output = new ChannelBufferOutputStream(buffer); - ObjectOutput objectOutput = getSerialization(channel).serialize(channel.getUrl(), output); - encodeData(channel, objectOutput, message); - objectOutput.flushBuffer(); - if (objectOutput instanceof Cleanable) { - ((Cleanable) objectOutput).cleanup(); - } - } - - @Override - public Object decode(Channel channel, ChannelBuffer buffer) throws IOException { - InputStream input = new ChannelBufferInputStream(buffer); - ObjectInput objectInput = getSerialization(channel).deserialize(channel.getUrl(), input); - Object object = decodeData(channel, objectInput); - if (objectInput instanceof Cleanable) { - ((Cleanable) objectInput).cleanup(); - } - return object; - } - - protected void encodeData(Channel channel, ObjectOutput output, Object message) throws IOException { - encodeData(output, message); - } - - protected Object decodeData(Channel channel, ObjectInput input) throws IOException { - return decodeData(input); - } - - protected void encodeData(ObjectOutput output, Object message) throws IOException { - output.writeObject(message); - } - - protected Object decodeData(ObjectInput input) throws IOException { - try { - return input.readObject(); - } catch (ClassNotFoundException e) { - throw new IOException("ClassNotFoundException: " + StringUtils.toString(e)); - } - } -} +/* + * 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.remoting.transport.codec; + +import org.apache.dubbo.common.serialize.Cleanable; +import org.apache.dubbo.common.serialize.ObjectInput; +import org.apache.dubbo.common.serialize.ObjectOutput; +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.remoting.Channel; +import org.apache.dubbo.remoting.buffer.ChannelBuffer; +import org.apache.dubbo.remoting.buffer.ChannelBufferInputStream; +import org.apache.dubbo.remoting.buffer.ChannelBufferOutputStream; +import org.apache.dubbo.remoting.transport.AbstractCodec; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * Subclasses {@link org.apache.dubbo.remoting.telnet.codec.TelnetCodec} and {@link org.apache.dubbo.remoting.exchange.codec.ExchangeCodec} + * both override all the methods declared in this class. + */ +@Deprecated +public class TransportCodec extends AbstractCodec { + + @Override + public void encode(Channel channel, ChannelBuffer buffer, Object message) throws IOException { + OutputStream output = new ChannelBufferOutputStream(buffer); + ObjectOutput objectOutput = getSerialization(channel).serialize(channel.getUrl(), output); + encodeData(channel, objectOutput, message); + objectOutput.flushBuffer(); + if (objectOutput instanceof Cleanable) { + ((Cleanable) objectOutput).cleanup(); + } + } + + @Override + public Object decode(Channel channel, ChannelBuffer buffer) throws IOException { + InputStream input = new ChannelBufferInputStream(buffer); + ObjectInput objectInput = getSerialization(channel).deserialize(channel.getUrl(), input); + Object object = decodeData(channel, objectInput); + if (objectInput instanceof Cleanable) { + ((Cleanable) objectInput).cleanup(); + } + return object; + } + + protected void encodeData(Channel channel, ObjectOutput output, Object message) throws IOException { + encodeData(output, message); + } + + protected Object decodeData(Channel channel, ObjectInput input) throws IOException { + return decodeData(input); + } + + protected void encodeData(ObjectOutput output, Object message) throws IOException { + output.writeObject(message); + } + + protected Object decodeData(ObjectInput input) throws IOException { + try { + return input.readObject(); + } catch (ClassNotFoundException e) { + throw new IOException("ClassNotFoundException: " + StringUtils.toString(e)); + } + } +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/dispatcher/ChannelEventRunnable.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/dispatcher/ChannelEventRunnable.java index 315170429f..ffd6f2a381 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/dispatcher/ChannelEventRunnable.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/dispatcher/ChannelEventRunnable.java @@ -1,134 +1,134 @@ -/* - * 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.remoting.transport.dispatcher; - -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.remoting.Channel; -import org.apache.dubbo.remoting.ChannelHandler; - -public class ChannelEventRunnable implements Runnable { - private static final Logger logger = LoggerFactory.getLogger(ChannelEventRunnable.class); - - private final ChannelHandler handler; - private final Channel channel; - private final ChannelState state; - private final Throwable exception; - private final Object message; - - public ChannelEventRunnable(Channel channel, ChannelHandler handler, ChannelState state) { - this(channel, handler, state, null); - } - - public ChannelEventRunnable(Channel channel, ChannelHandler handler, ChannelState state, Object message) { - this(channel, handler, state, message, null); - } - - public ChannelEventRunnable(Channel channel, ChannelHandler handler, ChannelState state, Throwable t) { - this(channel, handler, state, null, t); - } - - public ChannelEventRunnable(Channel channel, ChannelHandler handler, ChannelState state, Object message, Throwable exception) { - this.channel = channel; - this.handler = handler; - this.state = state; - this.message = message; - this.exception = exception; - } - - @Override - public void run() { - if (state == ChannelState.RECEIVED) { - try { - handler.received(channel, message); - } catch (Exception e) { - logger.warn("ChannelEventRunnable handle " + state + " operation error, channel is " + channel - + ", message is " + message, e); - } - } else { - switch (state) { - case CONNECTED: - try { - handler.connected(channel); - } catch (Exception e) { - logger.warn("ChannelEventRunnable handle " + state + " operation error, channel is " + channel, e); - } - break; - case DISCONNECTED: - try { - handler.disconnected(channel); - } catch (Exception e) { - logger.warn("ChannelEventRunnable handle " + state + " operation error, channel is " + channel, e); - } - break; - case SENT: - try { - handler.sent(channel, message); - } catch (Exception e) { - logger.warn("ChannelEventRunnable handle " + state + " operation error, channel is " + channel - + ", message is " + message, e); - } - break; - case CAUGHT: - try { - handler.caught(channel, exception); - } catch (Exception e) { - logger.warn("ChannelEventRunnable handle " + state + " operation error, channel is " + channel - + ", message is: " + message + ", exception is " + exception, e); - } - break; - default: - logger.warn("unknown state: " + state + ", message is " + message); - } - } - - } - - /** - * ChannelState - * - * - */ - public enum ChannelState { - - /** - * CONNECTED - */ - CONNECTED, - - /** - * DISCONNECTED - */ - DISCONNECTED, - - /** - * SENT - */ - SENT, - - /** - * RECEIVED - */ - RECEIVED, - - /** - * CAUGHT - */ - CAUGHT - } - -} +/* + * 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.remoting.transport.dispatcher; + +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.remoting.Channel; +import org.apache.dubbo.remoting.ChannelHandler; + +public class ChannelEventRunnable implements Runnable { + private static final Logger logger = LoggerFactory.getLogger(ChannelEventRunnable.class); + + private final ChannelHandler handler; + private final Channel channel; + private final ChannelState state; + private final Throwable exception; + private final Object message; + + public ChannelEventRunnable(Channel channel, ChannelHandler handler, ChannelState state) { + this(channel, handler, state, null); + } + + public ChannelEventRunnable(Channel channel, ChannelHandler handler, ChannelState state, Object message) { + this(channel, handler, state, message, null); + } + + public ChannelEventRunnable(Channel channel, ChannelHandler handler, ChannelState state, Throwable t) { + this(channel, handler, state, null, t); + } + + public ChannelEventRunnable(Channel channel, ChannelHandler handler, ChannelState state, Object message, Throwable exception) { + this.channel = channel; + this.handler = handler; + this.state = state; + this.message = message; + this.exception = exception; + } + + @Override + public void run() { + if (state == ChannelState.RECEIVED) { + try { + handler.received(channel, message); + } catch (Exception e) { + logger.warn("ChannelEventRunnable handle " + state + " operation error, channel is " + channel + + ", message is " + message, e); + } + } else { + switch (state) { + case CONNECTED: + try { + handler.connected(channel); + } catch (Exception e) { + logger.warn("ChannelEventRunnable handle " + state + " operation error, channel is " + channel, e); + } + break; + case DISCONNECTED: + try { + handler.disconnected(channel); + } catch (Exception e) { + logger.warn("ChannelEventRunnable handle " + state + " operation error, channel is " + channel, e); + } + break; + case SENT: + try { + handler.sent(channel, message); + } catch (Exception e) { + logger.warn("ChannelEventRunnable handle " + state + " operation error, channel is " + channel + + ", message is " + message, e); + } + break; + case CAUGHT: + try { + handler.caught(channel, exception); + } catch (Exception e) { + logger.warn("ChannelEventRunnable handle " + state + " operation error, channel is " + channel + + ", message is: " + message + ", exception is " + exception, e); + } + break; + default: + logger.warn("unknown state: " + state + ", message is " + message); + } + } + + } + + /** + * ChannelState + * + * + */ + public enum ChannelState { + + /** + * CONNECTED + */ + CONNECTED, + + /** + * DISCONNECTED + */ + DISCONNECTED, + + /** + * SENT + */ + SENT, + + /** + * RECEIVED + */ + RECEIVED, + + /** + * CAUGHT + */ + CAUGHT + } + +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/dispatcher/all/AllChannelHandler.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/dispatcher/all/AllChannelHandler.java index 25158d0d21..422e8ec4ff 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/dispatcher/all/AllChannelHandler.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/dispatcher/all/AllChannelHandler.java @@ -61,10 +61,10 @@ public class AllChannelHandler extends WrappedChannelHandler { try { executor.execute(new ChannelEventRunnable(channel, handler, ChannelState.RECEIVED, message)); } catch (Throwable t) { - if(message instanceof Request && t instanceof RejectedExecutionException){ + if(message instanceof Request && t instanceof RejectedExecutionException){ sendFeedback(channel, (Request) message, t); return; - } + } throw new ExecutionException(message, channel, getClass() + " error when process received event .", t); } } diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.Dispatcher b/dubbo-remoting/dubbo-remoting-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.Dispatcher index 052fb2bfd9..ed36096a96 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.Dispatcher +++ b/dubbo-remoting/dubbo-remoting-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.Dispatcher @@ -1,5 +1,5 @@ -all=org.apache.dubbo.remoting.transport.dispatcher.all.AllDispatcher -direct=org.apache.dubbo.remoting.transport.dispatcher.direct.DirectDispatcher -message=org.apache.dubbo.remoting.transport.dispatcher.message.MessageOnlyDispatcher -execution=org.apache.dubbo.remoting.transport.dispatcher.execution.ExecutionDispatcher +all=org.apache.dubbo.remoting.transport.dispatcher.all.AllDispatcher +direct=org.apache.dubbo.remoting.transport.dispatcher.direct.DirectDispatcher +message=org.apache.dubbo.remoting.transport.dispatcher.message.MessageOnlyDispatcher +execution=org.apache.dubbo.remoting.transport.dispatcher.execution.ExecutionDispatcher connection=org.apache.dubbo.remoting.transport.dispatcher.connection.ConnectionOrderedDispatcher \ No newline at end of file diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.telnet.TelnetHandler b/dubbo-remoting/dubbo-remoting-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.telnet.TelnetHandler index 5a04f8040e..48b65ae3ae 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.telnet.TelnetHandler +++ b/dubbo-remoting/dubbo-remoting-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.telnet.TelnetHandler @@ -1,5 +1,5 @@ -clear=org.apache.dubbo.remoting.telnet.support.command.ClearTelnetHandler -exit=org.apache.dubbo.remoting.telnet.support.command.ExitTelnetHandler -help=org.apache.dubbo.remoting.telnet.support.command.HelpTelnetHandler -status=org.apache.dubbo.remoting.telnet.support.command.StatusTelnetHandler +clear=org.apache.dubbo.remoting.telnet.support.command.ClearTelnetHandler +exit=org.apache.dubbo.remoting.telnet.support.command.ExitTelnetHandler +help=org.apache.dubbo.remoting.telnet.support.command.HelpTelnetHandler +status=org.apache.dubbo.remoting.telnet.support.command.StatusTelnetHandler log=org.apache.dubbo.remoting.telnet.support.command.LogTelnetHandler \ No newline at end of file diff --git a/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/PerformanceClientCloseTest.java b/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/PerformanceClientCloseTest.java index 0d153fac0c..e7f53f6fe1 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/PerformanceClientCloseTest.java +++ b/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/PerformanceClientCloseTest.java @@ -1,105 +1,105 @@ -/* - * 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.remoting; - -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.remoting.exchange.ExchangeClient; -import org.apache.dubbo.remoting.exchange.Exchangers; - -import org.junit.jupiter.api.Test; - -import java.util.concurrent.atomic.AtomicInteger; - -import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_TIMEOUT; -import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY; - -/** - * ProformanceClient - * The test class will report abnormal thread pool, because the judgment on the thread pool concurrency problems produced in DefaultChannelHandler (connected event has been executed asynchronously, judgment, then closed the thread pool, thread pool and execution error, this problem can be specified through the Constants.CHANNEL_HANDLER_KEY=connection.) - */ -public class PerformanceClientCloseTest { - - private static final Logger logger = LoggerFactory.getLogger(PerformanceClientCloseTest.class); - - @Test - public void testClient() throws Throwable { - // read server info from property - if (PerformanceUtils.getProperty("server", null) == null) { - logger.warn("Please set -Dserver=127.0.0.1:9911"); - return; - } - final String server = System.getProperty("server", "127.0.0.1:9911"); - final String transporter = PerformanceUtils.getProperty(Constants.TRANSPORTER_KEY, Constants.DEFAULT_TRANSPORTER); - final String serialization = PerformanceUtils.getProperty(Constants.SERIALIZATION_KEY, Constants.DEFAULT_REMOTING_SERIALIZATION); - final int timeout = PerformanceUtils.getIntProperty(TIMEOUT_KEY, DEFAULT_TIMEOUT); - final int concurrent = PerformanceUtils.getIntProperty("concurrent", 1); - final int runs = PerformanceUtils.getIntProperty("runs", Integer.MAX_VALUE); - final String onerror = PerformanceUtils.getProperty("onerror", "continue"); - - final String url = "exchange://" + server + "?transporter=" + transporter - + "&serialization=" + serialization -// + "&"+Constants.CHANNEL_HANDLER_KEY+"=connection" - + "&timeout=" + timeout; - - final AtomicInteger count = new AtomicInteger(); - final AtomicInteger error = new AtomicInteger(); - for (int n = 0; n < concurrent; n++) { - new Thread(new Runnable() { - public void run() { - for (int i = 0; i < runs; i++) { - ExchangeClient client = null; - try { - client = Exchangers.connect(url); - int c = count.incrementAndGet(); - if (c % 100 == 0) { - System.out.println("count: " + count.get() + ", error: " + error.get()); - } - } catch (Exception e) { - error.incrementAndGet(); - e.printStackTrace(); - System.out.println("count: " + count.get() + ", error: " + error.get()); - if ("exit".equals(onerror)) { - System.exit(-1); - } else if ("break".equals(onerror)) { - break; - } else if ("sleep".equals(onerror)) { - try { - Thread.sleep(30000); - } catch (InterruptedException e1) { - } - } - } finally { - if (client != null) { - client.close(); - } - } - } - } - }).start(); - } - synchronized (PerformanceServerTest.class) { - while (true) { - try { - PerformanceServerTest.class.wait(); - } catch (InterruptedException e) { - } - } - } - } - -} +/* + * 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.remoting; + +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.remoting.exchange.ExchangeClient; +import org.apache.dubbo.remoting.exchange.Exchangers; + +import org.junit.jupiter.api.Test; + +import java.util.concurrent.atomic.AtomicInteger; + +import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_TIMEOUT; +import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY; + +/** + * ProformanceClient + * The test class will report abnormal thread pool, because the judgment on the thread pool concurrency problems produced in DefaultChannelHandler (connected event has been executed asynchronously, judgment, then closed the thread pool, thread pool and execution error, this problem can be specified through the Constants.CHANNEL_HANDLER_KEY=connection.) + */ +public class PerformanceClientCloseTest { + + private static final Logger logger = LoggerFactory.getLogger(PerformanceClientCloseTest.class); + + @Test + public void testClient() throws Throwable { + // read server info from property + if (PerformanceUtils.getProperty("server", null) == null) { + logger.warn("Please set -Dserver=127.0.0.1:9911"); + return; + } + final String server = System.getProperty("server", "127.0.0.1:9911"); + final String transporter = PerformanceUtils.getProperty(Constants.TRANSPORTER_KEY, Constants.DEFAULT_TRANSPORTER); + final String serialization = PerformanceUtils.getProperty(Constants.SERIALIZATION_KEY, Constants.DEFAULT_REMOTING_SERIALIZATION); + final int timeout = PerformanceUtils.getIntProperty(TIMEOUT_KEY, DEFAULT_TIMEOUT); + final int concurrent = PerformanceUtils.getIntProperty("concurrent", 1); + final int runs = PerformanceUtils.getIntProperty("runs", Integer.MAX_VALUE); + final String onerror = PerformanceUtils.getProperty("onerror", "continue"); + + final String url = "exchange://" + server + "?transporter=" + transporter + + "&serialization=" + serialization +// + "&"+Constants.CHANNEL_HANDLER_KEY+"=connection" + + "&timeout=" + timeout; + + final AtomicInteger count = new AtomicInteger(); + final AtomicInteger error = new AtomicInteger(); + for (int n = 0; n < concurrent; n++) { + new Thread(new Runnable() { + public void run() { + for (int i = 0; i < runs; i++) { + ExchangeClient client = null; + try { + client = Exchangers.connect(url); + int c = count.incrementAndGet(); + if (c % 100 == 0) { + System.out.println("count: " + count.get() + ", error: " + error.get()); + } + } catch (Exception e) { + error.incrementAndGet(); + e.printStackTrace(); + System.out.println("count: " + count.get() + ", error: " + error.get()); + if ("exit".equals(onerror)) { + System.exit(-1); + } else if ("break".equals(onerror)) { + break; + } else if ("sleep".equals(onerror)) { + try { + Thread.sleep(30000); + } catch (InterruptedException e1) { + } + } + } finally { + if (client != null) { + client.close(); + } + } + } + } + }).start(); + } + synchronized (PerformanceServerTest.class) { + while (true) { + try { + PerformanceServerTest.class.wait(); + } catch (InterruptedException e) { + } + } + } + } + +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/PerformanceClientFixedTest.java b/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/PerformanceClientFixedTest.java index 8380f5a675..0b1a04eeff 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/PerformanceClientFixedTest.java +++ b/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/PerformanceClientFixedTest.java @@ -1,138 +1,138 @@ -/* - * 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.remoting; - -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.remoting.exchange.ExchangeClient; -import org.apache.dubbo.remoting.exchange.Exchangers; - -import org.junit.jupiter.api.Test; - -import java.util.ArrayList; -import java.util.Random; - -import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_TIMEOUT; -import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY; -import static org.apache.dubbo.remoting.Constants.CONNECTIONS_KEY; - -public class PerformanceClientFixedTest { - - private static final Logger logger = LoggerFactory.getLogger(PerformanceClientTest.class); - - @Test - public void testClient() throws Exception { - // read the parameters - if (PerformanceUtils.getProperty("server", null) == null) { - logger.warn("Please set -Dserver=127.0.0.1:9911"); - return; - } - final String server = System.getProperty("server", "127.0.0.1:9911"); - final String transporter = PerformanceUtils.getProperty(Constants.TRANSPORTER_KEY, Constants.DEFAULT_TRANSPORTER); - final String serialization = PerformanceUtils.getProperty(Constants.SERIALIZATION_KEY, Constants.DEFAULT_REMOTING_SERIALIZATION); - final int timeout = PerformanceUtils.getIntProperty(TIMEOUT_KEY, DEFAULT_TIMEOUT); - //final int length = PerformanceUtils.getIntProperty("length", 1024); - final int connectionCount = PerformanceUtils.getIntProperty(CONNECTIONS_KEY, 1); - //final int concurrent = PerformanceUtils.getIntProperty("concurrent", 100); - //int r = PerformanceUtils.getIntProperty("runs", 10000); - //final int runs = r > 0 ? r : Integer.MAX_VALUE; - //final String onerror = PerformanceUtils.getProperty("onerror", "continue"); - final String url = "exchange://" + server + "?transporter=" + transporter + "&serialization=" + serialization + "&timeout=" + timeout; - - //int idx = server.indexOf(':'); - Random rd = new Random(connectionCount); - ArrayList arrays = new ArrayList(); - String oneKBlock = null; - String messageBlock = null; - int s = 0; - int f = 0; - System.out.println("initialize arrays " + url); - while (s < connectionCount) { - ExchangeClient client = null; - try { - System.out.println("open connection " + s + " " + url + arrays.size()); - - client = Exchangers.connect(url); - - System.out.println("run after open"); - - if (client.isConnected()) { - arrays.add(client); - s++; - System.out.println("open client success " + s); - } else { - System.out.println("open client failed, try again."); - } - } catch (Throwable t) { - t.printStackTrace(); - } finally { - if (client != null && !client.isConnected()) { - f++; - System.out.println("open client failed, try again " + f); - client.close(); - } - } - } - - StringBuilder sb1 = new StringBuilder(); - Random rd2 = new Random(); - char[] numbersAndLetters = ("0123456789abcdefghijklmnopqrstuvwxyz" + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ").toCharArray(); - int size1 = numbersAndLetters.length; - for (int j = 0; j < 1024; j++) { - sb1.append(numbersAndLetters[rd2.nextInt(size1)]); - } - oneKBlock = sb1.toString(); - - for (int j = 0; j < Integer.MAX_VALUE; j++) { - try { - String size = "10"; - - int request_size = 10; - try { - request_size = Integer.parseInt(size); - } catch (Throwable t) { - request_size = 10; - } - - if (messageBlock == null) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < request_size; i++) { - sb.append(oneKBlock); - } - messageBlock = sb.toString(); - - System.out.println("set messageBlock to " + messageBlock); - } - int index = rd.nextInt(connectionCount); - ExchangeClient client = arrays.get(index); - // ExchangeClient client = arrays.get(0); - String output = (String) client.request(messageBlock).get(); - - if (output.lastIndexOf(messageBlock) < 0) { - System.out.println("send messageBlock;get " + output); - throw new Throwable("return results invalid"); - } else { - if (j % 100 == 0) - System.out.println("OK: " + j); - } - } catch (Throwable t) { - t.printStackTrace(); - } - } - } - -} +/* + * 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.remoting; + +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.remoting.exchange.ExchangeClient; +import org.apache.dubbo.remoting.exchange.Exchangers; + +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.Random; + +import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_TIMEOUT; +import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY; +import static org.apache.dubbo.remoting.Constants.CONNECTIONS_KEY; + +public class PerformanceClientFixedTest { + + private static final Logger logger = LoggerFactory.getLogger(PerformanceClientTest.class); + + @Test + public void testClient() throws Exception { + // read the parameters + if (PerformanceUtils.getProperty("server", null) == null) { + logger.warn("Please set -Dserver=127.0.0.1:9911"); + return; + } + final String server = System.getProperty("server", "127.0.0.1:9911"); + final String transporter = PerformanceUtils.getProperty(Constants.TRANSPORTER_KEY, Constants.DEFAULT_TRANSPORTER); + final String serialization = PerformanceUtils.getProperty(Constants.SERIALIZATION_KEY, Constants.DEFAULT_REMOTING_SERIALIZATION); + final int timeout = PerformanceUtils.getIntProperty(TIMEOUT_KEY, DEFAULT_TIMEOUT); + //final int length = PerformanceUtils.getIntProperty("length", 1024); + final int connectionCount = PerformanceUtils.getIntProperty(CONNECTIONS_KEY, 1); + //final int concurrent = PerformanceUtils.getIntProperty("concurrent", 100); + //int r = PerformanceUtils.getIntProperty("runs", 10000); + //final int runs = r > 0 ? r : Integer.MAX_VALUE; + //final String onerror = PerformanceUtils.getProperty("onerror", "continue"); + final String url = "exchange://" + server + "?transporter=" + transporter + "&serialization=" + serialization + "&timeout=" + timeout; + + //int idx = server.indexOf(':'); + Random rd = new Random(connectionCount); + ArrayList arrays = new ArrayList(); + String oneKBlock = null; + String messageBlock = null; + int s = 0; + int f = 0; + System.out.println("initialize arrays " + url); + while (s < connectionCount) { + ExchangeClient client = null; + try { + System.out.println("open connection " + s + " " + url + arrays.size()); + + client = Exchangers.connect(url); + + System.out.println("run after open"); + + if (client.isConnected()) { + arrays.add(client); + s++; + System.out.println("open client success " + s); + } else { + System.out.println("open client failed, try again."); + } + } catch (Throwable t) { + t.printStackTrace(); + } finally { + if (client != null && !client.isConnected()) { + f++; + System.out.println("open client failed, try again " + f); + client.close(); + } + } + } + + StringBuilder sb1 = new StringBuilder(); + Random rd2 = new Random(); + char[] numbersAndLetters = ("0123456789abcdefghijklmnopqrstuvwxyz" + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ").toCharArray(); + int size1 = numbersAndLetters.length; + for (int j = 0; j < 1024; j++) { + sb1.append(numbersAndLetters[rd2.nextInt(size1)]); + } + oneKBlock = sb1.toString(); + + for (int j = 0; j < Integer.MAX_VALUE; j++) { + try { + String size = "10"; + + int request_size = 10; + try { + request_size = Integer.parseInt(size); + } catch (Throwable t) { + request_size = 10; + } + + if (messageBlock == null) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < request_size; i++) { + sb.append(oneKBlock); + } + messageBlock = sb.toString(); + + System.out.println("set messageBlock to " + messageBlock); + } + int index = rd.nextInt(connectionCount); + ExchangeClient client = arrays.get(index); + // ExchangeClient client = arrays.get(0); + String output = (String) client.request(messageBlock).get(); + + if (output.lastIndexOf(messageBlock) < 0) { + System.out.println("send messageBlock;get " + output); + throw new Throwable("return results invalid"); + } else { + if (j % 100 == 0) + System.out.println("OK: " + j); + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + } + +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/PerformanceClientMain.java b/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/PerformanceClientMain.java index d2fda965a0..0628f7fb24 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/PerformanceClientMain.java +++ b/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/PerformanceClientMain.java @@ -1,29 +1,29 @@ -/* - * 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.remoting; - - -/** - * PerformanceClientMain - */ -public class PerformanceClientMain { - - public static void main(String[] args) throws Throwable { - new PerformanceClientTest().testClient(); - } - -} \ No newline at end of file +/* + * 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.remoting; + + +/** + * PerformanceClientMain + */ +public class PerformanceClientMain { + + public static void main(String[] args) throws Throwable { + new PerformanceClientTest().testClient(); + } + +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/PerformanceClientTest.java b/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/PerformanceClientTest.java index f4dfbc2a3e..f9623cc8ac 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/PerformanceClientTest.java +++ b/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/PerformanceClientTest.java @@ -1,230 +1,230 @@ -/* - * 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.remoting; - -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.remoting.exchange.ExchangeClient; -import org.apache.dubbo.remoting.exchange.Exchangers; -import org.apache.dubbo.remoting.exchange.support.ExchangeHandlerAdapter; - -import org.junit.jupiter.api.Test; - -import java.text.DecimalFormat; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; - -import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_TIMEOUT; -import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY; -import static org.apache.dubbo.remoting.Constants.CONNECTIONS_KEY; - -/** - * PerformanceClientTest - *

- * mvn clean test -Dtest=*PerformanceClientTest -Dserver=10.20.153.187:9911 - */ -public class PerformanceClientTest { - - private static final Logger logger = LoggerFactory.getLogger(PerformanceClientTest.class); - - @Test - @SuppressWarnings("unchecked") - public void testClient() throws Throwable { - // read server info from property - if (PerformanceUtils.getProperty("server", null) == null) { - logger.warn("Please set -Dserver=127.0.0.1:9911"); - return; - } - final String server = System.getProperty("server", "127.0.0.1:9911"); - final String transporter = PerformanceUtils.getProperty(Constants.TRANSPORTER_KEY, Constants.DEFAULT_TRANSPORTER); - final String serialization = PerformanceUtils.getProperty(Constants.SERIALIZATION_KEY, Constants.DEFAULT_REMOTING_SERIALIZATION); - final int timeout = PerformanceUtils.getIntProperty(TIMEOUT_KEY, DEFAULT_TIMEOUT); - final int length = PerformanceUtils.getIntProperty("length", 1024); - final int connections = PerformanceUtils.getIntProperty(CONNECTIONS_KEY, 1); - final int concurrent = PerformanceUtils.getIntProperty("concurrent", 100); - int r = PerformanceUtils.getIntProperty("runs", 10000); - final int runs = r > 0 ? r : Integer.MAX_VALUE; - final String onerror = PerformanceUtils.getProperty("onerror", "continue"); - - final String url = "exchange://" + server + "?transporter=" + transporter + "&serialization=" + serialization + "&timeout=" + timeout; - // Create clients and build connections - final ExchangeClient[] exchangeClients = new ExchangeClient[connections]; - for (int i = 0; i < connections; i++) { - //exchangeClients[i] = Exchangers.connect(url,handler); - exchangeClients[i] = Exchangers.connect(url); - } - - List serverEnvironment = (List) exchangeClients[0].request("environment").get(); - List serverScene = (List) exchangeClients[0].request("scene").get(); - - // Create some data for test - StringBuilder buf = new StringBuilder(length); - for (int i = 0; i < length; i++) { - buf.append("A"); - } - final String data = buf.toString(); - - // counters - final AtomicLong count = new AtomicLong(); - final AtomicLong error = new AtomicLong(); - final AtomicLong time = new AtomicLong(); - final AtomicLong all = new AtomicLong(); - - // Start multiple threads - final CountDownLatch latch = new CountDownLatch(concurrent); - for (int i = 0; i < concurrent; i++) { - new Thread(new Runnable() { - public void run() { - try { - AtomicInteger index = new AtomicInteger(); - long init = System.currentTimeMillis(); - for (int i = 0; i < runs; i++) { - try { - count.incrementAndGet(); - ExchangeClient client = exchangeClients[index.getAndIncrement() % connections]; - long start = System.currentTimeMillis(); - String result = (String) client.request(data).get(); - long end = System.currentTimeMillis(); - if (!data.equals(result)) { - throw new IllegalStateException("Invalid result " + result); - } - time.addAndGet(end - start); - } catch (Exception e) { - error.incrementAndGet(); - e.printStackTrace(); - if ("exit".equals(onerror)) { - System.exit(-1); - } else if ("break".equals(onerror)) { - break; - } else if ("sleep".equals(onerror)) { - try { - Thread.sleep(30000); - } catch (InterruptedException e1) { - } - } - } - } - all.addAndGet(System.currentTimeMillis() - init); - } finally { - latch.countDown(); - } - } - }).start(); - } - - // Output, tps is not for accuracy, but it reflects the situation to a certain extent. - new Thread(new Runnable() { - public void run() { - try { - SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); - long lastCount = count.get(); - long sleepTime = 2000; - long elapsd = sleepTime / 1000; - boolean bfirst = true; - while (latch.getCount() > 0) { - long c = count.get() - lastCount; - if (!bfirst)// The first time is inaccurate. - System.out.println("[" + dateFormat.format(new Date()) + "] count: " + count.get() + ", error: " + error.get() + ",tps:" + (c / elapsd)); - - bfirst = false; - lastCount = count.get(); - Thread.sleep(sleepTime); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - }).start(); - - latch.await(); - - for (ExchangeClient client : exchangeClients) { - if (client.isConnected()) { - client.close(); - } - } - - long total = count.get(); - long failed = error.get(); - long succeeded = total - failed; - long elapsed = time.get(); - long allElapsed = all.get(); - long clientElapsed = allElapsed - elapsed; - long art = 0; - long qps = 0; - long throughput = 0; - if (elapsed > 0) { - art = elapsed / succeeded; - qps = concurrent * succeeded * 1000 / elapsed; - throughput = concurrent * succeeded * length * 2 * 1000 / elapsed; - } - - PerformanceUtils.printBorder(); - PerformanceUtils.printHeader("Dubbo Remoting Performance Test Report"); - PerformanceUtils.printBorder(); - PerformanceUtils.printHeader("Test Environment"); - PerformanceUtils.printSeparator(); - for (String item : serverEnvironment) { - PerformanceUtils.printBody("Server " + item); - } - PerformanceUtils.printSeparator(); - List clientEnvironment = PerformanceUtils.getEnvironment(); - for (String item : clientEnvironment) { - PerformanceUtils.printBody("Client " + item); - } - PerformanceUtils.printSeparator(); - PerformanceUtils.printHeader("Test Scene"); - PerformanceUtils.printSeparator(); - for (String item : serverScene) { - PerformanceUtils.printBody("Server " + item); - } - PerformanceUtils.printBody("Client Transporter: " + transporter); - PerformanceUtils.printBody("Serialization: " + serialization); - PerformanceUtils.printBody("Response Timeout: " + timeout + " ms"); - PerformanceUtils.printBody("Data Length: " + length + " bytes"); - PerformanceUtils.printBody("Client Shared Connections: " + connections); - PerformanceUtils.printBody("Client Concurrent Threads: " + concurrent); - PerformanceUtils.printBody("Run Times Per Thread: " + runs); - PerformanceUtils.printSeparator(); - PerformanceUtils.printHeader("Test Result"); - PerformanceUtils.printSeparator(); - PerformanceUtils.printBody("Succeeded Requests: " + DecimalFormat.getIntegerInstance().format(succeeded)); - PerformanceUtils.printBody("Failed Requests: " + failed); - PerformanceUtils.printBody("Client Elapsed Time: " + clientElapsed + " ms"); - PerformanceUtils.printBody("Average Response Time: " + art + " ms"); - PerformanceUtils.printBody("Requests Per Second: " + qps + "/s"); - PerformanceUtils.printBody("Throughput Per Second: " + DecimalFormat.getIntegerInstance().format(throughput) + " bytes/s"); - PerformanceUtils.printBorder(); - } - - static class PeformanceTestHandler extends ExchangeHandlerAdapter { - - @Override - public void connected(Channel channel) throws RemotingException { - System.out.println("connected event,chanel;" + channel); - } - - @Override - public void disconnected(Channel channel) throws RemotingException { - System.out.println("disconnected event,chanel;" + channel); - } - } -} +/* + * 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.remoting; + +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.remoting.exchange.ExchangeClient; +import org.apache.dubbo.remoting.exchange.Exchangers; +import org.apache.dubbo.remoting.exchange.support.ExchangeHandlerAdapter; + +import org.junit.jupiter.api.Test; + +import java.text.DecimalFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; + +import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_TIMEOUT; +import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY; +import static org.apache.dubbo.remoting.Constants.CONNECTIONS_KEY; + +/** + * PerformanceClientTest + *

+ * mvn clean test -Dtest=*PerformanceClientTest -Dserver=10.20.153.187:9911 + */ +public class PerformanceClientTest { + + private static final Logger logger = LoggerFactory.getLogger(PerformanceClientTest.class); + + @Test + @SuppressWarnings("unchecked") + public void testClient() throws Throwable { + // read server info from property + if (PerformanceUtils.getProperty("server", null) == null) { + logger.warn("Please set -Dserver=127.0.0.1:9911"); + return; + } + final String server = System.getProperty("server", "127.0.0.1:9911"); + final String transporter = PerformanceUtils.getProperty(Constants.TRANSPORTER_KEY, Constants.DEFAULT_TRANSPORTER); + final String serialization = PerformanceUtils.getProperty(Constants.SERIALIZATION_KEY, Constants.DEFAULT_REMOTING_SERIALIZATION); + final int timeout = PerformanceUtils.getIntProperty(TIMEOUT_KEY, DEFAULT_TIMEOUT); + final int length = PerformanceUtils.getIntProperty("length", 1024); + final int connections = PerformanceUtils.getIntProperty(CONNECTIONS_KEY, 1); + final int concurrent = PerformanceUtils.getIntProperty("concurrent", 100); + int r = PerformanceUtils.getIntProperty("runs", 10000); + final int runs = r > 0 ? r : Integer.MAX_VALUE; + final String onerror = PerformanceUtils.getProperty("onerror", "continue"); + + final String url = "exchange://" + server + "?transporter=" + transporter + "&serialization=" + serialization + "&timeout=" + timeout; + // Create clients and build connections + final ExchangeClient[] exchangeClients = new ExchangeClient[connections]; + for (int i = 0; i < connections; i++) { + //exchangeClients[i] = Exchangers.connect(url,handler); + exchangeClients[i] = Exchangers.connect(url); + } + + List serverEnvironment = (List) exchangeClients[0].request("environment").get(); + List serverScene = (List) exchangeClients[0].request("scene").get(); + + // Create some data for test + StringBuilder buf = new StringBuilder(length); + for (int i = 0; i < length; i++) { + buf.append("A"); + } + final String data = buf.toString(); + + // counters + final AtomicLong count = new AtomicLong(); + final AtomicLong error = new AtomicLong(); + final AtomicLong time = new AtomicLong(); + final AtomicLong all = new AtomicLong(); + + // Start multiple threads + final CountDownLatch latch = new CountDownLatch(concurrent); + for (int i = 0; i < concurrent; i++) { + new Thread(new Runnable() { + public void run() { + try { + AtomicInteger index = new AtomicInteger(); + long init = System.currentTimeMillis(); + for (int i = 0; i < runs; i++) { + try { + count.incrementAndGet(); + ExchangeClient client = exchangeClients[index.getAndIncrement() % connections]; + long start = System.currentTimeMillis(); + String result = (String) client.request(data).get(); + long end = System.currentTimeMillis(); + if (!data.equals(result)) { + throw new IllegalStateException("Invalid result " + result); + } + time.addAndGet(end - start); + } catch (Exception e) { + error.incrementAndGet(); + e.printStackTrace(); + if ("exit".equals(onerror)) { + System.exit(-1); + } else if ("break".equals(onerror)) { + break; + } else if ("sleep".equals(onerror)) { + try { + Thread.sleep(30000); + } catch (InterruptedException e1) { + } + } + } + } + all.addAndGet(System.currentTimeMillis() - init); + } finally { + latch.countDown(); + } + } + }).start(); + } + + // Output, tps is not for accuracy, but it reflects the situation to a certain extent. + new Thread(new Runnable() { + public void run() { + try { + SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); + long lastCount = count.get(); + long sleepTime = 2000; + long elapsd = sleepTime / 1000; + boolean bfirst = true; + while (latch.getCount() > 0) { + long c = count.get() - lastCount; + if (!bfirst)// The first time is inaccurate. + System.out.println("[" + dateFormat.format(new Date()) + "] count: " + count.get() + ", error: " + error.get() + ",tps:" + (c / elapsd)); + + bfirst = false; + lastCount = count.get(); + Thread.sleep(sleepTime); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + }).start(); + + latch.await(); + + for (ExchangeClient client : exchangeClients) { + if (client.isConnected()) { + client.close(); + } + } + + long total = count.get(); + long failed = error.get(); + long succeeded = total - failed; + long elapsed = time.get(); + long allElapsed = all.get(); + long clientElapsed = allElapsed - elapsed; + long art = 0; + long qps = 0; + long throughput = 0; + if (elapsed > 0) { + art = elapsed / succeeded; + qps = concurrent * succeeded * 1000 / elapsed; + throughput = concurrent * succeeded * length * 2 * 1000 / elapsed; + } + + PerformanceUtils.printBorder(); + PerformanceUtils.printHeader("Dubbo Remoting Performance Test Report"); + PerformanceUtils.printBorder(); + PerformanceUtils.printHeader("Test Environment"); + PerformanceUtils.printSeparator(); + for (String item : serverEnvironment) { + PerformanceUtils.printBody("Server " + item); + } + PerformanceUtils.printSeparator(); + List clientEnvironment = PerformanceUtils.getEnvironment(); + for (String item : clientEnvironment) { + PerformanceUtils.printBody("Client " + item); + } + PerformanceUtils.printSeparator(); + PerformanceUtils.printHeader("Test Scene"); + PerformanceUtils.printSeparator(); + for (String item : serverScene) { + PerformanceUtils.printBody("Server " + item); + } + PerformanceUtils.printBody("Client Transporter: " + transporter); + PerformanceUtils.printBody("Serialization: " + serialization); + PerformanceUtils.printBody("Response Timeout: " + timeout + " ms"); + PerformanceUtils.printBody("Data Length: " + length + " bytes"); + PerformanceUtils.printBody("Client Shared Connections: " + connections); + PerformanceUtils.printBody("Client Concurrent Threads: " + concurrent); + PerformanceUtils.printBody("Run Times Per Thread: " + runs); + PerformanceUtils.printSeparator(); + PerformanceUtils.printHeader("Test Result"); + PerformanceUtils.printSeparator(); + PerformanceUtils.printBody("Succeeded Requests: " + DecimalFormat.getIntegerInstance().format(succeeded)); + PerformanceUtils.printBody("Failed Requests: " + failed); + PerformanceUtils.printBody("Client Elapsed Time: " + clientElapsed + " ms"); + PerformanceUtils.printBody("Average Response Time: " + art + " ms"); + PerformanceUtils.printBody("Requests Per Second: " + qps + "/s"); + PerformanceUtils.printBody("Throughput Per Second: " + DecimalFormat.getIntegerInstance().format(throughput) + " bytes/s"); + PerformanceUtils.printBorder(); + } + + static class PeformanceTestHandler extends ExchangeHandlerAdapter { + + @Override + public void connected(Channel channel) throws RemotingException { + System.out.println("connected event,chanel;" + channel); + } + + @Override + public void disconnected(Channel channel) throws RemotingException { + System.out.println("disconnected event,chanel;" + channel); + } + } +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/PerformanceServerMain.java b/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/PerformanceServerMain.java index 22b88af349..878221b75d 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/PerformanceServerMain.java +++ b/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/PerformanceServerMain.java @@ -1,28 +1,28 @@ -/* - * 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.remoting; - -/** - * PerformanceServerMain - */ -public class PerformanceServerMain { - - public static void main(String[] args) throws Exception { - new PerformanceServerTest().testServer(); - } - -} \ No newline at end of file +/* + * 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.remoting; + +/** + * PerformanceServerMain + */ +public class PerformanceServerMain { + + public static void main(String[] args) throws Exception { + new PerformanceServerTest().testServer(); + } + +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/PerformanceUtils.java b/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/PerformanceUtils.java index 1922be47e6..b3a56ddde1 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/PerformanceUtils.java +++ b/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/PerformanceUtils.java @@ -1,126 +1,126 @@ -/* - * 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.remoting; - -import java.net.NetworkInterface; -import java.net.SocketException; -import java.text.DecimalFormat; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.List; - -/** - * PerformanceUtils - */ -public class PerformanceUtils { - - private static final int WIDTH = 64; - - public static String getProperty(String key, String defaultValue) { - String value = System.getProperty(key); - if (value == null || value.trim().length() == 0 || value.startsWith("$")) { - return defaultValue; - } - return value.trim(); - } - - public static int getIntProperty(String key, int defaultValue) { - String value = System.getProperty(key); - if (value == null || value.trim().length() == 0 || value.startsWith("$")) { - return defaultValue; - } - return Integer.parseInt(value.trim()); - } - - public static boolean getBooleanProperty(String key, boolean defaultValue) { - String value = System.getProperty(key); - if (value == null || value.trim().length() == 0 || value.startsWith("$")) { - return defaultValue; - } - return Boolean.parseBoolean(value.trim()); - } - - public static List getEnvironment() { - List environment = new ArrayList(); - environment.add("OS: " + System.getProperty("os.name") + " " + System.getProperty("os.version") + " " + System.getProperty("os.arch", "")); - environment.add("CPU: " + Runtime.getRuntime().availableProcessors() + " cores"); - environment.add("JVM: " + System.getProperty("java.vm.name") + " " + System.getProperty("java.runtime.version")); - environment.add("Memory: " + DecimalFormat.getIntegerInstance().format(Runtime.getRuntime().totalMemory()) - + " bytes (Max: " + DecimalFormat.getIntegerInstance().format(Runtime.getRuntime().maxMemory()) + " bytes)"); - NetworkInterface ni = PerformanceUtils.getNetworkInterface(); - if (ni != null) { - environment.add("Network: " + ni.getDisplayName()); - } - return environment; - } - - public static void printSeparator() { - StringBuilder pad = new StringBuilder(); - for (int i = 0; i < WIDTH; i++) { - pad.append("-"); - } - System.out.println("+" + pad + "+"); - } - - public static void printBorder() { - StringBuilder pad = new StringBuilder(); - for (int i = 0; i < WIDTH; i++) { - pad.append("="); - } - System.out.println("+" + pad + "+"); - } - - public static void printBody(String msg) { - StringBuilder pad = new StringBuilder(); - int len = WIDTH - msg.length() - 1; - if (len > 0) { - for (int i = 0; i < len; i++) { - pad.append(" "); - } - } - System.out.println("| " + msg + pad + "|"); - } - - public static void printHeader(String msg) { - StringBuilder pad = new StringBuilder(); - int len = WIDTH - msg.length(); - if (len > 0) { - int half = len / 2; - for (int i = 0; i < half; i++) { - pad.append(" "); - } - } - System.out.println("|" + pad + msg + pad + ((len % 2 == 0) ? "" : " ") + "|"); - } - - public static NetworkInterface getNetworkInterface() { - try { - Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); - if (interfaces != null) { - while (interfaces.hasMoreElements()) { - try { - return interfaces.nextElement(); - } catch (Throwable e) { - } - } - } - } catch (SocketException e) { - } - return null; - } - -} \ No newline at end of file +/* + * 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.remoting; + +import java.net.NetworkInterface; +import java.net.SocketException; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; + +/** + * PerformanceUtils + */ +public class PerformanceUtils { + + private static final int WIDTH = 64; + + public static String getProperty(String key, String defaultValue) { + String value = System.getProperty(key); + if (value == null || value.trim().length() == 0 || value.startsWith("$")) { + return defaultValue; + } + return value.trim(); + } + + public static int getIntProperty(String key, int defaultValue) { + String value = System.getProperty(key); + if (value == null || value.trim().length() == 0 || value.startsWith("$")) { + return defaultValue; + } + return Integer.parseInt(value.trim()); + } + + public static boolean getBooleanProperty(String key, boolean defaultValue) { + String value = System.getProperty(key); + if (value == null || value.trim().length() == 0 || value.startsWith("$")) { + return defaultValue; + } + return Boolean.parseBoolean(value.trim()); + } + + public static List getEnvironment() { + List environment = new ArrayList(); + environment.add("OS: " + System.getProperty("os.name") + " " + System.getProperty("os.version") + " " + System.getProperty("os.arch", "")); + environment.add("CPU: " + Runtime.getRuntime().availableProcessors() + " cores"); + environment.add("JVM: " + System.getProperty("java.vm.name") + " " + System.getProperty("java.runtime.version")); + environment.add("Memory: " + DecimalFormat.getIntegerInstance().format(Runtime.getRuntime().totalMemory()) + + " bytes (Max: " + DecimalFormat.getIntegerInstance().format(Runtime.getRuntime().maxMemory()) + " bytes)"); + NetworkInterface ni = PerformanceUtils.getNetworkInterface(); + if (ni != null) { + environment.add("Network: " + ni.getDisplayName()); + } + return environment; + } + + public static void printSeparator() { + StringBuilder pad = new StringBuilder(); + for (int i = 0; i < WIDTH; i++) { + pad.append("-"); + } + System.out.println("+" + pad + "+"); + } + + public static void printBorder() { + StringBuilder pad = new StringBuilder(); + for (int i = 0; i < WIDTH; i++) { + pad.append("="); + } + System.out.println("+" + pad + "+"); + } + + public static void printBody(String msg) { + StringBuilder pad = new StringBuilder(); + int len = WIDTH - msg.length() - 1; + if (len > 0) { + for (int i = 0; i < len; i++) { + pad.append(" "); + } + } + System.out.println("| " + msg + pad + "|"); + } + + public static void printHeader(String msg) { + StringBuilder pad = new StringBuilder(); + int len = WIDTH - msg.length(); + if (len > 0) { + int half = len / 2; + for (int i = 0; i < half; i++) { + pad.append(" "); + } + } + System.out.println("|" + pad + msg + pad + ((len % 2 == 0) ? "" : " ") + "|"); + } + + public static NetworkInterface getNetworkInterface() { + try { + Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); + if (interfaces != null) { + while (interfaces.hasMoreElements()) { + try { + return interfaces.nextElement(); + } catch (Throwable e) { + } + } + } + } catch (SocketException e) { + } + return null; + } + +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/TelnetServer.java b/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/TelnetServer.java index 1364628a19..8a6aef4a33 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/TelnetServer.java +++ b/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/TelnetServer.java @@ -1,50 +1,50 @@ -/* - * 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.remoting; - -import org.apache.dubbo.remoting.transport.ChannelHandlerAdapter; - -/** - * TelnetServer - */ -public class TelnetServer { - - public static void main(String[] args) throws Exception { - Transporters.bind("telnet://0.0.0.0:23", new ChannelHandlerAdapter() { - @Override - public void connected(Channel channel) throws RemotingException { - channel.send("telnet> "); - } - - @Override - public void received(Channel channel, Object message) throws RemotingException { - channel.send("Echo: " + message + "\r\n"); - channel.send("telnet> "); - } - }); - // Prevent JVM from exiting - synchronized (TelnetServer.class) { - while (true) { - try { - TelnetServer.class.wait(); - } catch (InterruptedException e) { - } - } - } - } - -} +/* + * 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.remoting; + +import org.apache.dubbo.remoting.transport.ChannelHandlerAdapter; + +/** + * TelnetServer + */ +public class TelnetServer { + + public static void main(String[] args) throws Exception { + Transporters.bind("telnet://0.0.0.0:23", new ChannelHandlerAdapter() { + @Override + public void connected(Channel channel) throws RemotingException { + channel.send("telnet> "); + } + + @Override + public void received(Channel channel, Object message) throws RemotingException { + channel.send("Echo: " + message + "\r\n"); + channel.send("telnet> "); + } + }); + // Prevent JVM from exiting + synchronized (TelnetServer.class) { + while (true) { + try { + TelnetServer.class.wait(); + } catch (InterruptedException e) { + } + } + } + } + +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/api/ConnectionTest.java b/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/api/ConnectionTest.java index 507bb3b5f4..eb8aac92b8 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/api/ConnectionTest.java +++ b/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/api/ConnectionTest.java @@ -55,4 +55,4 @@ class ConnectionTest { latch.await(); Assertions.assertEquals(0, latch.getCount()); } -} \ No newline at end of file +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/handler/WrappedChannelHandlerTest.java b/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/handler/WrappedChannelHandlerTest.java index 5d8c78b82b..53bebb1711 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/handler/WrappedChannelHandlerTest.java +++ b/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/handler/WrappedChannelHandlerTest.java @@ -143,4 +143,4 @@ public class WrappedChannelHandlerTest { class BizException extends RuntimeException { private static final long serialVersionUID = -7541893754900723624L; } -} \ No newline at end of file +} diff --git a/dubbo-remoting/dubbo-remoting-api/src/test/resources/log4j.xml b/dubbo-remoting/dubbo-remoting-api/src/test/resources/log4j.xml index 927212a49b..16da2d9e1d 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/test/resources/log4j.xml +++ b/dubbo-remoting/dubbo-remoting-api/src/test/resources/log4j.xml @@ -1,29 +1,29 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + \ No newline at end of file diff --git a/dubbo-remoting/dubbo-remoting-http/src/main/java/org/apache/dubbo/remoting/http/HttpHandler.java b/dubbo-remoting/dubbo-remoting-http/src/main/java/org/apache/dubbo/remoting/http/HttpHandler.java index c8cd21781b..b05e065341 100644 --- a/dubbo-remoting/dubbo-remoting-http/src/main/java/org/apache/dubbo/remoting/http/HttpHandler.java +++ b/dubbo-remoting/dubbo-remoting-http/src/main/java/org/apache/dubbo/remoting/http/HttpHandler.java @@ -36,4 +36,4 @@ public interface HttpHandler { */ void handle(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException; -} \ No newline at end of file +} diff --git a/dubbo-remoting/dubbo-remoting-http/src/main/java/org/apache/dubbo/remoting/http/HttpServer.java b/dubbo-remoting/dubbo-remoting-http/src/main/java/org/apache/dubbo/remoting/http/HttpServer.java index 2cc6766af3..57d5399e10 100644 --- a/dubbo-remoting/dubbo-remoting-http/src/main/java/org/apache/dubbo/remoting/http/HttpServer.java +++ b/dubbo-remoting/dubbo-remoting-http/src/main/java/org/apache/dubbo/remoting/http/HttpServer.java @@ -69,4 +69,4 @@ public interface HttpServer extends Resetable, RemotingServer { */ boolean isClosed(); -} \ No newline at end of file +} diff --git a/dubbo-remoting/dubbo-remoting-netty/src/main/java/org/apache/dubbo/remoting/transport/netty/NettyClient.java b/dubbo-remoting/dubbo-remoting-netty/src/main/java/org/apache/dubbo/remoting/transport/netty/NettyClient.java index dc26ffd6c9..4a163ae925 100644 --- a/dubbo-remoting/dubbo-remoting-netty/src/main/java/org/apache/dubbo/remoting/transport/netty/NettyClient.java +++ b/dubbo-remoting/dubbo-remoting-netty/src/main/java/org/apache/dubbo/remoting/transport/netty/NettyClient.java @@ -1,170 +1,170 @@ -/* - * 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.remoting.transport.netty; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.Version; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.utils.NamedThreadFactory; -import org.apache.dubbo.common.utils.NetUtils; -import org.apache.dubbo.remoting.ChannelHandler; -import org.apache.dubbo.remoting.Constants; -import org.apache.dubbo.remoting.RemotingException; -import org.apache.dubbo.remoting.transport.AbstractClient; - -import org.jboss.netty.bootstrap.ClientBootstrap; -import org.jboss.netty.channel.Channel; -import org.jboss.netty.channel.ChannelFactory; -import org.jboss.netty.channel.ChannelFuture; -import org.jboss.netty.channel.ChannelPipeline; -import org.jboss.netty.channel.ChannelPipelineFactory; -import org.jboss.netty.channel.Channels; -import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory; - -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -/** - * NettyClient. - */ -public class NettyClient extends AbstractClient { - - private static final Logger logger = LoggerFactory.getLogger(NettyClient.class); - - // ChannelFactory's closure has a DirectMemory leak, using static to avoid - // https://issues.jboss.org/browse/NETTY-424 - private static final ChannelFactory CHANNEL_FACTORY = new NioClientSocketChannelFactory(Executors.newCachedThreadPool(new NamedThreadFactory("NettyClientBoss", true)), - Executors.newCachedThreadPool(new NamedThreadFactory("NettyClientWorker", true)), - Constants.DEFAULT_IO_THREADS); - private ClientBootstrap bootstrap; - - private volatile Channel channel; // volatile, please copy reference to use - - public NettyClient(final URL url, final ChannelHandler handler) throws RemotingException { - super(url, wrapChannelHandler(url, handler)); - } - - @Override - protected void doOpen() throws Throwable { - NettyHelper.setNettyLoggerFactory(); - bootstrap = new ClientBootstrap(CHANNEL_FACTORY); - // config - // @see org.jboss.netty.channel.socket.SocketChannelConfig - bootstrap.setOption("keepAlive", true); - bootstrap.setOption("tcpNoDelay", true); - bootstrap.setOption("connectTimeoutMillis", getConnectTimeout()); - final NettyHandler nettyHandler = new NettyHandler(getUrl(), this); - bootstrap.setPipelineFactory(new ChannelPipelineFactory() { - @Override - public ChannelPipeline getPipeline() { - NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(), getUrl(), NettyClient.this); - ChannelPipeline pipeline = Channels.pipeline(); - pipeline.addLast("decoder", adapter.getDecoder()); - pipeline.addLast("encoder", adapter.getEncoder()); - pipeline.addLast("handler", nettyHandler); - return pipeline; - } - }); - } - - @Override - protected void doConnect() throws Throwable { - long start = System.currentTimeMillis(); - ChannelFuture future = bootstrap.connect(getConnectAddress()); - try { - boolean ret = future.awaitUninterruptibly(getConnectTimeout(), TimeUnit.MILLISECONDS); - - if (ret && future.isSuccess()) { - Channel newChannel = future.getChannel(); - newChannel.setInterestOps(Channel.OP_READ_WRITE); - try { - // Close old channel - Channel oldChannel = NettyClient.this.channel; // copy reference - if (oldChannel != null) { - try { - if (logger.isInfoEnabled()) { - logger.info("Close old netty channel " + oldChannel + " on create new netty channel " + newChannel); - } - oldChannel.close(); - } finally { - NettyChannel.removeChannelIfDisconnected(oldChannel); - } - } - } finally { - if (NettyClient.this.isClosed()) { - try { - if (logger.isInfoEnabled()) { - logger.info("Close new netty channel " + newChannel + ", because the client closed."); - } - newChannel.close(); - } finally { - NettyClient.this.channel = null; - NettyChannel.removeChannelIfDisconnected(newChannel); - } - } else { - NettyClient.this.channel = newChannel; - } - } - } else if (future.getCause() != null) { - throw new RemotingException(this, "client(url: " + getUrl() + ") failed to connect to server " - + getRemoteAddress() + ", error message is:" + future.getCause().getMessage(), future.getCause()); - } else { - throw new RemotingException(this, "client(url: " + getUrl() + ") failed to connect to server " - + getRemoteAddress() + " client-side timeout " - + getConnectTimeout() + "ms (elapsed: " + (System.currentTimeMillis() - start) + "ms) from netty client " - + NetUtils.getLocalHost() + " using dubbo version " + Version.getVersion()); - } - } finally { - if (!isConnected()) { - future.cancel(); - } - } - } - - @Override - protected void doDisConnect() throws Throwable { - try { - NettyChannel.removeChannelIfDisconnected(channel); - } catch (Throwable t) { - logger.warn(t.getMessage()); - } - } - - @Override - protected void doClose() throws Throwable { - /*try { - bootstrap.releaseExternalResources(); - } catch (Throwable t) { - logger.warn(t.getMessage()); - }*/ - } - - @Override - protected org.apache.dubbo.remoting.Channel getChannel() { - Channel c = channel; - if (c == null || !c.isConnected()) { - return null; - } - return NettyChannel.getOrAddChannel(c, getUrl(), this); - } - - Channel getNettyChannel() { - return channel; - } - -} +/* + * 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.remoting.transport.netty; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.Version; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.NamedThreadFactory; +import org.apache.dubbo.common.utils.NetUtils; +import org.apache.dubbo.remoting.ChannelHandler; +import org.apache.dubbo.remoting.Constants; +import org.apache.dubbo.remoting.RemotingException; +import org.apache.dubbo.remoting.transport.AbstractClient; + +import org.jboss.netty.bootstrap.ClientBootstrap; +import org.jboss.netty.channel.Channel; +import org.jboss.netty.channel.ChannelFactory; +import org.jboss.netty.channel.ChannelFuture; +import org.jboss.netty.channel.ChannelPipeline; +import org.jboss.netty.channel.ChannelPipelineFactory; +import org.jboss.netty.channel.Channels; +import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory; + +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +/** + * NettyClient. + */ +public class NettyClient extends AbstractClient { + + private static final Logger logger = LoggerFactory.getLogger(NettyClient.class); + + // ChannelFactory's closure has a DirectMemory leak, using static to avoid + // https://issues.jboss.org/browse/NETTY-424 + private static final ChannelFactory CHANNEL_FACTORY = new NioClientSocketChannelFactory(Executors.newCachedThreadPool(new NamedThreadFactory("NettyClientBoss", true)), + Executors.newCachedThreadPool(new NamedThreadFactory("NettyClientWorker", true)), + Constants.DEFAULT_IO_THREADS); + private ClientBootstrap bootstrap; + + private volatile Channel channel; // volatile, please copy reference to use + + public NettyClient(final URL url, final ChannelHandler handler) throws RemotingException { + super(url, wrapChannelHandler(url, handler)); + } + + @Override + protected void doOpen() throws Throwable { + NettyHelper.setNettyLoggerFactory(); + bootstrap = new ClientBootstrap(CHANNEL_FACTORY); + // config + // @see org.jboss.netty.channel.socket.SocketChannelConfig + bootstrap.setOption("keepAlive", true); + bootstrap.setOption("tcpNoDelay", true); + bootstrap.setOption("connectTimeoutMillis", getConnectTimeout()); + final NettyHandler nettyHandler = new NettyHandler(getUrl(), this); + bootstrap.setPipelineFactory(new ChannelPipelineFactory() { + @Override + public ChannelPipeline getPipeline() { + NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(), getUrl(), NettyClient.this); + ChannelPipeline pipeline = Channels.pipeline(); + pipeline.addLast("decoder", adapter.getDecoder()); + pipeline.addLast("encoder", adapter.getEncoder()); + pipeline.addLast("handler", nettyHandler); + return pipeline; + } + }); + } + + @Override + protected void doConnect() throws Throwable { + long start = System.currentTimeMillis(); + ChannelFuture future = bootstrap.connect(getConnectAddress()); + try { + boolean ret = future.awaitUninterruptibly(getConnectTimeout(), TimeUnit.MILLISECONDS); + + if (ret && future.isSuccess()) { + Channel newChannel = future.getChannel(); + newChannel.setInterestOps(Channel.OP_READ_WRITE); + try { + // Close old channel + Channel oldChannel = NettyClient.this.channel; // copy reference + if (oldChannel != null) { + try { + if (logger.isInfoEnabled()) { + logger.info("Close old netty channel " + oldChannel + " on create new netty channel " + newChannel); + } + oldChannel.close(); + } finally { + NettyChannel.removeChannelIfDisconnected(oldChannel); + } + } + } finally { + if (NettyClient.this.isClosed()) { + try { + if (logger.isInfoEnabled()) { + logger.info("Close new netty channel " + newChannel + ", because the client closed."); + } + newChannel.close(); + } finally { + NettyClient.this.channel = null; + NettyChannel.removeChannelIfDisconnected(newChannel); + } + } else { + NettyClient.this.channel = newChannel; + } + } + } else if (future.getCause() != null) { + throw new RemotingException(this, "client(url: " + getUrl() + ") failed to connect to server " + + getRemoteAddress() + ", error message is:" + future.getCause().getMessage(), future.getCause()); + } else { + throw new RemotingException(this, "client(url: " + getUrl() + ") failed to connect to server " + + getRemoteAddress() + " client-side timeout " + + getConnectTimeout() + "ms (elapsed: " + (System.currentTimeMillis() - start) + "ms) from netty client " + + NetUtils.getLocalHost() + " using dubbo version " + Version.getVersion()); + } + } finally { + if (!isConnected()) { + future.cancel(); + } + } + } + + @Override + protected void doDisConnect() throws Throwable { + try { + NettyChannel.removeChannelIfDisconnected(channel); + } catch (Throwable t) { + logger.warn(t.getMessage()); + } + } + + @Override + protected void doClose() throws Throwable { + /*try { + bootstrap.releaseExternalResources(); + } catch (Throwable t) { + logger.warn(t.getMessage()); + }*/ + } + + @Override + protected org.apache.dubbo.remoting.Channel getChannel() { + Channel c = channel; + if (c == null || !c.isConnected()) { + return null; + } + return NettyChannel.getOrAddChannel(c, getUrl(), this); + } + + Channel getNettyChannel() { + return channel; + } + +} diff --git a/dubbo-remoting/dubbo-remoting-netty/src/main/java/org/apache/dubbo/remoting/transport/netty/NettyCodecAdapter.java b/dubbo-remoting/dubbo-remoting-netty/src/main/java/org/apache/dubbo/remoting/transport/netty/NettyCodecAdapter.java index 94e6c17125..984ec89a40 100644 --- a/dubbo-remoting/dubbo-remoting-netty/src/main/java/org/apache/dubbo/remoting/transport/netty/NettyCodecAdapter.java +++ b/dubbo-remoting/dubbo-remoting-netty/src/main/java/org/apache/dubbo/remoting/transport/netty/NettyCodecAdapter.java @@ -168,4 +168,4 @@ final class NettyCodecAdapter { ctx.sendUpstream(e); } } -} \ No newline at end of file +} diff --git a/dubbo-remoting/dubbo-remoting-netty/src/main/java/org/apache/dubbo/remoting/transport/netty/NettyHandler.java b/dubbo-remoting/dubbo-remoting-netty/src/main/java/org/apache/dubbo/remoting/transport/netty/NettyHandler.java index b8d0419b26..db6e2dded6 100644 --- a/dubbo-remoting/dubbo-remoting-netty/src/main/java/org/apache/dubbo/remoting/transport/netty/NettyHandler.java +++ b/dubbo-remoting/dubbo-remoting-netty/src/main/java/org/apache/dubbo/remoting/transport/netty/NettyHandler.java @@ -126,4 +126,4 @@ public class NettyHandler extends SimpleChannelHandler { } } -} \ No newline at end of file +} diff --git a/dubbo-remoting/dubbo-remoting-netty/src/main/java/org/apache/dubbo/remoting/transport/netty/NettyServer.java b/dubbo-remoting/dubbo-remoting-netty/src/main/java/org/apache/dubbo/remoting/transport/netty/NettyServer.java index 0eac68d6d5..a74412d1c9 100644 --- a/dubbo-remoting/dubbo-remoting-netty/src/main/java/org/apache/dubbo/remoting/transport/netty/NettyServer.java +++ b/dubbo-remoting/dubbo-remoting-netty/src/main/java/org/apache/dubbo/remoting/transport/netty/NettyServer.java @@ -1,166 +1,166 @@ -/* - * 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.remoting.transport.netty; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.utils.CollectionUtils; -import org.apache.dubbo.common.utils.ExecutorUtil; -import org.apache.dubbo.common.utils.NamedThreadFactory; -import org.apache.dubbo.common.utils.NetUtils; -import org.apache.dubbo.remoting.Channel; -import org.apache.dubbo.remoting.ChannelHandler; -import org.apache.dubbo.remoting.Constants; -import org.apache.dubbo.remoting.RemotingException; -import org.apache.dubbo.remoting.RemotingServer; -import org.apache.dubbo.remoting.transport.AbstractServer; -import org.apache.dubbo.remoting.transport.dispatcher.ChannelHandlers; - -import org.jboss.netty.bootstrap.ServerBootstrap; -import org.jboss.netty.channel.ChannelFactory; -import org.jboss.netty.channel.ChannelPipeline; -import org.jboss.netty.channel.ChannelPipelineFactory; -import org.jboss.netty.channel.Channels; -import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; - -import java.net.InetSocketAddress; -import java.util.Collection; -import java.util.HashSet; -import java.util.Map; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import static org.apache.dubbo.common.constants.CommonConstants.BACKLOG_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.IO_THREADS_KEY; - -/** - * NettyServer - */ -public class NettyServer extends AbstractServer implements RemotingServer { - - private static final Logger logger = LoggerFactory.getLogger(NettyServer.class); - - private Map channels; // - - private ServerBootstrap bootstrap; - - private org.jboss.netty.channel.Channel channel; - - public NettyServer(URL url, ChannelHandler handler) throws RemotingException { - super(ExecutorUtil.setThreadName(url, SERVER_THREAD_POOL_NAME), ChannelHandlers.wrap(handler, url)); - } - - @Override - protected void doOpen() throws Throwable { - NettyHelper.setNettyLoggerFactory(); - ExecutorService boss = Executors.newCachedThreadPool(new NamedThreadFactory("NettyServerBoss", true)); - ExecutorService worker = Executors.newCachedThreadPool(new NamedThreadFactory("NettyServerWorker", true)); - ChannelFactory channelFactory = new NioServerSocketChannelFactory(boss, worker, getUrl().getPositiveParameter(IO_THREADS_KEY, Constants.DEFAULT_IO_THREADS)); - bootstrap = new ServerBootstrap(channelFactory); - - final NettyHandler nettyHandler = new NettyHandler(getUrl(), this); - channels = nettyHandler.getChannels(); - // https://issues.jboss.org/browse/NETTY-365 - // https://issues.jboss.org/browse/NETTY-379 - // final Timer timer = new HashedWheelTimer(new NamedThreadFactory("NettyIdleTimer", true)); - bootstrap.setOption("child.tcpNoDelay", true); - bootstrap.setOption("backlog", getUrl().getPositiveParameter(BACKLOG_KEY, Constants.DEFAULT_BACKLOG)); - bootstrap.setPipelineFactory(new ChannelPipelineFactory() { - @Override - public ChannelPipeline getPipeline() { - NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(), getUrl(), NettyServer.this); - ChannelPipeline pipeline = Channels.pipeline(); - /*int idleTimeout = getIdleTimeout(); - if (idleTimeout > 10000) { - pipeline.addLast("timer", new IdleStateHandler(timer, idleTimeout / 1000, 0, 0)); - }*/ - pipeline.addLast("decoder", adapter.getDecoder()); - pipeline.addLast("encoder", adapter.getEncoder()); - pipeline.addLast("handler", nettyHandler); - return pipeline; - } - }); - // bind - channel = bootstrap.bind(getBindAddress()); - } - - @Override - protected void doClose() throws Throwable { - try { - if (channel != null) { - // unbind. - channel.close(); - } - } catch (Throwable e) { - logger.warn(e.getMessage(), e); - } - try { - Collection channels = getChannels(); - if (CollectionUtils.isNotEmpty(channels)) { - for (org.apache.dubbo.remoting.Channel channel : channels) { - try { - channel.close(); - } catch (Throwable e) { - logger.warn(e.getMessage(), e); - } - } - } - } catch (Throwable e) { - logger.warn(e.getMessage(), e); - } - try { - if (bootstrap != null) { - // release external resource. - bootstrap.releaseExternalResources(); - } - } catch (Throwable e) { - logger.warn(e.getMessage(), e); - } - try { - if (channels != null) { - channels.clear(); - } - } catch (Throwable e) { - logger.warn(e.getMessage(), e); - } - } - - @Override - public Collection getChannels() { - Collection chs = new HashSet(); - for (Channel channel : this.channels.values()) { - if (channel.isConnected()) { - chs.add(channel); - } else { - channels.remove(NetUtils.toAddressString(channel.getRemoteAddress())); - } - } - return chs; - } - - @Override - public Channel getChannel(InetSocketAddress remoteAddress) { - return channels.get(NetUtils.toAddressString(remoteAddress)); - } - - @Override - public boolean isBound() { - return channel.isBound(); - } - -} +/* + * 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.remoting.transport.netty; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.common.utils.ExecutorUtil; +import org.apache.dubbo.common.utils.NamedThreadFactory; +import org.apache.dubbo.common.utils.NetUtils; +import org.apache.dubbo.remoting.Channel; +import org.apache.dubbo.remoting.ChannelHandler; +import org.apache.dubbo.remoting.Constants; +import org.apache.dubbo.remoting.RemotingException; +import org.apache.dubbo.remoting.RemotingServer; +import org.apache.dubbo.remoting.transport.AbstractServer; +import org.apache.dubbo.remoting.transport.dispatcher.ChannelHandlers; + +import org.jboss.netty.bootstrap.ServerBootstrap; +import org.jboss.netty.channel.ChannelFactory; +import org.jboss.netty.channel.ChannelPipeline; +import org.jboss.netty.channel.ChannelPipelineFactory; +import org.jboss.netty.channel.Channels; +import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; + +import java.net.InetSocketAddress; +import java.util.Collection; +import java.util.HashSet; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import static org.apache.dubbo.common.constants.CommonConstants.BACKLOG_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.IO_THREADS_KEY; + +/** + * NettyServer + */ +public class NettyServer extends AbstractServer implements RemotingServer { + + private static final Logger logger = LoggerFactory.getLogger(NettyServer.class); + + private Map channels; // + + private ServerBootstrap bootstrap; + + private org.jboss.netty.channel.Channel channel; + + public NettyServer(URL url, ChannelHandler handler) throws RemotingException { + super(ExecutorUtil.setThreadName(url, SERVER_THREAD_POOL_NAME), ChannelHandlers.wrap(handler, url)); + } + + @Override + protected void doOpen() throws Throwable { + NettyHelper.setNettyLoggerFactory(); + ExecutorService boss = Executors.newCachedThreadPool(new NamedThreadFactory("NettyServerBoss", true)); + ExecutorService worker = Executors.newCachedThreadPool(new NamedThreadFactory("NettyServerWorker", true)); + ChannelFactory channelFactory = new NioServerSocketChannelFactory(boss, worker, getUrl().getPositiveParameter(IO_THREADS_KEY, Constants.DEFAULT_IO_THREADS)); + bootstrap = new ServerBootstrap(channelFactory); + + final NettyHandler nettyHandler = new NettyHandler(getUrl(), this); + channels = nettyHandler.getChannels(); + // https://issues.jboss.org/browse/NETTY-365 + // https://issues.jboss.org/browse/NETTY-379 + // final Timer timer = new HashedWheelTimer(new NamedThreadFactory("NettyIdleTimer", true)); + bootstrap.setOption("child.tcpNoDelay", true); + bootstrap.setOption("backlog", getUrl().getPositiveParameter(BACKLOG_KEY, Constants.DEFAULT_BACKLOG)); + bootstrap.setPipelineFactory(new ChannelPipelineFactory() { + @Override + public ChannelPipeline getPipeline() { + NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(), getUrl(), NettyServer.this); + ChannelPipeline pipeline = Channels.pipeline(); + /*int idleTimeout = getIdleTimeout(); + if (idleTimeout > 10000) { + pipeline.addLast("timer", new IdleStateHandler(timer, idleTimeout / 1000, 0, 0)); + }*/ + pipeline.addLast("decoder", adapter.getDecoder()); + pipeline.addLast("encoder", adapter.getEncoder()); + pipeline.addLast("handler", nettyHandler); + return pipeline; + } + }); + // bind + channel = bootstrap.bind(getBindAddress()); + } + + @Override + protected void doClose() throws Throwable { + try { + if (channel != null) { + // unbind. + channel.close(); + } + } catch (Throwable e) { + logger.warn(e.getMessage(), e); + } + try { + Collection channels = getChannels(); + if (CollectionUtils.isNotEmpty(channels)) { + for (org.apache.dubbo.remoting.Channel channel : channels) { + try { + channel.close(); + } catch (Throwable e) { + logger.warn(e.getMessage(), e); + } + } + } + } catch (Throwable e) { + logger.warn(e.getMessage(), e); + } + try { + if (bootstrap != null) { + // release external resource. + bootstrap.releaseExternalResources(); + } + } catch (Throwable e) { + logger.warn(e.getMessage(), e); + } + try { + if (channels != null) { + channels.clear(); + } + } catch (Throwable e) { + logger.warn(e.getMessage(), e); + } + } + + @Override + public Collection getChannels() { + Collection chs = new HashSet(); + for (Channel channel : this.channels.values()) { + if (channel.isConnected()) { + chs.add(channel); + } else { + channels.remove(NetUtils.toAddressString(channel.getRemoteAddress())); + } + } + return chs; + } + + @Override + public Channel getChannel(InetSocketAddress remoteAddress) { + return channels.get(NetUtils.toAddressString(remoteAddress)); + } + + @Override + public boolean isBound() { + return channel.isBound(); + } + +} diff --git a/dubbo-remoting/dubbo-remoting-netty/src/main/java/org/apache/dubbo/remoting/transport/netty/NettyTransporter.java b/dubbo-remoting/dubbo-remoting-netty/src/main/java/org/apache/dubbo/remoting/transport/netty/NettyTransporter.java index 1df5b72ecc..4dde31eb26 100644 --- a/dubbo-remoting/dubbo-remoting-netty/src/main/java/org/apache/dubbo/remoting/transport/netty/NettyTransporter.java +++ b/dubbo-remoting/dubbo-remoting-netty/src/main/java/org/apache/dubbo/remoting/transport/netty/NettyTransporter.java @@ -1,40 +1,40 @@ -/* - * 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.remoting.transport.netty; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.remoting.ChannelHandler; -import org.apache.dubbo.remoting.Client; -import org.apache.dubbo.remoting.RemotingException; -import org.apache.dubbo.remoting.RemotingServer; -import org.apache.dubbo.remoting.Transporter; - -public class NettyTransporter implements Transporter { - - public static final String NAME = "netty3"; - - @Override - public RemotingServer bind(URL url, ChannelHandler handler) throws RemotingException { - return new NettyServer(url, handler); - } - - @Override - public Client connect(URL url, ChannelHandler handler) throws RemotingException { - return new NettyClient(url, handler); - } - -} +/* + * 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.remoting.transport.netty; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.remoting.ChannelHandler; +import org.apache.dubbo.remoting.Client; +import org.apache.dubbo.remoting.RemotingException; +import org.apache.dubbo.remoting.RemotingServer; +import org.apache.dubbo.remoting.Transporter; + +public class NettyTransporter implements Transporter { + + public static final String NAME = "netty3"; + + @Override + public RemotingServer bind(URL url, ChannelHandler handler) throws RemotingException { + return new NettyServer(url, handler); + } + + @Override + public Client connect(URL url, ChannelHandler handler) throws RemotingException { + return new NettyClient(url, handler); + } + +} diff --git a/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/ClientReconnectTest.java b/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/ClientReconnectTest.java index a75a4292f0..167647a4b4 100644 --- a/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/ClientReconnectTest.java +++ b/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/ClientReconnectTest.java @@ -1,96 +1,96 @@ -/* - * 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.remoting.transport.netty; - -import org.apache.dubbo.common.utils.DubboAppender; -import org.apache.dubbo.common.utils.NetUtils; -import org.apache.dubbo.remoting.Channel; -import org.apache.dubbo.remoting.Client; -import org.apache.dubbo.remoting.Constants; -import org.apache.dubbo.remoting.RemotingException; -import org.apache.dubbo.remoting.RemotingServer; -import org.apache.dubbo.remoting.exchange.Exchangers; -import org.apache.dubbo.remoting.exchange.support.ExchangeHandlerAdapter; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -/** - * Client reconnect test - */ -public class ClientReconnectTest { - - @BeforeEach - public void clear() { - DubboAppender.clear(); - } - - @Test - public void testReconnect() throws RemotingException, InterruptedException { - { - int port = NetUtils.getAvailablePort(); - Client client = startClient(port, 200); - Assertions.assertFalse(client.isConnected()); - RemotingServer server = startServer(port); - for (int i = 0; i < 1000 && !client.isConnected(); i++) { - Thread.sleep(10); - } - Assertions.assertTrue(client.isConnected()); - client.close(2000); - server.close(2000); - } - { - int port = NetUtils.getAvailablePort(); - Client client = startClient(port, 20000); - Assertions.assertFalse(client.isConnected()); - RemotingServer server = startServer(port); - for (int i = 0; i < 5; i++) { - Thread.sleep(200); - } - Assertions.assertFalse(client.isConnected()); - client.close(2000); - server.close(2000); - } - } - - - public Client startClient(int port, int heartbeat) throws RemotingException { - final String url = "exchange://127.0.0.1:" + port + "/client.reconnect.test?check=false&client=netty3&" + - Constants.HEARTBEAT_KEY + "=" + heartbeat; - return Exchangers.connect(url); - } - - public RemotingServer startServer(int port) throws RemotingException { - final String url = "exchange://127.0.0.1:" + port + "/client.reconnect.test?server=netty3"; - return Exchangers.bind(url, new HandlerAdapter()); - } - - static class HandlerAdapter extends ExchangeHandlerAdapter { - @Override - public void connected(Channel channel) throws RemotingException { - } - - @Override - public void disconnected(Channel channel) throws RemotingException { - } - - @Override - public void caught(Channel channel, Throwable exception) throws RemotingException { - } - } -} +/* + * 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.remoting.transport.netty; + +import org.apache.dubbo.common.utils.DubboAppender; +import org.apache.dubbo.common.utils.NetUtils; +import org.apache.dubbo.remoting.Channel; +import org.apache.dubbo.remoting.Client; +import org.apache.dubbo.remoting.Constants; +import org.apache.dubbo.remoting.RemotingException; +import org.apache.dubbo.remoting.RemotingServer; +import org.apache.dubbo.remoting.exchange.Exchangers; +import org.apache.dubbo.remoting.exchange.support.ExchangeHandlerAdapter; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +/** + * Client reconnect test + */ +public class ClientReconnectTest { + + @BeforeEach + public void clear() { + DubboAppender.clear(); + } + + @Test + public void testReconnect() throws RemotingException, InterruptedException { + { + int port = NetUtils.getAvailablePort(); + Client client = startClient(port, 200); + Assertions.assertFalse(client.isConnected()); + RemotingServer server = startServer(port); + for (int i = 0; i < 1000 && !client.isConnected(); i++) { + Thread.sleep(10); + } + Assertions.assertTrue(client.isConnected()); + client.close(2000); + server.close(2000); + } + { + int port = NetUtils.getAvailablePort(); + Client client = startClient(port, 20000); + Assertions.assertFalse(client.isConnected()); + RemotingServer server = startServer(port); + for (int i = 0; i < 5; i++) { + Thread.sleep(200); + } + Assertions.assertFalse(client.isConnected()); + client.close(2000); + server.close(2000); + } + } + + + public Client startClient(int port, int heartbeat) throws RemotingException { + final String url = "exchange://127.0.0.1:" + port + "/client.reconnect.test?check=false&client=netty3&" + + Constants.HEARTBEAT_KEY + "=" + heartbeat; + return Exchangers.connect(url); + } + + public RemotingServer startServer(int port) throws RemotingException { + final String url = "exchange://127.0.0.1:" + port + "/client.reconnect.test?server=netty3"; + return Exchangers.bind(url, new HandlerAdapter()); + } + + static class HandlerAdapter extends ExchangeHandlerAdapter { + @Override + public void connected(Channel channel) throws RemotingException { + } + + @Override + public void disconnected(Channel channel) throws RemotingException { + } + + @Override + public void caught(Channel channel, Throwable exception) throws RemotingException { + } + } +} diff --git a/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/ClientToServerTest.java b/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/ClientToServerTest.java index d89227f3fa..f7a90bcdf6 100644 --- a/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/ClientToServerTest.java +++ b/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/ClientToServerTest.java @@ -88,4 +88,4 @@ public abstract class ClientToServerTest { // } // } -} \ No newline at end of file +} diff --git a/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/ClientsTest.java b/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/ClientsTest.java index b131880de9..1be36d333e 100644 --- a/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/ClientsTest.java +++ b/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/ClientsTest.java @@ -1,64 +1,64 @@ -/* - * 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.remoting.transport.netty; - -import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.remoting.Transporter; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.fail; - -public class ClientsTest { - - @Test - public void testGetTransportEmpty() { - try { - ExtensionLoader.getExtensionLoader(Transporter.class).getExtension(""); - fail(); - } catch (IllegalArgumentException expected) { - assertThat(expected.getMessage(), containsString("Extension name == null")); - } - } - - @Test - public void testGetTransportNull() { - Assertions.assertThrows(IllegalArgumentException.class, () -> { - String name = null; - ExtensionLoader.getExtensionLoader(Transporter.class).getExtension(name); - }); - } - - @Test - public void testGetTransport3() { - String name = "netty3"; - assertEquals(NettyTransporter.class, ExtensionLoader.getExtensionLoader(Transporter.class).getExtension(name).getClass()); - } - - @Test - public void testGetTransportWrong() { - Assertions.assertThrows(IllegalStateException.class, () -> { - String name = "nety"; - assertNull(ExtensionLoader.getExtensionLoader(Transporter.class).getExtension(name).getClass()); - }); - } -} +/* + * 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.remoting.transport.netty; + +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.remoting.Transporter; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.fail; + +public class ClientsTest { + + @Test + public void testGetTransportEmpty() { + try { + ExtensionLoader.getExtensionLoader(Transporter.class).getExtension(""); + fail(); + } catch (IllegalArgumentException expected) { + assertThat(expected.getMessage(), containsString("Extension name == null")); + } + } + + @Test + public void testGetTransportNull() { + Assertions.assertThrows(IllegalArgumentException.class, () -> { + String name = null; + ExtensionLoader.getExtensionLoader(Transporter.class).getExtension(name); + }); + } + + @Test + public void testGetTransport3() { + String name = "netty3"; + assertEquals(NettyTransporter.class, ExtensionLoader.getExtensionLoader(Transporter.class).getExtension(name).getClass()); + } + + @Test + public void testGetTransportWrong() { + Assertions.assertThrows(IllegalStateException.class, () -> { + String name = "nety"; + assertNull(ExtensionLoader.getExtensionLoader(Transporter.class).getExtension(name).getClass()); + }); + } +} diff --git a/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/Hello.java b/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/Hello.java index 5445acc626..52ce36b2a8 100644 --- a/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/Hello.java +++ b/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/Hello.java @@ -42,4 +42,4 @@ public class Hello implements Serializable { this.name = name; } -} \ No newline at end of file +} diff --git a/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/NettyClientTest.java b/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/NettyClientTest.java index 3976964319..6ac5374a8a 100644 --- a/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/NettyClientTest.java +++ b/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/NettyClientTest.java @@ -78,4 +78,4 @@ public class NettyClientTest { aServer.close(); } } -} \ No newline at end of file +} diff --git a/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/NettyStringTest.java b/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/NettyStringTest.java index a5e95891d1..d08d78153d 100644 --- a/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/NettyStringTest.java +++ b/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/NettyStringTest.java @@ -1,66 +1,66 @@ -/* - * 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.remoting.transport.netty; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.utils.NetUtils; -import org.apache.dubbo.remoting.exchange.ExchangeChannel; -import org.apache.dubbo.remoting.exchange.ExchangeServer; -import org.apache.dubbo.remoting.exchange.Exchangers; - -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -/** - * Date: 4/26/11 - * Time: 4:13 PM - */ -public class NettyStringTest { - static ExchangeServer server; - static ExchangeChannel client; - - @BeforeAll - public static void setUp() throws Exception { - //int port = (int) (1000 * Math.random() + 10000); - //int port = 10001; - int port = NetUtils.getAvailablePort(); - System.out.println(port); - server = Exchangers.bind(URL.valueOf("telnet://0.0.0.0:" + port + "?server=netty3"), new TelnetServerHandler()); - client = Exchangers.connect(URL.valueOf("telnet://127.0.0.1:" + port + "?client=netty3"), new TelnetClientHandler()); - } - - @AfterAll - public static void tearDown() throws Exception { - try { - if (server != null) - server.close(); - } finally { - if (client != null) - client.close(); - } - } - - @Test - public void testHandler() throws Exception { - //Thread.sleep(20000); - /*client.request("world\r\n"); - Future future = client.request("world", 10000); - String result = (String)future.get(); - Assertions.assertEquals("Did you say 'world'?\r\n",result);*/ - } -} \ No newline at end of file +/* + * 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.remoting.transport.netty; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.utils.NetUtils; +import org.apache.dubbo.remoting.exchange.ExchangeChannel; +import org.apache.dubbo.remoting.exchange.ExchangeServer; +import org.apache.dubbo.remoting.exchange.Exchangers; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +/** + * Date: 4/26/11 + * Time: 4:13 PM + */ +public class NettyStringTest { + static ExchangeServer server; + static ExchangeChannel client; + + @BeforeAll + public static void setUp() throws Exception { + //int port = (int) (1000 * Math.random() + 10000); + //int port = 10001; + int port = NetUtils.getAvailablePort(); + System.out.println(port); + server = Exchangers.bind(URL.valueOf("telnet://0.0.0.0:" + port + "?server=netty3"), new TelnetServerHandler()); + client = Exchangers.connect(URL.valueOf("telnet://127.0.0.1:" + port + "?client=netty3"), new TelnetClientHandler()); + } + + @AfterAll + public static void tearDown() throws Exception { + try { + if (server != null) + server.close(); + } finally { + if (client != null) + client.close(); + } + } + + @Test + public void testHandler() throws Exception { + //Thread.sleep(20000); + /*client.request("world\r\n"); + Future future = client.request("world", 10000); + String result = (String)future.get(); + Assertions.assertEquals("Did you say 'world'?\r\n",result);*/ + } +} diff --git a/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/TelnetClientHandler.java b/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/TelnetClientHandler.java index 0e0d917387..354d2591d5 100644 --- a/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/TelnetClientHandler.java +++ b/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/TelnetClientHandler.java @@ -33,4 +33,4 @@ public class TelnetClientHandler implements Replier { public Object reply(ExchangeChannel channel, String msg) throws RemotingException { return msg; } -} \ No newline at end of file +} diff --git a/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/TelnetServerHandler.java b/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/TelnetServerHandler.java index 12b016ddc0..54b951b5de 100644 --- a/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/TelnetServerHandler.java +++ b/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/TelnetServerHandler.java @@ -43,4 +43,4 @@ public class TelnetServerHandler implements Replier { return response; } -} \ No newline at end of file +} diff --git a/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/World.java b/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/World.java index 3e940908aa..7185da312a 100644 --- a/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/World.java +++ b/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/World.java @@ -42,4 +42,4 @@ public class World implements Serializable { this.name = name; } -} \ No newline at end of file +} diff --git a/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/WorldHandler.java b/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/WorldHandler.java index 23dcab40e7..689f978ccf 100644 --- a/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/WorldHandler.java +++ b/dubbo-remoting/dubbo-remoting-netty/src/test/java/org/apache/dubbo/remoting/transport/netty/WorldHandler.java @@ -33,4 +33,4 @@ public class WorldHandler implements Replier { return new Hello("hello," + msg.getName()); } -} \ No newline at end of file +} diff --git a/dubbo-remoting/dubbo-remoting-netty/src/test/resources/log4j.xml b/dubbo-remoting/dubbo-remoting-netty/src/test/resources/log4j.xml index fc40926e12..e0eda90175 100644 --- a/dubbo-remoting/dubbo-remoting-netty/src/test/resources/log4j.xml +++ b/dubbo-remoting/dubbo-remoting-netty/src/test/resources/log4j.xml @@ -1,38 +1,38 @@ - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyClient.java b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyClient.java index 202fd395c9..4260e7efd5 100644 --- a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyClient.java +++ b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyClient.java @@ -78,9 +78,9 @@ public class NettyClient extends AbstractClient { * It wil init and start netty. */ public NettyClient(final URL url, final ChannelHandler handler) throws RemotingException { - // you can customize name and type of client thread pool by THREAD_NAME_KEY and THREADPOOL_KEY in CommonConstants. - // the handler will be wrapped: MultiMessageHandler->HeartbeatHandler->handler - super(url, wrapChannelHandler(url, handler)); + // you can customize name and type of client thread pool by THREAD_NAME_KEY and THREADPOOL_KEY in CommonConstants. + // the handler will be wrapped: MultiMessageHandler->HeartbeatHandler->handler + super(url, wrapChannelHandler(url, handler)); } /** diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyServer.java b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyServer.java index 46df48e782..786805712e 100644 --- a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyServer.java +++ b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyServer.java @@ -68,7 +68,7 @@ public class NettyServer extends AbstractServer implements RemotingServer { /** * the boss channel that receive connections and dispatch these to worker channel. */ - private io.netty.channel.Channel channel; + private io.netty.channel.Channel channel; private EventLoopGroup bossGroup; private EventLoopGroup workerGroup; diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/ClientToServerTest.java b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/ClientToServerTest.java index 1015a53d4a..9da53e8e7e 100644 --- a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/ClientToServerTest.java +++ b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/ClientToServerTest.java @@ -70,4 +70,4 @@ public abstract class ClientToServerTest { Hello result = (Hello) future.get(); Assertions.assertEquals("hello,world", result.getName()); } -} \ No newline at end of file +} diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/DemoService.java b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/DemoService.java index 2734ed8b2d..cd622b9f07 100644 --- a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/DemoService.java +++ b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/DemoService.java @@ -1,27 +1,27 @@ -/* - * 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.remoting.transport.netty4; - -/** - * TestService - */ - -public interface DemoService { - void sayHello(String name); - - int plus(int a, int b); -} \ No newline at end of file +/* + * 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.remoting.transport.netty4; + +/** + * TestService + */ + +public interface DemoService { + void sayHello(String name); + + int plus(int a, int b); +} diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/DemoServiceImpl.java b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/DemoServiceImpl.java index 02b67f9752..22cb86cf4d 100644 --- a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/DemoServiceImpl.java +++ b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/DemoServiceImpl.java @@ -28,4 +28,4 @@ public class DemoServiceImpl implements DemoService { public int plus(int a, int b) { return a + b; } -} \ No newline at end of file +} diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/Hello.java b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/Hello.java index 5634f923ec..f99bb4ab95 100644 --- a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/Hello.java +++ b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/Hello.java @@ -42,4 +42,4 @@ public class Hello implements Serializable { this.name = name; } -} \ No newline at end of file +} diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/MockResult.java b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/MockResult.java index db1a8142b1..fbd05f796a 100644 --- a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/MockResult.java +++ b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/MockResult.java @@ -34,4 +34,4 @@ public class MockResult implements Serializable { public Object getResult() { return mResult; } -} \ No newline at end of file +} diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/ReplierDispatcherTest.java b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/ReplierDispatcherTest.java index 37940e65a1..8dffd09d94 100644 --- a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/ReplierDispatcherTest.java +++ b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/ReplierDispatcherTest.java @@ -155,4 +155,4 @@ public class ReplierDispatcherTest { return mText; } } -} \ No newline at end of file +} diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/RpcMessage.java b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/RpcMessage.java index 4f5f413f3d..44630924a6 100755 --- a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/RpcMessage.java +++ b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/RpcMessage.java @@ -1,59 +1,59 @@ -/* - * 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.remoting.transport.netty4; - -import java.io.Serializable; - -/** - * RpcMessage. - */ - -public class RpcMessage implements Serializable { - private static final long serialVersionUID = -5148079121106659095L; - - private String mClassName; - - private String mMethodDesc; - - private Class[] mParameterTypes; - - private Object[] mArguments; - - public RpcMessage(String cn, String desc, Class[] parameterTypes, Object[] args) { - mClassName = cn; - mMethodDesc = desc; - mParameterTypes = parameterTypes; - mArguments = args; - } - - public String getClassName() { - return mClassName; - } - - public String getMethodDesc() { - return mMethodDesc; - } - - public Class[] getParameterTypes() { - return mParameterTypes; - } - - public Object[] getArguments() { - return mArguments; - } - -} \ No newline at end of file +/* + * 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.remoting.transport.netty4; + +import java.io.Serializable; + +/** + * RpcMessage. + */ + +public class RpcMessage implements Serializable { + private static final long serialVersionUID = -5148079121106659095L; + + private String mClassName; + + private String mMethodDesc; + + private Class[] mParameterTypes; + + private Object[] mArguments; + + public RpcMessage(String cn, String desc, Class[] parameterTypes, Object[] args) { + mClassName = cn; + mMethodDesc = desc; + mParameterTypes = parameterTypes; + mArguments = args; + } + + public String getClassName() { + return mClassName; + } + + public String getMethodDesc() { + return mMethodDesc; + } + + public Class[] getParameterTypes() { + return mParameterTypes; + } + + public Object[] getArguments() { + return mArguments; + } + +} diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/RpcMessageHandler.java b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/RpcMessageHandler.java index 120d454cd0..76e63bd7e1 100755 --- a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/RpcMessageHandler.java +++ b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/RpcMessageHandler.java @@ -1,77 +1,77 @@ -/* - * 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.remoting.transport.netty4; - -import org.apache.dubbo.common.bytecode.NoSuchMethodException; -import org.apache.dubbo.common.bytecode.Wrapper; -import org.apache.dubbo.remoting.RemotingException; -import org.apache.dubbo.remoting.exchange.ExchangeChannel; -import org.apache.dubbo.remoting.exchange.support.Replier; - -import java.lang.reflect.InvocationTargetException; - -/** - * RpcMessageHandler. - */ - -public class RpcMessageHandler implements Replier { - private final static ServiceProvider DEFAULT_PROVIDER = new ServiceProvider() { - public Object getImplementation(String service) { - String impl = service + "Impl"; - try { - Class cl = Thread.currentThread().getContextClassLoader().loadClass(impl); - return cl.newInstance(); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - }; - private ServiceProvider mProvider; - - public RpcMessageHandler() { - this(DEFAULT_PROVIDER); - } - - public RpcMessageHandler(ServiceProvider prov) { - mProvider = prov; - } - - public Class interest() { - return RpcMessage.class; - } - - public Object reply(ExchangeChannel channel, RpcMessage msg) throws RemotingException { - String desc = msg.getMethodDesc(); - Object[] args = msg.getArguments(); - Object impl = mProvider.getImplementation(msg.getClassName()); - Wrapper wrap = Wrapper.getWrapper(impl.getClass()); - try { - return new MockResult(wrap.invokeMethod(impl, desc, msg.getParameterTypes(), args)); - } catch (NoSuchMethodException e) { - throw new RemotingException(channel, "Service method not found."); - } catch (InvocationTargetException e) { - return new MockResult(e.getTargetException()); - } - - } - - public interface ServiceProvider { - Object getImplementation(String service); - } - -} \ No newline at end of file +/* + * 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.remoting.transport.netty4; + +import org.apache.dubbo.common.bytecode.NoSuchMethodException; +import org.apache.dubbo.common.bytecode.Wrapper; +import org.apache.dubbo.remoting.RemotingException; +import org.apache.dubbo.remoting.exchange.ExchangeChannel; +import org.apache.dubbo.remoting.exchange.support.Replier; + +import java.lang.reflect.InvocationTargetException; + +/** + * RpcMessageHandler. + */ + +public class RpcMessageHandler implements Replier { + private final static ServiceProvider DEFAULT_PROVIDER = new ServiceProvider() { + public Object getImplementation(String service) { + String impl = service + "Impl"; + try { + Class cl = Thread.currentThread().getContextClassLoader().loadClass(impl); + return cl.newInstance(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + }; + private ServiceProvider mProvider; + + public RpcMessageHandler() { + this(DEFAULT_PROVIDER); + } + + public RpcMessageHandler(ServiceProvider prov) { + mProvider = prov; + } + + public Class interest() { + return RpcMessage.class; + } + + public Object reply(ExchangeChannel channel, RpcMessage msg) throws RemotingException { + String desc = msg.getMethodDesc(); + Object[] args = msg.getArguments(); + Object impl = mProvider.getImplementation(msg.getClassName()); + Wrapper wrap = Wrapper.getWrapper(impl.getClass()); + try { + return new MockResult(wrap.invokeMethod(impl, desc, msg.getParameterTypes(), args)); + } catch (NoSuchMethodException e) { + throw new RemotingException(channel, "Service method not found."); + } catch (InvocationTargetException e) { + return new MockResult(e.getTargetException()); + } + + } + + public interface ServiceProvider { + Object getImplementation(String service); + } + +} diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/World.java b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/World.java index 5d2641e442..9ee2814cd3 100644 --- a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/World.java +++ b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/World.java @@ -42,4 +42,4 @@ public class World implements Serializable { this.name = name; } -} \ No newline at end of file +} diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/WorldHandler.java b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/WorldHandler.java index f31c3ec557..7b83598154 100644 --- a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/WorldHandler.java +++ b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/WorldHandler.java @@ -33,4 +33,4 @@ public class WorldHandler implements Replier { return new Hello("hello," + msg.getName()); } -} \ No newline at end of file +} diff --git a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/org/apache/dubbo/remoting/zookeeper/curator/CuratorZookeeperClient.java b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/org/apache/dubbo/remoting/zookeeper/curator/CuratorZookeeperClient.java index 0f6f973575..419c5fb447 100644 --- a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/org/apache/dubbo/remoting/zookeeper/curator/CuratorZookeeperClient.java +++ b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/org/apache/dubbo/remoting/zookeeper/curator/CuratorZookeeperClient.java @@ -1,438 +1,438 @@ -/* - * 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.remoting.zookeeper.curator; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.config.configcenter.ConfigItem; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.remoting.zookeeper.ChildListener; -import org.apache.dubbo.remoting.zookeeper.DataListener; -import org.apache.dubbo.remoting.zookeeper.EventType; -import org.apache.dubbo.remoting.zookeeper.StateListener; -import org.apache.dubbo.remoting.zookeeper.support.AbstractZookeeperClient; - -import org.apache.curator.framework.CuratorFramework; -import org.apache.curator.framework.CuratorFrameworkFactory; -import org.apache.curator.framework.api.CuratorWatcher; -import org.apache.curator.framework.recipes.cache.ChildData; -import org.apache.curator.framework.recipes.cache.NodeCache; -import org.apache.curator.framework.recipes.cache.NodeCacheListener; -import org.apache.curator.framework.state.ConnectionState; -import org.apache.curator.framework.state.ConnectionStateListener; -import org.apache.curator.retry.RetryNTimes; -import org.apache.zookeeper.CreateMode; -import org.apache.zookeeper.KeeperException.NoNodeException; -import org.apache.zookeeper.KeeperException.NodeExistsException; -import org.apache.zookeeper.WatchedEvent; -import org.apache.zookeeper.Watcher; -import org.apache.zookeeper.data.Stat; - -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.Executor; -import java.util.concurrent.TimeUnit; - -import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY; - - -public class CuratorZookeeperClient extends AbstractZookeeperClient { - - protected static final Logger logger = LoggerFactory.getLogger(CuratorZookeeperClient.class); - private static final String ZK_SESSION_EXPIRE_KEY = "zk.session.expire"; - - private static final Charset CHARSET = StandardCharsets.UTF_8; - private final CuratorFramework client; - private static Map nodeCacheMap = new ConcurrentHashMap<>(); - - public CuratorZookeeperClient(URL url) { - super(url); - try { - int timeout = url.getParameter(TIMEOUT_KEY, DEFAULT_CONNECTION_TIMEOUT_MS); - int sessionExpireMs = url.getParameter(ZK_SESSION_EXPIRE_KEY, DEFAULT_SESSION_TIMEOUT_MS); - CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder() - .connectString(url.getBackupAddress()) - .retryPolicy(new RetryNTimes(1, 1000)) - .connectionTimeoutMs(timeout) - .sessionTimeoutMs(sessionExpireMs); - String authority = url.getAuthority(); - if (authority != null && authority.length() > 0) { - builder = builder.authorization("digest", authority.getBytes()); - } - client = builder.build(); - client.getConnectionStateListenable().addListener(new CuratorConnectionStateListener(url)); - client.start(); - boolean connected = client.blockUntilConnected(timeout, TimeUnit.MILLISECONDS); - if (!connected) { - throw new IllegalStateException("zookeeper not connected"); - } - } catch (Exception e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - - @Override - public void createPersistent(String path) { - try { - client.create().forPath(path); - } catch (NodeExistsException e) { - logger.warn("ZNode " + path + " already exists.", e); - } catch (Exception e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - - @Override - public void createEphemeral(String path) { - try { - client.create().withMode(CreateMode.EPHEMERAL).forPath(path); - } catch (NodeExistsException e) { - logger.warn("ZNode " + path + " already exists, since we will only try to recreate a node on a session expiration" + - ", this duplication might be caused by a delete delay from the zk server, which means the old expired session" + - " may still holds this ZNode and the server just hasn't got time to do the deletion. In this case, " + - "we can just try to delete and create again.", e); - deletePath(path); - createEphemeral(path); - } catch (Exception e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - - @Override - protected void createPersistent(String path, String data) { - byte[] dataBytes = data.getBytes(CHARSET); - try { - client.create().forPath(path, dataBytes); - } catch (NodeExistsException e) { - try { - client.setData().forPath(path, dataBytes); - } catch (Exception e1) { - throw new IllegalStateException(e.getMessage(), e1); - } - } catch (Exception e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - - @Override - protected void createEphemeral(String path, String data) { - byte[] dataBytes = data.getBytes(CHARSET); - try { - client.create().withMode(CreateMode.EPHEMERAL).forPath(path, dataBytes); - } catch (NodeExistsException e) { - logger.warn("ZNode " + path + " already exists, since we will only try to recreate a node on a session expiration" + - ", this duplication might be caused by a delete delay from the zk server, which means the old expired session" + - " may still holds this ZNode and the server just hasn't got time to do the deletion. In this case, " + - "we can just try to delete and create again.", e); - deletePath(path); - createEphemeral(path, data); - } catch (Exception e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - - @Override - protected void update(String path, String data, int version) { - byte[] dataBytes = data.getBytes(CHARSET); - try { - client.setData().withVersion(version).forPath(path, dataBytes); - } catch (Exception e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - - @Override - protected void createOrUpdatePersistent(String path, String data, int version) { - try { - if (checkExists(path)) { - update(path, data, version); - } else { - createPersistent(path, data); - } - } catch (Exception e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - - @Override - protected void createOrUpdateEphemeral(String path, String data, int version) { - try { - if (checkExists(path)) { - update(path, data, version); - } else { - createEphemeral(path, data); - } - } catch (Exception e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - - @Override - protected void deletePath(String path) { - try { - client.delete().deletingChildrenIfNeeded().forPath(path); - } catch (NoNodeException ignored) { - } catch (Exception e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - - @Override - public List getChildren(String path) { - try { - return client.getChildren().forPath(path); - } catch (NoNodeException e) { - return null; - } catch (Exception e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - - @Override - public boolean checkExists(String path) { - try { - if (client.checkExists().forPath(path) != null) { - return true; - } - } catch (Exception ignored) { - } - return false; - } - - @Override - public boolean isConnected() { - return client.getZookeeperClient().isConnected(); - } - - @Override - public String doGetContent(String path) { - try { - byte[] dataBytes = client.getData().forPath(path); - return (dataBytes == null || dataBytes.length == 0) ? null : new String(dataBytes, CHARSET); - } catch (NoNodeException e) { - // ignore NoNode Exception. - } catch (Exception e) { - throw new IllegalStateException(e.getMessage(), e); - } - return null; - } - - @Override - public ConfigItem doGetConfigItem(String path) { - String content; - Stat stat; - try { - stat = new Stat(); - byte[] dataBytes = client.getData().storingStatIn(stat).forPath(path); - content = (dataBytes == null || dataBytes.length == 0) ? null : new String(dataBytes, CHARSET); - } catch (NoNodeException e) { - return new ConfigItem(); - } catch (Exception e) { - throw new IllegalStateException(e.getMessage(), e); - } - return new ConfigItem(content, stat); - } - - @Override - public void doClose() { - client.close(); - } - - @Override - public CuratorZookeeperClient.CuratorWatcherImpl createTargetChildListener(String path, ChildListener listener) { - return new CuratorZookeeperClient.CuratorWatcherImpl(client, listener, path); - } - - @Override - public List addTargetChildListener(String path, CuratorWatcherImpl listener) { - try { - return client.getChildren().usingWatcher(listener).forPath(path); - } catch (NoNodeException e) { - return null; - } catch (Exception e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - - @Override - protected CuratorZookeeperClient.NodeCacheListenerImpl createTargetDataListener(String path, DataListener listener) { - return new NodeCacheListenerImpl(client, listener, path); - } - - @Override - protected void addTargetDataListener(String path, CuratorZookeeperClient.NodeCacheListenerImpl nodeCacheListener) { - this.addTargetDataListener(path, nodeCacheListener, null); - } - - @Override - protected void addTargetDataListener(String path, CuratorZookeeperClient.NodeCacheListenerImpl nodeCacheListener, Executor executor) { - try { - NodeCache nodeCache = new NodeCache(client, path); - if (nodeCacheMap.putIfAbsent(path, nodeCache) != null) { - return; - } - if (executor == null) { - nodeCache.getListenable().addListener(nodeCacheListener); - } else { - nodeCache.getListenable().addListener(nodeCacheListener, executor); - } - - nodeCache.start(); - } catch (Exception e) { - throw new IllegalStateException("Add nodeCache listener for path:" + path, e); - } - } - - @Override - protected void removeTargetDataListener(String path, CuratorZookeeperClient.NodeCacheListenerImpl nodeCacheListener) { - NodeCache nodeCache = nodeCacheMap.get(path); - if (nodeCache != null) { - nodeCache.getListenable().removeListener(nodeCacheListener); - } - nodeCacheListener.dataListener = null; - } - - @Override - public void removeTargetChildListener(String path, CuratorWatcherImpl listener) { - listener.unwatch(); - } - - static class NodeCacheListenerImpl implements NodeCacheListener { - - private CuratorFramework client; - - private volatile DataListener dataListener; - - private String path; - - protected NodeCacheListenerImpl() { - } - - public NodeCacheListenerImpl(CuratorFramework client, DataListener dataListener, String path) { - this.client = client; - this.dataListener = dataListener; - this.path = path; - } - - @Override - public void nodeChanged() throws Exception { - ChildData childData = nodeCacheMap.get(path).getCurrentData(); - String content = null; - EventType eventType; - if (childData == null) { - eventType = EventType.NodeDeleted; - } else { - content = new String(childData.getData(), CHARSET); - eventType = EventType.NodeDataChanged; - } - dataListener.dataChanged(path, content, eventType); - } - } - - static class CuratorWatcherImpl implements CuratorWatcher { - - private CuratorFramework client; - private volatile ChildListener childListener; - private String path; - - public CuratorWatcherImpl(CuratorFramework client, ChildListener listener, String path) { - this.client = client; - this.childListener = listener; - this.path = path; - } - - protected CuratorWatcherImpl() { - } - - public void unwatch() { - this.childListener = null; - } - - @Override - public void process(WatchedEvent event) throws Exception { - // if client connect or disconnect to server, zookeeper will queue - // watched event(Watcher.Event.EventType.None, .., path = null). - if (event.getType() == Watcher.Event.EventType.None) { - return; - } - - if (childListener != null) { - childListener.childChanged(path, client.getChildren().usingWatcher(this).forPath(path)); - } - } - } - - private class CuratorConnectionStateListener implements ConnectionStateListener { - private final long UNKNOWN_SESSION_ID = -1L; - - private long lastSessionId; - private int timeout; - private int sessionExpireMs; - - public CuratorConnectionStateListener(URL url) { - this.timeout = url.getParameter(TIMEOUT_KEY, DEFAULT_CONNECTION_TIMEOUT_MS); - this.sessionExpireMs = url.getParameter(ZK_SESSION_EXPIRE_KEY, DEFAULT_SESSION_TIMEOUT_MS); - } - - @Override - public void stateChanged(CuratorFramework client, ConnectionState state) { - long sessionId = UNKNOWN_SESSION_ID; - try { - sessionId = client.getZookeeperClient().getZooKeeper().getSessionId(); - } catch (Exception e) { - logger.warn("Curator client state changed, but failed to get the related zk session instance."); - } - - if (state == ConnectionState.LOST) { - logger.warn("Curator zookeeper session " + Long.toHexString(lastSessionId) + " expired."); - CuratorZookeeperClient.this.stateChanged(StateListener.SESSION_LOST); - } else if (state == ConnectionState.SUSPENDED) { - logger.warn("Curator zookeeper connection of session " + Long.toHexString(sessionId) + " timed out. " + - "connection timeout value is " + timeout + ", session expire timeout value is " + sessionExpireMs); - CuratorZookeeperClient.this.stateChanged(StateListener.SUSPENDED); - } else if (state == ConnectionState.CONNECTED) { - lastSessionId = sessionId; - logger.info("Curator zookeeper client instance initiated successfully, session id is " + Long.toHexString(sessionId)); - CuratorZookeeperClient.this.stateChanged(StateListener.CONNECTED); - } else if (state == ConnectionState.RECONNECTED) { - if (lastSessionId == sessionId && sessionId != UNKNOWN_SESSION_ID) { - logger.warn("Curator zookeeper connection recovered from connection lose, " + - "reuse the old session " + Long.toHexString(sessionId)); - CuratorZookeeperClient.this.stateChanged(StateListener.RECONNECTED); - } else { - logger.warn("New session created after old session lost, " + - "old session " + Long.toHexString(lastSessionId) + ", new session " + Long.toHexString(sessionId)); - lastSessionId = sessionId; - CuratorZookeeperClient.this.stateChanged(StateListener.NEW_SESSION_CREATED); - } - } - } - - } - - /** - * just for unit test - * - * @return - */ - CuratorFramework getClient() { - return client; - } -} +/* + * 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.remoting.zookeeper.curator; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.config.configcenter.ConfigItem; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.remoting.zookeeper.ChildListener; +import org.apache.dubbo.remoting.zookeeper.DataListener; +import org.apache.dubbo.remoting.zookeeper.EventType; +import org.apache.dubbo.remoting.zookeeper.StateListener; +import org.apache.dubbo.remoting.zookeeper.support.AbstractZookeeperClient; + +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.CuratorFrameworkFactory; +import org.apache.curator.framework.api.CuratorWatcher; +import org.apache.curator.framework.recipes.cache.ChildData; +import org.apache.curator.framework.recipes.cache.NodeCache; +import org.apache.curator.framework.recipes.cache.NodeCacheListener; +import org.apache.curator.framework.state.ConnectionState; +import org.apache.curator.framework.state.ConnectionStateListener; +import org.apache.curator.retry.RetryNTimes; +import org.apache.zookeeper.CreateMode; +import org.apache.zookeeper.KeeperException.NoNodeException; +import org.apache.zookeeper.KeeperException.NodeExistsException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; + +import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY; + + +public class CuratorZookeeperClient extends AbstractZookeeperClient { + + protected static final Logger logger = LoggerFactory.getLogger(CuratorZookeeperClient.class); + private static final String ZK_SESSION_EXPIRE_KEY = "zk.session.expire"; + + private static final Charset CHARSET = StandardCharsets.UTF_8; + private final CuratorFramework client; + private static Map nodeCacheMap = new ConcurrentHashMap<>(); + + public CuratorZookeeperClient(URL url) { + super(url); + try { + int timeout = url.getParameter(TIMEOUT_KEY, DEFAULT_CONNECTION_TIMEOUT_MS); + int sessionExpireMs = url.getParameter(ZK_SESSION_EXPIRE_KEY, DEFAULT_SESSION_TIMEOUT_MS); + CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder() + .connectString(url.getBackupAddress()) + .retryPolicy(new RetryNTimes(1, 1000)) + .connectionTimeoutMs(timeout) + .sessionTimeoutMs(sessionExpireMs); + String authority = url.getAuthority(); + if (authority != null && authority.length() > 0) { + builder = builder.authorization("digest", authority.getBytes()); + } + client = builder.build(); + client.getConnectionStateListenable().addListener(new CuratorConnectionStateListener(url)); + client.start(); + boolean connected = client.blockUntilConnected(timeout, TimeUnit.MILLISECONDS); + if (!connected) { + throw new IllegalStateException("zookeeper not connected"); + } + } catch (Exception e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + @Override + public void createPersistent(String path) { + try { + client.create().forPath(path); + } catch (NodeExistsException e) { + logger.warn("ZNode " + path + " already exists.", e); + } catch (Exception e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + @Override + public void createEphemeral(String path) { + try { + client.create().withMode(CreateMode.EPHEMERAL).forPath(path); + } catch (NodeExistsException e) { + logger.warn("ZNode " + path + " already exists, since we will only try to recreate a node on a session expiration" + + ", this duplication might be caused by a delete delay from the zk server, which means the old expired session" + + " may still holds this ZNode and the server just hasn't got time to do the deletion. In this case, " + + "we can just try to delete and create again.", e); + deletePath(path); + createEphemeral(path); + } catch (Exception e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + @Override + protected void createPersistent(String path, String data) { + byte[] dataBytes = data.getBytes(CHARSET); + try { + client.create().forPath(path, dataBytes); + } catch (NodeExistsException e) { + try { + client.setData().forPath(path, dataBytes); + } catch (Exception e1) { + throw new IllegalStateException(e.getMessage(), e1); + } + } catch (Exception e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + @Override + protected void createEphemeral(String path, String data) { + byte[] dataBytes = data.getBytes(CHARSET); + try { + client.create().withMode(CreateMode.EPHEMERAL).forPath(path, dataBytes); + } catch (NodeExistsException e) { + logger.warn("ZNode " + path + " already exists, since we will only try to recreate a node on a session expiration" + + ", this duplication might be caused by a delete delay from the zk server, which means the old expired session" + + " may still holds this ZNode and the server just hasn't got time to do the deletion. In this case, " + + "we can just try to delete and create again.", e); + deletePath(path); + createEphemeral(path, data); + } catch (Exception e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + @Override + protected void update(String path, String data, int version) { + byte[] dataBytes = data.getBytes(CHARSET); + try { + client.setData().withVersion(version).forPath(path, dataBytes); + } catch (Exception e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + @Override + protected void createOrUpdatePersistent(String path, String data, int version) { + try { + if (checkExists(path)) { + update(path, data, version); + } else { + createPersistent(path, data); + } + } catch (Exception e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + @Override + protected void createOrUpdateEphemeral(String path, String data, int version) { + try { + if (checkExists(path)) { + update(path, data, version); + } else { + createEphemeral(path, data); + } + } catch (Exception e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + @Override + protected void deletePath(String path) { + try { + client.delete().deletingChildrenIfNeeded().forPath(path); + } catch (NoNodeException ignored) { + } catch (Exception e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + @Override + public List getChildren(String path) { + try { + return client.getChildren().forPath(path); + } catch (NoNodeException e) { + return null; + } catch (Exception e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + @Override + public boolean checkExists(String path) { + try { + if (client.checkExists().forPath(path) != null) { + return true; + } + } catch (Exception ignored) { + } + return false; + } + + @Override + public boolean isConnected() { + return client.getZookeeperClient().isConnected(); + } + + @Override + public String doGetContent(String path) { + try { + byte[] dataBytes = client.getData().forPath(path); + return (dataBytes == null || dataBytes.length == 0) ? null : new String(dataBytes, CHARSET); + } catch (NoNodeException e) { + // ignore NoNode Exception. + } catch (Exception e) { + throw new IllegalStateException(e.getMessage(), e); + } + return null; + } + + @Override + public ConfigItem doGetConfigItem(String path) { + String content; + Stat stat; + try { + stat = new Stat(); + byte[] dataBytes = client.getData().storingStatIn(stat).forPath(path); + content = (dataBytes == null || dataBytes.length == 0) ? null : new String(dataBytes, CHARSET); + } catch (NoNodeException e) { + return new ConfigItem(); + } catch (Exception e) { + throw new IllegalStateException(e.getMessage(), e); + } + return new ConfigItem(content, stat); + } + + @Override + public void doClose() { + client.close(); + } + + @Override + public CuratorZookeeperClient.CuratorWatcherImpl createTargetChildListener(String path, ChildListener listener) { + return new CuratorZookeeperClient.CuratorWatcherImpl(client, listener, path); + } + + @Override + public List addTargetChildListener(String path, CuratorWatcherImpl listener) { + try { + return client.getChildren().usingWatcher(listener).forPath(path); + } catch (NoNodeException e) { + return null; + } catch (Exception e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + @Override + protected CuratorZookeeperClient.NodeCacheListenerImpl createTargetDataListener(String path, DataListener listener) { + return new NodeCacheListenerImpl(client, listener, path); + } + + @Override + protected void addTargetDataListener(String path, CuratorZookeeperClient.NodeCacheListenerImpl nodeCacheListener) { + this.addTargetDataListener(path, nodeCacheListener, null); + } + + @Override + protected void addTargetDataListener(String path, CuratorZookeeperClient.NodeCacheListenerImpl nodeCacheListener, Executor executor) { + try { + NodeCache nodeCache = new NodeCache(client, path); + if (nodeCacheMap.putIfAbsent(path, nodeCache) != null) { + return; + } + if (executor == null) { + nodeCache.getListenable().addListener(nodeCacheListener); + } else { + nodeCache.getListenable().addListener(nodeCacheListener, executor); + } + + nodeCache.start(); + } catch (Exception e) { + throw new IllegalStateException("Add nodeCache listener for path:" + path, e); + } + } + + @Override + protected void removeTargetDataListener(String path, CuratorZookeeperClient.NodeCacheListenerImpl nodeCacheListener) { + NodeCache nodeCache = nodeCacheMap.get(path); + if (nodeCache != null) { + nodeCache.getListenable().removeListener(nodeCacheListener); + } + nodeCacheListener.dataListener = null; + } + + @Override + public void removeTargetChildListener(String path, CuratorWatcherImpl listener) { + listener.unwatch(); + } + + static class NodeCacheListenerImpl implements NodeCacheListener { + + private CuratorFramework client; + + private volatile DataListener dataListener; + + private String path; + + protected NodeCacheListenerImpl() { + } + + public NodeCacheListenerImpl(CuratorFramework client, DataListener dataListener, String path) { + this.client = client; + this.dataListener = dataListener; + this.path = path; + } + + @Override + public void nodeChanged() throws Exception { + ChildData childData = nodeCacheMap.get(path).getCurrentData(); + String content = null; + EventType eventType; + if (childData == null) { + eventType = EventType.NodeDeleted; + } else { + content = new String(childData.getData(), CHARSET); + eventType = EventType.NodeDataChanged; + } + dataListener.dataChanged(path, content, eventType); + } + } + + static class CuratorWatcherImpl implements CuratorWatcher { + + private CuratorFramework client; + private volatile ChildListener childListener; + private String path; + + public CuratorWatcherImpl(CuratorFramework client, ChildListener listener, String path) { + this.client = client; + this.childListener = listener; + this.path = path; + } + + protected CuratorWatcherImpl() { + } + + public void unwatch() { + this.childListener = null; + } + + @Override + public void process(WatchedEvent event) throws Exception { + // if client connect or disconnect to server, zookeeper will queue + // watched event(Watcher.Event.EventType.None, .., path = null). + if (event.getType() == Watcher.Event.EventType.None) { + return; + } + + if (childListener != null) { + childListener.childChanged(path, client.getChildren().usingWatcher(this).forPath(path)); + } + } + } + + private class CuratorConnectionStateListener implements ConnectionStateListener { + private final long UNKNOWN_SESSION_ID = -1L; + + private long lastSessionId; + private int timeout; + private int sessionExpireMs; + + public CuratorConnectionStateListener(URL url) { + this.timeout = url.getParameter(TIMEOUT_KEY, DEFAULT_CONNECTION_TIMEOUT_MS); + this.sessionExpireMs = url.getParameter(ZK_SESSION_EXPIRE_KEY, DEFAULT_SESSION_TIMEOUT_MS); + } + + @Override + public void stateChanged(CuratorFramework client, ConnectionState state) { + long sessionId = UNKNOWN_SESSION_ID; + try { + sessionId = client.getZookeeperClient().getZooKeeper().getSessionId(); + } catch (Exception e) { + logger.warn("Curator client state changed, but failed to get the related zk session instance."); + } + + if (state == ConnectionState.LOST) { + logger.warn("Curator zookeeper session " + Long.toHexString(lastSessionId) + " expired."); + CuratorZookeeperClient.this.stateChanged(StateListener.SESSION_LOST); + } else if (state == ConnectionState.SUSPENDED) { + logger.warn("Curator zookeeper connection of session " + Long.toHexString(sessionId) + " timed out. " + + "connection timeout value is " + timeout + ", session expire timeout value is " + sessionExpireMs); + CuratorZookeeperClient.this.stateChanged(StateListener.SUSPENDED); + } else if (state == ConnectionState.CONNECTED) { + lastSessionId = sessionId; + logger.info("Curator zookeeper client instance initiated successfully, session id is " + Long.toHexString(sessionId)); + CuratorZookeeperClient.this.stateChanged(StateListener.CONNECTED); + } else if (state == ConnectionState.RECONNECTED) { + if (lastSessionId == sessionId && sessionId != UNKNOWN_SESSION_ID) { + logger.warn("Curator zookeeper connection recovered from connection lose, " + + "reuse the old session " + Long.toHexString(sessionId)); + CuratorZookeeperClient.this.stateChanged(StateListener.RECONNECTED); + } else { + logger.warn("New session created after old session lost, " + + "old session " + Long.toHexString(lastSessionId) + ", new session " + Long.toHexString(sessionId)); + lastSessionId = sessionId; + CuratorZookeeperClient.this.stateChanged(StateListener.NEW_SESSION_CREATED); + } + } + } + + } + + /** + * just for unit test + * + * @return + */ + CuratorFramework getClient() { + return client; + } +} diff --git a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/org/apache/dubbo/remoting/zookeeper/support/AbstractZookeeperClient.java b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/org/apache/dubbo/remoting/zookeeper/support/AbstractZookeeperClient.java index debc70e9ba..178c4bd12b 100644 --- a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/org/apache/dubbo/remoting/zookeeper/support/AbstractZookeeperClient.java +++ b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/org/apache/dubbo/remoting/zookeeper/support/AbstractZookeeperClient.java @@ -1,257 +1,257 @@ -/* - * 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.remoting.zookeeper.support; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.config.configcenter.ConfigItem; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.utils.ConcurrentHashSet; -import org.apache.dubbo.remoting.zookeeper.ChildListener; -import org.apache.dubbo.remoting.zookeeper.DataListener; -import org.apache.dubbo.remoting.zookeeper.StateListener; -import org.apache.dubbo.remoting.zookeeper.ZookeeperClient; - -import java.util.List; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.CopyOnWriteArraySet; -import java.util.concurrent.Executor; - -public abstract class AbstractZookeeperClient implements ZookeeperClient { - - protected static final Logger logger = LoggerFactory.getLogger(AbstractZookeeperClient.class); - - protected int DEFAULT_CONNECTION_TIMEOUT_MS = 5 * 1000; - protected int DEFAULT_SESSION_TIMEOUT_MS = 60 * 1000; - - private final URL url; - - private final Set stateListeners = new CopyOnWriteArraySet(); - - private final ConcurrentMap> childListeners = - new ConcurrentHashMap>(); - - private final ConcurrentMap> listeners = - new ConcurrentHashMap>(); - - private volatile boolean closed = false; - - private final Set persistentExistNodePath = new ConcurrentHashSet<>(); - - public AbstractZookeeperClient(URL url) { - this.url = url; - } - - @Override - public URL getUrl() { - return url; - } - - @Override - public void delete(String path) { - //never mind if ephemeral - persistentExistNodePath.remove(path); - deletePath(path); - } - - - @Override - public void create(String path, boolean ephemeral) { - if (!ephemeral) { - if (persistentExistNodePath.contains(path)) { - return; - } - if (checkExists(path)) { - persistentExistNodePath.add(path); - return; - } - } - int i = path.lastIndexOf('/'); - if (i > 0) { - create(path.substring(0, i), false); - } - if (ephemeral) { - createEphemeral(path); - } else { - createPersistent(path); - persistentExistNodePath.add(path); - } - } - - @Override - public void addStateListener(StateListener listener) { - stateListeners.add(listener); - } - - @Override - public void removeStateListener(StateListener listener) { - stateListeners.remove(listener); - } - - public Set getSessionListeners() { - return stateListeners; - } - - @Override - public List addChildListener(String path, final ChildListener listener) { - ConcurrentMap listeners = childListeners.computeIfAbsent(path, k -> new ConcurrentHashMap<>()); - TargetChildListener targetListener = listeners.computeIfAbsent(listener, k -> createTargetChildListener(path, k)); - return addTargetChildListener(path, targetListener); - } - - @Override - public void addDataListener(String path, DataListener listener) { - this.addDataListener(path, listener, null); - } - - @Override - public void addDataListener(String path, DataListener listener, Executor executor) { - ConcurrentMap dataListenerMap = listeners.computeIfAbsent(path, k -> new ConcurrentHashMap<>()); - TargetDataListener targetListener = dataListenerMap.computeIfAbsent(listener, k -> createTargetDataListener(path, k)); - addTargetDataListener(path, targetListener, executor); - } - - @Override - public void removeDataListener(String path, DataListener listener) { - ConcurrentMap dataListenerMap = listeners.get(path); - if (dataListenerMap != null) { - TargetDataListener targetListener = dataListenerMap.remove(listener); - if (targetListener != null) { - removeTargetDataListener(path, targetListener); - } - } - } - - @Override - public void removeChildListener(String path, ChildListener listener) { - ConcurrentMap listeners = childListeners.get(path); - if (listeners != null) { - TargetChildListener targetListener = listeners.remove(listener); - if (targetListener != null) { - removeTargetChildListener(path, targetListener); - } - } - } - - protected void stateChanged(int state) { - for (StateListener sessionListener : getSessionListeners()) { - sessionListener.stateChanged(state); - } - } - - @Override - public void close() { - if (closed) { - return; - } - closed = true; - try { - doClose(); - } catch (Throwable t) { - logger.warn(t.getMessage(), t); - } - } - - @Override - public void create(String path, String content, boolean ephemeral) { - if (checkExists(path)) { - delete(path); - } - int i = path.lastIndexOf('/'); - if (i > 0) { - create(path.substring(0, i), false); - } - if (ephemeral) { - createEphemeral(path, content); - } else { - createPersistent(path, content); - } - } - - @Override - public void createOrUpdate(String path, String content, boolean ephemeral, int version) { - int i = path.lastIndexOf('/'); - if (i > 0) { - create(path.substring(0, i), false); - } - if (ephemeral) { - createOrUpdateEphemeral(path, content, version); - } else { - createOrUpdatePersistent(path, content, version); - } - } - - @Override - public String getContent(String path) { - if (!checkExists(path)) { - return null; - } - return doGetContent(path); - } - - @Override - public ConfigItem getConfigItem(String path) { - return doGetConfigItem(path); - } - - protected abstract void doClose(); - - protected abstract void createPersistent(String path); - - protected abstract void createEphemeral(String path); - - protected abstract void createPersistent(String path, String data); - - protected abstract void createEphemeral(String path, String data); - - protected abstract void update(String path, String data, int version); - - protected abstract void createOrUpdatePersistent(String path, String data, int version); - - protected abstract void createOrUpdateEphemeral(String path, String data, int version); - - @Override - public abstract boolean checkExists(String path); - - protected abstract TargetChildListener createTargetChildListener(String path, ChildListener listener); - - protected abstract List addTargetChildListener(String path, TargetChildListener listener); - - protected abstract TargetDataListener createTargetDataListener(String path, DataListener listener); - - protected abstract void addTargetDataListener(String path, TargetDataListener listener); - - protected abstract void addTargetDataListener(String path, TargetDataListener listener, Executor executor); - - protected abstract void removeTargetDataListener(String path, TargetDataListener listener); - - protected abstract void removeTargetChildListener(String path, TargetChildListener listener); - - protected abstract String doGetContent(String path); - - protected abstract ConfigItem doGetConfigItem(String path); - - /** - * we invoke the zookeeper client to delete the node - * - * @param path the node path - */ - protected abstract void deletePath(String path); - -} +/* + * 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.remoting.zookeeper.support; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.config.configcenter.ConfigItem; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.ConcurrentHashSet; +import org.apache.dubbo.remoting.zookeeper.ChildListener; +import org.apache.dubbo.remoting.zookeeper.DataListener; +import org.apache.dubbo.remoting.zookeeper.StateListener; +import org.apache.dubbo.remoting.zookeeper.ZookeeperClient; + +import java.util.List; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.Executor; + +public abstract class AbstractZookeeperClient implements ZookeeperClient { + + protected static final Logger logger = LoggerFactory.getLogger(AbstractZookeeperClient.class); + + protected int DEFAULT_CONNECTION_TIMEOUT_MS = 5 * 1000; + protected int DEFAULT_SESSION_TIMEOUT_MS = 60 * 1000; + + private final URL url; + + private final Set stateListeners = new CopyOnWriteArraySet(); + + private final ConcurrentMap> childListeners = + new ConcurrentHashMap>(); + + private final ConcurrentMap> listeners = + new ConcurrentHashMap>(); + + private volatile boolean closed = false; + + private final Set persistentExistNodePath = new ConcurrentHashSet<>(); + + public AbstractZookeeperClient(URL url) { + this.url = url; + } + + @Override + public URL getUrl() { + return url; + } + + @Override + public void delete(String path) { + //never mind if ephemeral + persistentExistNodePath.remove(path); + deletePath(path); + } + + + @Override + public void create(String path, boolean ephemeral) { + if (!ephemeral) { + if (persistentExistNodePath.contains(path)) { + return; + } + if (checkExists(path)) { + persistentExistNodePath.add(path); + return; + } + } + int i = path.lastIndexOf('/'); + if (i > 0) { + create(path.substring(0, i), false); + } + if (ephemeral) { + createEphemeral(path); + } else { + createPersistent(path); + persistentExistNodePath.add(path); + } + } + + @Override + public void addStateListener(StateListener listener) { + stateListeners.add(listener); + } + + @Override + public void removeStateListener(StateListener listener) { + stateListeners.remove(listener); + } + + public Set getSessionListeners() { + return stateListeners; + } + + @Override + public List addChildListener(String path, final ChildListener listener) { + ConcurrentMap listeners = childListeners.computeIfAbsent(path, k -> new ConcurrentHashMap<>()); + TargetChildListener targetListener = listeners.computeIfAbsent(listener, k -> createTargetChildListener(path, k)); + return addTargetChildListener(path, targetListener); + } + + @Override + public void addDataListener(String path, DataListener listener) { + this.addDataListener(path, listener, null); + } + + @Override + public void addDataListener(String path, DataListener listener, Executor executor) { + ConcurrentMap dataListenerMap = listeners.computeIfAbsent(path, k -> new ConcurrentHashMap<>()); + TargetDataListener targetListener = dataListenerMap.computeIfAbsent(listener, k -> createTargetDataListener(path, k)); + addTargetDataListener(path, targetListener, executor); + } + + @Override + public void removeDataListener(String path, DataListener listener) { + ConcurrentMap dataListenerMap = listeners.get(path); + if (dataListenerMap != null) { + TargetDataListener targetListener = dataListenerMap.remove(listener); + if (targetListener != null) { + removeTargetDataListener(path, targetListener); + } + } + } + + @Override + public void removeChildListener(String path, ChildListener listener) { + ConcurrentMap listeners = childListeners.get(path); + if (listeners != null) { + TargetChildListener targetListener = listeners.remove(listener); + if (targetListener != null) { + removeTargetChildListener(path, targetListener); + } + } + } + + protected void stateChanged(int state) { + for (StateListener sessionListener : getSessionListeners()) { + sessionListener.stateChanged(state); + } + } + + @Override + public void close() { + if (closed) { + return; + } + closed = true; + try { + doClose(); + } catch (Throwable t) { + logger.warn(t.getMessage(), t); + } + } + + @Override + public void create(String path, String content, boolean ephemeral) { + if (checkExists(path)) { + delete(path); + } + int i = path.lastIndexOf('/'); + if (i > 0) { + create(path.substring(0, i), false); + } + if (ephemeral) { + createEphemeral(path, content); + } else { + createPersistent(path, content); + } + } + + @Override + public void createOrUpdate(String path, String content, boolean ephemeral, int version) { + int i = path.lastIndexOf('/'); + if (i > 0) { + create(path.substring(0, i), false); + } + if (ephemeral) { + createOrUpdateEphemeral(path, content, version); + } else { + createOrUpdatePersistent(path, content, version); + } + } + + @Override + public String getContent(String path) { + if (!checkExists(path)) { + return null; + } + return doGetContent(path); + } + + @Override + public ConfigItem getConfigItem(String path) { + return doGetConfigItem(path); + } + + protected abstract void doClose(); + + protected abstract void createPersistent(String path); + + protected abstract void createEphemeral(String path); + + protected abstract void createPersistent(String path, String data); + + protected abstract void createEphemeral(String path, String data); + + protected abstract void update(String path, String data, int version); + + protected abstract void createOrUpdatePersistent(String path, String data, int version); + + protected abstract void createOrUpdateEphemeral(String path, String data, int version); + + @Override + public abstract boolean checkExists(String path); + + protected abstract TargetChildListener createTargetChildListener(String path, ChildListener listener); + + protected abstract List addTargetChildListener(String path, TargetChildListener listener); + + protected abstract TargetDataListener createTargetDataListener(String path, DataListener listener); + + protected abstract void addTargetDataListener(String path, TargetDataListener listener); + + protected abstract void addTargetDataListener(String path, TargetDataListener listener, Executor executor); + + protected abstract void removeTargetDataListener(String path, TargetDataListener listener); + + protected abstract void removeTargetChildListener(String path, TargetChildListener listener); + + protected abstract String doGetContent(String path); + + protected abstract ConfigItem doGetConfigItem(String path); + + /** + * we invoke the zookeeper client to delete the node + * + * @param path the node path + */ + protected abstract void deletePath(String path); + +} diff --git a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter index f8cbd5b417..44f9374cd1 100644 --- a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter +++ b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter @@ -1 +1 @@ -curator=org.apache.dubbo.remoting.zookeeper.curator.CuratorZookeeperTransporter +curator=org.apache.dubbo.remoting.zookeeper.curator.CuratorZookeeperTransporter diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/AttachmentsAdapter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/AttachmentsAdapter.java index def349a753..44b36cb797 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/AttachmentsAdapter.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/AttachmentsAdapter.java @@ -69,4 +69,4 @@ public class AttachmentsAdapter { super.putAll(map); } } -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Exporter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Exporter.java index c0a71164f0..d02a4050dc 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Exporter.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Exporter.java @@ -1,44 +1,44 @@ -/* - * 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.rpc; - -/** - * Exporter. (API/SPI, Prototype, ThreadSafe) - * - * @see org.apache.dubbo.rpc.Protocol#export(Invoker) - * @see org.apache.dubbo.rpc.ExporterListener - * @see org.apache.dubbo.rpc.protocol.AbstractExporter - */ -public interface Exporter { - - /** - * get invoker. - * - * @return invoker - */ - Invoker getInvoker(); - - /** - * unexport. - *

- * - * getInvoker().destroy(); - * - */ - void unexport(); - -} \ No newline at end of file +/* + * 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.rpc; + +/** + * Exporter. (API/SPI, Prototype, ThreadSafe) + * + * @see org.apache.dubbo.rpc.Protocol#export(Invoker) + * @see org.apache.dubbo.rpc.ExporterListener + * @see org.apache.dubbo.rpc.protocol.AbstractExporter + */ +public interface Exporter { + + /** + * get invoker. + * + * @return invoker + */ + Invoker getInvoker(); + + /** + * unexport. + *

+ * + * getInvoker().destroy(); + * + */ + void unexport(); + +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/ExporterListener.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/ExporterListener.java index a7c9c5de8a..d20cc1bedc 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/ExporterListener.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/ExporterListener.java @@ -1,45 +1,45 @@ -/* - * 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.rpc; - -import org.apache.dubbo.common.extension.SPI; - -/** - * ExporterListener. (SPI, Singleton, ThreadSafe) - */ -@SPI -public interface ExporterListener { - - /** - * The exporter exported. - * - * @param exporter - * @throws RpcException - * @see org.apache.dubbo.rpc.Protocol#export(Invoker) - */ - void exported(Exporter exporter) throws RpcException; - - /** - * The exporter unexported. - * - * @param exporter - * @throws RpcException - * @see org.apache.dubbo.rpc.Exporter#unexport() - */ - void unexported(Exporter exporter); - -} \ No newline at end of file +/* + * 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.rpc; + +import org.apache.dubbo.common.extension.SPI; + +/** + * ExporterListener. (SPI, Singleton, ThreadSafe) + */ +@SPI +public interface ExporterListener { + + /** + * The exporter exported. + * + * @param exporter + * @throws RpcException + * @see org.apache.dubbo.rpc.Protocol#export(Invoker) + */ + void exported(Exporter exporter) throws RpcException; + + /** + * The exporter unexported. + * + * @param exporter + * @throws RpcException + * @see org.apache.dubbo.rpc.Exporter#unexport() + */ + void unexported(Exporter exporter); + +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Filter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Filter.java index 74acb51d4b..da26f6e8db 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Filter.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Filter.java @@ -1,71 +1,71 @@ -/* - * 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.rpc; - -import org.apache.dubbo.common.extension.SPI; - -/** - * Extension for intercepting the invocation for both service provider and consumer, furthermore, most of - * functions in dubbo are implemented base on the same mechanism. Since every time when remote method is - * invoked, the filter extensions will be executed too, the corresponding penalty should be considered before - * more filters are added. - *

- *  They way filter work from sequence point of view is
- *    
- *    ...code before filter ...
- *          invoker.invoke(invocation) //filter work in a filter implementation class
- *          ...code after filter ...
- *    
- *    Caching is implemented in dubbo using filter approach. If cache is configured for invocation then before
- *    remote call configured caching type's (e.g. Thread Local, JCache etc) implementation invoke method gets called.
- * 
- * - * Start from 3.0, the semantics of the Filter component at the consumer side has changed. - * Instead of intercepting a specific instance of invoker, Filter in 3.0 now intercepts ClusterInvoker. A new SPI named - * InstanceFilter is introduced to work as the same semantic as Filter in 2.x. - * - * The difference of Filter is as follows: - * - * 3.x Filter - * - * -> InstanceFilter -> Invoker - * - * Proxy -> Filter -> Filter -> ClusterInvoker -> InstanceFilter -> Invoker - * - * -> InstanceFilter -> Invoker - * - * - * 2.x Filter - * - * Filter -> Filter -> Invoker - * - * Proxy -> ClusterInvoker -> Filter -> Filter -> Invoker - * - * Filter -> Filter -> Invoker - * - * If you want to a Filter - * - * Filter. (SPI, Singleton, ThreadSafe) - * - * @see org.apache.dubbo.rpc.filter.GenericFilter - * @see org.apache.dubbo.rpc.filter.EchoFilter - * @see org.apache.dubbo.rpc.filter.TokenFilter - * @see org.apache.dubbo.rpc.filter.TpsLimitFilter - */ -@SPI -public interface Filter extends BaseFilter { -} \ No newline at end of file +/* + * 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.rpc; + +import org.apache.dubbo.common.extension.SPI; + +/** + * Extension for intercepting the invocation for both service provider and consumer, furthermore, most of + * functions in dubbo are implemented base on the same mechanism. Since every time when remote method is + * invoked, the filter extensions will be executed too, the corresponding penalty should be considered before + * more filters are added. + *
+ *  They way filter work from sequence point of view is
+ *    
+ *    ...code before filter ...
+ *          invoker.invoke(invocation) //filter work in a filter implementation class
+ *          ...code after filter ...
+ *    
+ *    Caching is implemented in dubbo using filter approach. If cache is configured for invocation then before
+ *    remote call configured caching type's (e.g. Thread Local, JCache etc) implementation invoke method gets called.
+ * 
+ * + * Start from 3.0, the semantics of the Filter component at the consumer side has changed. + * Instead of intercepting a specific instance of invoker, Filter in 3.0 now intercepts ClusterInvoker. A new SPI named + * InstanceFilter is introduced to work as the same semantic as Filter in 2.x. + * + * The difference of Filter is as follows: + * + * 3.x Filter + * + * -> InstanceFilter -> Invoker + * + * Proxy -> Filter -> Filter -> ClusterInvoker -> InstanceFilter -> Invoker + * + * -> InstanceFilter -> Invoker + * + * + * 2.x Filter + * + * Filter -> Filter -> Invoker + * + * Proxy -> ClusterInvoker -> Filter -> Filter -> Invoker + * + * Filter -> Filter -> Invoker + * + * If you want to a Filter + * + * Filter. (SPI, Singleton, ThreadSafe) + * + * @see org.apache.dubbo.rpc.filter.GenericFilter + * @see org.apache.dubbo.rpc.filter.EchoFilter + * @see org.apache.dubbo.rpc.filter.TokenFilter + * @see org.apache.dubbo.rpc.filter.TpsLimitFilter + */ +@SPI +public interface Filter extends BaseFilter { +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Invocation.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Invocation.java index 5da0a73eda..bedd350af1 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Invocation.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Invocation.java @@ -143,4 +143,4 @@ public interface Invocation { Object get(Object key); Map getAttributes(); -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Invoker.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Invoker.java index 04186fad82..6bf3a3a3ce 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Invoker.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Invoker.java @@ -1,46 +1,46 @@ -/* - * 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.rpc; - -import org.apache.dubbo.common.Node; - -/** - * Invoker. (API/SPI, Prototype, ThreadSafe) - * - * @see org.apache.dubbo.rpc.Protocol#refer(Class, org.apache.dubbo.common.URL) - * @see org.apache.dubbo.rpc.InvokerListener - * @see org.apache.dubbo.rpc.protocol.AbstractInvoker - */ -public interface Invoker extends Node { - - /** - * get service interface. - * - * @return service interface. - */ - Class getInterface(); - - /** - * invoke. - * - * @param invocation - * @return result - * @throws RpcException - */ - Result invoke(Invocation invocation) throws RpcException; - -} \ No newline at end of file +/* + * 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.rpc; + +import org.apache.dubbo.common.Node; + +/** + * Invoker. (API/SPI, Prototype, ThreadSafe) + * + * @see org.apache.dubbo.rpc.Protocol#refer(Class, org.apache.dubbo.common.URL) + * @see org.apache.dubbo.rpc.InvokerListener + * @see org.apache.dubbo.rpc.protocol.AbstractInvoker + */ +public interface Invoker extends Node { + + /** + * get service interface. + * + * @return service interface. + */ + Class getInterface(); + + /** + * invoke. + * + * @param invocation + * @return result + * @throws RpcException + */ + Result invoke(Invocation invocation) throws RpcException; + +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/InvokerListener.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/InvokerListener.java index 5516b07836..b81de6ab4c 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/InvokerListener.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/InvokerListener.java @@ -1,44 +1,44 @@ -/* - * 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.rpc; - -import org.apache.dubbo.common.extension.SPI; - -/** - * InvokerListener. (SPI, Singleton, ThreadSafe) - */ -@SPI -public interface InvokerListener { - - /** - * The invoker referred - * - * @param invoker - * @throws RpcException - * @see org.apache.dubbo.rpc.Protocol#refer(Class, org.apache.dubbo.common.URL) - */ - void referred(Invoker invoker) throws RpcException; - - /** - * The invoker destroyed. - * - * @param invoker - * @see org.apache.dubbo.rpc.Invoker#destroy() - */ - void destroyed(Invoker invoker); - -} \ No newline at end of file +/* + * 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.rpc; + +import org.apache.dubbo.common.extension.SPI; + +/** + * InvokerListener. (SPI, Singleton, ThreadSafe) + */ +@SPI +public interface InvokerListener { + + /** + * The invoker referred + * + * @param invoker + * @throws RpcException + * @see org.apache.dubbo.rpc.Protocol#refer(Class, org.apache.dubbo.common.URL) + */ + void referred(Invoker invoker) throws RpcException; + + /** + * The invoker destroyed. + * + * @param invoker + * @see org.apache.dubbo.rpc.Invoker#destroy() + */ + void destroyed(Invoker invoker); + +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Protocol.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Protocol.java index dc3a0201a1..5f86ec5901 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Protocol.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Protocol.java @@ -1,90 +1,90 @@ -/* - * 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.rpc; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.extension.Adaptive; -import org.apache.dubbo.common.extension.SPI; - -import java.util.Collections; -import java.util.List; - -/** - * Protocol. (API/SPI, Singleton, ThreadSafe) - */ -@SPI("dubbo") -public interface Protocol { - - /** - * Get default port when user doesn't config the port. - * - * @return default port - */ - int getDefaultPort(); - - /** - * Export service for remote invocation:
- * 1. Protocol should record request source address after receive a request: - * RpcContext.getServerAttachment().setRemoteAddress();
- * 2. export() must be idempotent, that is, there's no difference between invoking once and invoking twice when - * export the same URL
- * 3. Invoker instance is passed in by the framework, protocol needs not to care
- * - * @param Service type - * @param invoker Service invoker - * @return exporter reference for exported service, useful for unexport the service later - * @throws RpcException thrown when error occurs during export the service, for example: port is occupied - */ - @Adaptive - Exporter export(Invoker invoker) throws RpcException; - - /** - * Refer a remote service:
- * 1. When user calls `invoke()` method of `Invoker` object which's returned from `refer()` call, the protocol - * needs to correspondingly execute `invoke()` method of `Invoker` object
- * 2. It's protocol's responsibility to implement `Invoker` which's returned from `refer()`. Generally speaking, - * protocol sends remote request in the `Invoker` implementation.
- * 3. When there's check=false set in URL, the implementation must not throw exception but try to recover when - * connection fails. - * - * @param Service type - * @param type Service class - * @param url URL address for the remote service - * @return invoker service's local proxy - * @throws RpcException when there's any error while connecting to the service provider - */ - @Adaptive - Invoker refer(Class type, URL url) throws RpcException; - - /** - * Destroy protocol:
- * 1. Cancel all services this protocol exports and refers
- * 2. Release all occupied resources, for example: connection, port, etc.
- * 3. Protocol can continue to export and refer new service even after it's destroyed. - */ - void destroy(); - - /** - * Get all servers serving this protocol - * - * @return - */ - default List getServers() { - return Collections.emptyList(); - } - -} \ No newline at end of file +/* + * 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.rpc; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.Adaptive; +import org.apache.dubbo.common.extension.SPI; + +import java.util.Collections; +import java.util.List; + +/** + * Protocol. (API/SPI, Singleton, ThreadSafe) + */ +@SPI("dubbo") +public interface Protocol { + + /** + * Get default port when user doesn't config the port. + * + * @return default port + */ + int getDefaultPort(); + + /** + * Export service for remote invocation:
+ * 1. Protocol should record request source address after receive a request: + * RpcContext.getServerAttachment().setRemoteAddress();
+ * 2. export() must be idempotent, that is, there's no difference between invoking once and invoking twice when + * export the same URL
+ * 3. Invoker instance is passed in by the framework, protocol needs not to care
+ * + * @param Service type + * @param invoker Service invoker + * @return exporter reference for exported service, useful for unexport the service later + * @throws RpcException thrown when error occurs during export the service, for example: port is occupied + */ + @Adaptive + Exporter export(Invoker invoker) throws RpcException; + + /** + * Refer a remote service:
+ * 1. When user calls `invoke()` method of `Invoker` object which's returned from `refer()` call, the protocol + * needs to correspondingly execute `invoke()` method of `Invoker` object
+ * 2. It's protocol's responsibility to implement `Invoker` which's returned from `refer()`. Generally speaking, + * protocol sends remote request in the `Invoker` implementation.
+ * 3. When there's check=false set in URL, the implementation must not throw exception but try to recover when + * connection fails. + * + * @param Service type + * @param type Service class + * @param url URL address for the remote service + * @return invoker service's local proxy + * @throws RpcException when there's any error while connecting to the service provider + */ + @Adaptive + Invoker refer(Class type, URL url) throws RpcException; + + /** + * Destroy protocol:
+ * 1. Cancel all services this protocol exports and refers
+ * 2. Release all occupied resources, for example: connection, port, etc.
+ * 3. Protocol can continue to export and refer new service even after it's destroyed. + */ + void destroy(); + + /** + * Get all servers serving this protocol + * + * @return + */ + default List getServers() { + return Collections.emptyList(); + } + +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/ProxyFactory.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/ProxyFactory.java index c745a765de..f7e607f11f 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/ProxyFactory.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/ProxyFactory.java @@ -58,4 +58,4 @@ public interface ProxyFactory { @Adaptive({PROXY_KEY}) Invoker getInvoker(T proxy, Class type, URL url) throws RpcException; -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Result.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Result.java index 7620465a80..b0dd6f6286 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Result.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Result.java @@ -186,4 +186,4 @@ public interface Result extends Serializable { Result get() throws InterruptedException, ExecutionException; Result get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcConstants.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcConstants.java index 2c7186f6d9..18e6ed3c15 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcConstants.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcConstants.java @@ -1,37 +1,37 @@ -/* - * 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.rpc; - -import org.apache.dubbo.common.constants.CommonConstants; -import org.apache.dubbo.common.constants.FilterConstants; -import org.apache.dubbo.common.constants.QosConstants; -import org.apache.dubbo.common.constants.RegistryConstants; -import org.apache.dubbo.common.constants.RemotingConstants; - -/** - * RpcConstants - * - * @deprecated Replace to org.apache.dubbo.common.Constants - */ -@Deprecated -public final class RpcConstants implements CommonConstants, QosConstants, FilterConstants, - RegistryConstants, RemotingConstants { - - private RpcConstants() { - } - -} +/* + * 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.rpc; + +import org.apache.dubbo.common.constants.CommonConstants; +import org.apache.dubbo.common.constants.FilterConstants; +import org.apache.dubbo.common.constants.QosConstants; +import org.apache.dubbo.common.constants.RegistryConstants; +import org.apache.dubbo.common.constants.RemotingConstants; + +/** + * RpcConstants + * + * @deprecated Replace to org.apache.dubbo.common.Constants + */ +@Deprecated +public final class RpcConstants implements CommonConstants, QosConstants, FilterConstants, + RegistryConstants, RemotingConstants { + + private RpcConstants() { + } + +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcException.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcException.java index d57815158d..be6ed6875a 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcException.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcException.java @@ -116,4 +116,4 @@ public /**final**/ class RpcException extends RuntimeException { public boolean isLimitExceed() { return code == LIMIT_EXCEEDED_EXCEPTION || getCause() instanceof LimitExceededException; } -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcStatus.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcStatus.java index 093baf581d..d451c342aa 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcStatus.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcStatus.java @@ -1,320 +1,320 @@ -/* - * 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.rpc; - -import org.apache.dubbo.common.URL; - -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; - -/** - * URL statistics. (API, Cached, ThreadSafe) - * - * @see org.apache.dubbo.rpc.filter.ActiveLimitFilter - * @see org.apache.dubbo.rpc.filter.ExecuteLimitFilter - * @see org.apache.dubbo.rpc.cluster.loadbalance.LeastActiveLoadBalance - */ -public class RpcStatus { - - private static final ConcurrentMap SERVICE_STATISTICS = new ConcurrentHashMap(); - - private static final ConcurrentMap> METHOD_STATISTICS = - new ConcurrentHashMap>(); - - private final ConcurrentMap values = new ConcurrentHashMap(); - - private final AtomicInteger active = new AtomicInteger(); - private final AtomicLong total = new AtomicLong(); - private final AtomicInteger failed = new AtomicInteger(); - private final AtomicLong totalElapsed = new AtomicLong(); - private final AtomicLong failedElapsed = new AtomicLong(); - private final AtomicLong maxElapsed = new AtomicLong(); - private final AtomicLong failedMaxElapsed = new AtomicLong(); - private final AtomicLong succeededMaxElapsed = new AtomicLong(); - - private RpcStatus() { - } - - /** - * @param url - * @return status - */ - public static RpcStatus getStatus(URL url) { - String uri = url.toIdentityString(); - return SERVICE_STATISTICS.computeIfAbsent(uri, key -> new RpcStatus()); - } - - /** - * @param url - */ - public static void removeStatus(URL url) { - String uri = url.toIdentityString(); - SERVICE_STATISTICS.remove(uri); - } - - /** - * @param url - * @param methodName - * @return status - */ - public static RpcStatus getStatus(URL url, String methodName) { - String uri = url.toIdentityString(); - ConcurrentMap map = METHOD_STATISTICS.computeIfAbsent(uri, k -> new ConcurrentHashMap<>()); - return map.computeIfAbsent(methodName, k -> new RpcStatus()); - } - - /** - * @param url - */ - public static void removeStatus(URL url, String methodName) { - String uri = url.toIdentityString(); - ConcurrentMap map = METHOD_STATISTICS.get(uri); - if (map != null) { - map.remove(methodName); - } - } - - public static void beginCount(URL url, String methodName) { - beginCount(url, methodName, Integer.MAX_VALUE); - } - - /** - * @param url - */ - public static boolean beginCount(URL url, String methodName, int max) { - max = (max <= 0) ? Integer.MAX_VALUE : max; - RpcStatus appStatus = getStatus(url); - RpcStatus methodStatus = getStatus(url, methodName); - if (methodStatus.active.get() == Integer.MAX_VALUE) { - return false; - } - for (int i; ; ) { - i = methodStatus.active.get(); - - if (i == Integer.MAX_VALUE || i + 1 > max) { - return false; - } - - if (methodStatus.active.compareAndSet(i, i + 1)) { - break; - } - } - - appStatus.active.incrementAndGet(); - - return true; - } - - /** - * @param url - * @param elapsed - * @param succeeded - */ - public static void endCount(URL url, String methodName, long elapsed, boolean succeeded) { - endCount(getStatus(url), elapsed, succeeded); - endCount(getStatus(url, methodName), elapsed, succeeded); - } - - private static void endCount(RpcStatus status, long elapsed, boolean succeeded) { - status.active.decrementAndGet(); - status.total.incrementAndGet(); - status.totalElapsed.addAndGet(elapsed); - - if (status.maxElapsed.get() < elapsed) { - status.maxElapsed.set(elapsed); - } - - if (succeeded) { - if (status.succeededMaxElapsed.get() < elapsed) { - status.succeededMaxElapsed.set(elapsed); - } - - } else { - status.failed.incrementAndGet(); - status.failedElapsed.addAndGet(elapsed); - if (status.failedMaxElapsed.get() < elapsed) { - status.failedMaxElapsed.set(elapsed); - } - } - } - - /** - * set value. - * - * @param key - * @param value - */ - public void set(String key, Object value) { - values.put(key, value); - } - - /** - * get value. - * - * @param key - * @return value - */ - public Object get(String key) { - return values.get(key); - } - - /** - * get active. - * - * @return active - */ - public int getActive() { - return active.get(); - } - - /** - * get total. - * - * @return total - */ - public long getTotal() { - return total.longValue(); - } - - /** - * get total elapsed. - * - * @return total elapsed - */ - public long getTotalElapsed() { - return totalElapsed.get(); - } - - /** - * get average elapsed. - * - * @return average elapsed - */ - public long getAverageElapsed() { - long total = getTotal(); - if (total == 0) { - return 0; - } - return getTotalElapsed() / total; - } - - /** - * get max elapsed. - * - * @return max elapsed - */ - public long getMaxElapsed() { - return maxElapsed.get(); - } - - /** - * get failed. - * - * @return failed - */ - public int getFailed() { - return failed.get(); - } - - /** - * get failed elapsed. - * - * @return failed elapsed - */ - public long getFailedElapsed() { - return failedElapsed.get(); - } - - /** - * get failed average elapsed. - * - * @return failed average elapsed - */ - public long getFailedAverageElapsed() { - long failed = getFailed(); - if (failed == 0) { - return 0; - } - return getFailedElapsed() / failed; - } - - /** - * get failed max elapsed. - * - * @return failed max elapsed - */ - public long getFailedMaxElapsed() { - return failedMaxElapsed.get(); - } - - /** - * get succeeded. - * - * @return succeeded - */ - public long getSucceeded() { - return getTotal() - getFailed(); - } - - /** - * get succeeded elapsed. - * - * @return succeeded elapsed - */ - public long getSucceededElapsed() { - return getTotalElapsed() - getFailedElapsed(); - } - - /** - * get succeeded average elapsed. - * - * @return succeeded average elapsed - */ - public long getSucceededAverageElapsed() { - long succeeded = getSucceeded(); - if (succeeded == 0) { - return 0; - } - return getSucceededElapsed() / succeeded; - } - - /** - * get succeeded max elapsed. - * - * @return succeeded max elapsed. - */ - public long getSucceededMaxElapsed() { - return succeededMaxElapsed.get(); - } - - /** - * Calculate average TPS (Transaction per second). - * - * @return tps - */ - public long getAverageTps() { - if (getTotalElapsed() >= 1000L) { - return getTotal() / (getTotalElapsed() / 1000L); - } - return getTotal(); - } - - -} +/* + * 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.rpc; + +import org.apache.dubbo.common.URL; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; + +/** + * URL statistics. (API, Cached, ThreadSafe) + * + * @see org.apache.dubbo.rpc.filter.ActiveLimitFilter + * @see org.apache.dubbo.rpc.filter.ExecuteLimitFilter + * @see org.apache.dubbo.rpc.cluster.loadbalance.LeastActiveLoadBalance + */ +public class RpcStatus { + + private static final ConcurrentMap SERVICE_STATISTICS = new ConcurrentHashMap(); + + private static final ConcurrentMap> METHOD_STATISTICS = + new ConcurrentHashMap>(); + + private final ConcurrentMap values = new ConcurrentHashMap(); + + private final AtomicInteger active = new AtomicInteger(); + private final AtomicLong total = new AtomicLong(); + private final AtomicInteger failed = new AtomicInteger(); + private final AtomicLong totalElapsed = new AtomicLong(); + private final AtomicLong failedElapsed = new AtomicLong(); + private final AtomicLong maxElapsed = new AtomicLong(); + private final AtomicLong failedMaxElapsed = new AtomicLong(); + private final AtomicLong succeededMaxElapsed = new AtomicLong(); + + private RpcStatus() { + } + + /** + * @param url + * @return status + */ + public static RpcStatus getStatus(URL url) { + String uri = url.toIdentityString(); + return SERVICE_STATISTICS.computeIfAbsent(uri, key -> new RpcStatus()); + } + + /** + * @param url + */ + public static void removeStatus(URL url) { + String uri = url.toIdentityString(); + SERVICE_STATISTICS.remove(uri); + } + + /** + * @param url + * @param methodName + * @return status + */ + public static RpcStatus getStatus(URL url, String methodName) { + String uri = url.toIdentityString(); + ConcurrentMap map = METHOD_STATISTICS.computeIfAbsent(uri, k -> new ConcurrentHashMap<>()); + return map.computeIfAbsent(methodName, k -> new RpcStatus()); + } + + /** + * @param url + */ + public static void removeStatus(URL url, String methodName) { + String uri = url.toIdentityString(); + ConcurrentMap map = METHOD_STATISTICS.get(uri); + if (map != null) { + map.remove(methodName); + } + } + + public static void beginCount(URL url, String methodName) { + beginCount(url, methodName, Integer.MAX_VALUE); + } + + /** + * @param url + */ + public static boolean beginCount(URL url, String methodName, int max) { + max = (max <= 0) ? Integer.MAX_VALUE : max; + RpcStatus appStatus = getStatus(url); + RpcStatus methodStatus = getStatus(url, methodName); + if (methodStatus.active.get() == Integer.MAX_VALUE) { + return false; + } + for (int i; ; ) { + i = methodStatus.active.get(); + + if (i == Integer.MAX_VALUE || i + 1 > max) { + return false; + } + + if (methodStatus.active.compareAndSet(i, i + 1)) { + break; + } + } + + appStatus.active.incrementAndGet(); + + return true; + } + + /** + * @param url + * @param elapsed + * @param succeeded + */ + public static void endCount(URL url, String methodName, long elapsed, boolean succeeded) { + endCount(getStatus(url), elapsed, succeeded); + endCount(getStatus(url, methodName), elapsed, succeeded); + } + + private static void endCount(RpcStatus status, long elapsed, boolean succeeded) { + status.active.decrementAndGet(); + status.total.incrementAndGet(); + status.totalElapsed.addAndGet(elapsed); + + if (status.maxElapsed.get() < elapsed) { + status.maxElapsed.set(elapsed); + } + + if (succeeded) { + if (status.succeededMaxElapsed.get() < elapsed) { + status.succeededMaxElapsed.set(elapsed); + } + + } else { + status.failed.incrementAndGet(); + status.failedElapsed.addAndGet(elapsed); + if (status.failedMaxElapsed.get() < elapsed) { + status.failedMaxElapsed.set(elapsed); + } + } + } + + /** + * set value. + * + * @param key + * @param value + */ + public void set(String key, Object value) { + values.put(key, value); + } + + /** + * get value. + * + * @param key + * @return value + */ + public Object get(String key) { + return values.get(key); + } + + /** + * get active. + * + * @return active + */ + public int getActive() { + return active.get(); + } + + /** + * get total. + * + * @return total + */ + public long getTotal() { + return total.longValue(); + } + + /** + * get total elapsed. + * + * @return total elapsed + */ + public long getTotalElapsed() { + return totalElapsed.get(); + } + + /** + * get average elapsed. + * + * @return average elapsed + */ + public long getAverageElapsed() { + long total = getTotal(); + if (total == 0) { + return 0; + } + return getTotalElapsed() / total; + } + + /** + * get max elapsed. + * + * @return max elapsed + */ + public long getMaxElapsed() { + return maxElapsed.get(); + } + + /** + * get failed. + * + * @return failed + */ + public int getFailed() { + return failed.get(); + } + + /** + * get failed elapsed. + * + * @return failed elapsed + */ + public long getFailedElapsed() { + return failedElapsed.get(); + } + + /** + * get failed average elapsed. + * + * @return failed average elapsed + */ + public long getFailedAverageElapsed() { + long failed = getFailed(); + if (failed == 0) { + return 0; + } + return getFailedElapsed() / failed; + } + + /** + * get failed max elapsed. + * + * @return failed max elapsed + */ + public long getFailedMaxElapsed() { + return failedMaxElapsed.get(); + } + + /** + * get succeeded. + * + * @return succeeded + */ + public long getSucceeded() { + return getTotal() - getFailed(); + } + + /** + * get succeeded elapsed. + * + * @return succeeded elapsed + */ + public long getSucceededElapsed() { + return getTotalElapsed() - getFailedElapsed(); + } + + /** + * get succeeded average elapsed. + * + * @return succeeded average elapsed + */ + public long getSucceededAverageElapsed() { + long succeeded = getSucceeded(); + if (succeeded == 0) { + return 0; + } + return getSucceededElapsed() / succeeded; + } + + /** + * get succeeded max elapsed. + * + * @return succeeded max elapsed. + */ + public long getSucceededMaxElapsed() { + return succeededMaxElapsed.get(); + } + + /** + * Calculate average TPS (Transaction per second). + * + * @return tps + */ + public long getAverageTps() { + if (getTotalElapsed() >= 1000L) { + return getTotal() / (getTotalElapsed() / 1000L); + } + return getTotal(); + } + + +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/listener/DeprecatedInvokerListener.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/listener/DeprecatedInvokerListener.java index 5e98370801..a647769e83 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/listener/DeprecatedInvokerListener.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/listener/DeprecatedInvokerListener.java @@ -1,42 +1,42 @@ -/* - * 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.rpc.listener; - -import org.apache.dubbo.common.extension.Activate; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.RpcException; - -import static org.apache.dubbo.rpc.Constants.DEPRECATED_KEY; - -/** - * DeprecatedProtocolFilter - */ -@Activate(DEPRECATED_KEY) -public class DeprecatedInvokerListener extends InvokerListenerAdapter { - - private static final Logger LOGGER = LoggerFactory.getLogger(DeprecatedInvokerListener.class); - - @Override - public void referred(Invoker invoker) throws RpcException { - if (invoker.getUrl().getParameter(DEPRECATED_KEY, false)) { - LOGGER.error("The service " + invoker.getInterface().getName() + " is DEPRECATED! Declare from " + invoker.getUrl()); - } - } - -} +/* + * 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.rpc.listener; + +import org.apache.dubbo.common.extension.Activate; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.RpcException; + +import static org.apache.dubbo.rpc.Constants.DEPRECATED_KEY; + +/** + * DeprecatedProtocolFilter + */ +@Activate(DEPRECATED_KEY) +public class DeprecatedInvokerListener extends InvokerListenerAdapter { + + private static final Logger LOGGER = LoggerFactory.getLogger(DeprecatedInvokerListener.class); + + @Override + public void referred(Invoker invoker) throws RpcException { + if (invoker.getUrl().getParameter(DEPRECATED_KEY, false)) { + LOGGER.error("The service " + invoker.getInterface().getName() + " is DEPRECATED! Declare from " + invoker.getUrl()); + } + } + +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/listener/ExporterListenerAdapter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/listener/ExporterListenerAdapter.java index e4f9e50d56..001bc9c5c5 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/listener/ExporterListenerAdapter.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/listener/ExporterListenerAdapter.java @@ -1,36 +1,36 @@ -/* - * 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.rpc.listener; - -import org.apache.dubbo.rpc.Exporter; -import org.apache.dubbo.rpc.ExporterListener; -import org.apache.dubbo.rpc.RpcException; - -/** - * ExporterListenerAdapter - */ -public abstract class ExporterListenerAdapter implements ExporterListener { - - @Override - public void exported(Exporter exporter) throws RpcException { - } - - @Override - public void unexported(Exporter exporter) throws RpcException { - } - -} +/* + * 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.rpc.listener; + +import org.apache.dubbo.rpc.Exporter; +import org.apache.dubbo.rpc.ExporterListener; +import org.apache.dubbo.rpc.RpcException; + +/** + * ExporterListenerAdapter + */ +public abstract class ExporterListenerAdapter implements ExporterListener { + + @Override + public void exported(Exporter exporter) throws RpcException { + } + + @Override + public void unexported(Exporter exporter) throws RpcException { + } + +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/listener/InvokerListenerAdapter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/listener/InvokerListenerAdapter.java index 4de28e9c83..ebe5a9ea4c 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/listener/InvokerListenerAdapter.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/listener/InvokerListenerAdapter.java @@ -1,36 +1,36 @@ -/* - * 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.rpc.listener; - -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.InvokerListener; -import org.apache.dubbo.rpc.RpcException; - -/** - * InvokerListenerAdapter - */ -public abstract class InvokerListenerAdapter implements InvokerListener { - - @Override - public void referred(Invoker invoker) throws RpcException { - } - - @Override - public void destroyed(Invoker invoker) { - } - -} +/* + * 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.rpc.listener; + +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.InvokerListener; +import org.apache.dubbo.rpc.RpcException; + +/** + * InvokerListenerAdapter + */ +public abstract class InvokerListenerAdapter implements InvokerListener { + + @Override + public void referred(Invoker invoker) throws RpcException { + } + + @Override + public void destroyed(Invoker invoker) { + } + +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/listener/ListenerExporterWrapper.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/listener/ListenerExporterWrapper.java index 7ac188e21d..df3497f690 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/listener/ListenerExporterWrapper.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/listener/ListenerExporterWrapper.java @@ -1,92 +1,92 @@ -/* - * 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.rpc.listener; - -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.utils.CollectionUtils; -import org.apache.dubbo.rpc.Exporter; -import org.apache.dubbo.rpc.ExporterListener; -import org.apache.dubbo.rpc.Invoker; - -import java.util.List; - -/** - * ListenerExporter - */ -public class ListenerExporterWrapper implements Exporter { - - private static final Logger logger = LoggerFactory.getLogger(ListenerExporterWrapper.class); - - private final Exporter exporter; - - private final List listeners; - - public ListenerExporterWrapper(Exporter exporter, List listeners) { - if (exporter == null) { - throw new IllegalArgumentException("exporter == null"); - } - this.exporter = exporter; - this.listeners = listeners; - if (CollectionUtils.isNotEmpty(listeners)) { - RuntimeException exception = null; - for (ExporterListener listener : listeners) { - if (listener != null) { - try { - listener.exported(this); - } catch (RuntimeException t) { - logger.error(t.getMessage(), t); - exception = t; - } - } - } - if (exception != null) { - throw exception; - } - } - } - - @Override - public Invoker getInvoker() { - return exporter.getInvoker(); - } - - @Override - public void unexport() { - try { - exporter.unexport(); - } finally { - if (CollectionUtils.isNotEmpty(listeners)) { - RuntimeException exception = null; - for (ExporterListener listener : listeners) { - if (listener != null) { - try { - listener.unexported(this); - } catch (RuntimeException t) { - logger.error(t.getMessage(), t); - exception = t; - } - } - } - if (exception != null) { - throw exception; - } - } - } - } - -} +/* + * 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.rpc.listener; + +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.rpc.Exporter; +import org.apache.dubbo.rpc.ExporterListener; +import org.apache.dubbo.rpc.Invoker; + +import java.util.List; + +/** + * ListenerExporter + */ +public class ListenerExporterWrapper implements Exporter { + + private static final Logger logger = LoggerFactory.getLogger(ListenerExporterWrapper.class); + + private final Exporter exporter; + + private final List listeners; + + public ListenerExporterWrapper(Exporter exporter, List listeners) { + if (exporter == null) { + throw new IllegalArgumentException("exporter == null"); + } + this.exporter = exporter; + this.listeners = listeners; + if (CollectionUtils.isNotEmpty(listeners)) { + RuntimeException exception = null; + for (ExporterListener listener : listeners) { + if (listener != null) { + try { + listener.exported(this); + } catch (RuntimeException t) { + logger.error(t.getMessage(), t); + exception = t; + } + } + } + if (exception != null) { + throw exception; + } + } + } + + @Override + public Invoker getInvoker() { + return exporter.getInvoker(); + } + + @Override + public void unexport() { + try { + exporter.unexport(); + } finally { + if (CollectionUtils.isNotEmpty(listeners)) { + RuntimeException exception = null; + for (ExporterListener listener : listeners) { + if (listener != null) { + try { + listener.unexported(this); + } catch (RuntimeException t) { + logger.error(t.getMessage(), t); + exception = t; + } + } + } + if (exception != null) { + throw exception; + } + } + } + } + +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/listener/ListenerInvokerWrapper.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/listener/ListenerInvokerWrapper.java index 4c5498a383..a0fea1066f 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/listener/ListenerInvokerWrapper.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/listener/ListenerInvokerWrapper.java @@ -1,105 +1,105 @@ -/* - * 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.rpc.listener; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.utils.CollectionUtils; -import org.apache.dubbo.rpc.Invocation; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.InvokerListener; -import org.apache.dubbo.rpc.Result; -import org.apache.dubbo.rpc.RpcException; - -import java.util.List; - -/** - * ListenerInvoker - */ -public class ListenerInvokerWrapper implements Invoker { - - private static final Logger logger = LoggerFactory.getLogger(ListenerInvokerWrapper.class); - - private final Invoker invoker; - - private final List listeners; - - public ListenerInvokerWrapper(Invoker invoker, List listeners) { - if (invoker == null) { - throw new IllegalArgumentException("invoker == null"); - } - this.invoker = invoker; - this.listeners = listeners; - if (CollectionUtils.isNotEmpty(listeners)) { - for (InvokerListener listener : listeners) { - if (listener != null) { - try { - listener.referred(invoker); - } catch (Throwable t) { - logger.error(t.getMessage(), t); - } - } - } - } - } - - @Override - public Class getInterface() { - return invoker.getInterface(); - } - - @Override - public URL getUrl() { - return invoker.getUrl(); - } - - @Override - public boolean isAvailable() { - return invoker.isAvailable(); - } - - @Override - public Result invoke(Invocation invocation) throws RpcException { - return invoker.invoke(invocation); - } - - @Override - public String toString() { - return getInterface() + " -> " + (getUrl() == null ? " " : getUrl().toString()); - } - - @Override - public void destroy() { - try { - invoker.destroy(); - } finally { - if (CollectionUtils.isNotEmpty(listeners)) { - for (InvokerListener listener : listeners) { - if (listener != null) { - try { - listener.destroyed(invoker); - } catch (Throwable t) { - logger.error(t.getMessage(), t); - } - } - } - } - } - } - -} +/* + * 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.rpc.listener; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.InvokerListener; +import org.apache.dubbo.rpc.Result; +import org.apache.dubbo.rpc.RpcException; + +import java.util.List; + +/** + * ListenerInvoker + */ +public class ListenerInvokerWrapper implements Invoker { + + private static final Logger logger = LoggerFactory.getLogger(ListenerInvokerWrapper.class); + + private final Invoker invoker; + + private final List listeners; + + public ListenerInvokerWrapper(Invoker invoker, List listeners) { + if (invoker == null) { + throw new IllegalArgumentException("invoker == null"); + } + this.invoker = invoker; + this.listeners = listeners; + if (CollectionUtils.isNotEmpty(listeners)) { + for (InvokerListener listener : listeners) { + if (listener != null) { + try { + listener.referred(invoker); + } catch (Throwable t) { + logger.error(t.getMessage(), t); + } + } + } + } + } + + @Override + public Class getInterface() { + return invoker.getInterface(); + } + + @Override + public URL getUrl() { + return invoker.getUrl(); + } + + @Override + public boolean isAvailable() { + return invoker.isAvailable(); + } + + @Override + public Result invoke(Invocation invocation) throws RpcException { + return invoker.invoke(invocation); + } + + @Override + public String toString() { + return getInterface() + " -> " + (getUrl() == null ? " " : getUrl().toString()); + } + + @Override + public void destroy() { + try { + invoker.destroy(); + } finally { + if (CollectionUtils.isNotEmpty(listeners)) { + for (InvokerListener listener : listeners) { + if (listener != null) { + try { + listener.destroyed(invoker); + } catch (Throwable t) { + logger.error(t.getMessage(), t); + } + } + } + } + } + } + +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractExporter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractExporter.java index 99c9ebd2ff..41e4eccb95 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractExporter.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractExporter.java @@ -1,74 +1,74 @@ -/* - * 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.rpc.protocol; - -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.rpc.Exporter; -import org.apache.dubbo.rpc.Invoker; - -/** - * AbstractExporter. - */ -public abstract class AbstractExporter implements Exporter { - - protected final Logger logger = LoggerFactory.getLogger(getClass()); - - private final Invoker invoker; - - private volatile boolean unexported = false; - - public AbstractExporter(Invoker invoker) { - if (invoker == null) { - throw new IllegalStateException("service invoker == null"); - } - if (invoker.getInterface() == null) { - throw new IllegalStateException("service type == null"); - } - if (invoker.getUrl() == null) { - throw new IllegalStateException("service url == null"); - } - this.invoker = invoker; - } - - @Override - public Invoker getInvoker() { - return invoker; - } - - @Override - final public void unexport() { - if (unexported) { - return; - } - unexported = true; - getInvoker().destroy(); - afterUnExport(); - } - - /** - * subclasses need to override this method to destroy resources. - */ - public void afterUnExport() { - } - - @Override - public String toString() { - return getInvoker().toString(); - } - -} +/* + * 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.rpc.protocol; + +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.rpc.Exporter; +import org.apache.dubbo.rpc.Invoker; + +/** + * AbstractExporter. + */ +public abstract class AbstractExporter implements Exporter { + + protected final Logger logger = LoggerFactory.getLogger(getClass()); + + private final Invoker invoker; + + private volatile boolean unexported = false; + + public AbstractExporter(Invoker invoker) { + if (invoker == null) { + throw new IllegalStateException("service invoker == null"); + } + if (invoker.getInterface() == null) { + throw new IllegalStateException("service type == null"); + } + if (invoker.getUrl() == null) { + throw new IllegalStateException("service url == null"); + } + this.invoker = invoker; + } + + @Override + public Invoker getInvoker() { + return invoker; + } + + @Override + final public void unexport() { + if (unexported) { + return; + } + unexported = true; + getInvoker().destroy(); + afterUnExport(); + } + + /** + * subclasses need to override this method to destroy resources. + */ + public void afterUnExport() { + } + + @Override + public String toString() { + return getInvoker().toString(); + } + +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractProxyProtocol.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractProxyProtocol.java index c9965a2bbc..fc22913ab4 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractProxyProtocol.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractProxyProtocol.java @@ -1,281 +1,281 @@ -/* - * 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.rpc.protocol; - -import org.apache.dubbo.common.Parameters; -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.utils.NetUtils; -import org.apache.dubbo.common.utils.StringUtils; -import org.apache.dubbo.remoting.Channel; -import org.apache.dubbo.remoting.ChannelHandler; -import org.apache.dubbo.remoting.Constants; -import org.apache.dubbo.remoting.RemotingException; -import org.apache.dubbo.remoting.RemotingServer; -import org.apache.dubbo.rpc.Exporter; -import org.apache.dubbo.rpc.Invocation; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.ProtocolServer; -import org.apache.dubbo.rpc.ProxyFactory; -import org.apache.dubbo.rpc.Result; -import org.apache.dubbo.rpc.RpcException; - -import java.net.InetSocketAddress; -import java.util.Collection; -import java.util.List; -import java.util.Objects; -import java.util.concurrent.CopyOnWriteArrayList; - -import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_VALUE; - -/** - * AbstractProxyProtocol - */ -public abstract class AbstractProxyProtocol extends AbstractProtocol { - - private final List> rpcExceptions = new CopyOnWriteArrayList>(); - - protected ProxyFactory proxyFactory; - - public AbstractProxyProtocol() { - } - - public AbstractProxyProtocol(Class... exceptions) { - for (Class exception : exceptions) { - addRpcException(exception); - } - } - - public void addRpcException(Class exception) { - this.rpcExceptions.add(exception); - } - - public ProxyFactory getProxyFactory() { - return proxyFactory; - } - - public void setProxyFactory(ProxyFactory proxyFactory) { - this.proxyFactory = proxyFactory; - } - - @Override - @SuppressWarnings("unchecked") - public Exporter export(final Invoker invoker) throws RpcException { - final String uri = serviceKey(invoker.getUrl()); - Exporter exporter = (Exporter) exporterMap.get(uri); - if (exporter != null) { - // When modifying the configuration through override, you need to re-expose the newly modified service. - if (Objects.equals(exporter.getInvoker().getUrl(), invoker.getUrl())) { - return exporter; - } - } - final Runnable runnable = doExport(proxyFactory.getProxy(invoker, true), invoker.getInterface(), invoker.getUrl()); - exporter = new AbstractExporter(invoker) { - @Override - public void afterUnExport() { - exporterMap.remove(uri); - if (runnable != null) { - try { - runnable.run(); - } catch (Throwable t) { - logger.warn(t.getMessage(), t); - } - } - } - }; - exporterMap.put(uri, exporter); - return exporter; - } - - @Override - protected Invoker protocolBindingRefer(final Class type, final URL url) throws RpcException { - final Invoker target = proxyFactory.getInvoker(doRefer(type, url), type, url); - Invoker invoker = new AbstractInvoker(type, url) { - @Override - protected Result doInvoke(Invocation invocation) throws Throwable { - try { - Result result = target.invoke(invocation); - // FIXME result is an AsyncRpcResult instance. - 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); - } - } - - @Override - public void destroy() { - super.destroy(); - target.destroy(); - invokers.remove(this); - } - }; - 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 String getAddr(URL url) { - String bindIp = url.getParameter(Constants.BIND_IP_KEY, url.getHost()); - if (url.getParameter(ANYHOST_KEY, false)) { - bindIp = ANYHOST_VALUE; - } - return NetUtils.getIpByHost(bindIp) + ":" + url.getParameter(Constants.BIND_PORT_KEY, url.getPort()); - } - - protected int getErrorCode(Throwable e) { - return RpcException.UNKNOWN_EXCEPTION; - } - - protected abstract Runnable doExport(T impl, Class type, URL url) throws RpcException; - - protected abstract T doRefer(Class type, URL url) throws RpcException; - - protected class ProxyProtocolServer implements ProtocolServer { - - private RemotingServer server; - private String address; - - public ProxyProtocolServer(RemotingServer server) { - this.server = server; - } - - @Override - public RemotingServer getRemotingServer() { - return server; - } - - @Override - public String getAddress() { - return StringUtils.isNotEmpty(address) ? address : server.getUrl().getAddress(); - } - - @Override - public void setAddress(String address) { - this.address = address; - } - - @Override - public URL getUrl() { - return server.getUrl(); - } - - @Override - public void close() { - server.close(); - } - } - - protected abstract class RemotingServerAdapter implements RemotingServer { - - public abstract Object getDelegateServer(); - - /** - * @return - */ - @Override - public boolean isBound() { - return false; - } - - @Override - public Collection getChannels() { - return null; - } - - @Override - public Channel getChannel(InetSocketAddress remoteAddress) { - return null; - } - - @Override - public void reset(Parameters parameters) { - - } - - @Override - public void reset(URL url) { - - } - - @Override - public URL getUrl() { - return null; - } - - @Override - public ChannelHandler getChannelHandler() { - return null; - } - - @Override - public InetSocketAddress getLocalAddress() { - return null; - } - - @Override - public void send(Object message) throws RemotingException { - - } - - @Override - public void send(Object message, boolean sent) throws RemotingException { - - } - - @Override - public void close() { - - } - - @Override - public void close(int timeout) { - - } - - @Override - public void startClose() { - - } - - @Override - public boolean isClosed() { - return false; - } - } - - -} +/* + * 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.rpc.protocol; + +import org.apache.dubbo.common.Parameters; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.utils.NetUtils; +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.remoting.Channel; +import org.apache.dubbo.remoting.ChannelHandler; +import org.apache.dubbo.remoting.Constants; +import org.apache.dubbo.remoting.RemotingException; +import org.apache.dubbo.remoting.RemotingServer; +import org.apache.dubbo.rpc.Exporter; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.ProtocolServer; +import org.apache.dubbo.rpc.ProxyFactory; +import org.apache.dubbo.rpc.Result; +import org.apache.dubbo.rpc.RpcException; + +import java.net.InetSocketAddress; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.CopyOnWriteArrayList; + +import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_VALUE; + +/** + * AbstractProxyProtocol + */ +public abstract class AbstractProxyProtocol extends AbstractProtocol { + + private final List> rpcExceptions = new CopyOnWriteArrayList>(); + + protected ProxyFactory proxyFactory; + + public AbstractProxyProtocol() { + } + + public AbstractProxyProtocol(Class... exceptions) { + for (Class exception : exceptions) { + addRpcException(exception); + } + } + + public void addRpcException(Class exception) { + this.rpcExceptions.add(exception); + } + + public ProxyFactory getProxyFactory() { + return proxyFactory; + } + + public void setProxyFactory(ProxyFactory proxyFactory) { + this.proxyFactory = proxyFactory; + } + + @Override + @SuppressWarnings("unchecked") + public Exporter export(final Invoker invoker) throws RpcException { + final String uri = serviceKey(invoker.getUrl()); + Exporter exporter = (Exporter) exporterMap.get(uri); + if (exporter != null) { + // When modifying the configuration through override, you need to re-expose the newly modified service. + if (Objects.equals(exporter.getInvoker().getUrl(), invoker.getUrl())) { + return exporter; + } + } + final Runnable runnable = doExport(proxyFactory.getProxy(invoker, true), invoker.getInterface(), invoker.getUrl()); + exporter = new AbstractExporter(invoker) { + @Override + public void afterUnExport() { + exporterMap.remove(uri); + if (runnable != null) { + try { + runnable.run(); + } catch (Throwable t) { + logger.warn(t.getMessage(), t); + } + } + } + }; + exporterMap.put(uri, exporter); + return exporter; + } + + @Override + protected Invoker protocolBindingRefer(final Class type, final URL url) throws RpcException { + final Invoker target = proxyFactory.getInvoker(doRefer(type, url), type, url); + Invoker invoker = new AbstractInvoker(type, url) { + @Override + protected Result doInvoke(Invocation invocation) throws Throwable { + try { + Result result = target.invoke(invocation); + // FIXME result is an AsyncRpcResult instance. + 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); + } + } + + @Override + public void destroy() { + super.destroy(); + target.destroy(); + invokers.remove(this); + } + }; + 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 String getAddr(URL url) { + String bindIp = url.getParameter(Constants.BIND_IP_KEY, url.getHost()); + if (url.getParameter(ANYHOST_KEY, false)) { + bindIp = ANYHOST_VALUE; + } + return NetUtils.getIpByHost(bindIp) + ":" + url.getParameter(Constants.BIND_PORT_KEY, url.getPort()); + } + + protected int getErrorCode(Throwable e) { + return RpcException.UNKNOWN_EXCEPTION; + } + + protected abstract Runnable doExport(T impl, Class type, URL url) throws RpcException; + + protected abstract T doRefer(Class type, URL url) throws RpcException; + + protected class ProxyProtocolServer implements ProtocolServer { + + private RemotingServer server; + private String address; + + public ProxyProtocolServer(RemotingServer server) { + this.server = server; + } + + @Override + public RemotingServer getRemotingServer() { + return server; + } + + @Override + public String getAddress() { + return StringUtils.isNotEmpty(address) ? address : server.getUrl().getAddress(); + } + + @Override + public void setAddress(String address) { + this.address = address; + } + + @Override + public URL getUrl() { + return server.getUrl(); + } + + @Override + public void close() { + server.close(); + } + } + + protected abstract class RemotingServerAdapter implements RemotingServer { + + public abstract Object getDelegateServer(); + + /** + * @return + */ + @Override + public boolean isBound() { + return false; + } + + @Override + public Collection getChannels() { + return null; + } + + @Override + public Channel getChannel(InetSocketAddress remoteAddress) { + return null; + } + + @Override + public void reset(Parameters parameters) { + + } + + @Override + public void reset(URL url) { + + } + + @Override + public URL getUrl() { + return null; + } + + @Override + public ChannelHandler getChannelHandler() { + return null; + } + + @Override + public InetSocketAddress getLocalAddress() { + return null; + } + + @Override + public void send(Object message) throws RemotingException { + + } + + @Override + public void send(Object message, boolean sent) throws RemotingException { + + } + + @Override + public void close() { + + } + + @Override + public void close(int timeout) { + + } + + @Override + public void startClose() { + + } + + @Override + public boolean isClosed() { + return false; + } + } + + +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/InvokerWrapper.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/InvokerWrapper.java index c85e69111e..0ab182ab73 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/InvokerWrapper.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/InvokerWrapper.java @@ -1,64 +1,64 @@ -/* - * 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.rpc.protocol; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.rpc.Invocation; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.Result; -import org.apache.dubbo.rpc.RpcException; - -/** - * InvokerWrapper - */ -public class InvokerWrapper implements Invoker { - - private final Invoker invoker; - - private final URL url; - - public InvokerWrapper(Invoker invoker, URL url) { - this.invoker = invoker; - this.url = url; - } - - @Override - public Class getInterface() { - return invoker.getInterface(); - } - - @Override - public URL getUrl() { - return url; - } - - @Override - public boolean isAvailable() { - return invoker.isAvailable(); - } - - @Override - public Result invoke(Invocation invocation) throws RpcException { - return invoker.invoke(invocation); - } - - @Override - public void destroy() { - invoker.destroy(); - } - -} +/* + * 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.rpc.protocol; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.Result; +import org.apache.dubbo.rpc.RpcException; + +/** + * InvokerWrapper + */ +public class InvokerWrapper implements Invoker { + + private final Invoker invoker; + + private final URL url; + + public InvokerWrapper(Invoker invoker, URL url) { + this.invoker = invoker; + this.url = url; + } + + @Override + public Class getInterface() { + return invoker.getInterface(); + } + + @Override + public URL getUrl() { + return url; + } + + @Override + public boolean isAvailable() { + return invoker.isAvailable(); + } + + @Override + public Result invoke(Invocation invocation) throws RpcException { + return invoker.invoke(invocation); + } + + @Override + public void destroy() { + invoker.destroy(); + } + +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/package-info.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/package-info.java index 712f508fcf..06e75668f7 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/package-info.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/package-info.java @@ -19,4 +19,4 @@ * {@link org.apache.dubbo.rpc.protocol.dubbo.FutureAdapter} was in dubbo-rpc-dubbo module, * considering some users will use this class directly, keep the package not changed. */ -package org.apache.dubbo.rpc.protocol.dubbo; \ No newline at end of file +package org.apache.dubbo.rpc.protocol.dubbo; diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/AbstractProxyFactory.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/AbstractProxyFactory.java index 5a00daabe8..695ca02412 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/AbstractProxyFactory.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/AbstractProxyFactory.java @@ -1,87 +1,87 @@ -/* - * 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.rpc.proxy; - -import org.apache.dubbo.common.utils.ReflectUtils; -import org.apache.dubbo.rpc.Constants; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.ProxyFactory; -import org.apache.dubbo.rpc.RpcException; -import org.apache.dubbo.rpc.service.Destroyable; -import org.apache.dubbo.rpc.service.EchoService; -import org.apache.dubbo.rpc.service.GenericService; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN; -import static org.apache.dubbo.rpc.Constants.INTERFACES; - -/** - * AbstractProxyFactory - */ -public abstract class AbstractProxyFactory implements ProxyFactory { - private static final Class[] INTERNAL_INTERFACES = new Class[]{ - EchoService.class, Destroyable.class - }; - - @Override - public T getProxy(Invoker invoker) throws RpcException { - return getProxy(invoker, false); - } - - @Override - public T getProxy(Invoker invoker, boolean generic) throws RpcException { - Set> interfaces = new HashSet<>(); - - String config = invoker.getUrl().getParameter(INTERFACES); - if (config != null && config.length() > 0) { - String[] types = COMMA_SPLIT_PATTERN.split(config); - for (String type : types) { - // TODO can we load successfully for a different classloader?. - interfaces.add(ReflectUtils.forName(type)); - } - } - - if (generic) { - if (GenericService.class.equals(invoker.getInterface()) || !GenericService.class.isAssignableFrom(invoker.getInterface())) { - interfaces.add(com.alibaba.dubbo.rpc.service.GenericService.class); - } - - try { - // find the real interface from url - String realInterface = invoker.getUrl().getParameter(Constants.INTERFACE); - interfaces.add(ReflectUtils.forName(realInterface)); - } catch (Throwable e) { - // ignore - } - } - - interfaces.add(invoker.getInterface()); - interfaces.addAll(Arrays.asList(INTERNAL_INTERFACES)); - - return getProxy(invoker, interfaces.toArray(new Class[0])); - } - - public static Class[] getInternalInterfaces() { - return INTERNAL_INTERFACES.clone(); - } - - public abstract T getProxy(Invoker invoker, Class[] types); - -} +/* + * 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.rpc.proxy; + +import org.apache.dubbo.common.utils.ReflectUtils; +import org.apache.dubbo.rpc.Constants; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.ProxyFactory; +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.service.Destroyable; +import org.apache.dubbo.rpc.service.EchoService; +import org.apache.dubbo.rpc.service.GenericService; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN; +import static org.apache.dubbo.rpc.Constants.INTERFACES; + +/** + * AbstractProxyFactory + */ +public abstract class AbstractProxyFactory implements ProxyFactory { + private static final Class[] INTERNAL_INTERFACES = new Class[]{ + EchoService.class, Destroyable.class + }; + + @Override + public T getProxy(Invoker invoker) throws RpcException { + return getProxy(invoker, false); + } + + @Override + public T getProxy(Invoker invoker, boolean generic) throws RpcException { + Set> interfaces = new HashSet<>(); + + String config = invoker.getUrl().getParameter(INTERFACES); + if (config != null && config.length() > 0) { + String[] types = COMMA_SPLIT_PATTERN.split(config); + for (String type : types) { + // TODO can we load successfully for a different classloader?. + interfaces.add(ReflectUtils.forName(type)); + } + } + + if (generic) { + if (GenericService.class.equals(invoker.getInterface()) || !GenericService.class.isAssignableFrom(invoker.getInterface())) { + interfaces.add(com.alibaba.dubbo.rpc.service.GenericService.class); + } + + try { + // find the real interface from url + String realInterface = invoker.getUrl().getParameter(Constants.INTERFACE); + interfaces.add(ReflectUtils.forName(realInterface)); + } catch (Throwable e) { + // ignore + } + } + + interfaces.add(invoker.getInterface()); + interfaces.addAll(Arrays.asList(INTERNAL_INTERFACES)); + + return getProxy(invoker, interfaces.toArray(new Class[0])); + } + + public static Class[] getInternalInterfaces() { + return INTERNAL_INTERFACES.clone(); + } + + public abstract T getProxy(Invoker invoker, Class[] types); + +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/AbstractProxyInvoker.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/AbstractProxyInvoker.java index 67feea895b..2230f50796 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/AbstractProxyInvoker.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/AbstractProxyInvoker.java @@ -107,7 +107,7 @@ public abstract class AbstractProxyInvoker implements Invoker { } } - private CompletableFuture wrapWithFuture(Object value) { + private CompletableFuture wrapWithFuture(Object value) { if (RpcContext.getServiceContext().isAsyncStarted()) { return ((AsyncContextImpl)(RpcContext.getServiceContext().getAsyncContext())).getInternalFuture(); } else if (value instanceof CompletableFuture) { diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/wrapper/StubProxyFactoryWrapper.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/wrapper/StubProxyFactoryWrapper.java index 414295a957..e8b0f197b6 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/wrapper/StubProxyFactoryWrapper.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/wrapper/StubProxyFactoryWrapper.java @@ -1,126 +1,126 @@ -/* - * 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.rpc.proxy.wrapper; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.URLBuilder; -import org.apache.dubbo.common.Version; -import org.apache.dubbo.common.bytecode.Wrapper; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -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.rpc.Exporter; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.Protocol; -import org.apache.dubbo.rpc.ProxyFactory; -import org.apache.dubbo.rpc.RpcException; -import org.apache.dubbo.rpc.service.GenericService; - -import java.lang.reflect.Constructor; - -import static org.apache.dubbo.common.constants.CommonConstants.STUB_EVENT_KEY; -import static org.apache.dubbo.rpc.Constants.DEFAULT_STUB_EVENT; -import static org.apache.dubbo.rpc.Constants.IS_SERVER_KEY; -import static org.apache.dubbo.rpc.Constants.LOCAL_KEY; -import static org.apache.dubbo.rpc.Constants.STUB_EVENT_METHODS_KEY; -import static org.apache.dubbo.rpc.Constants.STUB_KEY; - -/** - * StubProxyFactoryWrapper - */ -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; - } - - @Override - public T getProxy(Invoker invoker, boolean generic) throws RpcException { - T proxy = proxyFactory.getProxy(invoker, generic); - if (GenericService.class != invoker.getInterface()) { - URL url = invoker.getUrl(); - String stub = url.getParameter(STUB_KEY, url.getParameter(LOCAL_KEY)); - if (ConfigUtils.isNotEmpty(stub)) { - Class serviceType = invoker.getInterface(); - if (ConfigUtils.isDefault(stub)) { - if (url.hasParameter(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 implementation 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 - URLBuilder urlBuilder = URLBuilder.from(url); - if (url.getParameter(STUB_EVENT_KEY, DEFAULT_STUB_EVENT)) { - urlBuilder.addParameter(STUB_EVENT_METHODS_KEY, StringUtils.join(Wrapper.getWrapper(proxy.getClass()).getDeclaredMethodNames(), ",")); - urlBuilder.addParameter(IS_SERVER_KEY, Boolean.FALSE.toString()); - try { - export(proxy, (Class) invoker.getInterface(), urlBuilder.build()); - } 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 implementation class " + stubClass.getName(), e); - } - } catch (Throwable t) { - LOGGER.error("Failed to create stub implementation class " + stub + " in consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() + ", cause: " + t.getMessage(), t); - // ignore - } - } - } - return proxy; - - } - - @Override - @SuppressWarnings({"unchecked", "rawtypes"}) - public T getProxy(Invoker invoker) throws RpcException { - return getProxy(invoker, false); - } - - @Override - public Invoker getInvoker(T proxy, Class type, URL url) throws RpcException { - return proxyFactory.getInvoker(proxy, type, url); - } - - private Exporter export(T instance, Class type, URL url) { - return protocol.export(proxyFactory.getInvoker(instance, type, url)); - } - -} +/* + * 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.rpc.proxy.wrapper; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.URLBuilder; +import org.apache.dubbo.common.Version; +import org.apache.dubbo.common.bytecode.Wrapper; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +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.rpc.Exporter; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.Protocol; +import org.apache.dubbo.rpc.ProxyFactory; +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.service.GenericService; + +import java.lang.reflect.Constructor; + +import static org.apache.dubbo.common.constants.CommonConstants.STUB_EVENT_KEY; +import static org.apache.dubbo.rpc.Constants.DEFAULT_STUB_EVENT; +import static org.apache.dubbo.rpc.Constants.IS_SERVER_KEY; +import static org.apache.dubbo.rpc.Constants.LOCAL_KEY; +import static org.apache.dubbo.rpc.Constants.STUB_EVENT_METHODS_KEY; +import static org.apache.dubbo.rpc.Constants.STUB_KEY; + +/** + * StubProxyFactoryWrapper + */ +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; + } + + @Override + public T getProxy(Invoker invoker, boolean generic) throws RpcException { + T proxy = proxyFactory.getProxy(invoker, generic); + if (GenericService.class != invoker.getInterface()) { + URL url = invoker.getUrl(); + String stub = url.getParameter(STUB_KEY, url.getParameter(LOCAL_KEY)); + if (ConfigUtils.isNotEmpty(stub)) { + Class serviceType = invoker.getInterface(); + if (ConfigUtils.isDefault(stub)) { + if (url.hasParameter(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 implementation 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 + URLBuilder urlBuilder = URLBuilder.from(url); + if (url.getParameter(STUB_EVENT_KEY, DEFAULT_STUB_EVENT)) { + urlBuilder.addParameter(STUB_EVENT_METHODS_KEY, StringUtils.join(Wrapper.getWrapper(proxy.getClass()).getDeclaredMethodNames(), ",")); + urlBuilder.addParameter(IS_SERVER_KEY, Boolean.FALSE.toString()); + try { + export(proxy, (Class) invoker.getInterface(), urlBuilder.build()); + } 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 implementation class " + stubClass.getName(), e); + } + } catch (Throwable t) { + LOGGER.error("Failed to create stub implementation class " + stub + " in consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() + ", cause: " + t.getMessage(), t); + // ignore + } + } + } + return proxy; + + } + + @Override + @SuppressWarnings({"unchecked", "rawtypes"}) + public T getProxy(Invoker invoker) throws RpcException { + return getProxy(invoker, false); + } + + @Override + public Invoker getInvoker(T proxy, Class type, URL url) throws RpcException { + return proxyFactory.getInvoker(proxy, type, url); + } + + private Exporter export(T instance, Class type, URL url) { + return protocol.export(proxyFactory.getInvoker(instance, type, url)); + } + +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/MockInvoker.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/MockInvoker.java index 156494cd64..41a554557d 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/MockInvoker.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/MockInvoker.java @@ -1,285 +1,285 @@ -/* - * 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.rpc.support; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.extension.ExtensionFactory; -import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.common.utils.ArrayUtils; -import org.apache.dubbo.common.utils.ConfigUtils; -import org.apache.dubbo.common.utils.PojoUtils; -import org.apache.dubbo.common.utils.ReflectUtils; -import org.apache.dubbo.common.utils.StringUtils; -import org.apache.dubbo.rpc.AsyncRpcResult; -import org.apache.dubbo.rpc.Invocation; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.ProxyFactory; -import org.apache.dubbo.rpc.Result; -import org.apache.dubbo.rpc.RpcException; -import org.apache.dubbo.rpc.RpcInvocation; - -import com.alibaba.fastjson.JSON; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Type; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import static org.apache.dubbo.rpc.Constants.FAIL_PREFIX; -import static org.apache.dubbo.rpc.Constants.FORCE_PREFIX; -import static org.apache.dubbo.rpc.Constants.MOCK_KEY; -import static org.apache.dubbo.rpc.Constants.RETURN_KEY; -import static org.apache.dubbo.rpc.Constants.RETURN_PREFIX; -import static org.apache.dubbo.rpc.Constants.THROW_PREFIX; - -final public class MockInvoker implements Invoker { - private final static ProxyFactory PROXY_FACTORY = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); - private final static Map> MOCK_MAP = new ConcurrentHashMap>(); - private final static Map THROWABLE_MAP = new ConcurrentHashMap(); - - private final URL url; - private final Class type; - - public MockInvoker(URL url, Class type) { - this.url = url; - this.type = type; - } - - public static Object parseMockValue(String mock) throws Exception { - return parseMockValue(mock, null); - } - - public static Object parseMockValue(String mock, Type[] returnTypes) throws Exception { - Object value = null; - if ("empty".equals(mock)) { - value = ReflectUtils.getEmptyObject(returnTypes != null && returnTypes.length > 0 ? (Class) returnTypes[0] : null); - } else if ("null".equals(mock)) { - value = null; - } else if ("true".equals(mock)) { - value = true; - } else if ("false".equals(mock)) { - value = false; - } else if (mock.length() >= 2 && (mock.startsWith("\"") && mock.endsWith("\"") - || mock.startsWith("\'") && mock.endsWith("\'"))) { - value = mock.subSequence(1, mock.length() - 1); - } else if (returnTypes != null && returnTypes.length > 0 && returnTypes[0] == String.class) { - value = mock; - } else if (StringUtils.isNumeric(mock, false)) { - value = JSON.parse(mock); - } else if (mock.startsWith("{")) { - value = JSON.parseObject(mock, Map.class); - } else if (mock.startsWith("[")) { - value = JSON.parseObject(mock, List.class); - } else { - value = mock; - } - if (ArrayUtils.isNotEmpty(returnTypes)) { - value = PojoUtils.realize(value, (Class) returnTypes[0], returnTypes.length > 1 ? returnTypes[1] : null); - } - return value; - } - - @Override - public Result invoke(Invocation invocation) throws RpcException { - if (invocation instanceof RpcInvocation) { - ((RpcInvocation) invocation).setInvoker(this); - } - String mock = null; - if (getUrl().hasMethodParameter(invocation.getMethodName())) { - mock = getUrl().getParameter(invocation.getMethodName() + "." + MOCK_KEY); - } - if (StringUtils.isBlank(mock)) { - mock = getUrl().getParameter(MOCK_KEY); - } - - if (StringUtils.isBlank(mock)) { - throw new RpcException(new IllegalAccessException("mock can not be null. url :" + url)); - } - mock = normalizeMock(URL.decode(mock)); - if (mock.startsWith(RETURN_PREFIX)) { - mock = mock.substring(RETURN_PREFIX.length()).trim(); - try { - Type[] returnTypes = RpcUtils.getReturnTypes(invocation); - Object value = parseMockValue(mock, returnTypes); - return AsyncRpcResult.newDefaultAsyncResult(value, invocation); - } catch (Exception ew) { - throw new RpcException("mock return invoke error. method :" + invocation.getMethodName() - + ", mock:" + mock + ", url: " + url, ew); - } - } else if (mock.startsWith(THROW_PREFIX)) { - mock = mock.substring(THROW_PREFIX.length()).trim(); - if (StringUtils.isBlank(mock)) { - throw new RpcException("mocked exception for service degradation."); - } else { // user customized class - Throwable t = getThrowable(mock); - throw new RpcException(RpcException.BIZ_EXCEPTION, t); - } - } else { //impl mock - try { - Invoker invoker = getInvoker(mock); - return invoker.invoke(invocation); - } catch (Throwable t) { - throw new RpcException("Failed to create mock implementation class " + mock, t); - } - } - } - - public static Throwable getThrowable(String throwstr) { - Throwable throwable = THROWABLE_MAP.get(throwstr); - if (throwable != null) { - return throwable; - } - - try { - Throwable t; - Class bizException = ReflectUtils.forName(throwstr); - Constructor constructor; - constructor = ReflectUtils.findConstructor(bizException, String.class); - t = (Throwable) constructor.newInstance(new Object[]{"mocked exception for service degradation."}); - if (THROWABLE_MAP.size() < 1000) { - THROWABLE_MAP.put(throwstr, t); - } - return t; - } catch (Exception e) { - throw new RpcException("mock throw error :" + throwstr + " argument error.", e); - } - } - - @SuppressWarnings("unchecked") - private Invoker getInvoker(String mockService) { - Invoker invoker = (Invoker) MOCK_MAP.get(mockService); - if (invoker != null) { - return invoker; - } - - Class serviceType = (Class) ReflectUtils.forName(url.getServiceInterface()); - T mockObject = (T) getMockObject(mockService, serviceType); - invoker = PROXY_FACTORY.getInvoker(mockObject, serviceType, url); - if (MOCK_MAP.size() < 10000) { - MOCK_MAP.put(mockService, invoker); - } - return invoker; - } - - @SuppressWarnings("unchecked") - public static Object getMockObject(String mockService, Class serviceType) { - boolean isDefault = ConfigUtils.isDefault(mockService); - if (isDefault) { - mockService = serviceType.getName() + "Mock"; - } - - Class mockClass; - try { - mockClass = ReflectUtils.forName(mockService); - } catch (Exception e) { - if (!isDefault) {// does not check Spring bean if it is default config. - ExtensionFactory extensionFactory = - ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension(); - Object obj = extensionFactory.getExtension(serviceType, mockService); - if (obj != null) { - return obj; - } - } - throw new IllegalStateException("Did not find mock class or instance " - + mockService - + ", please check if there's mock class or instance implementing interface " - + serviceType.getName(), e); - } - if (mockClass == null || !serviceType.isAssignableFrom(mockClass)) { - throw new IllegalStateException("The mock class " + mockClass.getName() + - " not implement interface " + serviceType.getName()); - } - - try { - return mockClass.newInstance(); - } catch (InstantiationException e) { - throw new IllegalStateException("No default constructor from mock class " + mockClass.getName(), e); - } catch (IllegalAccessException e) { - throw new IllegalStateException(e); - } - } - - - /** - * Normalize mock string: - * - *
    - *
  1. return => return null
  2. - *
  3. fail => default
  4. - *
  5. force => default
  6. - *
  7. fail:throw/return foo => throw/return foo
  8. - *
  9. force:throw/return foo => throw/return foo
  10. - *
- * - * @param mock mock string - * @return normalized mock string - */ - public static String normalizeMock(String mock) { - if (mock == null) { - return mock; - } - - mock = mock.trim(); - - if (mock.length() == 0) { - return mock; - } - - if (RETURN_KEY.equalsIgnoreCase(mock)) { - return RETURN_PREFIX + "null"; - } - - if (ConfigUtils.isDefault(mock) || "fail".equalsIgnoreCase(mock) || "force".equalsIgnoreCase(mock)) { - return "default"; - } - - if (mock.startsWith(FAIL_PREFIX)) { - mock = mock.substring(FAIL_PREFIX.length()).trim(); - } - - if (mock.startsWith(FORCE_PREFIX)) { - mock = mock.substring(FORCE_PREFIX.length()).trim(); - } - - if (mock.startsWith(RETURN_PREFIX) || mock.startsWith(THROW_PREFIX)) { - mock = mock.replace('`', '"'); - } - - return mock; - } - - @Override - public URL getUrl() { - return this.url; - } - - @Override - public boolean isAvailable() { - return true; - } - - @Override - public void destroy() { - //do nothing - } - - @Override - public Class getInterface() { - return type; - } -} +/* + * 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.rpc.support; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.ExtensionFactory; +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.common.utils.ArrayUtils; +import org.apache.dubbo.common.utils.ConfigUtils; +import org.apache.dubbo.common.utils.PojoUtils; +import org.apache.dubbo.common.utils.ReflectUtils; +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.rpc.AsyncRpcResult; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.ProxyFactory; +import org.apache.dubbo.rpc.Result; +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.RpcInvocation; + +import com.alibaba.fastjson.JSON; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Type; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import static org.apache.dubbo.rpc.Constants.FAIL_PREFIX; +import static org.apache.dubbo.rpc.Constants.FORCE_PREFIX; +import static org.apache.dubbo.rpc.Constants.MOCK_KEY; +import static org.apache.dubbo.rpc.Constants.RETURN_KEY; +import static org.apache.dubbo.rpc.Constants.RETURN_PREFIX; +import static org.apache.dubbo.rpc.Constants.THROW_PREFIX; + +final public class MockInvoker implements Invoker { + private final static ProxyFactory PROXY_FACTORY = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); + private final static Map> MOCK_MAP = new ConcurrentHashMap>(); + private final static Map THROWABLE_MAP = new ConcurrentHashMap(); + + private final URL url; + private final Class type; + + public MockInvoker(URL url, Class type) { + this.url = url; + this.type = type; + } + + public static Object parseMockValue(String mock) throws Exception { + return parseMockValue(mock, null); + } + + public static Object parseMockValue(String mock, Type[] returnTypes) throws Exception { + Object value = null; + if ("empty".equals(mock)) { + value = ReflectUtils.getEmptyObject(returnTypes != null && returnTypes.length > 0 ? (Class) returnTypes[0] : null); + } else if ("null".equals(mock)) { + value = null; + } else if ("true".equals(mock)) { + value = true; + } else if ("false".equals(mock)) { + value = false; + } else if (mock.length() >= 2 && (mock.startsWith("\"") && mock.endsWith("\"") + || mock.startsWith("\'") && mock.endsWith("\'"))) { + value = mock.subSequence(1, mock.length() - 1); + } else if (returnTypes != null && returnTypes.length > 0 && returnTypes[0] == String.class) { + value = mock; + } else if (StringUtils.isNumeric(mock, false)) { + value = JSON.parse(mock); + } else if (mock.startsWith("{")) { + value = JSON.parseObject(mock, Map.class); + } else if (mock.startsWith("[")) { + value = JSON.parseObject(mock, List.class); + } else { + value = mock; + } + if (ArrayUtils.isNotEmpty(returnTypes)) { + value = PojoUtils.realize(value, (Class) returnTypes[0], returnTypes.length > 1 ? returnTypes[1] : null); + } + return value; + } + + @Override + public Result invoke(Invocation invocation) throws RpcException { + if (invocation instanceof RpcInvocation) { + ((RpcInvocation) invocation).setInvoker(this); + } + String mock = null; + if (getUrl().hasMethodParameter(invocation.getMethodName())) { + mock = getUrl().getParameter(invocation.getMethodName() + "." + MOCK_KEY); + } + if (StringUtils.isBlank(mock)) { + mock = getUrl().getParameter(MOCK_KEY); + } + + if (StringUtils.isBlank(mock)) { + throw new RpcException(new IllegalAccessException("mock can not be null. url :" + url)); + } + mock = normalizeMock(URL.decode(mock)); + if (mock.startsWith(RETURN_PREFIX)) { + mock = mock.substring(RETURN_PREFIX.length()).trim(); + try { + Type[] returnTypes = RpcUtils.getReturnTypes(invocation); + Object value = parseMockValue(mock, returnTypes); + return AsyncRpcResult.newDefaultAsyncResult(value, invocation); + } catch (Exception ew) { + throw new RpcException("mock return invoke error. method :" + invocation.getMethodName() + + ", mock:" + mock + ", url: " + url, ew); + } + } else if (mock.startsWith(THROW_PREFIX)) { + mock = mock.substring(THROW_PREFIX.length()).trim(); + if (StringUtils.isBlank(mock)) { + throw new RpcException("mocked exception for service degradation."); + } else { // user customized class + Throwable t = getThrowable(mock); + throw new RpcException(RpcException.BIZ_EXCEPTION, t); + } + } else { //impl mock + try { + Invoker invoker = getInvoker(mock); + return invoker.invoke(invocation); + } catch (Throwable t) { + throw new RpcException("Failed to create mock implementation class " + mock, t); + } + } + } + + public static Throwable getThrowable(String throwstr) { + Throwable throwable = THROWABLE_MAP.get(throwstr); + if (throwable != null) { + return throwable; + } + + try { + Throwable t; + Class bizException = ReflectUtils.forName(throwstr); + Constructor constructor; + constructor = ReflectUtils.findConstructor(bizException, String.class); + t = (Throwable) constructor.newInstance(new Object[]{"mocked exception for service degradation."}); + if (THROWABLE_MAP.size() < 1000) { + THROWABLE_MAP.put(throwstr, t); + } + return t; + } catch (Exception e) { + throw new RpcException("mock throw error :" + throwstr + " argument error.", e); + } + } + + @SuppressWarnings("unchecked") + private Invoker getInvoker(String mockService) { + Invoker invoker = (Invoker) MOCK_MAP.get(mockService); + if (invoker != null) { + return invoker; + } + + Class serviceType = (Class) ReflectUtils.forName(url.getServiceInterface()); + T mockObject = (T) getMockObject(mockService, serviceType); + invoker = PROXY_FACTORY.getInvoker(mockObject, serviceType, url); + if (MOCK_MAP.size() < 10000) { + MOCK_MAP.put(mockService, invoker); + } + return invoker; + } + + @SuppressWarnings("unchecked") + public static Object getMockObject(String mockService, Class serviceType) { + boolean isDefault = ConfigUtils.isDefault(mockService); + if (isDefault) { + mockService = serviceType.getName() + "Mock"; + } + + Class mockClass; + try { + mockClass = ReflectUtils.forName(mockService); + } catch (Exception e) { + if (!isDefault) {// does not check Spring bean if it is default config. + ExtensionFactory extensionFactory = + ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension(); + Object obj = extensionFactory.getExtension(serviceType, mockService); + if (obj != null) { + return obj; + } + } + throw new IllegalStateException("Did not find mock class or instance " + + mockService + + ", please check if there's mock class or instance implementing interface " + + serviceType.getName(), e); + } + if (mockClass == null || !serviceType.isAssignableFrom(mockClass)) { + throw new IllegalStateException("The mock class " + mockClass.getName() + + " not implement interface " + serviceType.getName()); + } + + try { + return mockClass.newInstance(); + } catch (InstantiationException e) { + throw new IllegalStateException("No default constructor from mock class " + mockClass.getName(), e); + } catch (IllegalAccessException e) { + throw new IllegalStateException(e); + } + } + + + /** + * Normalize mock string: + * + *
    + *
  1. return => return null
  2. + *
  3. fail => default
  4. + *
  5. force => default
  6. + *
  7. fail:throw/return foo => throw/return foo
  8. + *
  9. force:throw/return foo => throw/return foo
  10. + *
+ * + * @param mock mock string + * @return normalized mock string + */ + public static String normalizeMock(String mock) { + if (mock == null) { + return mock; + } + + mock = mock.trim(); + + if (mock.length() == 0) { + return mock; + } + + if (RETURN_KEY.equalsIgnoreCase(mock)) { + return RETURN_PREFIX + "null"; + } + + if (ConfigUtils.isDefault(mock) || "fail".equalsIgnoreCase(mock) || "force".equalsIgnoreCase(mock)) { + return "default"; + } + + if (mock.startsWith(FAIL_PREFIX)) { + mock = mock.substring(FAIL_PREFIX.length()).trim(); + } + + if (mock.startsWith(FORCE_PREFIX)) { + mock = mock.substring(FORCE_PREFIX.length()).trim(); + } + + if (mock.startsWith(RETURN_PREFIX) || mock.startsWith(THROW_PREFIX)) { + mock = mock.replace('`', '"'); + } + + return mock; + } + + @Override + public URL getUrl() { + return this.url; + } + + @Override + public boolean isAvailable() { + return true; + } + + @Override + public void destroy() { + //do nothing + } + + @Override + public Class getInterface() { + return type; + } +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/MockProtocol.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/MockProtocol.java index 4608996817..f2d46d80b4 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/MockProtocol.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/MockProtocol.java @@ -1,44 +1,44 @@ -/* - * 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.rpc.support; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.rpc.Exporter; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.RpcException; -import org.apache.dubbo.rpc.protocol.AbstractProtocol; - -/** - * MockProtocol is used for generating a mock invoker by URL and type on consumer side - */ -final public class MockProtocol extends AbstractProtocol { - - @Override - public int getDefaultPort() { - return 0; - } - - @Override - public Exporter export(Invoker invoker) throws RpcException { - throw new UnsupportedOperationException(); - } - - @Override - public Invoker protocolBindingRefer(Class type, URL url) throws RpcException { - return new MockInvoker<>(url, type); - } -} +/* + * 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.rpc.support; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.rpc.Exporter; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.protocol.AbstractProtocol; + +/** + * MockProtocol is used for generating a mock invoker by URL and type on consumer side + */ +final public class MockProtocol extends AbstractProtocol { + + @Override + public int getDefaultPort() { + return 0; + } + + @Override + public Exporter export(Invoker invoker) throws RpcException { + throw new UnsupportedOperationException(); + } + + @Override + public Invoker protocolBindingRefer(Class type, URL url) throws RpcException { + return new MockInvoker<>(url, type); + } +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.ProxyFactory b/dubbo-rpc/dubbo-rpc-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.ProxyFactory index a39a6f81da..cd58cd8773 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.ProxyFactory +++ b/dubbo-rpc/dubbo-rpc-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.ProxyFactory @@ -1,3 +1,3 @@ -stub=org.apache.dubbo.rpc.proxy.wrapper.StubProxyFactoryWrapper -jdk=org.apache.dubbo.rpc.proxy.jdk.JdkProxyFactory +stub=org.apache.dubbo.rpc.proxy.wrapper.StubProxyFactoryWrapper +jdk=org.apache.dubbo.rpc.proxy.jdk.JdkProxyFactory javassist=org.apache.dubbo.rpc.proxy.javassist.JavassistProxyFactory \ No newline at end of file diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/CustomArgument.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/CustomArgument.java index 53db49d9b4..ae4c3a3ab3 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/CustomArgument.java +++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/CustomArgument.java @@ -49,4 +49,4 @@ public class CustomArgument implements Serializable { public void setName(String name) { this.name = name; } -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/DemoRequest.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/DemoRequest.java index 97d9ddc523..d30bc23733 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/DemoRequest.java +++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/DemoRequest.java @@ -55,4 +55,4 @@ class DemoRequest implements Serializable { public Object[] getArguments() { return mArguments; } -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/AccessLogFilterTest.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/AccessLogFilterTest.java index e883950a9b..53e1537ed5 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/AccessLogFilterTest.java +++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/AccessLogFilterTest.java @@ -84,4 +84,4 @@ public class AccessLogFilterTest { accessLogFilter.invoke(invoker, invocation); } -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/CompatibleFilterFilterTest.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/CompatibleFilterFilterTest.java index c8f6a7f7d9..0bee557cb9 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/CompatibleFilterFilterTest.java +++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/CompatibleFilterFilterTest.java @@ -171,4 +171,4 @@ public class CompatibleFilterFilterTest { Result filterResult = compatibleFilter.invoke(invoker, invocation); assertEquals("hello", filterResult.getValue()); } -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/ContextFilterTest.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/ContextFilterTest.java index cb38f78468..84b6a686bf 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/ContextFilterTest.java +++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/ContextFilterTest.java @@ -73,4 +73,4 @@ public class ContextFilterTest { Result result = contextFilter.invoke(invoker, invocation); assertNull(RpcContext.getServiceContext().getInvoker()); } -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/DeprecatedFilterTest.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/DeprecatedFilterTest.java index 32835fffbf..2e1926473d 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/DeprecatedFilterTest.java +++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/DeprecatedFilterTest.java @@ -45,4 +45,4 @@ public class DeprecatedFilterTest { LogUtil.findMessage("The service method org.apache.dubbo.rpc.support.DemoService.echo(String) is DEPRECATED")); LogUtil.stop(); } -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/EchoFilterTest.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/EchoFilterTest.java index 3ed2df23f5..76ee02480c 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/EchoFilterTest.java +++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/EchoFilterTest.java @@ -77,4 +77,4 @@ public class EchoFilterTest { Result filterResult = echoFilter.invoke(invoker, invocation); assertEquals("High", filterResult.getValue()); } -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/ExceptionFilterTest.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/ExceptionFilterTest.java index 80086ef7de..9544369ba3 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/ExceptionFilterTest.java +++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/ExceptionFilterTest.java @@ -136,4 +136,4 @@ public class ExceptionFilterTest { Assertions.assertEquals(appResponse.getException().getClass(), RuntimeException.class); } -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/tps/StatItemTest.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/tps/StatItemTest.java index e8c6bf8023..1ebe753cee 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/tps/StatItemTest.java +++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/tps/StatItemTest.java @@ -42,15 +42,15 @@ public class StatItemTest { assertEquals(4, statItem.getToken()); } - @Test - public void testAccuracy() throws Exception { - final int EXPECTED_RATE = 5; - statItem = new StatItem("test", EXPECTED_RATE, 60_000L); - for (int i = 1; i <= EXPECTED_RATE; i++) { - assertEquals(true, statItem.isAllowable()); - } + @Test + public void testAccuracy() throws Exception { + final int EXPECTED_RATE = 5; + statItem = new StatItem("test", EXPECTED_RATE, 60_000L); + for (int i = 1; i <= EXPECTED_RATE; i++) { + assertEquals(true, statItem.isAllowable()); + } - // Must block the 6th item - assertEquals(false, statItem.isAllowable()); - } + // Must block the 6th item + assertEquals(false, statItem.isAllowable()); + } } diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/DemoRequest.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/DemoRequest.java index dfa5919792..28c100ae7a 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/DemoRequest.java +++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/DemoRequest.java @@ -55,4 +55,4 @@ class DemoRequest implements Serializable { public Object[] getArguments() { return mArguments; } -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/DemoService.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/DemoService.java index 4eac40ff37..dc3146976f 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/DemoService.java +++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/DemoService.java @@ -34,4 +34,4 @@ public interface DemoService { int stringLength(String str); Type enumlength(Type... types); -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/DemoServiceImpl.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/DemoServiceImpl.java index a8ece47e09..c61176b2d7 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/DemoServiceImpl.java +++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/DemoServiceImpl.java @@ -69,4 +69,4 @@ public class DemoServiceImpl implements DemoService { public int stringLength(String str) { return str.length(); } -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/RemoteService.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/RemoteService.java index ce462e587a..1cf9878afe 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/RemoteService.java +++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/RemoteService.java @@ -1,26 +1,26 @@ -/* - * 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.rpc.proxy; - -import java.rmi.Remote; -import java.rmi.RemoteException; - -public interface RemoteService extends Remote { - String sayHello(String name) throws RemoteException; - - String getThreadName() throws RemoteException; -} \ No newline at end of file +/* + * 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.rpc.proxy; + +import java.rmi.Remote; +import java.rmi.RemoteException; + +public interface RemoteService extends Remote { + String sayHello(String name) throws RemoteException; + + String getThreadName() throws RemoteException; +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/RemoteServiceImpl.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/RemoteServiceImpl.java index ccdab45f49..50b82b1997 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/RemoteServiceImpl.java +++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/RemoteServiceImpl.java @@ -29,4 +29,4 @@ public class RemoteServiceImpl implements RemoteService { public String sayHello(String name) throws RemoteException { return "hello " + name + "@" + RemoteServiceImpl.class.getName(); } -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/Type.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/Type.java index 994897cf91..bf59a4baa5 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/Type.java +++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/Type.java @@ -1,21 +1,21 @@ -/* - * 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.rpc.proxy; - -public enum Type { - High, Normal, Lower -} \ No newline at end of file +/* + * 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.rpc.proxy; + +public enum Type { + High, Normal, Lower +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/DemoService.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/DemoService.java index fb0892a9fc..571b8a55c3 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/DemoService.java +++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/DemoService.java @@ -41,7 +41,7 @@ public interface DemoService { Type enumlength(Type... types); -// Type enumlength(Type type); +// Type enumlength(Type type); String get(CustomArgument arg1); @@ -63,4 +63,4 @@ public interface DemoService { void $invoke(String s1, String s2); -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/DemoServiceImpl.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/DemoServiceImpl.java index e2b144b31b..d1ed931da0 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/DemoServiceImpl.java +++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/DemoServiceImpl.java @@ -125,4 +125,4 @@ public class DemoServiceImpl implements DemoService { public void $invoke(String s1, String s2) { } -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/IEcho.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/IEcho.java index 8f18699fb6..abf2b4abc4 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/IEcho.java +++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/IEcho.java @@ -1,21 +1,21 @@ -/* - * 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.rpc.support; - -public interface IEcho { - String echo(String e); -} \ No newline at end of file +/* + * 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.rpc.support; + +public interface IEcho { + String echo(String e); +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MockInvocation.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MockInvocation.java index 586c990bdd..8ebe8ac4db 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MockInvocation.java +++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MockInvocation.java @@ -154,4 +154,4 @@ public class MockInvocation implements Invocation { return result; } -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MyInvoker.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MyInvoker.java index 88c55d16a1..e15f2446f4 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MyInvoker.java +++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MyInvoker.java @@ -1,84 +1,84 @@ -/* - * 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.rpc.support; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.rpc.AppResponse; -import org.apache.dubbo.rpc.AsyncRpcResult; -import org.apache.dubbo.rpc.Invocation; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.Result; -import org.apache.dubbo.rpc.RpcException; - -import java.util.concurrent.CompletableFuture; - -/** - * MockInvoker.java - */ -public class MyInvoker implements Invoker { - - URL url; - Class type; - boolean hasException = false; - - public MyInvoker(URL url) { - this.url = url; - type = (Class) DemoService.class; - } - - public MyInvoker(URL url, boolean hasException) { - this.url = url; - type = (Class) DemoService.class; - this.hasException = hasException; - } - - @Override - public Class getInterface() { - return type; - } - - public URL getUrl() { - return url; - } - - @Override - public boolean isAvailable() { - return false; - } - - @Override - public Result invoke(Invocation invocation) throws RpcException { - AppResponse result = new AppResponse(); - if (!hasException) { - result.setValue("alibaba"); - } else { - result.setException(new RuntimeException("mocked exception")); - } - - return new AsyncRpcResult(CompletableFuture.completedFuture(result), invocation); - } - - @Override - public void destroy() { - } - - @Override - public String toString() { - return "MyInvoker.toString()"; - } - -} +/* + * 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.rpc.support; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.rpc.AppResponse; +import org.apache.dubbo.rpc.AsyncRpcResult; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.Result; +import org.apache.dubbo.rpc.RpcException; + +import java.util.concurrent.CompletableFuture; + +/** + * MockInvoker.java + */ +public class MyInvoker implements Invoker { + + URL url; + Class type; + boolean hasException = false; + + public MyInvoker(URL url) { + this.url = url; + type = (Class) DemoService.class; + } + + public MyInvoker(URL url, boolean hasException) { + this.url = url; + type = (Class) DemoService.class; + this.hasException = hasException; + } + + @Override + public Class getInterface() { + return type; + } + + public URL getUrl() { + return url; + } + + @Override + public boolean isAvailable() { + return false; + } + + @Override + public Result invoke(Invocation invocation) throws RpcException { + AppResponse result = new AppResponse(); + if (!hasException) { + result.setValue("alibaba"); + } else { + result.setException(new RuntimeException("mocked exception")); + } + + return new AsyncRpcResult(CompletableFuture.completedFuture(result), invocation); + } + + @Override + public void destroy() { + } + + @Override + public String toString() { + return "MyInvoker.toString()"; + } + +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/Person.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/Person.java index 7512d05215..d4570af5ca 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/Person.java +++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/Person.java @@ -1,52 +1,52 @@ -/* - * 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.rpc.support; - -import java.io.Serializable; - -/** - * Person.java - */ -public class Person implements Serializable { - - private static final long serialVersionUID = 1L; - private String name; - private int age; - - public Person() {} - - public Person(String name, int age) { - this.name = name; - this.age = age; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public int getAge() { - return age; - } - - public void setAge(int age) { - this.age = age; - } -} \ No newline at end of file +/* + * 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.rpc.support; + +import java.io.Serializable; + +/** + * Person.java + */ +public class Person implements Serializable { + + private static final long serialVersionUID = 1L; + private String name; + private int age; + + public Person() {} + + public Person(String name, int age) { + this.name = name; + this.age = age; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/Type.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/Type.java index d4d78c90c0..22ded46777 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/Type.java +++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/Type.java @@ -1,21 +1,21 @@ -/* - * 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.rpc.support; - -public enum Type { - High, Normal, Lower -} \ No newline at end of file +/* + * 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.rpc.support; + +public enum Type { + High, Normal, Lower +} diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboExporter.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboExporter.java index 57c1954f43..367f30894c 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboExporter.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboExporter.java @@ -42,4 +42,4 @@ public class DubboExporter extends AbstractExporter { exporterMap.remove(key); } -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/MultiThreadTest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/MultiThreadTest.java index 9b34edbe60..113ae7b5e3 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/MultiThreadTest.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/MultiThreadTest.java @@ -78,4 +78,4 @@ public class MultiThreadTest { exec.awaitTermination(10, TimeUnit.SECONDS); rpcExporter.unexport(); } -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/RpcFilterTest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/RpcFilterTest.java index d9776ef2e9..980d323671 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/RpcFilterTest.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/RpcFilterTest.java @@ -56,4 +56,4 @@ public class RpcFilterTest { Assertions.assertEquals(echo.$echo(1234), 1234); } -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/decode/DubboTelnetDecodeTest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/decode/DubboTelnetDecodeTest.java index 28ad49ed02..3122865df5 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/decode/DubboTelnetDecodeTest.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/decode/DubboTelnetDecodeTest.java @@ -503,4 +503,4 @@ public class DubboTelnetDecodeTest { future.complete(result); return future; } -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/CustomArgument.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/CustomArgument.java index 4391988aaf..952c8b27c5 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/CustomArgument.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/CustomArgument.java @@ -48,4 +48,4 @@ public class CustomArgument implements Serializable { public void setName(String name) { this.name = name; } -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/DemoRequest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/DemoRequest.java index d7de5ecf11..5a9e7451b4 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/DemoRequest.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/DemoRequest.java @@ -55,4 +55,4 @@ class DemoRequest implements Serializable { public Object[] getArguments() { return mArguments; } -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/DemoService.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/DemoService.java index fea53d66ac..ed1d584280 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/DemoService.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/DemoService.java @@ -68,4 +68,4 @@ public interface DemoService { String getRemoteApplicationName(); byte[] download(int size); -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/DemoServiceImpl.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/DemoServiceImpl.java index 89bbb37bcb..f31081dca0 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/DemoServiceImpl.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/DemoServiceImpl.java @@ -134,4 +134,4 @@ public class DemoServiceImpl implements DemoService { Arrays.fill(bytes, (byte) 0); return bytes; } -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/Man.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/Man.java index 440630ada1..0d584d0213 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/Man.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/Man.java @@ -43,4 +43,4 @@ public class Man implements Serializable { public void setAge(int age) { this.age = age; } -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/Person.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/Person.java index 58cb712e3a..65d1bbe7ac 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/Person.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/Person.java @@ -42,4 +42,4 @@ public class Person implements Serializable { public void setAge(int age) { this.age = age; } -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/ProtocolUtils.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/ProtocolUtils.java index 128e6c65e8..533e408be7 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/ProtocolUtils.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/ProtocolUtils.java @@ -62,4 +62,4 @@ public class ProtocolUtils { server.close(); } } -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/RemoteService.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/RemoteService.java index 0a84fa4bdc..a640ddc804 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/RemoteService.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/RemoteService.java @@ -23,4 +23,4 @@ public interface RemoteService extends Remote { String sayHello(String name) throws RemoteException; String getThreadName() throws RemoteException; -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/RemoteServiceImpl.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/RemoteServiceImpl.java index fe18a3e64e..0c0cd09f6e 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/RemoteServiceImpl.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/RemoteServiceImpl.java @@ -29,4 +29,4 @@ public class RemoteServiceImpl implements RemoteService { public String sayHello(String name) throws RemoteException { return "hello " + name + "@" + RemoteServiceImpl.class.getName(); } -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/Type.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/Type.java index 893907e19a..984c6c6436 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/Type.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/Type.java @@ -18,4 +18,4 @@ package org.apache.dubbo.rpc.protocol.dubbo.support; public enum Type { High, Normal, Lower -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-injvm/src/main/java/org/apache/dubbo/rpc/protocol/injvm/InjvmExporter.java b/dubbo-rpc/dubbo-rpc-injvm/src/main/java/org/apache/dubbo/rpc/protocol/injvm/InjvmExporter.java index cd899b4971..cd362a3c01 100644 --- a/dubbo-rpc/dubbo-rpc-injvm/src/main/java/org/apache/dubbo/rpc/protocol/injvm/InjvmExporter.java +++ b/dubbo-rpc/dubbo-rpc-injvm/src/main/java/org/apache/dubbo/rpc/protocol/injvm/InjvmExporter.java @@ -1,46 +1,46 @@ -/* - * 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.rpc.protocol.injvm; - -import org.apache.dubbo.rpc.Exporter; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.protocol.AbstractExporter; - -import java.util.Map; - -/** - * InjvmExporter - */ -class InjvmExporter extends AbstractExporter { - - private final String key; - - private final Map> exporterMap; - - InjvmExporter(Invoker invoker, String key, Map> exporterMap) { - super(invoker); - this.key = key; - this.exporterMap = exporterMap; - exporterMap.put(key, this); - } - - @Override - public void afterUnExport() { - exporterMap.remove(key); - } - -} +/* + * 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.rpc.protocol.injvm; + +import org.apache.dubbo.rpc.Exporter; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.protocol.AbstractExporter; + +import java.util.Map; + +/** + * InjvmExporter + */ +class InjvmExporter extends AbstractExporter { + + private final String key; + + private final Map> exporterMap; + + InjvmExporter(Invoker invoker, String key, Map> exporterMap) { + super(invoker); + this.key = key; + this.exporterMap = exporterMap; + exporterMap.put(key, this); + } + + @Override + public void afterUnExport() { + exporterMap.remove(key); + } + +} diff --git a/dubbo-rpc/dubbo-rpc-injvm/src/main/java/org/apache/dubbo/rpc/protocol/injvm/InjvmInvoker.java b/dubbo-rpc/dubbo-rpc-injvm/src/main/java/org/apache/dubbo/rpc/protocol/injvm/InjvmInvoker.java index 66594dd7de..04afe857c4 100644 --- a/dubbo-rpc/dubbo-rpc-injvm/src/main/java/org/apache/dubbo/rpc/protocol/injvm/InjvmInvoker.java +++ b/dubbo-rpc/dubbo-rpc-injvm/src/main/java/org/apache/dubbo/rpc/protocol/injvm/InjvmInvoker.java @@ -1,111 +1,111 @@ -/* - * 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.rpc.protocol.injvm; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.common.threadpool.manager.ExecutorRepository; -import org.apache.dubbo.rpc.AppResponse; -import org.apache.dubbo.rpc.AsyncRpcResult; -import org.apache.dubbo.rpc.Constants; -import org.apache.dubbo.rpc.Exporter; -import org.apache.dubbo.rpc.FutureContext; -import org.apache.dubbo.rpc.Invocation; -import org.apache.dubbo.rpc.InvokeMode; -import org.apache.dubbo.rpc.Result; -import org.apache.dubbo.rpc.RpcContext; -import org.apache.dubbo.rpc.RpcException; -import org.apache.dubbo.rpc.RpcInvocation; -import org.apache.dubbo.rpc.protocol.AbstractInvoker; - -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; - -import static org.apache.dubbo.common.constants.CommonConstants.LOCALHOST_VALUE; -import static org.apache.dubbo.rpc.Constants.ASYNC_KEY; - -/** - * InjvmInvoker - */ -class InjvmInvoker extends AbstractInvoker { - - private final String key; - - private final Map> exporterMap; - - private final ExecutorRepository executorRepository = ExtensionLoader.getExtensionLoader(ExecutorRepository.class).getDefaultExtension(); - - InjvmInvoker(Class type, URL url, String key, Map> exporterMap) { - super(type, url); - this.key = key; - this.exporterMap = exporterMap; - } - - @Override - public boolean isAvailable() { - InjvmExporter exporter = (InjvmExporter) exporterMap.get(key); - if (exporter == null) { - return false; - } else { - return super.isAvailable(); - } - } - - @Override - public Result doInvoke(Invocation invocation) throws Throwable { - Exporter exporter = InjvmProtocol.getExporter(exporterMap, getUrl()); - if (exporter == null) { - throw new RpcException("Service [" + key + "] not found."); - } - RpcContext.getServiceContext().setRemoteAddress(LOCALHOST_VALUE, 0); - // Solve local exposure, the server opens the token, and the client call fails. - URL serverURL = exporter.getInvoker().getUrl(); - boolean serverHasToken = serverURL.hasParameter(Constants.TOKEN_KEY); - if (serverHasToken) { - invocation.setAttachment(Constants.TOKEN_KEY, serverURL.getParameter(Constants.TOKEN_KEY)); - } - if (isAsync(exporter.getInvoker().getUrl(), getUrl())) { - ((RpcInvocation) invocation).setInvokeMode(InvokeMode.ASYNC); - // use consumer executor - ExecutorService executor = executorRepository.createExecutorIfAbsent(getUrl()); - CompletableFuture appResponseFuture = CompletableFuture.supplyAsync(() -> { - Result result = exporter.getInvoker().invoke(invocation); - if (result.hasException()) { - return new AppResponse(result.getException()); - } else { - return new AppResponse(result.getValue()); - } - }, executor); - // save for 2.6.x compatibility, for example, TraceFilter in Zipkin uses com.alibaba.xxx.FutureAdapter - FutureContext.getContext().setCompatibleFuture(appResponseFuture); - AsyncRpcResult result = new AsyncRpcResult(appResponseFuture, invocation); - result.setExecutor(executor); - return result; - } else { - return exporter.getInvoker().invoke(invocation); - } - } - - private boolean isAsync(URL remoteUrl, URL localUrl) { - if (localUrl.hasParameter(ASYNC_KEY)) { - return localUrl.getParameter(ASYNC_KEY, false); - } - return remoteUrl.getParameter(ASYNC_KEY, false); - } - -} +/* + * 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.rpc.protocol.injvm; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.common.threadpool.manager.ExecutorRepository; +import org.apache.dubbo.rpc.AppResponse; +import org.apache.dubbo.rpc.AsyncRpcResult; +import org.apache.dubbo.rpc.Constants; +import org.apache.dubbo.rpc.Exporter; +import org.apache.dubbo.rpc.FutureContext; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.InvokeMode; +import org.apache.dubbo.rpc.Result; +import org.apache.dubbo.rpc.RpcContext; +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.RpcInvocation; +import org.apache.dubbo.rpc.protocol.AbstractInvoker; + +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; + +import static org.apache.dubbo.common.constants.CommonConstants.LOCALHOST_VALUE; +import static org.apache.dubbo.rpc.Constants.ASYNC_KEY; + +/** + * InjvmInvoker + */ +class InjvmInvoker extends AbstractInvoker { + + private final String key; + + private final Map> exporterMap; + + private final ExecutorRepository executorRepository = ExtensionLoader.getExtensionLoader(ExecutorRepository.class).getDefaultExtension(); + + InjvmInvoker(Class type, URL url, String key, Map> exporterMap) { + super(type, url); + this.key = key; + this.exporterMap = exporterMap; + } + + @Override + public boolean isAvailable() { + InjvmExporter exporter = (InjvmExporter) exporterMap.get(key); + if (exporter == null) { + return false; + } else { + return super.isAvailable(); + } + } + + @Override + public Result doInvoke(Invocation invocation) throws Throwable { + Exporter exporter = InjvmProtocol.getExporter(exporterMap, getUrl()); + if (exporter == null) { + throw new RpcException("Service [" + key + "] not found."); + } + RpcContext.getServiceContext().setRemoteAddress(LOCALHOST_VALUE, 0); + // Solve local exposure, the server opens the token, and the client call fails. + URL serverURL = exporter.getInvoker().getUrl(); + boolean serverHasToken = serverURL.hasParameter(Constants.TOKEN_KEY); + if (serverHasToken) { + invocation.setAttachment(Constants.TOKEN_KEY, serverURL.getParameter(Constants.TOKEN_KEY)); + } + if (isAsync(exporter.getInvoker().getUrl(), getUrl())) { + ((RpcInvocation) invocation).setInvokeMode(InvokeMode.ASYNC); + // use consumer executor + ExecutorService executor = executorRepository.createExecutorIfAbsent(getUrl()); + CompletableFuture appResponseFuture = CompletableFuture.supplyAsync(() -> { + Result result = exporter.getInvoker().invoke(invocation); + if (result.hasException()) { + return new AppResponse(result.getException()); + } else { + return new AppResponse(result.getValue()); + } + }, executor); + // save for 2.6.x compatibility, for example, TraceFilter in Zipkin uses com.alibaba.xxx.FutureAdapter + FutureContext.getContext().setCompatibleFuture(appResponseFuture); + AsyncRpcResult result = new AsyncRpcResult(appResponseFuture, invocation); + result.setExecutor(executor); + return result; + } else { + return exporter.getInvoker().invoke(invocation); + } + } + + private boolean isAsync(URL remoteUrl, URL localUrl) { + if (localUrl.hasParameter(ASYNC_KEY)) { + return localUrl.getParameter(ASYNC_KEY, false); + } + return remoteUrl.getParameter(ASYNC_KEY, false); + } + +} diff --git a/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/DemoRequest.java b/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/DemoRequest.java index cbd2e340b2..3925531c88 100644 --- a/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/DemoRequest.java +++ b/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/DemoRequest.java @@ -55,4 +55,4 @@ class DemoRequest implements Serializable { public Object[] getArguments() { return mArguments; } -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/DemoService.java b/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/DemoService.java index ec42830cdc..c9d2e63d49 100644 --- a/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/DemoService.java +++ b/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/DemoService.java @@ -40,4 +40,4 @@ public interface DemoService { Type enumlength(Type... types); String getAsyncResult(); -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/DemoServiceImpl.java b/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/DemoServiceImpl.java index 2778d33ef9..c59847b298 100644 --- a/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/DemoServiceImpl.java +++ b/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/DemoServiceImpl.java @@ -80,4 +80,4 @@ public class DemoServiceImpl implements DemoService { return "DONE"; } -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/IEcho.java b/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/IEcho.java index 8e40a7ac2b..a4b3dd7058 100644 --- a/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/IEcho.java +++ b/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/IEcho.java @@ -1,21 +1,21 @@ -/* - * 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.rpc.protocol.injvm; - -public interface IEcho { - String echo(String e); -} \ No newline at end of file +/* + * 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.rpc.protocol.injvm; + +public interface IEcho { + String echo(String e); +} diff --git a/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/Type.java b/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/Type.java index 0598d34b53..05f251ede3 100644 --- a/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/Type.java +++ b/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/Type.java @@ -1,21 +1,21 @@ -/* - * 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.rpc.protocol.injvm; - -public enum Type { - High, Normal, Lower -} \ No newline at end of file +/* + * 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.rpc.protocol.injvm; + +public enum Type { + High, Normal, Lower +} diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/integration/swagger/DubboSwaggerApiListingResource.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/integration/swagger/DubboSwaggerApiListingResource.java index 41b8ff51fd..57ff74c74b 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/integration/swagger/DubboSwaggerApiListingResource.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/integration/swagger/DubboSwaggerApiListingResource.java @@ -45,4 +45,4 @@ public class DubboSwaggerApiListingResource extends BaseApiListingResource imple response.getHeaders().add("Access-Control-Allow-Methods","GET,POST,PUT,DELETE,OPTIONS"); return response; } -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/integration/swagger/DubboSwaggerService.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/integration/swagger/DubboSwaggerService.java index bc3eae8e49..e0e5a7d361 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/integration/swagger/DubboSwaggerService.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/integration/swagger/DubboSwaggerService.java @@ -40,4 +40,4 @@ public interface DubboSwaggerService { @Path("swagger") Response getListingJson(@Context Application app, @Context ServletConfig sc, @Context HttpHeaders headers, @Context UriInfo uriInfo) throws JsonProcessingException; -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/RpcExceptionMapperTest.java b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/RpcExceptionMapperTest.java index 74a133a45a..3eb8f065b3 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/RpcExceptionMapperTest.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/RpcExceptionMapperTest.java @@ -64,4 +64,4 @@ public class RpcExceptionMapperTest { assertThat(response, not(nullValue())); assertThat(response.getEntity(), instanceOf(String.class)); } -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/Metadata.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/Metadata.java index cf578ec27d..a4e926c399 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/Metadata.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/Metadata.java @@ -34,4 +34,4 @@ public interface Metadata extends Iterable boolean contains(CharSequence key); -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/GrpcStatusTest.java b/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/GrpcStatusTest.java index 7abed532c1..0d49a0f9ea 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/GrpcStatusTest.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/GrpcStatusTest.java @@ -39,4 +39,4 @@ class GrpcStatusTest { .withDescription(content); Assertions.assertNotEquals(content, status.toMessage()); } -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/UnaryClientStreamTest.java b/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/UnaryClientStreamTest.java index 345f873ce1..6dd6db122f 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/UnaryClientStreamTest.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/UnaryClientStreamTest.java @@ -77,4 +77,4 @@ class UnaryClientStreamTest { // observer.onNext(inv); } -} \ No newline at end of file +} diff --git a/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/UnaryServerStreamTest.java b/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/UnaryServerStreamTest.java index 2221e7b861..ce26f7a084 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/UnaryServerStreamTest.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/UnaryServerStreamTest.java @@ -29,4 +29,4 @@ class UnaryServerStreamTest { public void testInit() { URL url = new ServiceConfigURL("test", "1.2.3.4", 8080); } -} \ No newline at end of file +} diff --git a/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/DataInput.java b/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/DataInput.java index 7930d04d10..e2ac929514 100644 --- a/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/DataInput.java +++ b/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/DataInput.java @@ -94,4 +94,4 @@ public interface DataInput { * @throws IOException */ byte[] readBytes() throws IOException; -} \ No newline at end of file +} diff --git a/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/DataOutput.java b/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/DataOutput.java index 5897327154..02bf759939 100644 --- a/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/DataOutput.java +++ b/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/DataOutput.java @@ -111,4 +111,4 @@ public interface DataOutput { * @throws IOException */ void flushBuffer() throws IOException; -} \ No newline at end of file +} diff --git a/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/ObjectInput.java b/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/ObjectInput.java index 641b11a34a..0c68993523 100644 --- a/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/ObjectInput.java +++ b/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/ObjectInput.java @@ -86,4 +86,4 @@ public interface ObjectInput extends DataInput { default Map readAttachments() throws IOException, ClassNotFoundException { return readObject(Map.class); } -} \ No newline at end of file +} diff --git a/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/ObjectOutput.java b/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/ObjectOutput.java index 0109d56f8a..997f781ce4 100644 --- a/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/ObjectOutput.java +++ b/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/ObjectOutput.java @@ -57,4 +57,4 @@ public interface ObjectOutput extends DataOutput { writeObject(attachments); } -} \ No newline at end of file +} diff --git a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2SerializerFactory.java b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2SerializerFactory.java index f41e7dc35b..6a8db87897 100644 --- a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2SerializerFactory.java +++ b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2SerializerFactory.java @@ -28,4 +28,4 @@ public class Hessian2SerializerFactory extends SerializerFactory { return Thread.currentThread().getContextClassLoader(); } -} \ No newline at end of file +} diff --git a/dubbo-serialization/dubbo-serialization-jdk/src/main/java/org/apache/dubbo/common/serialize/java/CompactedObjectInputStream.java b/dubbo-serialization/dubbo-serialization-jdk/src/main/java/org/apache/dubbo/common/serialize/java/CompactedObjectInputStream.java index e8817746a6..2eaf7af6ab 100644 --- a/dubbo-serialization/dubbo-serialization-jdk/src/main/java/org/apache/dubbo/common/serialize/java/CompactedObjectInputStream.java +++ b/dubbo-serialization/dubbo-serialization-jdk/src/main/java/org/apache/dubbo/common/serialize/java/CompactedObjectInputStream.java @@ -61,4 +61,4 @@ public class CompactedObjectInputStream extends ObjectInputStream { private Class loadClass(String className) throws ClassNotFoundException { return mClassLoader.loadClass(className); } -} \ No newline at end of file +} diff --git a/dubbo-serialization/dubbo-serialization-jdk/src/main/java/org/apache/dubbo/common/serialize/java/CompactedObjectOutputStream.java b/dubbo-serialization/dubbo-serialization-jdk/src/main/java/org/apache/dubbo/common/serialize/java/CompactedObjectOutputStream.java index 56847e5e25..d93108311a 100644 --- a/dubbo-serialization/dubbo-serialization-jdk/src/main/java/org/apache/dubbo/common/serialize/java/CompactedObjectOutputStream.java +++ b/dubbo-serialization/dubbo-serialization-jdk/src/main/java/org/apache/dubbo/common/serialize/java/CompactedObjectOutputStream.java @@ -40,4 +40,4 @@ public class CompactedObjectOutputStream extends ObjectOutputStream { writeUTF(desc.getName()); } } -} \ No newline at end of file +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-actuator/README.md b/dubbo-spring-boot/dubbo-spring-boot-actuator/README.md index 3c478d9ba6..b501b9c3fe 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-actuator/README.md +++ b/dubbo-spring-boot/dubbo-spring-boot-actuator/README.md @@ -1,499 +1,499 @@ -# Dubbo Spring Boot Production-Ready - -`dubbo-spring-boot-actuator` provides production-ready features (e.g. [health checks](#health-checks), [endpoints](#endpoints), and [externalized configuration](#externalized-configuration)). - - - -## Content - -1. [Main Content](https://github.com/apache/dubbo-spring-boot-project) -2. [Integrate with Maven](#integrate-with-maven) -3. [Health Checks](#health-checks) -4. [Endpoints](#endpoints) -5. [Externalized Configuration](#externalized-configuration) - - - - -## Integrate with Maven - -You can introduce the latest `dubbo-spring-boot-actuator` to your project by adding the following dependency to your pom.xml -```xml - - org.apache.dubbo - dubbo-spring-boot-actuator - 2.7.4.1 - -``` - -If your project failed to resolve the dependency, try to add the following repository: -```xml - - - apache.snapshots.https - Apache Development Snapshot Repository - https://repository.apache.org/content/repositories/snapshots - - false - - - true - - - -``` - - - -## Health Checks - -`dubbo-spring-boot-actuator` supports the standard Spring Boot `HealthIndicator` as a production-ready feature , which will be aggregated into Spring Boot's `Health` and exported on `HealthEndpoint` that works MVC (Spring Web MVC) and JMX (Java Management Extensions) both if they are available. - - - -### Web Endpoint : `/health` - - - -Suppose a Spring Boot Web application did not specify `management.server.port`, you can access http://localhost:8080/actuator/health via Web Client and will get a response with JSON format is like below : - -```json -{ - "status": "UP", - "dubbo": { - "status": "UP", - "memory": { - "source": "management.health.dubbo.status.defaults", - "status": { - "level": "OK", - "message": "max:3641M,total:383M,used:92M,free:291M", - "description": null - } - }, - "load": { - "source": "management.health.dubbo.status.extras", - "status": { - "level": "OK", - "message": "load:1.73583984375,cpu:8", - "description": null - } - }, - "threadpool": { - "source": "management.health.dubbo.status.extras", - "status": { - "level": "OK", - "message": "Pool status:OK, max:200, core:200, largest:0, active:0, task:0, service port: 12345", - "description": null - } - }, - "server": { - "source": "dubbo@ProtocolConfig.getStatus()", - "status": { - "level": "OK", - "message": "/192.168.1.103:12345(clients:0)", - "description": null - } - } - } - // ignore others -} -``` - - - `memory`, `load`, `threadpool` and `server` are Dubbo's build-in `StatusChecker`s in above example. - Dubbo allows the application to extend `StatusChecker`'s SPI. - -Default , `memory` and `load` will be added into Dubbo's `HealthIndicator` , it could be overridden by -externalized configuration [`StatusChecker`'s defaults](#statuschecker-defaults). - - - -### JMX Endpoint : `Health` - - - -`Health` is a JMX (Java Management Extensions) Endpoint with ObjectName `org.springframework.boot:type=Endpoint,name=Health` , it can be managed by JMX agent ,e.g. JDK tools : `jconsole` and so on. - -![](JMX_HealthEndpoint.png) - - - -### Build-in `StatusChecker`s - - - - `META-INF/dubbo/internal/org.apache.dubbo.common.status.StatusChecker` declares Build-in `StatusChecker`s as follow : - -```properties -registry=org.apache.dubbo.registry.status.RegistryStatusChecker -spring=org.apache.dubbo.config.spring.status.SpringStatusChecker -datasource=org.apache.dubbo.config.spring.status.DataSourceStatusChecker -memory=org.apache.dubbo.common.status.support.MemoryStatusChecker -load=org.apache.dubbo.common.status.support.LoadStatusChecker -server=org.apache.dubbo.rpc.protocol.dubbo.status.ServerStatusChecker -threadpool=org.apache.dubbo.rpc.protocol.dubbo.status.ThreadPoolStatusChecker -``` - - - -The property key that is name of `StatusChecker` can be a valid value of `management.health.dubbo.status.*` in externalized configuration. - - - -## Endpoints - - - -Actuator endpoint `dubbo` supports Actuator Endpoints : - -| ID | Enabled | HTTP URI | HTTP Method | Description | Content Type | -| ------------------- | ----------- | ----------------------------------- | ------------------ | ------------------ | ------------------ | -| `dubbo` | `true` | `/actuator/dubbo` | `GET` | Exposes Dubbo's meta data | `application/json` | -| `dubboproperties` | `true` | `/actuator/dubbo/properties` | `GET` | Exposes all Dubbo's Properties | `application/json` | -| `dubboservices` | `false` | `/dubbo/services` | `GET` | Exposes all Dubbo's `ServiceBean` | `application/json` | -| `dubboreferences` | `false` | `/actuator/dubbo/references` | `GET` | Exposes all Dubbo's `ReferenceBean` | `application/json` | -| `dubboconfigs` | `true` | `/actuator/dubbo/configs` | `GET` | Exposes all Dubbo's `*Config` | `application/json` | -| `dubboshutdown` | `false` | `/actuator/dubbo/shutdown` | `POST` | Shutdown Dubbo services | `application/json` | - - - - - -### Web Endpoints - - - -#### `/actuator/dubbo` - -`/dubbo` exposes Dubbo's meta data : - -```json -{ - "timestamp": 1516623290166, - "versions": { - "dubbo-spring-boot": "2.7.5", - "dubbo": "2.7.5" - }, - "urls": { - "dubbo": "https://github.com/apache/dubbo/", - "google-group": "dev@dubbo.apache.org", - "github": "https://github.com/apache/dubbo-spring-boot-project", - "issues": "https://github.com/apache/dubbo-spring-boot-project/issues", - "git": "https://github.com/apache/dubbo-spring-boot-project.git" - } -} -``` - -### - -#### `/actuator/dubbo/properties` - -`/actuator/dubbo/properties` exposes all Dubbo's Properties from Spring Boot Externalized Configuration (a.k.a `PropertySources`) : - -```json -{ - "dubbo.application.id": "dubbo-provider-demo", - "dubbo.application.name": "dubbo-provider-demo", - "dubbo.application.qos-enable": "false", - "dubbo.application.qos-port": "33333", - "dubbo.protocol.id": "dubbo", - "dubbo.protocol.name": "dubbo", - "dubbo.protocol.port": "12345", - "dubbo.registry.address": "N/A", - "dubbo.registry.id": "my-registry", - "dubbo.scan.basePackages": "org.apache.dubbo.spring.boot.sample.provider.service" -} -``` - -The structure of JSON is simple Key-Value format , the key is property name as and the value is property value. - - - - - -#### `/actuator/dubbo/services` - -`/actuator/dubbo/services` exposes all Dubbo's `ServiceBean` that are declared via `` or `@Service` present in Spring `ApplicationContext` : - -```json -{ - "ServiceBean@org.apache.dubbo.spring.boot.sample.api.DemoService#defaultDemoService": { - "accesslog": null, - "actives": null, - "cache": null, - "callbacks": null, - "class": "org.apache.dubbo.config.spring.ServiceBean", - "cluster": null, - "connections": null, - "delay": null, - "document": null, - "executes": null, - "export": null, - "exported": true, - "filter": "", - "generic": "false", - "group": null, - "id": "org.apache.dubbo.spring.boot.sample.api.DemoService", - "interface": "org.apache.dubbo.spring.boot.sample.api.DemoService", - "interfaceClass": "org.apache.dubbo.spring.boot.sample.api.DemoService", - "layer": null, - "listener": "", - "loadbalance": null, - "local": null, - "merger": null, - "mock": null, - "onconnect": null, - "ondisconnect": null, - "owner": null, - "path": "org.apache.dubbo.spring.boot.sample.api.DemoService", - "proxy": null, - "retries": null, - "scope": null, - "sent": null, - "stub": null, - "timeout": null, - "token": null, - "unexported": false, - "uniqueServiceName": "org.apache.dubbo.spring.boot.sample.api.DemoService:1.0.0", - "validation": null, - "version": "1.0.0", - "warmup": null, - "weight": null, - "serviceClass": "DefaultDemoService" - } -} -``` - -The key is the Bean name of `ServiceBean` , `ServiceBean`'s properties compose value. - - - -#### `/actuator/dubbo/references` - -`/actuator/dubbo/references` exposes all Dubbo's `ReferenceBean` that are declared via `@Reference` annotating on `Field` or `Method ` : - -```json -{ - "private org.apache.dubbo.spring.boot.sample.api.DemoService org.apache.dubbo.spring.boot.sample.consumer.controller.DemoConsumerController.demoService": { - "actives": null, - "cache": null, - "callbacks": null, - "class": "org.apache.dubbo.config.spring.ReferenceBean", - "client": null, - "cluster": null, - "connections": null, - "filter": "", - "generic": null, - "group": null, - "id": "org.apache.dubbo.spring.boot.sample.api.DemoService", - "interface": "org.apache.dubbo.spring.boot.sample.api.DemoService", - "interfaceClass": "org.apache.dubbo.spring.boot.sample.api.DemoService", - "layer": null, - "lazy": null, - "listener": "", - "loadbalance": null, - "local": null, - "merger": null, - "mock": null, - "objectType": "org.apache.dubbo.spring.boot.sample.api.DemoService", - "onconnect": null, - "ondisconnect": null, - "owner": null, - "protocol": null, - "proxy": null, - "reconnect": null, - "retries": null, - "scope": null, - "sent": null, - "singleton": true, - "sticky": null, - "stub": null, - "stubevent": null, - "timeout": null, - "uniqueServiceName": "org.apache.dubbo.spring.boot.sample.api.DemoService:1.0.0", - "url": "dubbo://localhost:12345", - "validation": null, - "version": "1.0.0", - "invoker": { - "class": "org.apache.dubbo.common.bytecode.proxy0" - } - } -} -``` - -The key is the string presentation of `@Reference` `Field` or `Method ` , `ReferenceBean`'s properties compose value. - - - -#### `/actuator/dubbo/configs` - - `/actuator/dubbo/configs` exposes all Dubbo's `*Config` : - -```json -{ - "ApplicationConfig": { - "dubbo-consumer-demo": { - "architecture": null, - "class": "org.apache.dubbo.config.ApplicationConfig", - "compiler": null, - "dumpDirectory": null, - "environment": null, - "id": "dubbo-consumer-demo", - "logger": null, - "name": "dubbo-consumer-demo", - "organization": null, - "owner": null, - "version": null - } - }, - "ConsumerConfig": { - - }, - "MethodConfig": { - - }, - "ModuleConfig": { - - }, - "MonitorConfig": { - - }, - "ProtocolConfig": { - "dubbo": { - "accepts": null, - "accesslog": null, - "buffer": null, - "charset": null, - "class": "org.apache.dubbo.config.ProtocolConfig", - "client": null, - "codec": null, - "contextpath": null, - "dispatcher": null, - "dispather": null, - "exchanger": null, - "heartbeat": null, - "host": null, - "id": "dubbo", - "iothreads": null, - "name": "dubbo", - "networker": null, - "path": null, - "payload": null, - "port": 12345, - "prompt": null, - "queues": null, - "serialization": null, - "server": null, - "status": null, - "telnet": null, - "threadpool": null, - "threads": null, - "transporter": null - } - }, - "ProviderConfig": { - - }, - "ReferenceConfig": { - - }, - "RegistryConfig": { - - }, - "ServiceConfig": { - - } -} -``` - -The key is the simple name of Dubbo `*Config` Class , the value is`*Config` Beans' Name-Properties Map. - - - -#### `/actuator/dubbo/shutdown` - -`/actuator/dubbo/shutdown` shutdowns Dubbo's components including registries, protocols, services and references : - -```json -{ - "shutdown.count": { - "registries": 0, - "protocols": 1, - "services": 0, - "references": 1 - } -} -``` - -"shutdown.count" means the count of shutdown of Dubbo's components , and the value indicates how many components have been shutdown. - - - -## Externalized Configuration - - - -### `StatusChecker` Defaults - - - -`management.health.dubbo.status.defaults` is a property name for setting names of `StatusChecker`s , its value is allowed to multiple-values , for example : - -```properties -management.health.dubbo.status.defaults = registry,memory,load -``` - - - -#### Default Value - -The default value is : - -```properties -management.health.dubbo.status.defaults = memory,load -``` - - - -### `StatusChecker` Extras - - - -`management.health.dubbo.status.extras` is used to override the [ [`StatusChecker`'s defaults]](#statuschecker-defaults) , the multiple-values is delimited by comma : - -```properties -management.health.dubbo.status.extras = load,threadpool -``` - - - -### Health Checks Enabled - - - -`management.health.dubbo.enabled` is a enabled configuration to turn on or off health checks feature, its' default is `true`. - - If you'd like to disable health checks , you chould apply `management.health.dubbo.enabled` to be `false`: - -```properties -management.health.dubbo.enabled = false -``` - - - -### Endpoints Enabled - - - -Dubbo Spring Boot providers actuator endpoints , however some of them are disable. If you'd like to enable them , please add following properties into externalized configuration : - -```properties -# Enables Dubbo All Endpoints -management.endpoint.dubbo.enabled = true -management.endpoint.dubboshutdown.enabled = true -management.endpoint.dubboconfigs.enabled = true -management.endpoint.dubboservices.enabled = true -management.endpoint.dubboreferences.enabled = true -management.endpoint.dubboproperties.enabled = true -``` - +# Dubbo Spring Boot Production-Ready + +`dubbo-spring-boot-actuator` provides production-ready features (e.g. [health checks](#health-checks), [endpoints](#endpoints), and [externalized configuration](#externalized-configuration)). + + + +## Content + +1. [Main Content](https://github.com/apache/dubbo-spring-boot-project) +2. [Integrate with Maven](#integrate-with-maven) +3. [Health Checks](#health-checks) +4. [Endpoints](#endpoints) +5. [Externalized Configuration](#externalized-configuration) + + + + +## Integrate with Maven + +You can introduce the latest `dubbo-spring-boot-actuator` to your project by adding the following dependency to your pom.xml +```xml + + org.apache.dubbo + dubbo-spring-boot-actuator + 2.7.4.1 + +``` + +If your project failed to resolve the dependency, try to add the following repository: +```xml + + + apache.snapshots.https + Apache Development Snapshot Repository + https://repository.apache.org/content/repositories/snapshots + + false + + + true + + + +``` + + + +## Health Checks + +`dubbo-spring-boot-actuator` supports the standard Spring Boot `HealthIndicator` as a production-ready feature , which will be aggregated into Spring Boot's `Health` and exported on `HealthEndpoint` that works MVC (Spring Web MVC) and JMX (Java Management Extensions) both if they are available. + + + +### Web Endpoint : `/health` + + + +Suppose a Spring Boot Web application did not specify `management.server.port`, you can access http://localhost:8080/actuator/health via Web Client and will get a response with JSON format is like below : + +```json +{ + "status": "UP", + "dubbo": { + "status": "UP", + "memory": { + "source": "management.health.dubbo.status.defaults", + "status": { + "level": "OK", + "message": "max:3641M,total:383M,used:92M,free:291M", + "description": null + } + }, + "load": { + "source": "management.health.dubbo.status.extras", + "status": { + "level": "OK", + "message": "load:1.73583984375,cpu:8", + "description": null + } + }, + "threadpool": { + "source": "management.health.dubbo.status.extras", + "status": { + "level": "OK", + "message": "Pool status:OK, max:200, core:200, largest:0, active:0, task:0, service port: 12345", + "description": null + } + }, + "server": { + "source": "dubbo@ProtocolConfig.getStatus()", + "status": { + "level": "OK", + "message": "/192.168.1.103:12345(clients:0)", + "description": null + } + } + } + // ignore others +} +``` + + + `memory`, `load`, `threadpool` and `server` are Dubbo's build-in `StatusChecker`s in above example. + Dubbo allows the application to extend `StatusChecker`'s SPI. + +Default , `memory` and `load` will be added into Dubbo's `HealthIndicator` , it could be overridden by +externalized configuration [`StatusChecker`'s defaults](#statuschecker-defaults). + + + +### JMX Endpoint : `Health` + + + +`Health` is a JMX (Java Management Extensions) Endpoint with ObjectName `org.springframework.boot:type=Endpoint,name=Health` , it can be managed by JMX agent ,e.g. JDK tools : `jconsole` and so on. + +![](JMX_HealthEndpoint.png) + + + +### Build-in `StatusChecker`s + + + + `META-INF/dubbo/internal/org.apache.dubbo.common.status.StatusChecker` declares Build-in `StatusChecker`s as follow : + +```properties +registry=org.apache.dubbo.registry.status.RegistryStatusChecker +spring=org.apache.dubbo.config.spring.status.SpringStatusChecker +datasource=org.apache.dubbo.config.spring.status.DataSourceStatusChecker +memory=org.apache.dubbo.common.status.support.MemoryStatusChecker +load=org.apache.dubbo.common.status.support.LoadStatusChecker +server=org.apache.dubbo.rpc.protocol.dubbo.status.ServerStatusChecker +threadpool=org.apache.dubbo.rpc.protocol.dubbo.status.ThreadPoolStatusChecker +``` + + + +The property key that is name of `StatusChecker` can be a valid value of `management.health.dubbo.status.*` in externalized configuration. + + + +## Endpoints + + + +Actuator endpoint `dubbo` supports Actuator Endpoints : + +| ID | Enabled | HTTP URI | HTTP Method | Description | Content Type | +| ------------------- | ----------- | ----------------------------------- | ------------------ | ------------------ | ------------------ | +| `dubbo` | `true` | `/actuator/dubbo` | `GET` | Exposes Dubbo's meta data | `application/json` | +| `dubboproperties` | `true` | `/actuator/dubbo/properties` | `GET` | Exposes all Dubbo's Properties | `application/json` | +| `dubboservices` | `false` | `/dubbo/services` | `GET` | Exposes all Dubbo's `ServiceBean` | `application/json` | +| `dubboreferences` | `false` | `/actuator/dubbo/references` | `GET` | Exposes all Dubbo's `ReferenceBean` | `application/json` | +| `dubboconfigs` | `true` | `/actuator/dubbo/configs` | `GET` | Exposes all Dubbo's `*Config` | `application/json` | +| `dubboshutdown` | `false` | `/actuator/dubbo/shutdown` | `POST` | Shutdown Dubbo services | `application/json` | + + + + + +### Web Endpoints + + + +#### `/actuator/dubbo` + +`/dubbo` exposes Dubbo's meta data : + +```json +{ + "timestamp": 1516623290166, + "versions": { + "dubbo-spring-boot": "2.7.5", + "dubbo": "2.7.5" + }, + "urls": { + "dubbo": "https://github.com/apache/dubbo/", + "google-group": "dev@dubbo.apache.org", + "github": "https://github.com/apache/dubbo-spring-boot-project", + "issues": "https://github.com/apache/dubbo-spring-boot-project/issues", + "git": "https://github.com/apache/dubbo-spring-boot-project.git" + } +} +``` + +### + +#### `/actuator/dubbo/properties` + +`/actuator/dubbo/properties` exposes all Dubbo's Properties from Spring Boot Externalized Configuration (a.k.a `PropertySources`) : + +```json +{ + "dubbo.application.id": "dubbo-provider-demo", + "dubbo.application.name": "dubbo-provider-demo", + "dubbo.application.qos-enable": "false", + "dubbo.application.qos-port": "33333", + "dubbo.protocol.id": "dubbo", + "dubbo.protocol.name": "dubbo", + "dubbo.protocol.port": "12345", + "dubbo.registry.address": "N/A", + "dubbo.registry.id": "my-registry", + "dubbo.scan.basePackages": "org.apache.dubbo.spring.boot.sample.provider.service" +} +``` + +The structure of JSON is simple Key-Value format , the key is property name as and the value is property value. + + + + + +#### `/actuator/dubbo/services` + +`/actuator/dubbo/services` exposes all Dubbo's `ServiceBean` that are declared via `` or `@Service` present in Spring `ApplicationContext` : + +```json +{ + "ServiceBean@org.apache.dubbo.spring.boot.sample.api.DemoService#defaultDemoService": { + "accesslog": null, + "actives": null, + "cache": null, + "callbacks": null, + "class": "org.apache.dubbo.config.spring.ServiceBean", + "cluster": null, + "connections": null, + "delay": null, + "document": null, + "executes": null, + "export": null, + "exported": true, + "filter": "", + "generic": "false", + "group": null, + "id": "org.apache.dubbo.spring.boot.sample.api.DemoService", + "interface": "org.apache.dubbo.spring.boot.sample.api.DemoService", + "interfaceClass": "org.apache.dubbo.spring.boot.sample.api.DemoService", + "layer": null, + "listener": "", + "loadbalance": null, + "local": null, + "merger": null, + "mock": null, + "onconnect": null, + "ondisconnect": null, + "owner": null, + "path": "org.apache.dubbo.spring.boot.sample.api.DemoService", + "proxy": null, + "retries": null, + "scope": null, + "sent": null, + "stub": null, + "timeout": null, + "token": null, + "unexported": false, + "uniqueServiceName": "org.apache.dubbo.spring.boot.sample.api.DemoService:1.0.0", + "validation": null, + "version": "1.0.0", + "warmup": null, + "weight": null, + "serviceClass": "DefaultDemoService" + } +} +``` + +The key is the Bean name of `ServiceBean` , `ServiceBean`'s properties compose value. + + + +#### `/actuator/dubbo/references` + +`/actuator/dubbo/references` exposes all Dubbo's `ReferenceBean` that are declared via `@Reference` annotating on `Field` or `Method ` : + +```json +{ + "private org.apache.dubbo.spring.boot.sample.api.DemoService org.apache.dubbo.spring.boot.sample.consumer.controller.DemoConsumerController.demoService": { + "actives": null, + "cache": null, + "callbacks": null, + "class": "org.apache.dubbo.config.spring.ReferenceBean", + "client": null, + "cluster": null, + "connections": null, + "filter": "", + "generic": null, + "group": null, + "id": "org.apache.dubbo.spring.boot.sample.api.DemoService", + "interface": "org.apache.dubbo.spring.boot.sample.api.DemoService", + "interfaceClass": "org.apache.dubbo.spring.boot.sample.api.DemoService", + "layer": null, + "lazy": null, + "listener": "", + "loadbalance": null, + "local": null, + "merger": null, + "mock": null, + "objectType": "org.apache.dubbo.spring.boot.sample.api.DemoService", + "onconnect": null, + "ondisconnect": null, + "owner": null, + "protocol": null, + "proxy": null, + "reconnect": null, + "retries": null, + "scope": null, + "sent": null, + "singleton": true, + "sticky": null, + "stub": null, + "stubevent": null, + "timeout": null, + "uniqueServiceName": "org.apache.dubbo.spring.boot.sample.api.DemoService:1.0.0", + "url": "dubbo://localhost:12345", + "validation": null, + "version": "1.0.0", + "invoker": { + "class": "org.apache.dubbo.common.bytecode.proxy0" + } + } +} +``` + +The key is the string presentation of `@Reference` `Field` or `Method ` , `ReferenceBean`'s properties compose value. + + + +#### `/actuator/dubbo/configs` + + `/actuator/dubbo/configs` exposes all Dubbo's `*Config` : + +```json +{ + "ApplicationConfig": { + "dubbo-consumer-demo": { + "architecture": null, + "class": "org.apache.dubbo.config.ApplicationConfig", + "compiler": null, + "dumpDirectory": null, + "environment": null, + "id": "dubbo-consumer-demo", + "logger": null, + "name": "dubbo-consumer-demo", + "organization": null, + "owner": null, + "version": null + } + }, + "ConsumerConfig": { + + }, + "MethodConfig": { + + }, + "ModuleConfig": { + + }, + "MonitorConfig": { + + }, + "ProtocolConfig": { + "dubbo": { + "accepts": null, + "accesslog": null, + "buffer": null, + "charset": null, + "class": "org.apache.dubbo.config.ProtocolConfig", + "client": null, + "codec": null, + "contextpath": null, + "dispatcher": null, + "dispather": null, + "exchanger": null, + "heartbeat": null, + "host": null, + "id": "dubbo", + "iothreads": null, + "name": "dubbo", + "networker": null, + "path": null, + "payload": null, + "port": 12345, + "prompt": null, + "queues": null, + "serialization": null, + "server": null, + "status": null, + "telnet": null, + "threadpool": null, + "threads": null, + "transporter": null + } + }, + "ProviderConfig": { + + }, + "ReferenceConfig": { + + }, + "RegistryConfig": { + + }, + "ServiceConfig": { + + } +} +``` + +The key is the simple name of Dubbo `*Config` Class , the value is`*Config` Beans' Name-Properties Map. + + + +#### `/actuator/dubbo/shutdown` + +`/actuator/dubbo/shutdown` shutdowns Dubbo's components including registries, protocols, services and references : + +```json +{ + "shutdown.count": { + "registries": 0, + "protocols": 1, + "services": 0, + "references": 1 + } +} +``` + +"shutdown.count" means the count of shutdown of Dubbo's components , and the value indicates how many components have been shutdown. + + + +## Externalized Configuration + + + +### `StatusChecker` Defaults + + + +`management.health.dubbo.status.defaults` is a property name for setting names of `StatusChecker`s , its value is allowed to multiple-values , for example : + +```properties +management.health.dubbo.status.defaults = registry,memory,load +``` + + + +#### Default Value + +The default value is : + +```properties +management.health.dubbo.status.defaults = memory,load +``` + + + +### `StatusChecker` Extras + + + +`management.health.dubbo.status.extras` is used to override the [ [`StatusChecker`'s defaults]](#statuschecker-defaults) , the multiple-values is delimited by comma : + +```properties +management.health.dubbo.status.extras = load,threadpool +``` + + + +### Health Checks Enabled + + + +`management.health.dubbo.enabled` is a enabled configuration to turn on or off health checks feature, its' default is `true`. + + If you'd like to disable health checks , you chould apply `management.health.dubbo.enabled` to be `false`: + +```properties +management.health.dubbo.enabled = false +``` + + + +### Endpoints Enabled + + + +Dubbo Spring Boot providers actuator endpoints , however some of them are disable. If you'd like to enable them , please add following properties into externalized configuration : + +```properties +# Enables Dubbo All Endpoints +management.endpoint.dubbo.enabled = true +management.endpoint.dubboshutdown.enabled = true +management.endpoint.dubboconfigs.enabled = true +management.endpoint.dubboservices.enabled = true +management.endpoint.dubboreferences.enabled = true +management.endpoint.dubboproperties.enabled = true +``` + diff --git a/dubbo-spring-boot/dubbo-spring-boot-actuator/pom.xml b/dubbo-spring-boot/dubbo-spring-boot-actuator/pom.xml index c7e15bb081..c0ec86995a 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-actuator/pom.xml +++ b/dubbo-spring-boot/dubbo-spring-boot-actuator/pom.xml @@ -1,124 +1,124 @@ - - - - - org.apache.dubbo - dubbo-spring-boot - ${revision} - ../pom.xml - - 4.0.0 - - dubbo-spring-boot-actuator - jar - Apache Dubbo Spring Boot Actuator - - - - - org.apache.dubbo - dubbo-spring-boot-actuator-compatible - ${revision} - - - - - org.springframework.boot - spring-boot-starter-web - true - - - - org.springframework.boot - spring-boot-starter-actuator - true - - - - org.springframework.boot - spring-boot-autoconfigure - true - - - - - org.apache.dubbo - dubbo-spring-boot-autoconfigure - ${revision} - - - - - org.apache.dubbo - dubbo - ${revision} - - - - org.apache.dubbo - dubbo-common - ${revision} - true - - - - org.apache.dubbo - dubbo-config-spring - ${revision} - true - - - - org.apache.dubbo - dubbo-remoting-netty4 - ${revision} - true - - - - org.apache.dubbo - dubbo-serialization-hessian2 - ${revision} - true - - - - org.apache.dubbo - dubbo-rpc-dubbo - ${revision} - true - - - - - org.springframework.boot - spring-boot-starter-test - test - - - - org.junit.platform - junit-platform-runner - test - - - - + + + + + org.apache.dubbo + dubbo-spring-boot + ${revision} + ../pom.xml + + 4.0.0 + + dubbo-spring-boot-actuator + jar + Apache Dubbo Spring Boot Actuator + + + + + org.apache.dubbo + dubbo-spring-boot-actuator-compatible + ${revision} + + + + + org.springframework.boot + spring-boot-starter-web + true + + + + org.springframework.boot + spring-boot-starter-actuator + true + + + + org.springframework.boot + spring-boot-autoconfigure + true + + + + + org.apache.dubbo + dubbo-spring-boot-autoconfigure + ${revision} + + + + + org.apache.dubbo + dubbo + ${revision} + + + + org.apache.dubbo + dubbo-common + ${revision} + true + + + + org.apache.dubbo + dubbo-config-spring + ${revision} + true + + + + org.apache.dubbo + dubbo-remoting-netty4 + ${revision} + true + + + + org.apache.dubbo + dubbo-serialization-hessian2 + ${revision} + true + + + + org.apache.dubbo + dubbo-rpc-dubbo + ${revision} + true + + + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.junit.platform + junit-platform-runner + test + + + + \ No newline at end of file diff --git a/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/autoconfigure/DubboEndpointAnnotationAutoConfiguration.java b/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/autoconfigure/DubboEndpointAnnotationAutoConfiguration.java index 7ae8b848de..6db22db20f 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/autoconfigure/DubboEndpointAnnotationAutoConfiguration.java +++ b/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/autoconfigure/DubboEndpointAnnotationAutoConfiguration.java @@ -1,88 +1,88 @@ -/* - * 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.spring.boot.actuate.autoconfigure; - -import org.apache.dubbo.spring.boot.actuate.endpoint.DubboConfigsMetadataEndpoint; -import org.apache.dubbo.spring.boot.actuate.endpoint.DubboMetadataEndpoint; -import org.apache.dubbo.spring.boot.actuate.endpoint.DubboPropertiesMetadataEndpoint; -import org.apache.dubbo.spring.boot.actuate.endpoint.DubboReferencesMetadataEndpoint; -import org.apache.dubbo.spring.boot.actuate.endpoint.DubboServicesMetadataEndpoint; -import org.apache.dubbo.spring.boot.actuate.endpoint.DubboShutdownEndpoint; -import org.apache.dubbo.spring.boot.actuate.endpoint.condition.CompatibleConditionalOnEnabledEndpoint; - -import org.springframework.boot.actuate.endpoint.annotation.Endpoint; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.PropertySource; - -/** - * Dubbo {@link Endpoint @Endpoint} Auto-{@link Configuration} for Spring Boot Actuator 2.0 - * - * @see Endpoint - * @see Configuration - * @since 2.7.0 - */ -@Configuration -@PropertySource( - name = "Dubbo Endpoints Default Properties", - value = "classpath:/META-INF/dubbo-endpoints-default.properties") -public class DubboEndpointAnnotationAutoConfiguration { - - @Bean - @ConditionalOnMissingBean - @CompatibleConditionalOnEnabledEndpoint - public DubboMetadataEndpoint dubboEndpoint() { - return new DubboMetadataEndpoint(); - } - - @Bean - @ConditionalOnMissingBean - @CompatibleConditionalOnEnabledEndpoint - public DubboConfigsMetadataEndpoint dubboConfigsMetadataEndpoint() { - return new DubboConfigsMetadataEndpoint(); - } - - @Bean - @ConditionalOnMissingBean - @CompatibleConditionalOnEnabledEndpoint - public DubboPropertiesMetadataEndpoint dubboPropertiesEndpoint() { - return new DubboPropertiesMetadataEndpoint(); - } - - @Bean - @ConditionalOnMissingBean - @CompatibleConditionalOnEnabledEndpoint - public DubboReferencesMetadataEndpoint dubboReferencesMetadataEndpoint() { - return new DubboReferencesMetadataEndpoint(); - } - - @Bean - @ConditionalOnMissingBean - @CompatibleConditionalOnEnabledEndpoint - public DubboServicesMetadataEndpoint dubboServicesMetadataEndpoint() { - return new DubboServicesMetadataEndpoint(); - } - - @Bean - @ConditionalOnMissingBean - @CompatibleConditionalOnEnabledEndpoint - public DubboShutdownEndpoint dubboShutdownEndpoint() { - return new DubboShutdownEndpoint(); - } - -} +/* + * 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.spring.boot.actuate.autoconfigure; + +import org.apache.dubbo.spring.boot.actuate.endpoint.DubboConfigsMetadataEndpoint; +import org.apache.dubbo.spring.boot.actuate.endpoint.DubboMetadataEndpoint; +import org.apache.dubbo.spring.boot.actuate.endpoint.DubboPropertiesMetadataEndpoint; +import org.apache.dubbo.spring.boot.actuate.endpoint.DubboReferencesMetadataEndpoint; +import org.apache.dubbo.spring.boot.actuate.endpoint.DubboServicesMetadataEndpoint; +import org.apache.dubbo.spring.boot.actuate.endpoint.DubboShutdownEndpoint; +import org.apache.dubbo.spring.boot.actuate.endpoint.condition.CompatibleConditionalOnEnabledEndpoint; + +import org.springframework.boot.actuate.endpoint.annotation.Endpoint; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +/** + * Dubbo {@link Endpoint @Endpoint} Auto-{@link Configuration} for Spring Boot Actuator 2.0 + * + * @see Endpoint + * @see Configuration + * @since 2.7.0 + */ +@Configuration +@PropertySource( + name = "Dubbo Endpoints Default Properties", + value = "classpath:/META-INF/dubbo-endpoints-default.properties") +public class DubboEndpointAnnotationAutoConfiguration { + + @Bean + @ConditionalOnMissingBean + @CompatibleConditionalOnEnabledEndpoint + public DubboMetadataEndpoint dubboEndpoint() { + return new DubboMetadataEndpoint(); + } + + @Bean + @ConditionalOnMissingBean + @CompatibleConditionalOnEnabledEndpoint + public DubboConfigsMetadataEndpoint dubboConfigsMetadataEndpoint() { + return new DubboConfigsMetadataEndpoint(); + } + + @Bean + @ConditionalOnMissingBean + @CompatibleConditionalOnEnabledEndpoint + public DubboPropertiesMetadataEndpoint dubboPropertiesEndpoint() { + return new DubboPropertiesMetadataEndpoint(); + } + + @Bean + @ConditionalOnMissingBean + @CompatibleConditionalOnEnabledEndpoint + public DubboReferencesMetadataEndpoint dubboReferencesMetadataEndpoint() { + return new DubboReferencesMetadataEndpoint(); + } + + @Bean + @ConditionalOnMissingBean + @CompatibleConditionalOnEnabledEndpoint + public DubboServicesMetadataEndpoint dubboServicesMetadataEndpoint() { + return new DubboServicesMetadataEndpoint(); + } + + @Bean + @ConditionalOnMissingBean + @CompatibleConditionalOnEnabledEndpoint + public DubboShutdownEndpoint dubboShutdownEndpoint() { + return new DubboShutdownEndpoint(); + } + +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/DubboConfigsMetadataEndpoint.java b/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/DubboConfigsMetadataEndpoint.java index b861e5ccb0..77b1e2080c 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/DubboConfigsMetadataEndpoint.java +++ b/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/DubboConfigsMetadataEndpoint.java @@ -1,43 +1,43 @@ -/* - * 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.spring.boot.actuate.endpoint; - -import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.AbstractDubboMetadata; -import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboConfigsMetadata; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.actuate.endpoint.annotation.Endpoint; -import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; - -import java.util.Map; - -/** - * Dubbo Configs Metadata {@link Endpoint} - * - * @since 2.7.0 - */ -@Endpoint(id = "dubboconfigs") -public class DubboConfigsMetadataEndpoint extends AbstractDubboMetadata { - - @Autowired - private DubboConfigsMetadata dubboConfigsMetadata; - - @ReadOperation - public Map>> configs() { - return dubboConfigsMetadata.configs(); - } -} +/* + * 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.spring.boot.actuate.endpoint; + +import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.AbstractDubboMetadata; +import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboConfigsMetadata; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.endpoint.annotation.Endpoint; +import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; + +import java.util.Map; + +/** + * Dubbo Configs Metadata {@link Endpoint} + * + * @since 2.7.0 + */ +@Endpoint(id = "dubboconfigs") +public class DubboConfigsMetadataEndpoint extends AbstractDubboMetadata { + + @Autowired + private DubboConfigsMetadata dubboConfigsMetadata; + + @ReadOperation + public Map>> configs() { + return dubboConfigsMetadata.configs(); + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/DubboMetadataEndpoint.java b/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/DubboMetadataEndpoint.java index edf732840f..fb35b7f08f 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/DubboMetadataEndpoint.java +++ b/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/DubboMetadataEndpoint.java @@ -1,44 +1,44 @@ -/* - * 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.spring.boot.actuate.endpoint; - -import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboMetadata; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.actuate.endpoint.annotation.Endpoint; -import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; - -import java.util.Map; - -/** - * Actuator {@link Endpoint} to expose Dubbo Meta Data - * - * @see Endpoint - * @since 2.7.0 - */ -@Endpoint(id = "dubbo") -public class DubboMetadataEndpoint { - - @Autowired - private DubboMetadata dubboMetadata; - - @ReadOperation - public Map invoke() { - return dubboMetadata.invoke(); - } - -} +/* + * 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.spring.boot.actuate.endpoint; + +import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboMetadata; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.endpoint.annotation.Endpoint; +import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; + +import java.util.Map; + +/** + * Actuator {@link Endpoint} to expose Dubbo Meta Data + * + * @see Endpoint + * @since 2.7.0 + */ +@Endpoint(id = "dubbo") +public class DubboMetadataEndpoint { + + @Autowired + private DubboMetadata dubboMetadata; + + @ReadOperation + public Map invoke() { + return dubboMetadata.invoke(); + } + +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/DubboPropertiesMetadataEndpoint.java b/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/DubboPropertiesMetadataEndpoint.java index 4295113f75..8105e33011 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/DubboPropertiesMetadataEndpoint.java +++ b/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/DubboPropertiesMetadataEndpoint.java @@ -1,43 +1,43 @@ -/* - * 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.spring.boot.actuate.endpoint; - -import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.AbstractDubboMetadata; -import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboPropertiesMetadata; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.actuate.endpoint.annotation.Endpoint; -import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; - -import java.util.SortedMap; - -/** - * Dubbo Properties {@link Endpoint} - * - * @since 2.7.0 - */ -@Endpoint(id = "dubboproperties") -public class DubboPropertiesMetadataEndpoint extends AbstractDubboMetadata { - - @Autowired - private DubboPropertiesMetadata dubboPropertiesMetadata; - - @ReadOperation - public SortedMap properties() { - return dubboPropertiesMetadata.properties(); - } -} +/* + * 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.spring.boot.actuate.endpoint; + +import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.AbstractDubboMetadata; +import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboPropertiesMetadata; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.endpoint.annotation.Endpoint; +import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; + +import java.util.SortedMap; + +/** + * Dubbo Properties {@link Endpoint} + * + * @since 2.7.0 + */ +@Endpoint(id = "dubboproperties") +public class DubboPropertiesMetadataEndpoint extends AbstractDubboMetadata { + + @Autowired + private DubboPropertiesMetadata dubboPropertiesMetadata; + + @ReadOperation + public SortedMap properties() { + return dubboPropertiesMetadata.properties(); + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/DubboReferencesMetadataEndpoint.java b/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/DubboReferencesMetadataEndpoint.java index 18fc09b273..f2497da3f3 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/DubboReferencesMetadataEndpoint.java +++ b/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/DubboReferencesMetadataEndpoint.java @@ -1,44 +1,44 @@ -/* - * 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.spring.boot.actuate.endpoint; - -import org.apache.dubbo.config.annotation.DubboReference; -import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.AbstractDubboMetadata; -import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboReferencesMetadata; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.actuate.endpoint.annotation.Endpoint; -import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; - -import java.util.Map; - -/** - * {@link DubboReference} Metadata {@link Endpoint} - * - * @since 2.7.0 - */ -@Endpoint(id = "dubboreferences") -public class DubboReferencesMetadataEndpoint extends AbstractDubboMetadata { - - @Autowired - private DubboReferencesMetadata dubboReferencesMetadata; - - @ReadOperation - public Map> references() { - return dubboReferencesMetadata.references(); - } -} +/* + * 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.spring.boot.actuate.endpoint; + +import org.apache.dubbo.config.annotation.DubboReference; +import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.AbstractDubboMetadata; +import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboReferencesMetadata; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.endpoint.annotation.Endpoint; +import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; + +import java.util.Map; + +/** + * {@link DubboReference} Metadata {@link Endpoint} + * + * @since 2.7.0 + */ +@Endpoint(id = "dubboreferences") +public class DubboReferencesMetadataEndpoint extends AbstractDubboMetadata { + + @Autowired + private DubboReferencesMetadata dubboReferencesMetadata; + + @ReadOperation + public Map> references() { + return dubboReferencesMetadata.references(); + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/DubboServicesMetadataEndpoint.java b/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/DubboServicesMetadataEndpoint.java index 552e4b8c08..845dbc1f3f 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/DubboServicesMetadataEndpoint.java +++ b/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/DubboServicesMetadataEndpoint.java @@ -1,44 +1,44 @@ -/* - * 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.spring.boot.actuate.endpoint; - -import org.apache.dubbo.config.annotation.DubboService; -import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.AbstractDubboMetadata; -import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboServicesMetadata; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.actuate.endpoint.annotation.Endpoint; -import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; - -import java.util.Map; - -/** - * {@link DubboService} Metadata {@link Endpoint} - * - * @since 2.7.0 - */ -@Endpoint(id = "dubboservices") -public class DubboServicesMetadataEndpoint extends AbstractDubboMetadata { - - @Autowired - private DubboServicesMetadata dubboServicesMetadata; - - @ReadOperation - public Map> services() { - return dubboServicesMetadata.services(); - } -} +/* + * 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.spring.boot.actuate.endpoint; + +import org.apache.dubbo.config.annotation.DubboService; +import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.AbstractDubboMetadata; +import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboServicesMetadata; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.endpoint.annotation.Endpoint; +import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; + +import java.util.Map; + +/** + * {@link DubboService} Metadata {@link Endpoint} + * + * @since 2.7.0 + */ +@Endpoint(id = "dubboservices") +public class DubboServicesMetadataEndpoint extends AbstractDubboMetadata { + + @Autowired + private DubboServicesMetadata dubboServicesMetadata; + + @ReadOperation + public Map> services() { + return dubboServicesMetadata.services(); + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/DubboShutdownEndpoint.java b/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/DubboShutdownEndpoint.java index e62b57ba1b..9565e84979 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/DubboShutdownEndpoint.java +++ b/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/DubboShutdownEndpoint.java @@ -1,44 +1,44 @@ -/* - * 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.spring.boot.actuate.endpoint; - -import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.AbstractDubboMetadata; -import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboShutdownMetadata; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.actuate.endpoint.annotation.Endpoint; -import org.springframework.boot.actuate.endpoint.annotation.WriteOperation; - -import java.util.Map; - -/** - * Dubbo Shutdown - * - * @since 2.7.0 - */ -@Endpoint(id = "dubboshutdown") -public class DubboShutdownEndpoint extends AbstractDubboMetadata { - - @Autowired - private DubboShutdownMetadata dubboShutdownMetadata; - - @WriteOperation - public Map shutdown() throws Exception { - return dubboShutdownMetadata.shutdown(); - } - -} +/* + * 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.spring.boot.actuate.endpoint; + +import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.AbstractDubboMetadata; +import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboShutdownMetadata; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.endpoint.annotation.Endpoint; +import org.springframework.boot.actuate.endpoint.annotation.WriteOperation; + +import java.util.Map; + +/** + * Dubbo Shutdown + * + * @since 2.7.0 + */ +@Endpoint(id = "dubboshutdown") +public class DubboShutdownEndpoint extends AbstractDubboMetadata { + + @Autowired + private DubboShutdownMetadata dubboShutdownMetadata; + + @WriteOperation + public Map shutdown() throws Exception { + return dubboShutdownMetadata.shutdown(); + } + +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/condition/CompatibleConditionalOnEnabledEndpoint.java b/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/condition/CompatibleConditionalOnEnabledEndpoint.java index 245498040d..3c1bc1e1cb 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/condition/CompatibleConditionalOnEnabledEndpoint.java +++ b/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/condition/CompatibleConditionalOnEnabledEndpoint.java @@ -1,51 +1,51 @@ -/* - * 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.spring.boot.actuate.endpoint.condition; - -import org.springframework.boot.actuate.endpoint.annotation.Endpoint; -import org.springframework.boot.actuate.endpoint.annotation.EndpointExtension; -import org.springframework.context.annotation.Conditional; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * {@link Conditional} that checks whether or not an endpoint is enabled, which is compatible with - * org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint ([2.0.x, 2.2.x]) - * org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint - * - * @see CompatibleOnEnabledEndpointCondition - * @since 2.7.7 - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD, ElementType.TYPE}) -@Documented -@Conditional(CompatibleOnEnabledEndpointCondition.class) -public @interface CompatibleConditionalOnEnabledEndpoint { - - /** - * The endpoint type that should be checked. Inferred when the return type of the - * {@code @Bean} method is either an {@link Endpoint @Endpoint} or an - * {@link EndpointExtension @EndpointExtension}. - * - * @return the endpoint type to check - */ - Class endpoint() default Void.class; -} +/* + * 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.spring.boot.actuate.endpoint.condition; + +import org.springframework.boot.actuate.endpoint.annotation.Endpoint; +import org.springframework.boot.actuate.endpoint.annotation.EndpointExtension; +import org.springframework.context.annotation.Conditional; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * {@link Conditional} that checks whether or not an endpoint is enabled, which is compatible with + * org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint ([2.0.x, 2.2.x]) + * org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint + * + * @see CompatibleOnEnabledEndpointCondition + * @since 2.7.7 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD, ElementType.TYPE}) +@Documented +@Conditional(CompatibleOnEnabledEndpointCondition.class) +public @interface CompatibleConditionalOnEnabledEndpoint { + + /** + * The endpoint type that should be checked. Inferred when the return type of the + * {@code @Bean} method is either an {@link Endpoint @Endpoint} or an + * {@link EndpointExtension @EndpointExtension}. + * + * @return the endpoint type to check + */ + Class endpoint() default Void.class; +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/condition/CompatibleOnEnabledEndpointCondition.java b/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/condition/CompatibleOnEnabledEndpointCondition.java index 8de2a5682d..ebac25e300 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/condition/CompatibleOnEnabledEndpointCondition.java +++ b/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/condition/CompatibleOnEnabledEndpointCondition.java @@ -1,69 +1,69 @@ -/* - * 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.spring.boot.actuate.endpoint.condition; - -import org.springframework.beans.BeanUtils; -import org.springframework.context.annotation.Condition; -import org.springframework.context.annotation.ConditionContext; -import org.springframework.context.annotation.Conditional; -import org.springframework.core.type.AnnotatedTypeMetadata; -import org.springframework.util.ClassUtils; - -import java.util.stream.Stream; - -/** - * {@link Conditional} that checks whether or not an endpoint is enabled, which is compatible with - * org.springframework.boot.actuate.autoconfigure.endpoint.condition.OnEnabledEndpointCondition - * and org.springframework.boot.actuate.autoconfigure.endpoint.condition.OnAvailableEndpointCondition - * - * @see CompatibleConditionalOnEnabledEndpoint - * @since 2.7.7 - */ -class CompatibleOnEnabledEndpointCondition implements Condition { - - static String[] CONDITION_CLASS_NAMES = { - "org.springframework.boot.actuate.autoconfigure.endpoint.condition.OnAvailableEndpointCondition", // 2.2.0+ - "org.springframework.boot.actuate.autoconfigure.endpoint.condition.OnEnabledEndpointCondition" // [2.0.0 , 2.2.x] - }; - - - @Override - public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { - ClassLoader classLoader = context.getClassLoader(); - - Condition condition = Stream.of(CONDITION_CLASS_NAMES) // Iterate class names - .filter(className -> ClassUtils.isPresent(className, classLoader)) // Search class existing or not by name - .findFirst() // Find the first candidate - .map(className -> ClassUtils.resolveClassName(className, classLoader)) // Resolve class name to Class - .filter(Condition.class::isAssignableFrom) // Accept the Condition implementation - .map(BeanUtils::instantiateClass) // Instantiate Class to be instance - .map(Condition.class::cast) // Cast the instance to be Condition one - .orElse(NegativeCondition.INSTANCE); // Or else get a negative condition - - return condition.matches(context, metadata); - } - - private static class NegativeCondition implements Condition { - - static final NegativeCondition INSTANCE = new NegativeCondition(); - - @Override - public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { - return false; - } - } -} +/* + * 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.spring.boot.actuate.endpoint.condition; + +import org.springframework.beans.BeanUtils; +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.context.annotation.Conditional; +import org.springframework.core.type.AnnotatedTypeMetadata; +import org.springframework.util.ClassUtils; + +import java.util.stream.Stream; + +/** + * {@link Conditional} that checks whether or not an endpoint is enabled, which is compatible with + * org.springframework.boot.actuate.autoconfigure.endpoint.condition.OnEnabledEndpointCondition + * and org.springframework.boot.actuate.autoconfigure.endpoint.condition.OnAvailableEndpointCondition + * + * @see CompatibleConditionalOnEnabledEndpoint + * @since 2.7.7 + */ +class CompatibleOnEnabledEndpointCondition implements Condition { + + static String[] CONDITION_CLASS_NAMES = { + "org.springframework.boot.actuate.autoconfigure.endpoint.condition.OnAvailableEndpointCondition", // 2.2.0+ + "org.springframework.boot.actuate.autoconfigure.endpoint.condition.OnEnabledEndpointCondition" // [2.0.0 , 2.2.x] + }; + + + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + ClassLoader classLoader = context.getClassLoader(); + + Condition condition = Stream.of(CONDITION_CLASS_NAMES) // Iterate class names + .filter(className -> ClassUtils.isPresent(className, classLoader)) // Search class existing or not by name + .findFirst() // Find the first candidate + .map(className -> ClassUtils.resolveClassName(className, classLoader)) // Resolve class name to Class + .filter(Condition.class::isAssignableFrom) // Accept the Condition implementation + .map(BeanUtils::instantiateClass) // Instantiate Class to be instance + .map(Condition.class::cast) // Cast the instance to be Condition one + .orElse(NegativeCondition.INSTANCE); // Or else get a negative condition + + return condition.matches(context, metadata); + } + + private static class NegativeCondition implements Condition { + + static final NegativeCondition INSTANCE = new NegativeCondition(); + + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + return false; + } + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/resources/META-INF/dubbo-endpoints-default.properties b/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/resources/META-INF/dubbo-endpoints-default.properties index 4df591ed79..2eef0739c0 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/resources/META-INF/dubbo-endpoints-default.properties +++ b/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/resources/META-INF/dubbo-endpoints-default.properties @@ -1,21 +1,21 @@ -# Dubbo Endpoints Default Properties is loaded by @PropertySource with low order, -# those values of properties can be override by higher PropertySource -# @see DubboEndpointsAutoConfiguration - -# Set enabled for Dubbo Endpoints -management.endpoint.dubbo.enabled = true -management.endpoint.dubboshutdown.enabled = false -management.endpoint.dubboconfigs.enabled = true -management.endpoint.dubboservices.enabled = false -management.endpoint.dubboreferences.enabled = false -management.endpoint.dubboproperties.enabled = true - -# "management.endpoints.web.base-path" should not be configured in this file - -# Re-defines path-mapping of Dubbo Web Endpoints - -management.endpoints.web.path-mapping.dubboshutdown = dubbo/shutdown -management.endpoints.web.path-mapping.dubboconfigs = dubbo/configs -management.endpoints.web.path-mapping.dubboservices = dubbo/services -management.endpoints.web.path-mapping.dubboreferences = dubbo/references -management.endpoints.web.path-mapping.dubboproperties = dubbo/properties \ No newline at end of file +# Dubbo Endpoints Default Properties is loaded by @PropertySource with low order, +# those values of properties can be override by higher PropertySource +# @see DubboEndpointsAutoConfiguration + +# Set enabled for Dubbo Endpoints +management.endpoint.dubbo.enabled = true +management.endpoint.dubboshutdown.enabled = false +management.endpoint.dubboconfigs.enabled = true +management.endpoint.dubboservices.enabled = false +management.endpoint.dubboreferences.enabled = false +management.endpoint.dubboproperties.enabled = true + +# "management.endpoints.web.base-path" should not be configured in this file + +# Re-defines path-mapping of Dubbo Web Endpoints + +management.endpoints.web.path-mapping.dubboshutdown = dubbo/shutdown +management.endpoints.web.path-mapping.dubboconfigs = dubbo/configs +management.endpoints.web.path-mapping.dubboservices = dubbo/services +management.endpoints.web.path-mapping.dubboreferences = dubbo/references +management.endpoints.web.path-mapping.dubboproperties = dubbo/properties diff --git a/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/resources/META-INF/spring.factories b/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/resources/META-INF/spring.factories index 5dc6c60c18..53a1bb0d0d 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/resources/META-INF/spring.factories +++ b/dubbo-spring-boot/dubbo-spring-boot-actuator/src/main/resources/META-INF/spring.factories @@ -1,2 +1,2 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.apache.dubbo.spring.boot.actuate.autoconfigure.DubboEndpointAnnotationAutoConfiguration \ No newline at end of file diff --git a/dubbo-spring-boot/dubbo-spring-boot-actuator/src/test/java/org/apache/dubbo/spring/boot/actuate/autoconfigure/DubboEndpointAnnotationAutoConfigurationTest.java b/dubbo-spring-boot/dubbo-spring-boot-actuator/src/test/java/org/apache/dubbo/spring/boot/actuate/autoconfigure/DubboEndpointAnnotationAutoConfigurationTest.java index ac7bc6992c..b72d2cfef3 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-actuator/src/test/java/org/apache/dubbo/spring/boot/actuate/autoconfigure/DubboEndpointAnnotationAutoConfigurationTest.java +++ b/dubbo-spring-boot/dubbo-spring-boot-actuator/src/test/java/org/apache/dubbo/spring/boot/actuate/autoconfigure/DubboEndpointAnnotationAutoConfigurationTest.java @@ -1,264 +1,264 @@ -/* - * 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.spring.boot.actuate.autoconfigure; - -import org.apache.dubbo.common.BaseServiceMetadata; -import org.apache.dubbo.config.annotation.DubboReference; -import org.apache.dubbo.config.annotation.DubboService; -import org.apache.dubbo.config.bootstrap.DubboBootstrap; -import org.apache.dubbo.spring.boot.actuate.endpoint.DubboConfigsMetadataEndpoint; -import org.apache.dubbo.spring.boot.actuate.endpoint.DubboMetadataEndpoint; -import org.apache.dubbo.spring.boot.actuate.endpoint.DubboPropertiesMetadataEndpoint; -import org.apache.dubbo.spring.boot.actuate.endpoint.DubboReferencesMetadataEndpoint; -import org.apache.dubbo.spring.boot.actuate.endpoint.DubboServicesMetadataEndpoint; -import org.apache.dubbo.spring.boot.actuate.endpoint.DubboShutdownEndpoint; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Assert; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.annotation.Configuration; -import org.springframework.test.context.junit.jupiter.SpringExtension; -import org.springframework.web.client.RestTemplate; - -import java.util.Map; -import java.util.SortedMap; -import java.util.function.Supplier; - -/** - * {@link DubboEndpointAnnotationAutoConfiguration} Test - * - * @since 2.7.0 - */ -@ExtendWith(SpringExtension.class) -@SpringBootTest( - classes = { - DubboEndpointAnnotationAutoConfigurationTest.class, - DubboEndpointAnnotationAutoConfigurationTest.ConsumerConfiguration.class - }, - webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - properties = { - "dubbo.service.version = 1.0.0", - "dubbo.application.id = my-application", - "dubbo.application.name = dubbo-demo-application", - "dubbo.module.id = my-module", - "dubbo.module.name = dubbo-demo-module", - "dubbo.registry.id = my-registry", - "dubbo.registry.address = N/A", - "dubbo.protocol.id=my-protocol", - "dubbo.protocol.name=dubbo", - "dubbo.protocol.port=20880", - "dubbo.provider.id=my-provider", - "dubbo.provider.host=127.0.0.1", - "dubbo.scan.basePackages = org.apache.dubbo.spring.boot.actuate.autoconfigure", - "management.endpoint.dubbo.enabled = true", - "management.endpoint.dubboshutdown.enabled = true", - "management.endpoint.dubboconfigs.enabled = true", - "management.endpoint.dubboservices.enabled = true", - "management.endpoint.dubboreferences.enabled = true", - "management.endpoint.dubboproperties.enabled = true", - "management.endpoints.web.exposure.include = *", - }) -@EnableAutoConfiguration -@Disabled -public class DubboEndpointAnnotationAutoConfigurationTest { - - @Autowired - private DubboMetadataEndpoint dubboEndpoint; - - @Autowired - private DubboConfigsMetadataEndpoint dubboConfigsMetadataEndpoint; - - @Autowired - private DubboPropertiesMetadataEndpoint dubboPropertiesEndpoint; - - @Autowired - private DubboReferencesMetadataEndpoint dubboReferencesMetadataEndpoint; - - @Autowired - private DubboServicesMetadataEndpoint dubboServicesMetadataEndpoint; - - @Autowired - private DubboShutdownEndpoint dubboShutdownEndpoint; - - private RestTemplate restTemplate = new RestTemplate(); - - @Autowired - private ObjectMapper objectMapper; - - @Value("http://127.0.0.1:${local.management.port}${management.endpoints.web.base-path:/actuator}") - private String actuatorBaseURL; - - @BeforeEach - public void init() { - DubboBootstrap.reset(); - } - - @AfterEach - public void destroy() { - DubboBootstrap.reset(); - } - - @Test - public void testShutdown() throws Exception { - - Map value = dubboShutdownEndpoint.shutdown(); - - Map shutdownCounts = (Map) value.get("shutdown.count"); - - Assert.assertEquals(0, shutdownCounts.get("registries")); - Assert.assertEquals(1, shutdownCounts.get("protocols")); - Assert.assertEquals(1, shutdownCounts.get("services")); - Assert.assertEquals(0, shutdownCounts.get("references")); - - } - - @Test - public void testConfigs() { - - Map>> configsMap = dubboConfigsMetadataEndpoint.configs(); - - Map> beansMetadata = configsMap.get("ApplicationConfig"); - Assert.assertEquals("dubbo-demo-application", beansMetadata.get("my-application").get("name")); - - beansMetadata = configsMap.get("ConsumerConfig"); - Assert.assertTrue(beansMetadata.isEmpty()); - - beansMetadata = configsMap.get("MethodConfig"); - Assert.assertTrue(beansMetadata.isEmpty()); - - beansMetadata = configsMap.get("ModuleConfig"); - Assert.assertEquals("dubbo-demo-module", beansMetadata.get("my-module").get("name")); - - beansMetadata = configsMap.get("MonitorConfig"); - Assert.assertTrue(beansMetadata.isEmpty()); - - beansMetadata = configsMap.get("ProtocolConfig"); - Assert.assertEquals("dubbo", beansMetadata.get("my-protocol").get("name")); - - beansMetadata = configsMap.get("ProviderConfig"); - Assert.assertEquals("127.0.0.1", beansMetadata.get("my-provider").get("host")); - - beansMetadata = configsMap.get("ReferenceConfig"); - Assert.assertTrue(beansMetadata.isEmpty()); - - beansMetadata = configsMap.get("RegistryConfig"); - Assert.assertEquals("N/A", beansMetadata.get("my-registry").get("address")); - - beansMetadata = configsMap.get("ServiceConfig"); - Assert.assertFalse(beansMetadata.isEmpty()); - - } - - @Test - public void testServices() { - - Map> services = dubboServicesMetadataEndpoint.services(); - - Assert.assertEquals(1, services.size()); - - Map demoServiceMeta = services.get("ServiceBean:org.apache.dubbo.spring.boot.actuate.autoconfigure.DubboEndpointAnnotationAutoConfigurationTest$DemoService:1.0.0"); - - Assert.assertEquals("1.0.0", demoServiceMeta.get("version")); - - } - - @Test - public void testReferences() { - - Map> references = dubboReferencesMetadataEndpoint.references(); - - Assert.assertTrue(!references.isEmpty()); - String injectedField = "private " + DemoService.class.getName() + " " + ConsumerConfiguration.class.getName() + ".demoService"; - Map referenceMap = references.get(injectedField); - Assert.assertNotNull(referenceMap); - Assert.assertEquals(DemoService.class, referenceMap.get("interfaceClass")); - Assert.assertEquals(BaseServiceMetadata.buildServiceKey(DemoService.class.getName(),ConsumerConfiguration.DEMO_GROUP,ConsumerConfiguration.DEMO_VERSION), - referenceMap.get("uniqueServiceName")); - } - - @Test - public void testProperties() { - - SortedMap properties = dubboPropertiesEndpoint.properties(); - - Assert.assertEquals("my-application", properties.get("dubbo.application.id")); - Assert.assertEquals("dubbo-demo-application", properties.get("dubbo.application.name")); - Assert.assertEquals("my-module", properties.get("dubbo.module.id")); - Assert.assertEquals("dubbo-demo-module", properties.get("dubbo.module.name")); - Assert.assertEquals("my-registry", properties.get("dubbo.registry.id")); - Assert.assertEquals("N/A", properties.get("dubbo.registry.address")); - Assert.assertEquals("my-protocol", properties.get("dubbo.protocol.id")); - Assert.assertEquals("dubbo", properties.get("dubbo.protocol.name")); - Assert.assertEquals("20880", properties.get("dubbo.protocol.port")); - Assert.assertEquals("my-provider", properties.get("dubbo.provider.id")); - Assert.assertEquals("127.0.0.1", properties.get("dubbo.provider.host")); - Assert.assertEquals("org.apache.dubbo.spring.boot.actuate.autoconfigure", properties.get("dubbo.scan.basePackages")); - } - - @Test - public void testHttpEndpoints() throws JsonProcessingException { -// testHttpEndpoint("/dubbo", dubboEndpoint::invoke); - testHttpEndpoint("/dubbo/configs", dubboConfigsMetadataEndpoint::configs); - testHttpEndpoint("/dubbo/services", dubboServicesMetadataEndpoint::services); - testHttpEndpoint("/dubbo/references", dubboReferencesMetadataEndpoint::references); - testHttpEndpoint("/dubbo/properties", dubboPropertiesEndpoint::properties); - } - - private void testHttpEndpoint(String actuatorURI, Supplier resultsSupplier) throws JsonProcessingException { - String actuatorURL = actuatorBaseURL + actuatorURI; - String response = restTemplate.getForObject(actuatorURL, String.class); - Assert.assertEquals(objectMapper.writeValueAsString(resultsSupplier.get()), response); - } - - - interface DemoService { - String sayHello(String name); - } - - @DubboService( - version = "${dubbo.service.version}", - application = "${dubbo.application.id}", - protocol = "${dubbo.protocol.id}", - registry = "${dubbo.registry.id}" - ) - static class DefaultDemoService implements DemoService { - - public String sayHello(String name) { - return "Hello, " + name + " (from Spring Boot)"; - } - - } - - @Configuration - static class ConsumerConfiguration { - public static final String DEMO_GROUP = "demo"; - public static final String DEMO_VERSION = "1.0.0"; - - @DubboReference(group = DEMO_GROUP, version = DEMO_VERSION) - private DemoService demoService; - - } -} +/* + * 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.spring.boot.actuate.autoconfigure; + +import org.apache.dubbo.common.BaseServiceMetadata; +import org.apache.dubbo.config.annotation.DubboReference; +import org.apache.dubbo.config.annotation.DubboService; +import org.apache.dubbo.config.bootstrap.DubboBootstrap; +import org.apache.dubbo.spring.boot.actuate.endpoint.DubboConfigsMetadataEndpoint; +import org.apache.dubbo.spring.boot.actuate.endpoint.DubboMetadataEndpoint; +import org.apache.dubbo.spring.boot.actuate.endpoint.DubboPropertiesMetadataEndpoint; +import org.apache.dubbo.spring.boot.actuate.endpoint.DubboReferencesMetadataEndpoint; +import org.apache.dubbo.spring.boot.actuate.endpoint.DubboServicesMetadataEndpoint; +import org.apache.dubbo.spring.boot.actuate.endpoint.DubboShutdownEndpoint; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Assert; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.web.client.RestTemplate; + +import java.util.Map; +import java.util.SortedMap; +import java.util.function.Supplier; + +/** + * {@link DubboEndpointAnnotationAutoConfiguration} Test + * + * @since 2.7.0 + */ +@ExtendWith(SpringExtension.class) +@SpringBootTest( + classes = { + DubboEndpointAnnotationAutoConfigurationTest.class, + DubboEndpointAnnotationAutoConfigurationTest.ConsumerConfiguration.class + }, + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + properties = { + "dubbo.service.version = 1.0.0", + "dubbo.application.id = my-application", + "dubbo.application.name = dubbo-demo-application", + "dubbo.module.id = my-module", + "dubbo.module.name = dubbo-demo-module", + "dubbo.registry.id = my-registry", + "dubbo.registry.address = N/A", + "dubbo.protocol.id=my-protocol", + "dubbo.protocol.name=dubbo", + "dubbo.protocol.port=20880", + "dubbo.provider.id=my-provider", + "dubbo.provider.host=127.0.0.1", + "dubbo.scan.basePackages = org.apache.dubbo.spring.boot.actuate.autoconfigure", + "management.endpoint.dubbo.enabled = true", + "management.endpoint.dubboshutdown.enabled = true", + "management.endpoint.dubboconfigs.enabled = true", + "management.endpoint.dubboservices.enabled = true", + "management.endpoint.dubboreferences.enabled = true", + "management.endpoint.dubboproperties.enabled = true", + "management.endpoints.web.exposure.include = *", + }) +@EnableAutoConfiguration +@Disabled +public class DubboEndpointAnnotationAutoConfigurationTest { + + @Autowired + private DubboMetadataEndpoint dubboEndpoint; + + @Autowired + private DubboConfigsMetadataEndpoint dubboConfigsMetadataEndpoint; + + @Autowired + private DubboPropertiesMetadataEndpoint dubboPropertiesEndpoint; + + @Autowired + private DubboReferencesMetadataEndpoint dubboReferencesMetadataEndpoint; + + @Autowired + private DubboServicesMetadataEndpoint dubboServicesMetadataEndpoint; + + @Autowired + private DubboShutdownEndpoint dubboShutdownEndpoint; + + private RestTemplate restTemplate = new RestTemplate(); + + @Autowired + private ObjectMapper objectMapper; + + @Value("http://127.0.0.1:${local.management.port}${management.endpoints.web.base-path:/actuator}") + private String actuatorBaseURL; + + @BeforeEach + public void init() { + DubboBootstrap.reset(); + } + + @AfterEach + public void destroy() { + DubboBootstrap.reset(); + } + + @Test + public void testShutdown() throws Exception { + + Map value = dubboShutdownEndpoint.shutdown(); + + Map shutdownCounts = (Map) value.get("shutdown.count"); + + Assert.assertEquals(0, shutdownCounts.get("registries")); + Assert.assertEquals(1, shutdownCounts.get("protocols")); + Assert.assertEquals(1, shutdownCounts.get("services")); + Assert.assertEquals(0, shutdownCounts.get("references")); + + } + + @Test + public void testConfigs() { + + Map>> configsMap = dubboConfigsMetadataEndpoint.configs(); + + Map> beansMetadata = configsMap.get("ApplicationConfig"); + Assert.assertEquals("dubbo-demo-application", beansMetadata.get("my-application").get("name")); + + beansMetadata = configsMap.get("ConsumerConfig"); + Assert.assertTrue(beansMetadata.isEmpty()); + + beansMetadata = configsMap.get("MethodConfig"); + Assert.assertTrue(beansMetadata.isEmpty()); + + beansMetadata = configsMap.get("ModuleConfig"); + Assert.assertEquals("dubbo-demo-module", beansMetadata.get("my-module").get("name")); + + beansMetadata = configsMap.get("MonitorConfig"); + Assert.assertTrue(beansMetadata.isEmpty()); + + beansMetadata = configsMap.get("ProtocolConfig"); + Assert.assertEquals("dubbo", beansMetadata.get("my-protocol").get("name")); + + beansMetadata = configsMap.get("ProviderConfig"); + Assert.assertEquals("127.0.0.1", beansMetadata.get("my-provider").get("host")); + + beansMetadata = configsMap.get("ReferenceConfig"); + Assert.assertTrue(beansMetadata.isEmpty()); + + beansMetadata = configsMap.get("RegistryConfig"); + Assert.assertEquals("N/A", beansMetadata.get("my-registry").get("address")); + + beansMetadata = configsMap.get("ServiceConfig"); + Assert.assertFalse(beansMetadata.isEmpty()); + + } + + @Test + public void testServices() { + + Map> services = dubboServicesMetadataEndpoint.services(); + + Assert.assertEquals(1, services.size()); + + Map demoServiceMeta = services.get("ServiceBean:org.apache.dubbo.spring.boot.actuate.autoconfigure.DubboEndpointAnnotationAutoConfigurationTest$DemoService:1.0.0"); + + Assert.assertEquals("1.0.0", demoServiceMeta.get("version")); + + } + + @Test + public void testReferences() { + + Map> references = dubboReferencesMetadataEndpoint.references(); + + Assert.assertTrue(!references.isEmpty()); + String injectedField = "private " + DemoService.class.getName() + " " + ConsumerConfiguration.class.getName() + ".demoService"; + Map referenceMap = references.get(injectedField); + Assert.assertNotNull(referenceMap); + Assert.assertEquals(DemoService.class, referenceMap.get("interfaceClass")); + Assert.assertEquals(BaseServiceMetadata.buildServiceKey(DemoService.class.getName(),ConsumerConfiguration.DEMO_GROUP,ConsumerConfiguration.DEMO_VERSION), + referenceMap.get("uniqueServiceName")); + } + + @Test + public void testProperties() { + + SortedMap properties = dubboPropertiesEndpoint.properties(); + + Assert.assertEquals("my-application", properties.get("dubbo.application.id")); + Assert.assertEquals("dubbo-demo-application", properties.get("dubbo.application.name")); + Assert.assertEquals("my-module", properties.get("dubbo.module.id")); + Assert.assertEquals("dubbo-demo-module", properties.get("dubbo.module.name")); + Assert.assertEquals("my-registry", properties.get("dubbo.registry.id")); + Assert.assertEquals("N/A", properties.get("dubbo.registry.address")); + Assert.assertEquals("my-protocol", properties.get("dubbo.protocol.id")); + Assert.assertEquals("dubbo", properties.get("dubbo.protocol.name")); + Assert.assertEquals("20880", properties.get("dubbo.protocol.port")); + Assert.assertEquals("my-provider", properties.get("dubbo.provider.id")); + Assert.assertEquals("127.0.0.1", properties.get("dubbo.provider.host")); + Assert.assertEquals("org.apache.dubbo.spring.boot.actuate.autoconfigure", properties.get("dubbo.scan.basePackages")); + } + + @Test + public void testHttpEndpoints() throws JsonProcessingException { +// testHttpEndpoint("/dubbo", dubboEndpoint::invoke); + testHttpEndpoint("/dubbo/configs", dubboConfigsMetadataEndpoint::configs); + testHttpEndpoint("/dubbo/services", dubboServicesMetadataEndpoint::services); + testHttpEndpoint("/dubbo/references", dubboReferencesMetadataEndpoint::references); + testHttpEndpoint("/dubbo/properties", dubboPropertiesEndpoint::properties); + } + + private void testHttpEndpoint(String actuatorURI, Supplier resultsSupplier) throws JsonProcessingException { + String actuatorURL = actuatorBaseURL + actuatorURI; + String response = restTemplate.getForObject(actuatorURL, String.class); + Assert.assertEquals(objectMapper.writeValueAsString(resultsSupplier.get()), response); + } + + + interface DemoService { + String sayHello(String name); + } + + @DubboService( + version = "${dubbo.service.version}", + application = "${dubbo.application.id}", + protocol = "${dubbo.protocol.id}", + registry = "${dubbo.registry.id}" + ) + static class DefaultDemoService implements DemoService { + + public String sayHello(String name) { + return "Hello, " + name + " (from Spring Boot)"; + } + + } + + @Configuration + static class ConsumerConfiguration { + public static final String DEMO_GROUP = "demo"; + public static final String DEMO_VERSION = "1.0.0"; + + @DubboReference(group = DEMO_GROUP, version = DEMO_VERSION) + private DemoService demoService; + + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-actuator/src/test/java/org/apache/dubbo/spring/boot/actuate/endpoint/DubboEndpointTest.java b/dubbo-spring-boot/dubbo-spring-boot-actuator/src/test/java/org/apache/dubbo/spring/boot/actuate/endpoint/DubboEndpointTest.java index 738d21dba6..6fd8e3681f 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-actuator/src/test/java/org/apache/dubbo/spring/boot/actuate/endpoint/DubboEndpointTest.java +++ b/dubbo-spring-boot/dubbo-spring-boot-actuator/src/test/java/org/apache/dubbo/spring/boot/actuate/endpoint/DubboEndpointTest.java @@ -1,93 +1,93 @@ -/* - * 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.spring.boot.actuate.endpoint; - -import org.apache.dubbo.config.bootstrap.DubboBootstrap; -import org.apache.dubbo.spring.boot.util.DubboUtils; - -import org.junit.Assert; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit.jupiter.SpringExtension; - -import java.util.Map; - -import static org.apache.dubbo.common.Version.getVersion; - -/** - * {@link DubboMetadataEndpoint} Test - * - * @see DubboMetadataEndpoint - * @since 2.7.0 - */ -@ExtendWith(SpringExtension.class) -@SpringBootTest( - classes = { - DubboMetadataEndpoint.class - }, - properties = { - "dubbo.application.name = dubbo-demo-application" - } -) -@EnableAutoConfiguration -public class DubboEndpointTest { - - - @Autowired - private DubboMetadataEndpoint dubboEndpoint; - - @BeforeEach - public void init() { - DubboBootstrap.reset(); - } - - @AfterEach - public void destroy() { - DubboBootstrap.reset(); - } - - @Test - public void testInvoke() { - - Map metadata = dubboEndpoint.invoke(); - - Assert.assertNotNull(metadata.get("timestamp")); - - Map versions = (Map) metadata.get("versions"); - Map urls = (Map) metadata.get("urls"); - - Assert.assertFalse(versions.isEmpty()); - Assert.assertFalse(urls.isEmpty()); - - Assert.assertEquals(getVersion(DubboUtils.class, "1.0.0"), versions.get("dubbo-spring-boot")); - Assert.assertEquals(getVersion(), versions.get("dubbo")); - - Assert.assertEquals("https://github.com/apache/dubbo", urls.get("dubbo")); - Assert.assertEquals("dev@dubbo.apache.org", urls.get("mailing-list")); - Assert.assertEquals("https://github.com/apache/dubbo-spring-boot-project", urls.get("github")); - Assert.assertEquals("https://github.com/apache/dubbo-spring-boot-project/issues", urls.get("issues")); - Assert.assertEquals("https://github.com/apache/dubbo-spring-boot-project.git", urls.get("git")); - - } - - -} +/* + * 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.spring.boot.actuate.endpoint; + +import org.apache.dubbo.config.bootstrap.DubboBootstrap; +import org.apache.dubbo.spring.boot.util.DubboUtils; + +import org.junit.Assert; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.util.Map; + +import static org.apache.dubbo.common.Version.getVersion; + +/** + * {@link DubboMetadataEndpoint} Test + * + * @see DubboMetadataEndpoint + * @since 2.7.0 + */ +@ExtendWith(SpringExtension.class) +@SpringBootTest( + classes = { + DubboMetadataEndpoint.class + }, + properties = { + "dubbo.application.name = dubbo-demo-application" + } +) +@EnableAutoConfiguration +public class DubboEndpointTest { + + + @Autowired + private DubboMetadataEndpoint dubboEndpoint; + + @BeforeEach + public void init() { + DubboBootstrap.reset(); + } + + @AfterEach + public void destroy() { + DubboBootstrap.reset(); + } + + @Test + public void testInvoke() { + + Map metadata = dubboEndpoint.invoke(); + + Assert.assertNotNull(metadata.get("timestamp")); + + Map versions = (Map) metadata.get("versions"); + Map urls = (Map) metadata.get("urls"); + + Assert.assertFalse(versions.isEmpty()); + Assert.assertFalse(urls.isEmpty()); + + Assert.assertEquals(getVersion(DubboUtils.class, "1.0.0"), versions.get("dubbo-spring-boot")); + Assert.assertEquals(getVersion(), versions.get("dubbo")); + + Assert.assertEquals("https://github.com/apache/dubbo", urls.get("dubbo")); + Assert.assertEquals("dev@dubbo.apache.org", urls.get("mailing-list")); + Assert.assertEquals("https://github.com/apache/dubbo-spring-boot-project", urls.get("github")); + Assert.assertEquals("https://github.com/apache/dubbo-spring-boot-project/issues", urls.get("issues")); + Assert.assertEquals("https://github.com/apache/dubbo-spring-boot-project.git", urls.get("git")); + + } + + +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/README.md b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/README.md index b99cc47370..0e0dd0f0f0 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/README.md +++ b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/README.md @@ -1,225 +1,225 @@ -# Dubbo Spring Boot Auto-Configure - -`dubbo-spring-boot-autoconfigure` uses Spring Boot's `@EnableAutoConfiguration` which helps core Dubbo's components to be auto-configured by `DubboAutoConfiguration`. It reduces code, eliminates XML configuration. - - - -## Content - -1. [Main Content](https://github.com/apache/dubbo-spring-boot-project) -2. [Integrate with Maven](#integrate-with-maven) -3. [Auto Configuration](#auto-configuration) -4. [Externalized Configuration](#externalized-configuration) -5. [Dubbo Annotation-Driven (Chinese)](http://dubbo.apache.org/zh-cn/blog/dubbo-annotation-driven.html) -6. [Dubbo Externalized Configuration (Chinese)](http://dubbo.apache.org/zh-cn/blog/dubbo-externalized-configuration.html) - - - -## Integrate with Maven - -You can introduce the latest `dubbo-spring-boot-autoconfigure` to your project by adding the following dependency to your pom.xml - -```xml - - org.apache.dubbo - dubbo-spring-boot-autoconfigure - 2.7.4.1 - -``` - -If your project failed to resolve the dependency, try to add the following repository: -```xml - - - apache.snapshots.https - Apache Development Snapshot Repository - https://repository.apache.org/content/repositories/snapshots - - false - - - true - - - -``` - - - -## Auto Configuration - -Since `2.5.7` , Dubbo totally supports Annotation-Driven , core Dubbo's components that are registered and initialized in Spring application context , including exterialized configuration features. However , those features need to trigger in manual configuration , e.g `@DubboComponentScan` , `@EnableDubboConfig` or `@EnableDubbo`. - -> If you'd like to learn more , please read [Dubbo Annotation-Driven (Chinese)](http://dubbo.apache.org/zh-cn/blog/dubbo-annotation-driven.html) - - - -`dubbo-spring-boot-autoconfigure` uses Spring Boot's `@EnableAutoConfiguration` which helps core Dubbo's components to be auto-configured by `DubboAutoConfiguration`. It reduces code, eliminates XML configuration. - - - -## Externalized Configuration - -Externalized Configuration is a core feature of Spring Boot , Dubbo Spring Boot not only supports it definitely , but also inherits Dubbo's Externalized Configuration, thus it provides single and multiple Dubbo's `*Config` Bindings from `PropertySources` , and `"dubbo."` is a common prefix of property name. - -> If you'd like to learn more , please read [Dubbo Externalized Configuration](http://dubbo.apache.org/zh-cn/blog/dubbo-externalized-configuration.html)(Chinese). - - - -### Single Dubbo Config Bean Bindings - -In most use scenarios , "Single Dubbo Config Bean Bindings" is enough , because a Dubbo application only requires single Bean of `*Config` (e.g `ApplicationConfig`). You add properties in `application.properties` to configure Dubbo's `*Config` Beans that you want , be like this : - -```properties -dubbo.application.name = foo -dubbo.application.owner = bar -dubbo.registry.address = 10.20.153.10:9090 -``` - -There are two Spring Beans will be initialized when Spring `ApplicatonContext` is ready, their Bean types are `ApplicationConfig` and `RegistryConfig`. - - - -#### Getting Single Dubbo Config Bean - - If application requires current `ApplicationConfig` Bean in somewhere , you can get it from Spring `BeanFactory` as those code : - -```java -BeanFactory beanFactory = .... -ApplicationConfig applicationConfig = beanFactory.getBean(ApplicationConfig.class) -``` - -or inject it : - -```java -@Autowired -private ApplicationConfig application; -``` - - - -#### Identifying Single Dubbo Config Bean - -If you'd like to identify this `ApplicationConfig` Bean , you could add **"id"** property: - -```properties -dubbo.application.id = application-bean-id -``` - - - -#### Mapping Single Dubbo Config Bean - -The whole Properties Mapping of "Single Dubbo Config Bean Bindings" lists below : - -| Dubbo `*Config` Type | The prefix of property name for Single Bindings | -| -------------------- | ---------------------------------------- | -| `ProtocolConfig` | `dubbo.protocol` | -| `ApplicationConfig` | `dubbo.application` | -| `ModuleConfig` | `dubbo.module` | -| `RegistryConfig` | `dubbo.registry` | -| `MonitorConfig` | `dubbo.monitor` | -| `ProviderConfig` | `dubbo.provider` | -| `ConsumerConfig` | `dubbo.consumer` | - - - -An example properties : - -```properties -# Single Dubbo Config Bindings -## ApplicationConfig -dubbo.application.id = applicationBean -dubbo.application.name = dubbo-demo-application - -## ModuleConfig -dubbo.module.id = moduleBean -dubbo.module.name = dubbo-demo-module - -## RegistryConfig -dubbo.registry.address = zookeeper://192.168.99.100:32770 - -## ProtocolConfig -dubbo.protocol.name = dubbo -dubbo.protocol.port = 20880 - -## MonitorConfig -dubbo.monitor.address = zookeeper://127.0.0.1:32770 - -## ProviderConfig -dubbo.provider.host = 127.0.0.1 - -## ConsumerConfig -dubbo.consumer.client = netty -``` - - - -### Multiple Dubbo Config Bean Bindings - -In contrast , "Multiple Dubbo Config Bean Bindings" means Externalized Configuration will be used to configure multiple Dubbo `*Config` Beans. - - - -#### Getting Multiple Dubbo Config Bean - -The whole Properties Mapping of "Multiple Dubbo Config Bean Bindings" lists below : - -| Dubbo `*Config` Type | The prefix of property name for Multiple Bindings | -| -------------------- | ---------------------------------------- | -| `ProtocolConfig` | `dubbo.protocols` | -| `ApplicationConfig` | `dubbo.applications` | -| `ModuleConfig` | `dubbo.modules` | -| `RegistryConfig` | `dubbo.registries` | -| `MonitorConfig` | `dubbo.monitors` | -| `ProviderConfig` | `dubbo.providers` | -| `ConsumerConfig` | `dubbo.consumers` | - - - -#### Identifying Multiple Dubbo Config Bean - -There is a different way to identify Multiple Dubbo Config Bean , the configuration pattern is like this : - -`${config-property-prefix}.${config-bean-id}.${property-name} = some value` , let's explain those placehoders : - -- `${config-property-prefix}` : The The prefix of property name for Multiple Bindings , e.g. `dubbo.protocols`, `dubbo.applications` and so on. -- `${config-bean-id}` : The bean id of Dubbo's `*Config` -- `${property-name}`: The property name of `*Config` - -An example properties : - -```properties -dubbo.applications.application1.name = dubbo-demo-application -dubbo.applications.application2.name = dubbo-demo-application2 -dubbo.modules.module1.name = dubbo-demo-module -dubbo.registries.registry1.address = zookeeper://192.168.99.100:32770 -dubbo.protocols.protocol1.name = dubbo -dubbo.protocols.protocol1.port = 20880 -dubbo.monitors.monitor1.address = zookeeper://127.0.0.1:32770 -dubbo.providers.provider1.host = 127.0.0.1 -dubbo.consumers.consumer1.client = netty -``` - - - -### IDE Support - - - -If you used advanced IDE tools , for instance [Jetbrains IDEA Ultimate](https://www.jetbrains.com/idea/) develops Dubbo Spring Boot application, it will popup the tips of Dubbo Configuration Bindings in `application.properties` : - - - -#### Case 1 - Single Bindings - -![](config-popup-window.png) - - - -#### Case 2 - Mutiple Bindings - -![](mconfig-popup-window.png) - -​ - +# Dubbo Spring Boot Auto-Configure + +`dubbo-spring-boot-autoconfigure` uses Spring Boot's `@EnableAutoConfiguration` which helps core Dubbo's components to be auto-configured by `DubboAutoConfiguration`. It reduces code, eliminates XML configuration. + + + +## Content + +1. [Main Content](https://github.com/apache/dubbo-spring-boot-project) +2. [Integrate with Maven](#integrate-with-maven) +3. [Auto Configuration](#auto-configuration) +4. [Externalized Configuration](#externalized-configuration) +5. [Dubbo Annotation-Driven (Chinese)](http://dubbo.apache.org/zh-cn/blog/dubbo-annotation-driven.html) +6. [Dubbo Externalized Configuration (Chinese)](http://dubbo.apache.org/zh-cn/blog/dubbo-externalized-configuration.html) + + + +## Integrate with Maven + +You can introduce the latest `dubbo-spring-boot-autoconfigure` to your project by adding the following dependency to your pom.xml + +```xml + + org.apache.dubbo + dubbo-spring-boot-autoconfigure + 2.7.4.1 + +``` + +If your project failed to resolve the dependency, try to add the following repository: +```xml + + + apache.snapshots.https + Apache Development Snapshot Repository + https://repository.apache.org/content/repositories/snapshots + + false + + + true + + + +``` + + + +## Auto Configuration + +Since `2.5.7` , Dubbo totally supports Annotation-Driven , core Dubbo's components that are registered and initialized in Spring application context , including exterialized configuration features. However , those features need to trigger in manual configuration , e.g `@DubboComponentScan` , `@EnableDubboConfig` or `@EnableDubbo`. + +> If you'd like to learn more , please read [Dubbo Annotation-Driven (Chinese)](http://dubbo.apache.org/zh-cn/blog/dubbo-annotation-driven.html) + + + +`dubbo-spring-boot-autoconfigure` uses Spring Boot's `@EnableAutoConfiguration` which helps core Dubbo's components to be auto-configured by `DubboAutoConfiguration`. It reduces code, eliminates XML configuration. + + + +## Externalized Configuration + +Externalized Configuration is a core feature of Spring Boot , Dubbo Spring Boot not only supports it definitely , but also inherits Dubbo's Externalized Configuration, thus it provides single and multiple Dubbo's `*Config` Bindings from `PropertySources` , and `"dubbo."` is a common prefix of property name. + +> If you'd like to learn more , please read [Dubbo Externalized Configuration](http://dubbo.apache.org/zh-cn/blog/dubbo-externalized-configuration.html)(Chinese). + + + +### Single Dubbo Config Bean Bindings + +In most use scenarios , "Single Dubbo Config Bean Bindings" is enough , because a Dubbo application only requires single Bean of `*Config` (e.g `ApplicationConfig`). You add properties in `application.properties` to configure Dubbo's `*Config` Beans that you want , be like this : + +```properties +dubbo.application.name = foo +dubbo.application.owner = bar +dubbo.registry.address = 10.20.153.10:9090 +``` + +There are two Spring Beans will be initialized when Spring `ApplicatonContext` is ready, their Bean types are `ApplicationConfig` and `RegistryConfig`. + + + +#### Getting Single Dubbo Config Bean + + If application requires current `ApplicationConfig` Bean in somewhere , you can get it from Spring `BeanFactory` as those code : + +```java +BeanFactory beanFactory = .... +ApplicationConfig applicationConfig = beanFactory.getBean(ApplicationConfig.class) +``` + +or inject it : + +```java +@Autowired +private ApplicationConfig application; +``` + + + +#### Identifying Single Dubbo Config Bean + +If you'd like to identify this `ApplicationConfig` Bean , you could add **"id"** property: + +```properties +dubbo.application.id = application-bean-id +``` + + + +#### Mapping Single Dubbo Config Bean + +The whole Properties Mapping of "Single Dubbo Config Bean Bindings" lists below : + +| Dubbo `*Config` Type | The prefix of property name for Single Bindings | +| -------------------- | ---------------------------------------- | +| `ProtocolConfig` | `dubbo.protocol` | +| `ApplicationConfig` | `dubbo.application` | +| `ModuleConfig` | `dubbo.module` | +| `RegistryConfig` | `dubbo.registry` | +| `MonitorConfig` | `dubbo.monitor` | +| `ProviderConfig` | `dubbo.provider` | +| `ConsumerConfig` | `dubbo.consumer` | + + + +An example properties : + +```properties +# Single Dubbo Config Bindings +## ApplicationConfig +dubbo.application.id = applicationBean +dubbo.application.name = dubbo-demo-application + +## ModuleConfig +dubbo.module.id = moduleBean +dubbo.module.name = dubbo-demo-module + +## RegistryConfig +dubbo.registry.address = zookeeper://192.168.99.100:32770 + +## ProtocolConfig +dubbo.protocol.name = dubbo +dubbo.protocol.port = 20880 + +## MonitorConfig +dubbo.monitor.address = zookeeper://127.0.0.1:32770 + +## ProviderConfig +dubbo.provider.host = 127.0.0.1 + +## ConsumerConfig +dubbo.consumer.client = netty +``` + + + +### Multiple Dubbo Config Bean Bindings + +In contrast , "Multiple Dubbo Config Bean Bindings" means Externalized Configuration will be used to configure multiple Dubbo `*Config` Beans. + + + +#### Getting Multiple Dubbo Config Bean + +The whole Properties Mapping of "Multiple Dubbo Config Bean Bindings" lists below : + +| Dubbo `*Config` Type | The prefix of property name for Multiple Bindings | +| -------------------- | ---------------------------------------- | +| `ProtocolConfig` | `dubbo.protocols` | +| `ApplicationConfig` | `dubbo.applications` | +| `ModuleConfig` | `dubbo.modules` | +| `RegistryConfig` | `dubbo.registries` | +| `MonitorConfig` | `dubbo.monitors` | +| `ProviderConfig` | `dubbo.providers` | +| `ConsumerConfig` | `dubbo.consumers` | + + + +#### Identifying Multiple Dubbo Config Bean + +There is a different way to identify Multiple Dubbo Config Bean , the configuration pattern is like this : + +`${config-property-prefix}.${config-bean-id}.${property-name} = some value` , let's explain those placehoders : + +- `${config-property-prefix}` : The The prefix of property name for Multiple Bindings , e.g. `dubbo.protocols`, `dubbo.applications` and so on. +- `${config-bean-id}` : The bean id of Dubbo's `*Config` +- `${property-name}`: The property name of `*Config` + +An example properties : + +```properties +dubbo.applications.application1.name = dubbo-demo-application +dubbo.applications.application2.name = dubbo-demo-application2 +dubbo.modules.module1.name = dubbo-demo-module +dubbo.registries.registry1.address = zookeeper://192.168.99.100:32770 +dubbo.protocols.protocol1.name = dubbo +dubbo.protocols.protocol1.port = 20880 +dubbo.monitors.monitor1.address = zookeeper://127.0.0.1:32770 +dubbo.providers.provider1.host = 127.0.0.1 +dubbo.consumers.consumer1.client = netty +``` + + + +### IDE Support + + + +If you used advanced IDE tools , for instance [Jetbrains IDEA Ultimate](https://www.jetbrains.com/idea/) develops Dubbo Spring Boot application, it will popup the tips of Dubbo Configuration Bindings in `application.properties` : + + + +#### Case 1 - Single Bindings + +![](config-popup-window.png) + + + +#### Case 2 - Mutiple Bindings + +![](mconfig-popup-window.png) + +​ + diff --git a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/pom.xml b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/pom.xml index 98e6816624..80a063bfd9 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/pom.xml +++ b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/pom.xml @@ -1,85 +1,85 @@ - - - - - org.apache.dubbo - dubbo-spring-boot - ${revision} - ../pom.xml - - 4.0.0 - - dubbo-spring-boot-autoconfigure - jar - Apache Dubbo Spring Boot Auto-Configure - - - - - - - org.apache.dubbo - dubbo-spring-boot-autoconfigure-compatible - ${revision} - - - - - org.springframework.boot - spring-boot-autoconfigure - true - - - - org.springframework.boot - spring-boot-starter-logging - true - - - - - org.apache.dubbo - dubbo - ${revision} - - - - org.apache.dubbo - dubbo-common - ${revision} - true - - - - org.apache.dubbo - dubbo-config-spring - ${revision} - true - - - - - org.springframework.boot - spring-boot-starter-test - test - - - + + + + + org.apache.dubbo + dubbo-spring-boot + ${revision} + ../pom.xml + + 4.0.0 + + dubbo-spring-boot-autoconfigure + jar + Apache Dubbo Spring Boot Auto-Configure + + + + + + + org.apache.dubbo + dubbo-spring-boot-autoconfigure-compatible + ${revision} + + + + + org.springframework.boot + spring-boot-autoconfigure + true + + + + org.springframework.boot + spring-boot-starter-logging + true + + + + + org.apache.dubbo + dubbo + ${revision} + + + + org.apache.dubbo + dubbo-common + ${revision} + true + + + + org.apache.dubbo + dubbo-config-spring + ${revision} + true + + + + + org.springframework.boot + spring-boot-starter-test + test + + + \ No newline at end of file diff --git a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/BinderDubboConfigBinder.java b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/BinderDubboConfigBinder.java index 16e2dde977..3da5f0b410 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/BinderDubboConfigBinder.java +++ b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/BinderDubboConfigBinder.java @@ -1,79 +1,79 @@ -/* - * 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.spring.boot.autoconfigure; - -import org.apache.dubbo.config.spring.context.properties.DubboConfigBinder; - -import com.alibaba.spring.context.config.ConfigurationBeanBinder; -import org.springframework.boot.context.properties.bind.BindHandler; -import org.springframework.boot.context.properties.bind.Bindable; -import org.springframework.boot.context.properties.bind.Binder; -import org.springframework.boot.context.properties.bind.PropertySourcesPlaceholdersResolver; -import org.springframework.boot.context.properties.bind.handler.IgnoreErrorsBindHandler; -import org.springframework.boot.context.properties.bind.handler.NoUnboundElementsBindHandler; -import org.springframework.boot.context.properties.source.ConfigurationPropertySource; -import org.springframework.boot.context.properties.source.UnboundElementsSourceFilter; -import org.springframework.core.env.MapPropertySource; -import org.springframework.core.env.PropertySource; - -import java.util.Map; - -import static java.util.Arrays.asList; -import static org.springframework.boot.context.properties.source.ConfigurationPropertySources.from; - -/** - * Spring Boot Relaxed {@link DubboConfigBinder} implementation - * see org.springframework.boot.context.properties.ConfigurationPropertiesBinder - * - * @since 2.7.0 - */ -class BinderDubboConfigBinder implements ConfigurationBeanBinder { - - @Override - public void bind(Map configurationProperties, boolean ignoreUnknownFields, - boolean ignoreInvalidFields, Object configurationBean) { - - Iterable> propertySources = asList(new MapPropertySource("internal", configurationProperties)); - - // Converts ConfigurationPropertySources - Iterable configurationPropertySources = from(propertySources); - - // Wrap Bindable from DubboConfig instance - Bindable bindable = Bindable.ofInstance(configurationBean); - - Binder binder = new Binder(configurationPropertySources, new PropertySourcesPlaceholdersResolver(propertySources)); - - // Get BindHandler - BindHandler bindHandler = getBindHandler(ignoreUnknownFields, ignoreInvalidFields); - - // Bind - binder.bind("", bindable, bindHandler); - } - - private BindHandler getBindHandler(boolean ignoreUnknownFields, - boolean ignoreInvalidFields) { - BindHandler handler = BindHandler.DEFAULT; - if (ignoreInvalidFields) { - handler = new IgnoreErrorsBindHandler(handler); - } - if (!ignoreUnknownFields) { - UnboundElementsSourceFilter filter = new UnboundElementsSourceFilter(); - handler = new NoUnboundElementsBindHandler(handler, filter); - } - return handler; - } -} +/* + * 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.spring.boot.autoconfigure; + +import org.apache.dubbo.config.spring.context.properties.DubboConfigBinder; + +import com.alibaba.spring.context.config.ConfigurationBeanBinder; +import org.springframework.boot.context.properties.bind.BindHandler; +import org.springframework.boot.context.properties.bind.Bindable; +import org.springframework.boot.context.properties.bind.Binder; +import org.springframework.boot.context.properties.bind.PropertySourcesPlaceholdersResolver; +import org.springframework.boot.context.properties.bind.handler.IgnoreErrorsBindHandler; +import org.springframework.boot.context.properties.bind.handler.NoUnboundElementsBindHandler; +import org.springframework.boot.context.properties.source.ConfigurationPropertySource; +import org.springframework.boot.context.properties.source.UnboundElementsSourceFilter; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.PropertySource; + +import java.util.Map; + +import static java.util.Arrays.asList; +import static org.springframework.boot.context.properties.source.ConfigurationPropertySources.from; + +/** + * Spring Boot Relaxed {@link DubboConfigBinder} implementation + * see org.springframework.boot.context.properties.ConfigurationPropertiesBinder + * + * @since 2.7.0 + */ +class BinderDubboConfigBinder implements ConfigurationBeanBinder { + + @Override + public void bind(Map configurationProperties, boolean ignoreUnknownFields, + boolean ignoreInvalidFields, Object configurationBean) { + + Iterable> propertySources = asList(new MapPropertySource("internal", configurationProperties)); + + // Converts ConfigurationPropertySources + Iterable configurationPropertySources = from(propertySources); + + // Wrap Bindable from DubboConfig instance + Bindable bindable = Bindable.ofInstance(configurationBean); + + Binder binder = new Binder(configurationPropertySources, new PropertySourcesPlaceholdersResolver(propertySources)); + + // Get BindHandler + BindHandler bindHandler = getBindHandler(ignoreUnknownFields, ignoreInvalidFields); + + // Bind + binder.bind("", bindable, bindHandler); + } + + private BindHandler getBindHandler(boolean ignoreUnknownFields, + boolean ignoreInvalidFields) { + BindHandler handler = BindHandler.DEFAULT; + if (ignoreInvalidFields) { + handler = new IgnoreErrorsBindHandler(handler); + } + if (!ignoreUnknownFields) { + UnboundElementsSourceFilter filter = new UnboundElementsSourceFilter(); + handler = new NoUnboundElementsBindHandler(handler, filter); + } + return handler; + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboRelaxedBinding2AutoConfiguration.java b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboRelaxedBinding2AutoConfiguration.java index d82747d163..0b858f81c7 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboRelaxedBinding2AutoConfiguration.java +++ b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboRelaxedBinding2AutoConfiguration.java @@ -1,92 +1,92 @@ -/* - * 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.spring.boot.autoconfigure; - -import com.alibaba.spring.context.config.ConfigurationBeanBinder; -import org.springframework.boot.autoconfigure.AutoConfigureBefore; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.properties.source.ConfigurationPropertySources; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Scope; -import org.springframework.core.env.AbstractEnvironment; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.core.env.Environment; -import org.springframework.core.env.MapPropertySource; -import org.springframework.core.env.MutablePropertySources; -import org.springframework.core.env.PropertyResolver; - -import java.util.Map; -import java.util.Set; - -import static com.alibaba.spring.util.PropertySourcesUtils.getSubProperties; -import static java.util.Collections.emptySet; -import static org.apache.dubbo.spring.boot.util.DubboUtils.BASE_PACKAGES_BEAN_NAME; -import static org.apache.dubbo.spring.boot.util.DubboUtils.BASE_PACKAGES_PROPERTY_NAME; -import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_PREFIX; -import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_SCAN_PREFIX; -import static org.apache.dubbo.spring.boot.util.DubboUtils.RELAXED_DUBBO_CONFIG_BINDER_BEAN_NAME; -import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; - -/** - * Dubbo Relaxed Binding Auto-{@link Configuration} for Spring Boot 2.0 - * - * @see DubboRelaxedBindingAutoConfiguration - * @since 2.7.0 - */ -@Configuration -@ConditionalOnProperty(prefix = DUBBO_PREFIX, name = "enabled", matchIfMissing = true) -@ConditionalOnClass(name = "org.springframework.boot.context.properties.bind.Binder") -@AutoConfigureBefore(DubboRelaxedBindingAutoConfiguration.class) -public class DubboRelaxedBinding2AutoConfiguration { - - public PropertyResolver dubboScanBasePackagesPropertyResolver(ConfigurableEnvironment environment) { - ConfigurableEnvironment propertyResolver = new AbstractEnvironment() { - @Override - protected void customizePropertySources(MutablePropertySources propertySources) { - Map dubboScanProperties = getSubProperties(environment.getPropertySources(), DUBBO_SCAN_PREFIX); - propertySources.addLast(new MapPropertySource("dubboScanProperties", dubboScanProperties)); - } - }; - ConfigurationPropertySources.attach(propertyResolver); - return propertyResolver; - } - - /** - * The bean is used to scan the packages of Dubbo Service classes - * - * @param environment {@link Environment} instance - * @return non-null {@link Set} - * @since 2.7.8 - */ - @ConditionalOnMissingBean(name = BASE_PACKAGES_BEAN_NAME) - @Bean(name = BASE_PACKAGES_BEAN_NAME) - public Set dubboBasePackages(ConfigurableEnvironment environment) { - PropertyResolver propertyResolver = dubboScanBasePackagesPropertyResolver(environment); - return propertyResolver.getProperty(BASE_PACKAGES_PROPERTY_NAME, Set.class, emptySet()); - } - - @ConditionalOnMissingBean(name = RELAXED_DUBBO_CONFIG_BINDER_BEAN_NAME, value = ConfigurationBeanBinder.class) - @Bean(RELAXED_DUBBO_CONFIG_BINDER_BEAN_NAME) - @Scope(scopeName = SCOPE_PROTOTYPE) - public ConfigurationBeanBinder relaxedDubboConfigBinder() { - return new BinderDubboConfigBinder(); - } - -} +/* + * 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.spring.boot.autoconfigure; + +import com.alibaba.spring.context.config.ConfigurationBeanBinder; +import org.springframework.boot.autoconfigure.AutoConfigureBefore; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.source.ConfigurationPropertySources; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Scope; +import org.springframework.core.env.AbstractEnvironment; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.Environment; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.MutablePropertySources; +import org.springframework.core.env.PropertyResolver; + +import java.util.Map; +import java.util.Set; + +import static com.alibaba.spring.util.PropertySourcesUtils.getSubProperties; +import static java.util.Collections.emptySet; +import static org.apache.dubbo.spring.boot.util.DubboUtils.BASE_PACKAGES_BEAN_NAME; +import static org.apache.dubbo.spring.boot.util.DubboUtils.BASE_PACKAGES_PROPERTY_NAME; +import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_PREFIX; +import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_SCAN_PREFIX; +import static org.apache.dubbo.spring.boot.util.DubboUtils.RELAXED_DUBBO_CONFIG_BINDER_BEAN_NAME; +import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; + +/** + * Dubbo Relaxed Binding Auto-{@link Configuration} for Spring Boot 2.0 + * + * @see DubboRelaxedBindingAutoConfiguration + * @since 2.7.0 + */ +@Configuration +@ConditionalOnProperty(prefix = DUBBO_PREFIX, name = "enabled", matchIfMissing = true) +@ConditionalOnClass(name = "org.springframework.boot.context.properties.bind.Binder") +@AutoConfigureBefore(DubboRelaxedBindingAutoConfiguration.class) +public class DubboRelaxedBinding2AutoConfiguration { + + public PropertyResolver dubboScanBasePackagesPropertyResolver(ConfigurableEnvironment environment) { + ConfigurableEnvironment propertyResolver = new AbstractEnvironment() { + @Override + protected void customizePropertySources(MutablePropertySources propertySources) { + Map dubboScanProperties = getSubProperties(environment.getPropertySources(), DUBBO_SCAN_PREFIX); + propertySources.addLast(new MapPropertySource("dubboScanProperties", dubboScanProperties)); + } + }; + ConfigurationPropertySources.attach(propertyResolver); + return propertyResolver; + } + + /** + * The bean is used to scan the packages of Dubbo Service classes + * + * @param environment {@link Environment} instance + * @return non-null {@link Set} + * @since 2.7.8 + */ + @ConditionalOnMissingBean(name = BASE_PACKAGES_BEAN_NAME) + @Bean(name = BASE_PACKAGES_BEAN_NAME) + public Set dubboBasePackages(ConfigurableEnvironment environment) { + PropertyResolver propertyResolver = dubboScanBasePackagesPropertyResolver(environment); + return propertyResolver.getProperty(BASE_PACKAGES_PROPERTY_NAME, Set.class, emptySet()); + } + + @ConditionalOnMissingBean(name = RELAXED_DUBBO_CONFIG_BINDER_BEAN_NAME, value = ConfigurationBeanBinder.class) + @Bean(RELAXED_DUBBO_CONFIG_BINDER_BEAN_NAME) + @Scope(scopeName = SCOPE_PROTOTYPE) + public ConfigurationBeanBinder relaxedDubboConfigBinder() { + return new BinderDubboConfigBinder(); + } + +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories index 057eb45415..c88a29b244 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories +++ b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories @@ -1,2 +1,2 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.apache.dubbo.spring.boot.autoconfigure.DubboRelaxedBinding2AutoConfiguration \ No newline at end of file diff --git a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/BinderDubboConfigBinderTest.java b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/BinderDubboConfigBinderTest.java index 45b8c336f0..b992610af0 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/BinderDubboConfigBinderTest.java +++ b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/BinderDubboConfigBinderTest.java @@ -1,72 +1,72 @@ -/* - * 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.spring.boot.autoconfigure; - -import org.apache.dubbo.config.ApplicationConfig; -import org.apache.dubbo.config.ProtocolConfig; -import org.apache.dubbo.config.RegistryConfig; - -import com.alibaba.spring.context.config.ConfigurationBeanBinder; -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit4.SpringRunner; - -import java.util.Map; - -import static com.alibaba.spring.util.PropertySourcesUtils.getSubProperties; - -/** - * {@link BinderDubboConfigBinder} Test - * - * @since 2.7.0 - */ -@RunWith(SpringRunner.class) -@TestPropertySource(locations = "classpath:/dubbo.properties") -@ContextConfiguration(classes = BinderDubboConfigBinder.class) -public class BinderDubboConfigBinderTest { - - @Autowired - private ConfigurationBeanBinder dubboConfigBinder; - - @Autowired - private ConfigurableEnvironment environment; - - @Test - public void testBinder() { - - ApplicationConfig applicationConfig = new ApplicationConfig(); - Map properties = getSubProperties(environment.getPropertySources(), "dubbo.application"); - dubboConfigBinder.bind(properties, true, true, applicationConfig); - Assert.assertEquals("hello", applicationConfig.getName()); - Assert.assertEquals("world", applicationConfig.getOwner()); - - RegistryConfig registryConfig = new RegistryConfig(); - properties = getSubProperties(environment.getPropertySources(), "dubbo.registry"); - dubboConfigBinder.bind(properties, true, true, registryConfig); - Assert.assertEquals("10.20.153.17", registryConfig.getAddress()); - - ProtocolConfig protocolConfig = new ProtocolConfig(); - properties = getSubProperties(environment.getPropertySources(), "dubbo.protocol"); - dubboConfigBinder.bind(properties, true, true, protocolConfig); - Assert.assertEquals(Integer.valueOf(20881), protocolConfig.getPort()); - } -} +/* + * 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.spring.boot.autoconfigure; + +import org.apache.dubbo.config.ApplicationConfig; +import org.apache.dubbo.config.ProtocolConfig; +import org.apache.dubbo.config.RegistryConfig; + +import com.alibaba.spring.context.config.ConfigurationBeanBinder; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.Map; + +import static com.alibaba.spring.util.PropertySourcesUtils.getSubProperties; + +/** + * {@link BinderDubboConfigBinder} Test + * + * @since 2.7.0 + */ +@RunWith(SpringRunner.class) +@TestPropertySource(locations = "classpath:/dubbo.properties") +@ContextConfiguration(classes = BinderDubboConfigBinder.class) +public class BinderDubboConfigBinderTest { + + @Autowired + private ConfigurationBeanBinder dubboConfigBinder; + + @Autowired + private ConfigurableEnvironment environment; + + @Test + public void testBinder() { + + ApplicationConfig applicationConfig = new ApplicationConfig(); + Map properties = getSubProperties(environment.getPropertySources(), "dubbo.application"); + dubboConfigBinder.bind(properties, true, true, applicationConfig); + Assert.assertEquals("hello", applicationConfig.getName()); + Assert.assertEquals("world", applicationConfig.getOwner()); + + RegistryConfig registryConfig = new RegistryConfig(); + properties = getSubProperties(environment.getPropertySources(), "dubbo.registry"); + dubboConfigBinder.bind(properties, true, true, registryConfig); + Assert.assertEquals("10.20.153.17", registryConfig.getAddress()); + + ProtocolConfig protocolConfig = new ProtocolConfig(); + properties = getSubProperties(environment.getPropertySources(), "dubbo.protocol"); + dubboConfigBinder.bind(properties, true, true, protocolConfig); + Assert.assertEquals(Integer.valueOf(20881), protocolConfig.getPort()); + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/DubboRelaxedBinding2AutoConfigurationTest.java b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/DubboRelaxedBinding2AutoConfigurationTest.java index 9772baa9d3..b41cab18e5 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/DubboRelaxedBinding2AutoConfigurationTest.java +++ b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/DubboRelaxedBinding2AutoConfigurationTest.java @@ -1,94 +1,94 @@ -/* - * 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.spring.boot.autoconfigure; - -import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor; -import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationPostProcessor; - -import com.alibaba.spring.context.config.ConfigurationBeanBinder; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.ObjectProvider; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.annotation.PropertySource; -import org.springframework.core.env.Environment; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.util.ClassUtils; - -import java.util.Map; -import java.util.Set; - -import static org.apache.dubbo.spring.boot.util.DubboUtils.BASE_PACKAGES_BEAN_NAME; -import static org.apache.dubbo.spring.boot.util.DubboUtils.RELAXED_DUBBO_CONFIG_BINDER_BEAN_NAME; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -/** - * {@link DubboRelaxedBinding2AutoConfiguration} Test - */ -@RunWith(SpringRunner.class) -@SpringBootTest(classes = DubboRelaxedBinding2AutoConfigurationTest.class, properties = { - "dubbo.scan.basePackages = org.apache.dubbo.spring.boot.autoconfigure" -}) -@EnableAutoConfiguration -@PropertySource(value = "classpath:/dubbo.properties") -public class DubboRelaxedBinding2AutoConfigurationTest { - - @Autowired - @Qualifier(BASE_PACKAGES_BEAN_NAME) - private Set packagesToScan; - - @Autowired - @Qualifier(RELAXED_DUBBO_CONFIG_BINDER_BEAN_NAME) - private ConfigurationBeanBinder dubboConfigBinder; - - @Autowired - private ObjectProvider serviceAnnotationPostProcessor; - - @Autowired - private ObjectProvider referenceAnnotationBeanPostProcessor; - - @Autowired - private Environment environment; - - @Autowired - private Map environments; - - @Test - public void testBeans() { - - assertTrue(ClassUtils.isAssignableValue(BinderDubboConfigBinder.class, dubboConfigBinder)); - - assertNotNull(serviceAnnotationPostProcessor); - assertNotNull(serviceAnnotationPostProcessor.getIfAvailable()); - assertNotNull(referenceAnnotationBeanPostProcessor); - assertNotNull(referenceAnnotationBeanPostProcessor.getIfAvailable()); - - assertNotNull(environment); - assertNotNull(environments); - - - assertEquals(1, environments.size()); - - assertTrue(environments.containsValue(environment)); - } - -} \ No newline at end of file +/* + * 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.spring.boot.autoconfigure; + +import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor; +import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationPostProcessor; + +import com.alibaba.spring.context.config.ConfigurationBeanBinder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.util.ClassUtils; + +import java.util.Map; +import java.util.Set; + +import static org.apache.dubbo.spring.boot.util.DubboUtils.BASE_PACKAGES_BEAN_NAME; +import static org.apache.dubbo.spring.boot.util.DubboUtils.RELAXED_DUBBO_CONFIG_BINDER_BEAN_NAME; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +/** + * {@link DubboRelaxedBinding2AutoConfiguration} Test + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = DubboRelaxedBinding2AutoConfigurationTest.class, properties = { + "dubbo.scan.basePackages = org.apache.dubbo.spring.boot.autoconfigure" +}) +@EnableAutoConfiguration +@PropertySource(value = "classpath:/dubbo.properties") +public class DubboRelaxedBinding2AutoConfigurationTest { + + @Autowired + @Qualifier(BASE_PACKAGES_BEAN_NAME) + private Set packagesToScan; + + @Autowired + @Qualifier(RELAXED_DUBBO_CONFIG_BINDER_BEAN_NAME) + private ConfigurationBeanBinder dubboConfigBinder; + + @Autowired + private ObjectProvider serviceAnnotationPostProcessor; + + @Autowired + private ObjectProvider referenceAnnotationBeanPostProcessor; + + @Autowired + private Environment environment; + + @Autowired + private Map environments; + + @Test + public void testBeans() { + + assertTrue(ClassUtils.isAssignableValue(BinderDubboConfigBinder.class, dubboConfigBinder)); + + assertNotNull(serviceAnnotationPostProcessor); + assertNotNull(serviceAnnotationPostProcessor.getIfAvailable()); + assertNotNull(referenceAnnotationBeanPostProcessor); + assertNotNull(referenceAnnotationBeanPostProcessor.getIfAvailable()); + + assertNotNull(environment); + assertNotNull(environments); + + + assertEquals(1, environments.size()); + + assertTrue(environments.containsValue(environment)); + } + +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/test/java/org/apache/dubbo/spring/boot/env/DubboDefaultPropertiesEnvironmentPostProcessorTest.java b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/test/java/org/apache/dubbo/spring/boot/env/DubboDefaultPropertiesEnvironmentPostProcessorTest.java index 860bc2e8a3..9e2de9a822 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/test/java/org/apache/dubbo/spring/boot/env/DubboDefaultPropertiesEnvironmentPostProcessorTest.java +++ b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/test/java/org/apache/dubbo/spring/boot/env/DubboDefaultPropertiesEnvironmentPostProcessorTest.java @@ -1,97 +1,97 @@ -/* - * 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.spring.boot.env; - -import org.junit.Assert; -import org.junit.Test; -import org.springframework.boot.SpringApplication; -import org.springframework.core.Ordered; -import org.springframework.core.env.MapPropertySource; -import org.springframework.core.env.MutablePropertySources; -import org.springframework.core.env.PropertySource; -import org.springframework.mock.env.MockEnvironment; - -import java.util.HashMap; - -/** - * {@link DubboDefaultPropertiesEnvironmentPostProcessor} Test - */ -public class DubboDefaultPropertiesEnvironmentPostProcessorTest { - - private DubboDefaultPropertiesEnvironmentPostProcessor instance = - new DubboDefaultPropertiesEnvironmentPostProcessor(); - - private SpringApplication springApplication = new SpringApplication(); - - @Test - public void testOrder() { - Assert.assertEquals(Ordered.LOWEST_PRECEDENCE, instance.getOrder()); - } - - @Test - public void testPostProcessEnvironment() { - MockEnvironment environment = new MockEnvironment(); - // Case 1 : Not Any property - instance.postProcessEnvironment(environment, springApplication); - // Get PropertySources - MutablePropertySources propertySources = environment.getPropertySources(); - // Nothing to change - PropertySource defaultPropertySource = propertySources.get("defaultProperties"); - Assert.assertNotNull(defaultPropertySource); - Assert.assertEquals("true", defaultPropertySource.getProperty("dubbo.config.multiple")); - Assert.assertEquals("false", defaultPropertySource.getProperty("dubbo.application.qos-enable")); - - // Case 2 : Only set property "spring.application.name" - environment.setProperty("spring.application.name", "demo-dubbo-application"); - instance.postProcessEnvironment(environment, springApplication); - defaultPropertySource = propertySources.get("defaultProperties"); - Object dubboApplicationName = defaultPropertySource.getProperty("dubbo.application.name"); - Assert.assertEquals("demo-dubbo-application", dubboApplicationName); - - // Case 3 : Only set property "dubbo.application.name" - // Rest environment - environment = new MockEnvironment(); - propertySources = environment.getPropertySources(); - environment.setProperty("dubbo.application.name", "demo-dubbo-application"); - instance.postProcessEnvironment(environment, springApplication); - defaultPropertySource = propertySources.get("defaultProperties"); - Assert.assertNotNull(defaultPropertySource); - dubboApplicationName = environment.getProperty("dubbo.application.name"); - Assert.assertEquals("demo-dubbo-application", dubboApplicationName); - - // Case 4 : If "defaultProperties" PropertySource is present in PropertySources - // Rest environment - environment = new MockEnvironment(); - propertySources = environment.getPropertySources(); - propertySources.addLast(new MapPropertySource("defaultProperties", new HashMap())); - environment.setProperty("spring.application.name", "demo-dubbo-application"); - instance.postProcessEnvironment(environment, springApplication); - defaultPropertySource = propertySources.get("defaultProperties"); - dubboApplicationName = defaultPropertySource.getProperty("dubbo.application.name"); - Assert.assertEquals("demo-dubbo-application", dubboApplicationName); - - // Case 5 : Rest dubbo.config.multiple and dubbo.application.qos-enable - environment = new MockEnvironment(); - propertySources = environment.getPropertySources(); - propertySources.addLast(new MapPropertySource("defaultProperties", new HashMap())); - environment.setProperty("dubbo.config.multiple", "false"); - environment.setProperty("dubbo.application.qos-enable", "true"); - instance.postProcessEnvironment(environment, springApplication); - Assert.assertEquals("false", environment.getProperty("dubbo.config.multiple")); - Assert.assertEquals("true", environment.getProperty("dubbo.application.qos-enable")); - } -} \ No newline at end of file +/* + * 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.spring.boot.env; + +import org.junit.Assert; +import org.junit.Test; +import org.springframework.boot.SpringApplication; +import org.springframework.core.Ordered; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.MutablePropertySources; +import org.springframework.core.env.PropertySource; +import org.springframework.mock.env.MockEnvironment; + +import java.util.HashMap; + +/** + * {@link DubboDefaultPropertiesEnvironmentPostProcessor} Test + */ +public class DubboDefaultPropertiesEnvironmentPostProcessorTest { + + private DubboDefaultPropertiesEnvironmentPostProcessor instance = + new DubboDefaultPropertiesEnvironmentPostProcessor(); + + private SpringApplication springApplication = new SpringApplication(); + + @Test + public void testOrder() { + Assert.assertEquals(Ordered.LOWEST_PRECEDENCE, instance.getOrder()); + } + + @Test + public void testPostProcessEnvironment() { + MockEnvironment environment = new MockEnvironment(); + // Case 1 : Not Any property + instance.postProcessEnvironment(environment, springApplication); + // Get PropertySources + MutablePropertySources propertySources = environment.getPropertySources(); + // Nothing to change + PropertySource defaultPropertySource = propertySources.get("defaultProperties"); + Assert.assertNotNull(defaultPropertySource); + Assert.assertEquals("true", defaultPropertySource.getProperty("dubbo.config.multiple")); + Assert.assertEquals("false", defaultPropertySource.getProperty("dubbo.application.qos-enable")); + + // Case 2 : Only set property "spring.application.name" + environment.setProperty("spring.application.name", "demo-dubbo-application"); + instance.postProcessEnvironment(environment, springApplication); + defaultPropertySource = propertySources.get("defaultProperties"); + Object dubboApplicationName = defaultPropertySource.getProperty("dubbo.application.name"); + Assert.assertEquals("demo-dubbo-application", dubboApplicationName); + + // Case 3 : Only set property "dubbo.application.name" + // Rest environment + environment = new MockEnvironment(); + propertySources = environment.getPropertySources(); + environment.setProperty("dubbo.application.name", "demo-dubbo-application"); + instance.postProcessEnvironment(environment, springApplication); + defaultPropertySource = propertySources.get("defaultProperties"); + Assert.assertNotNull(defaultPropertySource); + dubboApplicationName = environment.getProperty("dubbo.application.name"); + Assert.assertEquals("demo-dubbo-application", dubboApplicationName); + + // Case 4 : If "defaultProperties" PropertySource is present in PropertySources + // Rest environment + environment = new MockEnvironment(); + propertySources = environment.getPropertySources(); + propertySources.addLast(new MapPropertySource("defaultProperties", new HashMap())); + environment.setProperty("spring.application.name", "demo-dubbo-application"); + instance.postProcessEnvironment(environment, springApplication); + defaultPropertySource = propertySources.get("defaultProperties"); + dubboApplicationName = defaultPropertySource.getProperty("dubbo.application.name"); + Assert.assertEquals("demo-dubbo-application", dubboApplicationName); + + // Case 5 : Rest dubbo.config.multiple and dubbo.application.qos-enable + environment = new MockEnvironment(); + propertySources = environment.getPropertySources(); + propertySources.addLast(new MapPropertySource("defaultProperties", new HashMap())); + environment.setProperty("dubbo.config.multiple", "false"); + environment.setProperty("dubbo.application.qos-enable", "true"); + instance.postProcessEnvironment(environment, springApplication); + Assert.assertEquals("false", environment.getProperty("dubbo.config.multiple")); + Assert.assertEquals("true", environment.getProperty("dubbo.application.qos-enable")); + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/test/resources/dubbo.properties b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/test/resources/dubbo.properties index abe14a103d..897ec0f456 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/test/resources/dubbo.properties +++ b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/test/resources/dubbo.properties @@ -1,5 +1,5 @@ -dubbo.application.NAME=hello -dubbo.application.owneR=world -dubbo.registry.Address=10.20.153.17 -dubbo.protocol.pORt=20881 -dubbo.service.invoke.timeout=2000 \ No newline at end of file +dubbo.application.NAME=hello +dubbo.application.owneR=world +dubbo.registry.Address=10.20.153.17 +dubbo.protocol.pORt=20881 +dubbo.service.invoke.timeout=2000 diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/pom.xml b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/pom.xml index 109e2de4fc..23af65866a 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/pom.xml +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/pom.xml @@ -1,101 +1,107 @@ - - - - - org.apache.dubbo - dubbo-spring-boot-compatible - ${revision} - ../pom.xml - - 4.0.0 - - dubbo-spring-boot-actuator-compatible - Apache Dubbo Spring Boot Compatible for Spring Boot 1.x Actuator - - - - - org.springframework.boot - spring-boot-starter-web - true - - - - org.springframework.boot - spring-boot-starter-actuator - true - - - - org.springframework.boot - spring-boot-autoconfigure - true - - - - - org.springframework.boot - spring-boot-configuration-processor - true - - - - - org.apache.dubbo - dubbo-spring-boot-autoconfigure-compatible - ${revision} - - - - org.apache.dubbo - dubbo - ${revision} - - - - org.apache.dubbo - dubbo-common - ${revision} - true - - - - org.apache.dubbo - dubbo-config-spring - ${revision} - true - - - - org.apache.dubbo - dubbo-rpc-dubbo - ${revision} - test - - - - - org.springframework.boot - spring-boot-starter-test - test - - - + + + + + org.apache.dubbo + dubbo-spring-boot-compatible + ${revision} + ../pom.xml + + 4.0.0 + + dubbo-spring-boot-actuator-compatible + Apache Dubbo Spring Boot Compatible for Spring Boot 1.x Actuator + + + + + org.springframework.boot + spring-boot-starter-web + true + + + + org.apache.tomcat.embed + tomcat-embed-core + true + + + + org.springframework.boot + spring-boot-starter-actuator + true + + + + org.springframework.boot + spring-boot-autoconfigure + true + + + + + org.springframework.boot + spring-boot-configuration-processor + true + + + + + org.apache.dubbo + dubbo-spring-boot-autoconfigure-compatible + ${revision} + + + + org.apache.dubbo + dubbo + ${revision} + + + + org.apache.dubbo + dubbo-common + ${revision} + true + + + + org.apache.dubbo + dubbo-config-spring + ${revision} + true + + + + org.apache.dubbo + dubbo-rpc-dubbo + ${revision} + test + + + + + org.springframework.boot + spring-boot-starter-test + test + + + \ No newline at end of file diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/autoconfigure/DubboEndpointAutoConfiguration.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/autoconfigure/DubboEndpointAutoConfiguration.java index 84091242bf..92a9ba0aa9 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/autoconfigure/DubboEndpointAutoConfiguration.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/autoconfigure/DubboEndpointAutoConfiguration.java @@ -1,55 +1,55 @@ -/* - * 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.spring.boot.actuate.autoconfigure; - - -import org.apache.dubbo.spring.boot.actuate.endpoint.DubboEndpoint; -import org.apache.dubbo.spring.boot.autoconfigure.DubboAutoConfiguration; -import org.apache.dubbo.spring.boot.autoconfigure.DubboRelaxedBindingAutoConfiguration; - -import org.springframework.boot.actuate.condition.ConditionalOnEnabledEndpoint; -import org.springframework.boot.actuate.endpoint.Endpoint; -import org.springframework.boot.autoconfigure.AutoConfigureAfter; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * Dubbo {@link Endpoint} Auto Configuration is compatible with Spring Boot Actuator 1.x - * - * @since 2.7.0 - */ -@Configuration -@ConditionalOnClass(name = { - "org.springframework.boot.actuate.endpoint.Endpoint" // Spring Boot 1.x -}) -@AutoConfigureAfter(value = { - DubboAutoConfiguration.class, - DubboRelaxedBindingAutoConfiguration.class -}) -@EnableConfigurationProperties(DubboEndpoint.class) -public class DubboEndpointAutoConfiguration { - - @Bean - @ConditionalOnMissingBean - @ConditionalOnEnabledEndpoint(value = "dubbo") - public DubboEndpoint dubboEndpoint() { - return new DubboEndpoint(); - } -} +/* + * 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.spring.boot.actuate.autoconfigure; + + +import org.apache.dubbo.spring.boot.actuate.endpoint.DubboEndpoint; +import org.apache.dubbo.spring.boot.autoconfigure.DubboAutoConfiguration; +import org.apache.dubbo.spring.boot.autoconfigure.DubboRelaxedBindingAutoConfiguration; + +import org.springframework.boot.actuate.condition.ConditionalOnEnabledEndpoint; +import org.springframework.boot.actuate.endpoint.Endpoint; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * Dubbo {@link Endpoint} Auto Configuration is compatible with Spring Boot Actuator 1.x + * + * @since 2.7.0 + */ +@Configuration +@ConditionalOnClass(name = { + "org.springframework.boot.actuate.endpoint.Endpoint" // Spring Boot 1.x +}) +@AutoConfigureAfter(value = { + DubboAutoConfiguration.class, + DubboRelaxedBindingAutoConfiguration.class +}) +@EnableConfigurationProperties(DubboEndpoint.class) +public class DubboEndpointAutoConfiguration { + + @Bean + @ConditionalOnMissingBean + @ConditionalOnEnabledEndpoint(value = "dubbo") + public DubboEndpoint dubboEndpoint() { + return new DubboEndpoint(); + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/autoconfigure/DubboEndpointMetadataAutoConfiguration.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/autoconfigure/DubboEndpointMetadataAutoConfiguration.java index e6dd0a4d16..fa754d6a32 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/autoconfigure/DubboEndpointMetadataAutoConfiguration.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/autoconfigure/DubboEndpointMetadataAutoConfiguration.java @@ -1,39 +1,39 @@ -/* - * 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.spring.boot.actuate.autoconfigure; - -import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.AbstractDubboMetadata; - -import org.springframework.boot.autoconfigure.AutoConfigureAfter; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; - -/** - * Dubbo Endpoints Metadata Auto-{@link Configuration} - */ -@ConditionalOnClass(name = { - "org.springframework.boot.actuate.health.Health" // If spring-boot-actuator is present -}) -@Configuration -@AutoConfigureAfter(name = { - "org.apache.dubbo.spring.boot.autoconfigure.DubboAutoConfiguration", - "org.apache.dubbo.spring.boot.autoconfigure.DubboRelaxedBindingAutoConfiguration" -}) -@ComponentScan(basePackageClasses = AbstractDubboMetadata.class) -public class DubboEndpointMetadataAutoConfiguration { -} +/* + * 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.spring.boot.actuate.autoconfigure; + +import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.AbstractDubboMetadata; + +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +/** + * Dubbo Endpoints Metadata Auto-{@link Configuration} + */ +@ConditionalOnClass(name = { + "org.springframework.boot.actuate.health.Health" // If spring-boot-actuator is present +}) +@Configuration +@AutoConfigureAfter(name = { + "org.apache.dubbo.spring.boot.autoconfigure.DubboAutoConfiguration", + "org.apache.dubbo.spring.boot.autoconfigure.DubboRelaxedBindingAutoConfiguration" +}) +@ComponentScan(basePackageClasses = AbstractDubboMetadata.class) +public class DubboEndpointMetadataAutoConfiguration { +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/autoconfigure/DubboHealthIndicatorAutoConfiguration.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/autoconfigure/DubboHealthIndicatorAutoConfiguration.java index 1bcfcb0b49..c5bcd792c9 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/autoconfigure/DubboHealthIndicatorAutoConfiguration.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/autoconfigure/DubboHealthIndicatorAutoConfiguration.java @@ -1,50 +1,50 @@ -/* - * 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.spring.boot.actuate.autoconfigure; - -import org.apache.dubbo.spring.boot.actuate.health.DubboHealthIndicator; -import org.apache.dubbo.spring.boot.actuate.health.DubboHealthIndicatorProperties; - -import org.springframework.boot.actuate.health.HealthIndicator; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * Dubbo {@link DubboHealthIndicator} Auto Configuration - * - * @see HealthIndicator - * @since 2.7.0 - */ -@Configuration -@ConditionalOnClass(name = { - "org.springframework.boot.actuate.health.Health" -}) -@ConditionalOnProperty(name = "management.health.dubbo.enabled", matchIfMissing = true, havingValue = "true") -@EnableConfigurationProperties(DubboHealthIndicatorProperties.class) -public class DubboHealthIndicatorAutoConfiguration { - - @Bean - @ConditionalOnMissingBean - public DubboHealthIndicator dubboHealthIndicator() { - return new DubboHealthIndicator(); - } - -} +/* + * 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.spring.boot.actuate.autoconfigure; + +import org.apache.dubbo.spring.boot.actuate.health.DubboHealthIndicator; +import org.apache.dubbo.spring.boot.actuate.health.DubboHealthIndicatorProperties; + +import org.springframework.boot.actuate.health.HealthIndicator; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * Dubbo {@link DubboHealthIndicator} Auto Configuration + * + * @see HealthIndicator + * @since 2.7.0 + */ +@Configuration +@ConditionalOnClass(name = { + "org.springframework.boot.actuate.health.Health" +}) +@ConditionalOnProperty(name = "management.health.dubbo.enabled", matchIfMissing = true, havingValue = "true") +@EnableConfigurationProperties(DubboHealthIndicatorProperties.class) +public class DubboHealthIndicatorAutoConfiguration { + + @Bean + @ConditionalOnMissingBean + public DubboHealthIndicator dubboHealthIndicator() { + return new DubboHealthIndicator(); + } + +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/autoconfigure/DubboMvcEndpointManagementContextConfiguration.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/autoconfigure/DubboMvcEndpointManagementContextConfiguration.java index 5b5991876f..b3cdabdc43 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/autoconfigure/DubboMvcEndpointManagementContextConfiguration.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/autoconfigure/DubboMvcEndpointManagementContextConfiguration.java @@ -1,49 +1,49 @@ -/* - * 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.spring.boot.actuate.autoconfigure; - - -import org.apache.dubbo.spring.boot.actuate.endpoint.DubboEndpoint; -import org.apache.dubbo.spring.boot.actuate.endpoint.mvc.DubboMvcEndpoint; - -import org.springframework.boot.actuate.autoconfigure.ManagementContextConfiguration; -import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; -import org.springframework.context.annotation.Bean; - -/** - * Dubbo {@link MvcEndpoint} {@link ManagementContextConfiguration} for Spring Boot 1.x - * - * @since 2.7.0 - */ -@ManagementContextConfiguration -@ConditionalOnClass(name = { - "org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter" -}) -@ConditionalOnWebApplication -public class DubboMvcEndpointManagementContextConfiguration { - - @Bean - @ConditionalOnBean(DubboEndpoint.class) - @ConditionalOnMissingBean - public DubboMvcEndpoint dubboMvcEndpoint(DubboEndpoint dubboEndpoint) { - return new DubboMvcEndpoint(dubboEndpoint); - } -} +/* + * 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.spring.boot.actuate.autoconfigure; + + +import org.apache.dubbo.spring.boot.actuate.endpoint.DubboEndpoint; +import org.apache.dubbo.spring.boot.actuate.endpoint.mvc.DubboMvcEndpoint; + +import org.springframework.boot.actuate.autoconfigure.ManagementContextConfiguration; +import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.context.annotation.Bean; + +/** + * Dubbo {@link MvcEndpoint} {@link ManagementContextConfiguration} for Spring Boot 1.x + * + * @since 2.7.0 + */ +@ManagementContextConfiguration +@ConditionalOnClass(name = { + "org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter" +}) +@ConditionalOnWebApplication +public class DubboMvcEndpointManagementContextConfiguration { + + @Bean + @ConditionalOnBean(DubboEndpoint.class) + @ConditionalOnMissingBean + public DubboMvcEndpoint dubboMvcEndpoint(DubboEndpoint dubboEndpoint) { + return new DubboMvcEndpoint(dubboEndpoint); + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/DubboEndpoint.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/DubboEndpoint.java index ef0d9b9565..375902d5ff 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/DubboEndpoint.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/DubboEndpoint.java @@ -1,49 +1,49 @@ -/* - * 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.spring.boot.actuate.endpoint; - - -import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboMetadata; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.actuate.endpoint.AbstractEndpoint; -import org.springframework.boot.actuate.endpoint.Endpoint; -import org.springframework.boot.context.properties.ConfigurationProperties; - -import java.util.Map; - -/** - * Actuator {@link Endpoint} to expose Dubbo Meta Data - * - * @see Endpoint - * @since 2.7.0 - */ -@ConfigurationProperties(prefix = "endpoints.dubbo", ignoreUnknownFields = false) -public class DubboEndpoint extends AbstractEndpoint> { - - @Autowired - private DubboMetadata dubboMetadata; - - public DubboEndpoint() { - super("dubbo", true, false); - } - - @Override - public Map invoke() { - return dubboMetadata.invoke(); - } -} +/* + * 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.spring.boot.actuate.endpoint; + + +import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboMetadata; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.endpoint.AbstractEndpoint; +import org.springframework.boot.actuate.endpoint.Endpoint; +import org.springframework.boot.context.properties.ConfigurationProperties; + +import java.util.Map; + +/** + * Actuator {@link Endpoint} to expose Dubbo Meta Data + * + * @see Endpoint + * @since 2.7.0 + */ +@ConfigurationProperties(prefix = "endpoints.dubbo", ignoreUnknownFields = false) +public class DubboEndpoint extends AbstractEndpoint> { + + @Autowired + private DubboMetadata dubboMetadata; + + public DubboEndpoint() { + super("dubbo", true, false); + } + + @Override + public Map invoke() { + return dubboMetadata.invoke(); + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/AbstractDubboMetadata.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/AbstractDubboMetadata.java index 3f6c3b0742..27ad5c97de 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/AbstractDubboMetadata.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/AbstractDubboMetadata.java @@ -1,124 +1,124 @@ -/* - * 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.spring.boot.actuate.endpoint.metadata; - -import org.apache.dubbo.config.ProtocolConfig; -import org.apache.dubbo.config.spring.ServiceBean; -import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor; - -import org.springframework.beans.BeansException; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.context.EnvironmentAware; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.core.env.Environment; - -import java.beans.BeanInfo; -import java.beans.Introspector; -import java.beans.PropertyDescriptor; -import java.lang.reflect.Method; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.net.URL; -import java.util.Date; -import java.util.LinkedHashMap; -import java.util.Map; - -import static org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor.BEAN_NAME; -import static org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors; -import static org.springframework.util.ClassUtils.isPrimitiveOrWrapper; - -/** - * Abstract Dubbo Meatadata - * - * @since 2.7.0 - */ -public abstract class AbstractDubboMetadata implements ApplicationContextAware, EnvironmentAware { - - protected ApplicationContext applicationContext; - - protected ConfigurableEnvironment environment; - - private static boolean isSimpleType(Class type) { - return isPrimitiveOrWrapper(type) - || type == String.class - || type == BigDecimal.class - || type == BigInteger.class - || type == Date.class - || type == URL.class - || type == Class.class - ; - } - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext = applicationContext; - } - - @Override - public void setEnvironment(Environment environment) { - if (environment instanceof ConfigurableEnvironment) { - this.environment = (ConfigurableEnvironment) environment; - } - } - - protected Map resolveBeanMetadata(final Object bean) { - - final Map beanMetadata = new LinkedHashMap<>(); - - try { - - BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass()); - PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); - - for (PropertyDescriptor propertyDescriptor : propertyDescriptors) { - - Method readMethod = propertyDescriptor.getReadMethod(); - - if (readMethod != null && isSimpleType(propertyDescriptor.getPropertyType())) { - - String name = Introspector.decapitalize(propertyDescriptor.getName()); - Object value = readMethod.invoke(bean); - if (value != null) { - beanMetadata.put(name, value); - } - } - - } - - } catch (Exception e) { - throw new RuntimeException(e); - } - - return beanMetadata; - - } - - protected Map getServiceBeansMap() { - return beansOfTypeIncludingAncestors(applicationContext, ServiceBean.class); - } - - protected ReferenceAnnotationBeanPostProcessor getReferenceAnnotationBeanPostProcessor() { - return applicationContext.getBean(BEAN_NAME, ReferenceAnnotationBeanPostProcessor.class); - } - - protected Map getProtocolConfigsBeanMap() { - return beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class); - } - - -} +/* + * 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.spring.boot.actuate.endpoint.metadata; + +import org.apache.dubbo.config.ProtocolConfig; +import org.apache.dubbo.config.spring.ServiceBean; +import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.EnvironmentAware; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.Environment; + +import java.beans.BeanInfo; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Method; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.net.URL; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.Map; + +import static org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor.BEAN_NAME; +import static org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors; +import static org.springframework.util.ClassUtils.isPrimitiveOrWrapper; + +/** + * Abstract Dubbo Meatadata + * + * @since 2.7.0 + */ +public abstract class AbstractDubboMetadata implements ApplicationContextAware, EnvironmentAware { + + protected ApplicationContext applicationContext; + + protected ConfigurableEnvironment environment; + + private static boolean isSimpleType(Class type) { + return isPrimitiveOrWrapper(type) + || type == String.class + || type == BigDecimal.class + || type == BigInteger.class + || type == Date.class + || type == URL.class + || type == Class.class + ; + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + } + + @Override + public void setEnvironment(Environment environment) { + if (environment instanceof ConfigurableEnvironment) { + this.environment = (ConfigurableEnvironment) environment; + } + } + + protected Map resolveBeanMetadata(final Object bean) { + + final Map beanMetadata = new LinkedHashMap<>(); + + try { + + BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass()); + PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); + + for (PropertyDescriptor propertyDescriptor : propertyDescriptors) { + + Method readMethod = propertyDescriptor.getReadMethod(); + + if (readMethod != null && isSimpleType(propertyDescriptor.getPropertyType())) { + + String name = Introspector.decapitalize(propertyDescriptor.getName()); + Object value = readMethod.invoke(bean); + if (value != null) { + beanMetadata.put(name, value); + } + } + + } + + } catch (Exception e) { + throw new RuntimeException(e); + } + + return beanMetadata; + + } + + protected Map getServiceBeansMap() { + return beansOfTypeIncludingAncestors(applicationContext, ServiceBean.class); + } + + protected ReferenceAnnotationBeanPostProcessor getReferenceAnnotationBeanPostProcessor() { + return applicationContext.getBean(BEAN_NAME, ReferenceAnnotationBeanPostProcessor.class); + } + + protected Map getProtocolConfigsBeanMap() { + return beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class); + } + + +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/DubboConfigsMetadata.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/DubboConfigsMetadata.java index 081c2c1a72..5df03b403e 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/DubboConfigsMetadata.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/DubboConfigsMetadata.java @@ -1,87 +1,87 @@ -/* - * 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.spring.boot.actuate.endpoint.metadata; - -import org.apache.dubbo.config.AbstractConfig; -import org.apache.dubbo.config.ApplicationConfig; -import org.apache.dubbo.config.ConsumerConfig; -import org.apache.dubbo.config.MethodConfig; -import org.apache.dubbo.config.ModuleConfig; -import org.apache.dubbo.config.MonitorConfig; -import org.apache.dubbo.config.ProtocolConfig; -import org.apache.dubbo.config.ProviderConfig; -import org.apache.dubbo.config.ReferenceConfig; -import org.apache.dubbo.config.RegistryConfig; -import org.apache.dubbo.config.ServiceConfig; - -import org.springframework.stereotype.Component; - -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.TreeMap; - -import static org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors; - -/** - * Dubbo Configs Metadata - * - * @since 2.7.0 - */ -@Component -public class DubboConfigsMetadata extends AbstractDubboMetadata { - - public Map>> configs() { - - Map>> configsMap = new LinkedHashMap<>(); - - addDubboConfigBeans(ApplicationConfig.class, configsMap); - addDubboConfigBeans(ConsumerConfig.class, configsMap); - addDubboConfigBeans(MethodConfig.class, configsMap); - addDubboConfigBeans(ModuleConfig.class, configsMap); - addDubboConfigBeans(MonitorConfig.class, configsMap); - addDubboConfigBeans(ProtocolConfig.class, configsMap); - addDubboConfigBeans(ProviderConfig.class, configsMap); - addDubboConfigBeans(ReferenceConfig.class, configsMap); - addDubboConfigBeans(RegistryConfig.class, configsMap); - addDubboConfigBeans(ServiceConfig.class, configsMap); - - return configsMap; - - } - - private void addDubboConfigBeans(Class dubboConfigClass, - Map>> configsMap) { - - Map dubboConfigBeans = beansOfTypeIncludingAncestors(applicationContext, dubboConfigClass); - - String name = dubboConfigClass.getSimpleName(); - - Map> beansMetadata = new TreeMap<>(); - - for (Map.Entry entry : dubboConfigBeans.entrySet()) { - - String beanName = entry.getKey(); - AbstractConfig configBean = entry.getValue(); - Map configBeanMeta = resolveBeanMetadata(configBean); - beansMetadata.put(beanName, configBeanMeta); - - } - - configsMap.put(name, beansMetadata); - - } -} +/* + * 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.spring.boot.actuate.endpoint.metadata; + +import org.apache.dubbo.config.AbstractConfig; +import org.apache.dubbo.config.ApplicationConfig; +import org.apache.dubbo.config.ConsumerConfig; +import org.apache.dubbo.config.MethodConfig; +import org.apache.dubbo.config.ModuleConfig; +import org.apache.dubbo.config.MonitorConfig; +import org.apache.dubbo.config.ProtocolConfig; +import org.apache.dubbo.config.ProviderConfig; +import org.apache.dubbo.config.ReferenceConfig; +import org.apache.dubbo.config.RegistryConfig; +import org.apache.dubbo.config.ServiceConfig; + +import org.springframework.stereotype.Component; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.TreeMap; + +import static org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors; + +/** + * Dubbo Configs Metadata + * + * @since 2.7.0 + */ +@Component +public class DubboConfigsMetadata extends AbstractDubboMetadata { + + public Map>> configs() { + + Map>> configsMap = new LinkedHashMap<>(); + + addDubboConfigBeans(ApplicationConfig.class, configsMap); + addDubboConfigBeans(ConsumerConfig.class, configsMap); + addDubboConfigBeans(MethodConfig.class, configsMap); + addDubboConfigBeans(ModuleConfig.class, configsMap); + addDubboConfigBeans(MonitorConfig.class, configsMap); + addDubboConfigBeans(ProtocolConfig.class, configsMap); + addDubboConfigBeans(ProviderConfig.class, configsMap); + addDubboConfigBeans(ReferenceConfig.class, configsMap); + addDubboConfigBeans(RegistryConfig.class, configsMap); + addDubboConfigBeans(ServiceConfig.class, configsMap); + + return configsMap; + + } + + private void addDubboConfigBeans(Class dubboConfigClass, + Map>> configsMap) { + + Map dubboConfigBeans = beansOfTypeIncludingAncestors(applicationContext, dubboConfigClass); + + String name = dubboConfigClass.getSimpleName(); + + Map> beansMetadata = new TreeMap<>(); + + for (Map.Entry entry : dubboConfigBeans.entrySet()) { + + String beanName = entry.getKey(); + AbstractConfig configBean = entry.getValue(); + Map configBeanMeta = resolveBeanMetadata(configBean); + beansMetadata.put(beanName, configBeanMeta); + + } + + configsMap.put(name, beansMetadata); + + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/DubboMetadata.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/DubboMetadata.java index 9149ca7f9d..77093478a7 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/DubboMetadata.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/DubboMetadata.java @@ -1,62 +1,62 @@ -/* - * 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.spring.boot.actuate.endpoint.metadata; - -import org.apache.dubbo.common.Version; -import org.apache.dubbo.spring.boot.util.DubboUtils; - -import org.springframework.stereotype.Component; - -import java.util.LinkedHashMap; -import java.util.Map; - -import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_GITHUB_URL; -import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_MAILING_LIST; -import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_SPRING_BOOT_GITHUB_URL; -import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_SPRING_BOOT_GIT_URL; -import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_SPRING_BOOT_ISSUES_URL; - -/** - * Dubbo Metadata - * @since 2.7.0 - */ -@Component -public class DubboMetadata { - - public Map invoke() { - - Map metaData = new LinkedHashMap<>(); - - metaData.put("timestamp", System.currentTimeMillis()); - - Map versions = new LinkedHashMap<>(); - versions.put("dubbo-spring-boot", Version.getVersion(DubboUtils.class, "1.0.0")); - versions.put("dubbo", Version.getVersion()); - - Map urls = new LinkedHashMap<>(); - urls.put("dubbo", DUBBO_GITHUB_URL); - urls.put("mailing-list", DUBBO_MAILING_LIST); - urls.put("github", DUBBO_SPRING_BOOT_GITHUB_URL); - urls.put("issues", DUBBO_SPRING_BOOT_ISSUES_URL); - urls.put("git", DUBBO_SPRING_BOOT_GIT_URL); - - metaData.put("versions", versions); - metaData.put("urls", urls); - - return metaData; - } -} +/* + * 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.spring.boot.actuate.endpoint.metadata; + +import org.apache.dubbo.common.Version; +import org.apache.dubbo.spring.boot.util.DubboUtils; + +import org.springframework.stereotype.Component; + +import java.util.LinkedHashMap; +import java.util.Map; + +import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_GITHUB_URL; +import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_MAILING_LIST; +import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_SPRING_BOOT_GITHUB_URL; +import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_SPRING_BOOT_GIT_URL; +import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_SPRING_BOOT_ISSUES_URL; + +/** + * Dubbo Metadata + * @since 2.7.0 + */ +@Component +public class DubboMetadata { + + public Map invoke() { + + Map metaData = new LinkedHashMap<>(); + + metaData.put("timestamp", System.currentTimeMillis()); + + Map versions = new LinkedHashMap<>(); + versions.put("dubbo-spring-boot", Version.getVersion(DubboUtils.class, "1.0.0")); + versions.put("dubbo", Version.getVersion()); + + Map urls = new LinkedHashMap<>(); + urls.put("dubbo", DUBBO_GITHUB_URL); + urls.put("mailing-list", DUBBO_MAILING_LIST); + urls.put("github", DUBBO_SPRING_BOOT_GITHUB_URL); + urls.put("issues", DUBBO_SPRING_BOOT_ISSUES_URL); + urls.put("git", DUBBO_SPRING_BOOT_GIT_URL); + + metaData.put("versions", versions); + metaData.put("urls", urls); + + return metaData; + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/DubboPropertiesMetadata.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/DubboPropertiesMetadata.java index b4e1b028e5..5e3d4c4385 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/DubboPropertiesMetadata.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/DubboPropertiesMetadata.java @@ -1,36 +1,36 @@ -/* - * 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.spring.boot.actuate.endpoint.metadata; - -import org.springframework.stereotype.Component; - -import java.util.SortedMap; - -import static org.apache.dubbo.config.spring.util.EnvironmentUtils.filterDubboProperties; - -/** - * Dubbo Properties Metadata - * - * @since 2.7.0 - */ -@Component -public class DubboPropertiesMetadata extends AbstractDubboMetadata { - - public SortedMap properties() { - return (SortedMap) filterDubboProperties(environment); - } -} \ No newline at end of file +/* + * 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.spring.boot.actuate.endpoint.metadata; + +import org.springframework.stereotype.Component; + +import java.util.SortedMap; + +import static org.apache.dubbo.config.spring.util.EnvironmentUtils.filterDubboProperties; + +/** + * Dubbo Properties Metadata + * + * @since 2.7.0 + */ +@Component +public class DubboPropertiesMetadata extends AbstractDubboMetadata { + + public SortedMap properties() { + return (SortedMap) filterDubboProperties(environment); + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/DubboReferencesMetadata.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/DubboReferencesMetadata.java index 7a590b3bad..c3d8ffbdb1 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/DubboReferencesMetadata.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/DubboReferencesMetadata.java @@ -1,79 +1,79 @@ -/* - * 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.spring.boot.actuate.endpoint.metadata; - -import org.apache.dubbo.config.ReferenceConfig; -import org.apache.dubbo.config.annotation.DubboReference; -import org.apache.dubbo.config.spring.ReferenceBean; -import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor; - -import org.springframework.beans.factory.annotation.InjectionMetadata; -import org.springframework.stereotype.Component; - -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * {@link DubboReference} Metadata - * - * @since 2.7.0 - */ -@Component -public class DubboReferencesMetadata extends AbstractDubboMetadata { - - public Map> references() { - - Map> referencesMetadata = new LinkedHashMap<>(); - - ReferenceAnnotationBeanPostProcessor beanPostProcessor = getReferenceAnnotationBeanPostProcessor(); - - referencesMetadata.putAll(buildReferencesMetadata(beanPostProcessor.getInjectedFieldReferenceBeanMap())); - referencesMetadata.putAll(buildReferencesMetadata(beanPostProcessor.getInjectedMethodReferenceBeanMap())); - - return referencesMetadata; - - } - - private Map> buildReferencesMetadata( - Map> injectedElementReferenceBeanMap) { - Map> referencesMetadata = new LinkedHashMap<>(); - - for (Map.Entry> entry : - injectedElementReferenceBeanMap.entrySet()) { - - InjectionMetadata.InjectedElement injectedElement = entry.getKey(); - - ReferenceBean referenceBean = entry.getValue(); - ReferenceConfig referenceConfig = referenceBean.getReferenceConfig(); - - Map beanMetadata = null; - if (referenceConfig != null) { - beanMetadata = resolveBeanMetadata(referenceConfig); - //beanMetadata.put("invoker", resolveBeanMetadata(referenceBean.get())); - } else { - // referenceBean is not initialized - beanMetadata = new LinkedHashMap<>(); - } - - referencesMetadata.put(String.valueOf(injectedElement.getMember()), beanMetadata); - - } - - return referencesMetadata; - } - -} +/* + * 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.spring.boot.actuate.endpoint.metadata; + +import org.apache.dubbo.config.ReferenceConfig; +import org.apache.dubbo.config.annotation.DubboReference; +import org.apache.dubbo.config.spring.ReferenceBean; +import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor; + +import org.springframework.beans.factory.annotation.InjectionMetadata; +import org.springframework.stereotype.Component; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * {@link DubboReference} Metadata + * + * @since 2.7.0 + */ +@Component +public class DubboReferencesMetadata extends AbstractDubboMetadata { + + public Map> references() { + + Map> referencesMetadata = new LinkedHashMap<>(); + + ReferenceAnnotationBeanPostProcessor beanPostProcessor = getReferenceAnnotationBeanPostProcessor(); + + referencesMetadata.putAll(buildReferencesMetadata(beanPostProcessor.getInjectedFieldReferenceBeanMap())); + referencesMetadata.putAll(buildReferencesMetadata(beanPostProcessor.getInjectedMethodReferenceBeanMap())); + + return referencesMetadata; + + } + + private Map> buildReferencesMetadata( + Map> injectedElementReferenceBeanMap) { + Map> referencesMetadata = new LinkedHashMap<>(); + + for (Map.Entry> entry : + injectedElementReferenceBeanMap.entrySet()) { + + InjectionMetadata.InjectedElement injectedElement = entry.getKey(); + + ReferenceBean referenceBean = entry.getValue(); + ReferenceConfig referenceConfig = referenceBean.getReferenceConfig(); + + Map beanMetadata = null; + if (referenceConfig != null) { + beanMetadata = resolveBeanMetadata(referenceConfig); + //beanMetadata.put("invoker", resolveBeanMetadata(referenceBean.get())); + } else { + // referenceBean is not initialized + beanMetadata = new LinkedHashMap<>(); + } + + referencesMetadata.put(String.valueOf(injectedElement.getMember()), beanMetadata); + + } + + return referencesMetadata; + } + +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/DubboServicesMetadata.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/DubboServicesMetadata.java index 0053e2be39..11ce4d567a 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/DubboServicesMetadata.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/DubboServicesMetadata.java @@ -1,84 +1,84 @@ -/* - * 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.spring.boot.actuate.endpoint.metadata; - -import org.apache.dubbo.config.annotation.DubboService; -import org.apache.dubbo.config.spring.ServiceBean; - -import org.springframework.stereotype.Component; - -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * {@link DubboService} Metadata - * - * @since 2.7.0 - */ -@Component -public class DubboServicesMetadata extends AbstractDubboMetadata { - - public Map> services() { - - Map serviceBeansMap = getServiceBeansMap(); - - Map> servicesMetadata = new LinkedHashMap<>(serviceBeansMap.size()); - - for (Map.Entry entry : serviceBeansMap.entrySet()) { - - String serviceBeanName = entry.getKey(); - - ServiceBean serviceBean = entry.getValue(); - - Map serviceBeanMetadata = resolveBeanMetadata(serviceBean); - - Object service = resolveServiceBean(serviceBeanName, serviceBean); - - if (service != null) { - // Add Service implementation class - serviceBeanMetadata.put("serviceClass", service.getClass().getName()); - } - - servicesMetadata.put(serviceBeanName, serviceBeanMetadata); - - } - - return servicesMetadata; - - } - - private Object resolveServiceBean(String serviceBeanName, ServiceBean serviceBean) { - - int index = serviceBeanName.indexOf("#"); - - if (index > -1) { - - Class interfaceClass = serviceBean.getInterfaceClass(); - - String serviceName = serviceBeanName.substring(index + 1); - - if (applicationContext.containsBean(serviceName)) { - return applicationContext.getBean(serviceName, interfaceClass); - } - - } - - return null; - - } - -} +/* + * 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.spring.boot.actuate.endpoint.metadata; + +import org.apache.dubbo.config.annotation.DubboService; +import org.apache.dubbo.config.spring.ServiceBean; + +import org.springframework.stereotype.Component; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * {@link DubboService} Metadata + * + * @since 2.7.0 + */ +@Component +public class DubboServicesMetadata extends AbstractDubboMetadata { + + public Map> services() { + + Map serviceBeansMap = getServiceBeansMap(); + + Map> servicesMetadata = new LinkedHashMap<>(serviceBeansMap.size()); + + for (Map.Entry entry : serviceBeansMap.entrySet()) { + + String serviceBeanName = entry.getKey(); + + ServiceBean serviceBean = entry.getValue(); + + Map serviceBeanMetadata = resolveBeanMetadata(serviceBean); + + Object service = resolveServiceBean(serviceBeanName, serviceBean); + + if (service != null) { + // Add Service implementation class + serviceBeanMetadata.put("serviceClass", service.getClass().getName()); + } + + servicesMetadata.put(serviceBeanName, serviceBeanMetadata); + + } + + return servicesMetadata; + + } + + private Object resolveServiceBean(String serviceBeanName, ServiceBean serviceBean) { + + int index = serviceBeanName.indexOf("#"); + + if (index > -1) { + + Class interfaceClass = serviceBean.getInterfaceClass(); + + String serviceName = serviceBeanName.substring(index + 1); + + if (applicationContext.containsBean(serviceName)) { + return applicationContext.getBean(serviceName, interfaceClass); + } + + } + + return null; + + } + +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/DubboShutdownMetadata.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/DubboShutdownMetadata.java index e62b55b1bd..3bd6113ac5 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/DubboShutdownMetadata.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/DubboShutdownMetadata.java @@ -1,78 +1,78 @@ -/* - * 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.spring.boot.actuate.endpoint.metadata; - -import org.apache.dubbo.config.ReferenceConfigBase; -import org.apache.dubbo.config.spring.ServiceBean; -import org.apache.dubbo.rpc.model.ApplicationModel; - -import org.springframework.stereotype.Component; - -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.TreeMap; - -import static org.apache.dubbo.registry.support.AbstractRegistryFactory.getRegistries; - -/** - * Dubbo Shutdown - * - * @since 2.7.0 - */ -@Component -public class DubboShutdownMetadata extends AbstractDubboMetadata { - - - public Map shutdown() throws Exception { - - Map shutdownCountData = new LinkedHashMap<>(); - - // registries - int registriesCount = getRegistries().size(); - - // protocols - int protocolsCount = getProtocolConfigsBeanMap().size(); - - shutdownCountData.put("registries", registriesCount); - shutdownCountData.put("protocols", protocolsCount); - - // Service Beans - Map serviceBeansMap = getServiceBeansMap(); - if (!serviceBeansMap.isEmpty()) { - for (ServiceBean serviceBean : serviceBeansMap.values()) { - serviceBean.destroy(); - } - } - shutdownCountData.put("services", serviceBeansMap.size()); - - // Reference Beans - Collection> references = ApplicationModel.getConfigManager().getReferences(); - for (ReferenceConfigBase reference : references) { - reference.destroy(); - } - shutdownCountData.put("references", references.size()); - - // Set Result to complete - Map shutdownData = new TreeMap<>(); - shutdownData.put("shutdown.count", shutdownCountData); - - - return shutdownData; - } - -} +/* + * 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.spring.boot.actuate.endpoint.metadata; + +import org.apache.dubbo.config.ReferenceConfigBase; +import org.apache.dubbo.config.spring.ServiceBean; +import org.apache.dubbo.rpc.model.ApplicationModel; + +import org.springframework.stereotype.Component; + +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.TreeMap; + +import static org.apache.dubbo.registry.support.AbstractRegistryFactory.getRegistries; + +/** + * Dubbo Shutdown + * + * @since 2.7.0 + */ +@Component +public class DubboShutdownMetadata extends AbstractDubboMetadata { + + + public Map shutdown() throws Exception { + + Map shutdownCountData = new LinkedHashMap<>(); + + // registries + int registriesCount = getRegistries().size(); + + // protocols + int protocolsCount = getProtocolConfigsBeanMap().size(); + + shutdownCountData.put("registries", registriesCount); + shutdownCountData.put("protocols", protocolsCount); + + // Service Beans + Map serviceBeansMap = getServiceBeansMap(); + if (!serviceBeansMap.isEmpty()) { + for (ServiceBean serviceBean : serviceBeansMap.values()) { + serviceBean.destroy(); + } + } + shutdownCountData.put("services", serviceBeansMap.size()); + + // Reference Beans + Collection> references = ApplicationModel.getConfigManager().getReferences(); + for (ReferenceConfigBase reference : references) { + reference.destroy(); + } + shutdownCountData.put("references", references.size()); + + // Set Result to complete + Map shutdownData = new TreeMap<>(); + shutdownData.put("shutdown.count", shutdownCountData); + + + return shutdownData; + } + +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/mvc/DubboMvcEndpoint.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/mvc/DubboMvcEndpoint.java index ac3bd1e7cf..965de4d255 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/mvc/DubboMvcEndpoint.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/mvc/DubboMvcEndpoint.java @@ -1,112 +1,112 @@ -/* - * 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.spring.boot.actuate.endpoint.mvc; - -import org.apache.dubbo.spring.boot.actuate.endpoint.DubboEndpoint; -import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboConfigsMetadata; -import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboPropertiesMetadata; -import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboReferencesMetadata; -import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboServicesMetadata; -import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboShutdownMetadata; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter; -import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint; -import org.springframework.http.MediaType; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.context.request.async.DeferredResult; - -import java.util.Map; -import java.util.SortedMap; - -/** - * {@link MvcEndpoint} to expose Dubbo Metadata - * - * @see MvcEndpoint - * @since 2.7.0 - */ -public class DubboMvcEndpoint extends EndpointMvcAdapter { - - public static final String DUBBO_SHUTDOWN_ENDPOINT_URI = "/shutdown"; - - public static final String DUBBO_CONFIGS_ENDPOINT_URI = "/configs"; - - public static final String DUBBO_SERVICES_ENDPOINT_URI = "/services"; - - public static final String DUBBO_REFERENCES_ENDPOINT_URI = "/references"; - - public static final String DUBBO_PROPERTIES_ENDPOINT_URI = "/properties"; - - private final Logger logger = LoggerFactory.getLogger(getClass()); - - @Autowired - private DubboShutdownMetadata dubboShutdownMetadata; - - @Autowired - private DubboConfigsMetadata dubboConfigsMetadata; - - @Autowired - private DubboServicesMetadata dubboServicesMetadata; - - @Autowired - private DubboReferencesMetadata dubboReferencesMetadata; - - @Autowired - private DubboPropertiesMetadata dubboPropertiesMetadata; - - public DubboMvcEndpoint(DubboEndpoint dubboEndpoint) { - super(dubboEndpoint); - } - - - @RequestMapping(value = DUBBO_SHUTDOWN_ENDPOINT_URI, method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) - @ResponseBody - public DeferredResult shutdown() throws Exception { - Map shutdownCountData = dubboShutdownMetadata.shutdown(); - return new DeferredResult(null, shutdownCountData); - } - - @RequestMapping(value = DUBBO_CONFIGS_ENDPOINT_URI, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - @ResponseBody - public Map>> configs() { - return dubboConfigsMetadata.configs(); - } - - - @RequestMapping(value = DUBBO_SERVICES_ENDPOINT_URI, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - @ResponseBody - public Map> services() { - return dubboServicesMetadata.services(); - } - - @RequestMapping(value = DUBBO_REFERENCES_ENDPOINT_URI, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - @ResponseBody - public Map> references() { - return dubboReferencesMetadata.references(); - } - - @RequestMapping(value = DUBBO_PROPERTIES_ENDPOINT_URI, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - @ResponseBody - public SortedMap properties() { - return dubboPropertiesMetadata.properties(); - - } -} +/* + * 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.spring.boot.actuate.endpoint.mvc; + +import org.apache.dubbo.spring.boot.actuate.endpoint.DubboEndpoint; +import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboConfigsMetadata; +import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboPropertiesMetadata; +import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboReferencesMetadata; +import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboServicesMetadata; +import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboShutdownMetadata; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter; +import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.context.request.async.DeferredResult; + +import java.util.Map; +import java.util.SortedMap; + +/** + * {@link MvcEndpoint} to expose Dubbo Metadata + * + * @see MvcEndpoint + * @since 2.7.0 + */ +public class DubboMvcEndpoint extends EndpointMvcAdapter { + + public static final String DUBBO_SHUTDOWN_ENDPOINT_URI = "/shutdown"; + + public static final String DUBBO_CONFIGS_ENDPOINT_URI = "/configs"; + + public static final String DUBBO_SERVICES_ENDPOINT_URI = "/services"; + + public static final String DUBBO_REFERENCES_ENDPOINT_URI = "/references"; + + public static final String DUBBO_PROPERTIES_ENDPOINT_URI = "/properties"; + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + @Autowired + private DubboShutdownMetadata dubboShutdownMetadata; + + @Autowired + private DubboConfigsMetadata dubboConfigsMetadata; + + @Autowired + private DubboServicesMetadata dubboServicesMetadata; + + @Autowired + private DubboReferencesMetadata dubboReferencesMetadata; + + @Autowired + private DubboPropertiesMetadata dubboPropertiesMetadata; + + public DubboMvcEndpoint(DubboEndpoint dubboEndpoint) { + super(dubboEndpoint); + } + + + @RequestMapping(value = DUBBO_SHUTDOWN_ENDPOINT_URI, method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseBody + public DeferredResult shutdown() throws Exception { + Map shutdownCountData = dubboShutdownMetadata.shutdown(); + return new DeferredResult(null, shutdownCountData); + } + + @RequestMapping(value = DUBBO_CONFIGS_ENDPOINT_URI, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseBody + public Map>> configs() { + return dubboConfigsMetadata.configs(); + } + + + @RequestMapping(value = DUBBO_SERVICES_ENDPOINT_URI, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseBody + public Map> services() { + return dubboServicesMetadata.services(); + } + + @RequestMapping(value = DUBBO_REFERENCES_ENDPOINT_URI, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseBody + public Map> references() { + return dubboReferencesMetadata.references(); + } + + @RequestMapping(value = DUBBO_PROPERTIES_ENDPOINT_URI, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseBody + public SortedMap properties() { + return dubboPropertiesMetadata.properties(); + + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/health/DubboHealthIndicator.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/health/DubboHealthIndicator.java index 94bf12288f..e653513006 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/health/DubboHealthIndicator.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/health/DubboHealthIndicator.java @@ -1,223 +1,223 @@ -/* - * 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.spring.boot.actuate.health; - -import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.common.status.StatusChecker; -import org.apache.dubbo.config.ProtocolConfig; -import org.apache.dubbo.config.ProviderConfig; - -import org.apache.dubbo.config.context.ConfigManager; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.actuate.health.AbstractHealthIndicator; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.HealthIndicator; -import org.springframework.util.StringUtils; - -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Set; - -import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader; - -/** - * Dubbo {@link HealthIndicator} - * - * @see HealthIndicator - * @since 2.7.0 - */ -public class DubboHealthIndicator extends AbstractHealthIndicator { - - @Autowired - private DubboHealthIndicatorProperties dubboHealthIndicatorProperties; - - //@Autowired(required = false) - private Map protocolConfigs = Collections.emptyMap(); - - //@Autowired(required = false) - private Map providerConfigs = Collections.emptyMap(); - - @Autowired - private ConfigManager configManager; - - @Override - protected void doHealthCheck(Health.Builder builder) throws Exception { - - ExtensionLoader extensionLoader = getExtensionLoader(StatusChecker.class); - - Map statusCheckerNamesMap = resolveStatusCheckerNamesMap(); - - boolean hasError = false; - - boolean hasUnknown = false; - - // Up first - builder.up(); - - for (Map.Entry entry : statusCheckerNamesMap.entrySet()) { - - String statusCheckerName = entry.getKey(); - - String source = entry.getValue(); - - StatusChecker checker = extensionLoader.getExtension(statusCheckerName); - - org.apache.dubbo.common.status.Status status = checker.check(); - - org.apache.dubbo.common.status.Status.Level level = status.getLevel(); - - if (!hasError && level.equals(org.apache.dubbo.common.status.Status.Level.ERROR)) { - hasError = true; - builder.down(); - } - - if (!hasError && !hasUnknown && level.equals(org.apache.dubbo.common.status.Status.Level.UNKNOWN)) { - hasUnknown = true; - builder.unknown(); - } - - Map detail = new LinkedHashMap<>(); - - detail.put("source", source); - detail.put("status", status); - - builder.withDetail(statusCheckerName, detail); - - } - - - } - - /** - * Resolves the map of {@link StatusChecker}'s name and its' source. - * - * @return non-null {@link Map} - */ - protected Map resolveStatusCheckerNamesMap() { - - Map statusCheckerNamesMap = new LinkedHashMap<>(); - - statusCheckerNamesMap.putAll(resolveStatusCheckerNamesMapFromDubboHealthIndicatorProperties()); - - statusCheckerNamesMap.putAll(resolveStatusCheckerNamesMapFromProtocolConfigs()); - - statusCheckerNamesMap.putAll(resolveStatusCheckerNamesMapFromProviderConfig()); - - return statusCheckerNamesMap; - - } - - private Map resolveStatusCheckerNamesMapFromDubboHealthIndicatorProperties() { - - DubboHealthIndicatorProperties.Status status = - dubboHealthIndicatorProperties.getStatus(); - - Map statusCheckerNamesMap = new LinkedHashMap<>(); - - for (String statusName : status.getDefaults()) { - - statusCheckerNamesMap.put(statusName, DubboHealthIndicatorProperties.PREFIX + ".status.defaults"); - - } - - for (String statusName : status.getExtras()) { - - statusCheckerNamesMap.put(statusName, DubboHealthIndicatorProperties.PREFIX + ".status.extras"); - - } - - return statusCheckerNamesMap; - - } - - - private Map resolveStatusCheckerNamesMapFromProtocolConfigs() { - - if (protocolConfigs.isEmpty()) { - protocolConfigs = configManager.getConfigsMap(ProtocolConfig.class); - } - - Map statusCheckerNamesMap = new LinkedHashMap<>(); - - for (Map.Entry entry : protocolConfigs.entrySet()) { - - String beanName = entry.getKey(); - - ProtocolConfig protocolConfig = entry.getValue(); - - Set statusCheckerNames = getStatusCheckerNames(protocolConfig); - - for (String statusCheckerName : statusCheckerNames) { - - String source = buildSource(beanName, protocolConfig); - - statusCheckerNamesMap.put(statusCheckerName, source); - - } - - } - - return statusCheckerNamesMap; - - } - - private Map resolveStatusCheckerNamesMapFromProviderConfig() { - - if (providerConfigs.isEmpty()) { - providerConfigs = configManager.getConfigsMap(ProviderConfig.class); - } - - Map statusCheckerNamesMap = new LinkedHashMap<>(); - - for (Map.Entry entry : providerConfigs.entrySet()) { - - String beanName = entry.getKey(); - - ProviderConfig providerConfig = entry.getValue(); - - Set statusCheckerNames = getStatusCheckerNames(providerConfig); - - for (String statusCheckerName : statusCheckerNames) { - - String source = buildSource(beanName, providerConfig); - - statusCheckerNamesMap.put(statusCheckerName, source); - - } - - } - - return statusCheckerNamesMap; - - } - - private Set getStatusCheckerNames(ProtocolConfig protocolConfig) { - String status = protocolConfig.getStatus(); - return StringUtils.commaDelimitedListToSet(status); - } - - private Set getStatusCheckerNames(ProviderConfig providerConfig) { - String status = providerConfig.getStatus(); - return StringUtils.commaDelimitedListToSet(status); - } - - private String buildSource(String beanName, Object bean) { - return beanName + "@" + bean.getClass().getSimpleName() + ".getStatus()"; - } - -} +/* + * 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.spring.boot.actuate.health; + +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.common.status.StatusChecker; +import org.apache.dubbo.config.ProtocolConfig; +import org.apache.dubbo.config.ProviderConfig; +import org.apache.dubbo.config.context.ConfigManager; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.health.AbstractHealthIndicator; +import org.springframework.boot.actuate.health.Health; +import org.springframework.boot.actuate.health.HealthIndicator; +import org.springframework.util.StringUtils; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader; + +/** + * Dubbo {@link HealthIndicator} + * + * @see HealthIndicator + * @since 2.7.0 + */ +public class DubboHealthIndicator extends AbstractHealthIndicator { + + @Autowired + private DubboHealthIndicatorProperties dubboHealthIndicatorProperties; + + //@Autowired(required = false) + private Map protocolConfigs = Collections.emptyMap(); + + //@Autowired(required = false) + private Map providerConfigs = Collections.emptyMap(); + + @Autowired + private ConfigManager configManager; + + @Override + protected void doHealthCheck(Health.Builder builder) throws Exception { + + ExtensionLoader extensionLoader = getExtensionLoader(StatusChecker.class); + + Map statusCheckerNamesMap = resolveStatusCheckerNamesMap(); + + boolean hasError = false; + + boolean hasUnknown = false; + + // Up first + builder.up(); + + for (Map.Entry entry : statusCheckerNamesMap.entrySet()) { + + String statusCheckerName = entry.getKey(); + + String source = entry.getValue(); + + StatusChecker checker = extensionLoader.getExtension(statusCheckerName); + + org.apache.dubbo.common.status.Status status = checker.check(); + + org.apache.dubbo.common.status.Status.Level level = status.getLevel(); + + if (!hasError && level.equals(org.apache.dubbo.common.status.Status.Level.ERROR)) { + hasError = true; + builder.down(); + } + + if (!hasError && !hasUnknown && level.equals(org.apache.dubbo.common.status.Status.Level.UNKNOWN)) { + hasUnknown = true; + builder.unknown(); + } + + Map detail = new LinkedHashMap<>(); + + detail.put("source", source); + detail.put("status", status); + + builder.withDetail(statusCheckerName, detail); + + } + + + } + + /** + * Resolves the map of {@link StatusChecker}'s name and its' source. + * + * @return non-null {@link Map} + */ + protected Map resolveStatusCheckerNamesMap() { + + Map statusCheckerNamesMap = new LinkedHashMap<>(); + + statusCheckerNamesMap.putAll(resolveStatusCheckerNamesMapFromDubboHealthIndicatorProperties()); + + statusCheckerNamesMap.putAll(resolveStatusCheckerNamesMapFromProtocolConfigs()); + + statusCheckerNamesMap.putAll(resolveStatusCheckerNamesMapFromProviderConfig()); + + return statusCheckerNamesMap; + + } + + private Map resolveStatusCheckerNamesMapFromDubboHealthIndicatorProperties() { + + DubboHealthIndicatorProperties.Status status = + dubboHealthIndicatorProperties.getStatus(); + + Map statusCheckerNamesMap = new LinkedHashMap<>(); + + for (String statusName : status.getDefaults()) { + + statusCheckerNamesMap.put(statusName, DubboHealthIndicatorProperties.PREFIX + ".status.defaults"); + + } + + for (String statusName : status.getExtras()) { + + statusCheckerNamesMap.put(statusName, DubboHealthIndicatorProperties.PREFIX + ".status.extras"); + + } + + return statusCheckerNamesMap; + + } + + + private Map resolveStatusCheckerNamesMapFromProtocolConfigs() { + + if (protocolConfigs.isEmpty()) { + protocolConfigs = configManager.getConfigsMap(ProtocolConfig.class); + } + + Map statusCheckerNamesMap = new LinkedHashMap<>(); + + for (Map.Entry entry : protocolConfigs.entrySet()) { + + String beanName = entry.getKey(); + + ProtocolConfig protocolConfig = entry.getValue(); + + Set statusCheckerNames = getStatusCheckerNames(protocolConfig); + + for (String statusCheckerName : statusCheckerNames) { + + String source = buildSource(beanName, protocolConfig); + + statusCheckerNamesMap.put(statusCheckerName, source); + + } + + } + + return statusCheckerNamesMap; + + } + + private Map resolveStatusCheckerNamesMapFromProviderConfig() { + + if (providerConfigs.isEmpty()) { + providerConfigs = configManager.getConfigsMap(ProviderConfig.class); + } + + Map statusCheckerNamesMap = new LinkedHashMap<>(); + + for (Map.Entry entry : providerConfigs.entrySet()) { + + String beanName = entry.getKey(); + + ProviderConfig providerConfig = entry.getValue(); + + Set statusCheckerNames = getStatusCheckerNames(providerConfig); + + for (String statusCheckerName : statusCheckerNames) { + + String source = buildSource(beanName, providerConfig); + + statusCheckerNamesMap.put(statusCheckerName, source); + + } + + } + + return statusCheckerNamesMap; + + } + + private Set getStatusCheckerNames(ProtocolConfig protocolConfig) { + String status = protocolConfig.getStatus(); + return StringUtils.commaDelimitedListToSet(status); + } + + private Set getStatusCheckerNames(ProviderConfig providerConfig) { + String status = providerConfig.getStatus(); + return StringUtils.commaDelimitedListToSet(status); + } + + private String buildSource(String beanName, Object bean) { + return beanName + "@" + bean.getClass().getSimpleName() + ".getStatus()"; + } + +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/health/DubboHealthIndicatorProperties.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/health/DubboHealthIndicatorProperties.java index 7ce20659e6..0bc1082ed7 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/health/DubboHealthIndicatorProperties.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/health/DubboHealthIndicatorProperties.java @@ -1,99 +1,99 @@ -/* - * 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.spring.boot.actuate.health; - -import org.apache.dubbo.common.status.StatusChecker; - -import org.springframework.boot.actuate.health.HealthIndicator; -import org.springframework.boot.context.properties.ConfigurationProperties; - -import java.util.Arrays; -import java.util.LinkedHashSet; -import java.util.Set; - -import static org.apache.dubbo.spring.boot.actuate.health.DubboHealthIndicatorProperties.PREFIX; - -/** - * Dubbo {@link HealthIndicator} Properties - * - * @see HealthIndicator - * @since 2.7.0 - */ -@ConfigurationProperties(prefix = PREFIX, ignoreUnknownFields = false) -public class DubboHealthIndicatorProperties { - - /** - * The prefix of {@link DubboHealthIndicatorProperties} - */ - public static final String PREFIX = "management.health.dubbo"; - - private Status status = new Status(); - - public Status getStatus() { - return status; - } - - public void setStatus(Status status) { - this.status = status; - } - - /** - * The nested class for {@link StatusChecker}'s names - *
-     * registry= org.apache.dubbo.registry.status.RegistryStatusChecker
-     * spring= org.apache.dubbo.config.spring.status.SpringStatusChecker
-     * datasource= org.apache.dubbo.config.spring.status.DataSourceStatusChecker
-     * memory= org.apache.dubbo.common.status.support.MemoryStatusChecker
-     * load= org.apache.dubbo.common.status.support.LoadStatusChecker
-     * server= org.apache.dubbo.rpc.protocol.dubbo.status.ServerStatusChecker
-     * threadpool= org.apache.dubbo.rpc.protocol.dubbo.status.ThreadPoolStatusChecker
-     * 
- * - * @see StatusChecker - */ - public static class Status { - - /** - * The defaults names of {@link StatusChecker} - *

- * The defaults : "memory", "load" - */ - private Set defaults = new LinkedHashSet<>(Arrays.asList("memory", "load")); - - /** - * The extra names of {@link StatusChecker} - */ - private Set extras = new LinkedHashSet<>(); - - public Set getDefaults() { - return defaults; - } - - public void setDefaults(Set defaults) { - this.defaults = defaults; - } - - public Set getExtras() { - return extras; - } - - public void setExtras(Set extras) { - this.extras = extras; - } - } - -} +/* + * 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.spring.boot.actuate.health; + +import org.apache.dubbo.common.status.StatusChecker; + +import org.springframework.boot.actuate.health.HealthIndicator; +import org.springframework.boot.context.properties.ConfigurationProperties; + +import java.util.Arrays; +import java.util.LinkedHashSet; +import java.util.Set; + +import static org.apache.dubbo.spring.boot.actuate.health.DubboHealthIndicatorProperties.PREFIX; + +/** + * Dubbo {@link HealthIndicator} Properties + * + * @see HealthIndicator + * @since 2.7.0 + */ +@ConfigurationProperties(prefix = PREFIX, ignoreUnknownFields = false) +public class DubboHealthIndicatorProperties { + + /** + * The prefix of {@link DubboHealthIndicatorProperties} + */ + public static final String PREFIX = "management.health.dubbo"; + + private Status status = new Status(); + + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } + + /** + * The nested class for {@link StatusChecker}'s names + *

+     * registry= org.apache.dubbo.registry.status.RegistryStatusChecker
+     * spring= org.apache.dubbo.config.spring.status.SpringStatusChecker
+     * datasource= org.apache.dubbo.config.spring.status.DataSourceStatusChecker
+     * memory= org.apache.dubbo.common.status.support.MemoryStatusChecker
+     * load= org.apache.dubbo.common.status.support.LoadStatusChecker
+     * server= org.apache.dubbo.rpc.protocol.dubbo.status.ServerStatusChecker
+     * threadpool= org.apache.dubbo.rpc.protocol.dubbo.status.ThreadPoolStatusChecker
+     * 
+ * + * @see StatusChecker + */ + public static class Status { + + /** + * The defaults names of {@link StatusChecker} + *

+ * The defaults : "memory", "load" + */ + private Set defaults = new LinkedHashSet<>(Arrays.asList("memory", "load")); + + /** + * The extra names of {@link StatusChecker} + */ + private Set extras = new LinkedHashSet<>(); + + public Set getDefaults() { + return defaults; + } + + public void setDefaults(Set defaults) { + this.defaults = defaults; + } + + public Set getExtras() { + return extras; + } + + public void setExtras(Set extras) { + this.extras = extras; + } + } + +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/resources/META-INF/spring.factories b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/resources/META-INF/spring.factories index db1b811c3e..bea4633af2 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/resources/META-INF/spring.factories +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/resources/META-INF/spring.factories @@ -1,6 +1,6 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -org.apache.dubbo.spring.boot.actuate.autoconfigure.DubboEndpointAutoConfiguration,\ -org.apache.dubbo.spring.boot.actuate.autoconfigure.DubboHealthIndicatorAutoConfiguration,\ -org.apache.dubbo.spring.boot.actuate.autoconfigure.DubboEndpointMetadataAutoConfiguration -org.springframework.boot.actuate.autoconfigure.ManagementContextConfiguration=\ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ +org.apache.dubbo.spring.boot.actuate.autoconfigure.DubboEndpointAutoConfiguration,\ +org.apache.dubbo.spring.boot.actuate.autoconfigure.DubboHealthIndicatorAutoConfiguration,\ +org.apache.dubbo.spring.boot.actuate.autoconfigure.DubboEndpointMetadataAutoConfiguration +org.springframework.boot.actuate.autoconfigure.ManagementContextConfiguration=\ org.apache.dubbo.spring.boot.actuate.autoconfigure.DubboMvcEndpointManagementContextConfiguration \ No newline at end of file diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/test/java/org/apache/dubbo/spring/boot/actuate/autoconfigure/DubboEndpointAutoConfigurationTest.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/test/java/org/apache/dubbo/spring/boot/actuate/autoconfigure/DubboEndpointAutoConfigurationTest.java index f383bc09b2..c4d62da487 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/test/java/org/apache/dubbo/spring/boot/actuate/autoconfigure/DubboEndpointAutoConfigurationTest.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/test/java/org/apache/dubbo/spring/boot/actuate/autoconfigure/DubboEndpointAutoConfigurationTest.java @@ -1,238 +1,238 @@ -/* - * 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.spring.boot.actuate.autoconfigure; - -import org.apache.dubbo.config.annotation.DubboService; -import org.apache.dubbo.spring.boot.actuate.endpoint.DubboEndpoint; -import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboConfigsMetadata; -import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboPropertiesMetadata; -import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboReferencesMetadata; -import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboServicesMetadata; -import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboShutdownMetadata; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Assert; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.web.client.RestTemplate; - -import java.util.Map; -import java.util.SortedMap; -import java.util.function.Supplier; - -/** - * {@link DubboEndpointAutoConfiguration} Test - * - * @since 2.7.0 - */ -@RunWith(SpringRunner.class) -@SpringBootTest( - classes = { - DubboEndpointAutoConfiguration.class, - DubboEndpointAutoConfigurationTest.class - }, - webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - properties = { - "dubbo.service.version = 1.0.0", - "dubbo.application.id = my-application", - "dubbo.application.name = dubbo-demo-application", - "dubbo.module.id = my-module", - "dubbo.module.name = dubbo-demo-module", - "dubbo.registry.id = my-registry", - "dubbo.registry.address = N/A", - "dubbo.protocol.id=my-protocol", - "dubbo.protocol.name=dubbo", - "dubbo.protocol.port=20880", - "dubbo.provider.id=my-provider", - "dubbo.provider.host=127.0.0.1", - "dubbo.scan.basePackages=org.apache.dubbo.spring.boot.actuate.autoconfigure", - "endpoints.enabled = true", - "management.security.enabled = false", - "management.contextPath = /actuator", - "endpoints.dubbo.enabled = true", - "endpoints.dubbo.sensitive = false", - "endpoints.dubboshutdown.enabled = true", - "endpoints.dubboconfigs.enabled = true", - "endpoints.dubboservices.enabled = true", - "endpoints.dubboreferences.enabled = true", - "endpoints.dubboproperties.enabled = true", - }) -@EnableAutoConfiguration -@Ignore -public class DubboEndpointAutoConfigurationTest { - - @Autowired - private DubboEndpoint dubboEndpoint; - - @Autowired - private DubboConfigsMetadata dubboConfigsMetadata; - - @Autowired - private DubboPropertiesMetadata dubboProperties; - - @Autowired - private DubboReferencesMetadata dubboReferencesMetadata; - - @Autowired - private DubboServicesMetadata dubboServicesMetadata; - - @Autowired - private DubboShutdownMetadata dubboShutdownMetadata; - - private RestTemplate restTemplate = new RestTemplate(); - - @Autowired - private ObjectMapper objectMapper; - - @Value("http://127.0.0.1:${local.management.port}${management.contextPath:}") - private String actuatorBaseURL; - - @Test - public void testShutdown() throws Exception { - - Map value = dubboShutdownMetadata.shutdown(); - - Map shutdownCounts = (Map) value.get("shutdown.count"); - - Assert.assertEquals(0, shutdownCounts.get("registries")); - Assert.assertEquals(1, shutdownCounts.get("protocols")); - Assert.assertEquals(1, shutdownCounts.get("services")); - Assert.assertEquals(0, shutdownCounts.get("references")); - - } - - @Test - public void testConfigs() { - - Map>> configsMap = dubboConfigsMetadata.configs(); - - Map> beansMetadata = configsMap.get("ApplicationConfig"); - Assert.assertEquals("dubbo-demo-application", beansMetadata.get("my-application").get("name")); - - beansMetadata = configsMap.get("ConsumerConfig"); - Assert.assertTrue(beansMetadata.isEmpty()); - - beansMetadata = configsMap.get("MethodConfig"); - Assert.assertTrue(beansMetadata.isEmpty()); - - beansMetadata = configsMap.get("ModuleConfig"); - Assert.assertEquals("dubbo-demo-module", beansMetadata.get("my-module").get("name")); - - beansMetadata = configsMap.get("MonitorConfig"); - Assert.assertTrue(beansMetadata.isEmpty()); - - beansMetadata = configsMap.get("ProtocolConfig"); - Assert.assertEquals("dubbo", beansMetadata.get("my-protocol").get("name")); - - beansMetadata = configsMap.get("ProviderConfig"); - Assert.assertEquals("127.0.0.1", beansMetadata.get("my-provider").get("host")); - - beansMetadata = configsMap.get("ReferenceConfig"); - Assert.assertTrue(beansMetadata.isEmpty()); - - beansMetadata = configsMap.get("RegistryConfig"); - Assert.assertEquals("N/A", beansMetadata.get("my-registry").get("address")); - - beansMetadata = configsMap.get("ServiceConfig"); - Assert.assertFalse(beansMetadata.isEmpty()); - - } - - @Test - public void testServices() { - - Map> services = dubboServicesMetadata.services(); - - Assert.assertEquals(1, services.size()); - - Map demoServiceMeta = services.get("ServiceBean:org.apache.dubbo.spring.boot.actuate.autoconfigure.DubboEndpointAutoConfigurationTest$DemoService:1.0.0"); - - Assert.assertEquals("1.0.0", demoServiceMeta.get("version")); - - } - - @Test - public void testReferences() { - - Map> references = dubboReferencesMetadata.references(); - - Assert.assertTrue(references.isEmpty()); - - } - - @Test - public void testProperties() { - - SortedMap properties = dubboProperties.properties(); - - Assert.assertEquals("my-application", properties.get("dubbo.application.id")); - Assert.assertEquals("dubbo-demo-application", properties.get("dubbo.application.name")); - Assert.assertEquals("my-module", properties.get("dubbo.module.id")); - Assert.assertEquals("dubbo-demo-module", properties.get("dubbo.module.name")); - Assert.assertEquals("my-registry", properties.get("dubbo.registry.id")); - Assert.assertEquals("N/A", properties.get("dubbo.registry.address")); - Assert.assertEquals("my-protocol", properties.get("dubbo.protocol.id")); - Assert.assertEquals("dubbo", properties.get("dubbo.protocol.name")); - Assert.assertEquals("20880", properties.get("dubbo.protocol.port")); - Assert.assertEquals("my-provider", properties.get("dubbo.provider.id")); - Assert.assertEquals("127.0.0.1", properties.get("dubbo.provider.host")); - Assert.assertEquals("org.apache.dubbo.spring.boot.actuate.autoconfigure", properties.get("dubbo.scan.basePackages")); - } - - @Test - public void testHttpEndpoints() throws JsonProcessingException { -// testHttpEndpoint("/dubbo", dubboEndpoint::invoke); - testHttpEndpoint("/dubbo/configs", dubboConfigsMetadata::configs); - testHttpEndpoint("/dubbo/services", dubboServicesMetadata::services); - testHttpEndpoint("/dubbo/references", dubboReferencesMetadata::references); - testHttpEndpoint("/dubbo/properties", dubboProperties::properties); - } - - private void testHttpEndpoint(String actuatorURI, Supplier resultsSupplier) throws JsonProcessingException { - String actuatorURL = actuatorBaseURL + actuatorURI; - String response = restTemplate.getForObject(actuatorURL, String.class); - Assert.assertEquals(objectMapper.writeValueAsString(resultsSupplier.get()), response); - } - - - interface DemoService { - String sayHello(String name); - } - - @DubboService( - version = "${dubbo.service.version}", - application = "${dubbo.application.id}", - protocol = "${dubbo.protocol.id}", - registry = "${dubbo.registry.id}" - ) - static class DefaultDemoService implements DemoService { - - public String sayHello(String name) { - return "Hello, " + name + " (from Spring Boot)"; - } - - } - - -} +/* + * 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.spring.boot.actuate.autoconfigure; + +import org.apache.dubbo.config.annotation.DubboService; +import org.apache.dubbo.spring.boot.actuate.endpoint.DubboEndpoint; +import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboConfigsMetadata; +import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboPropertiesMetadata; +import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboReferencesMetadata; +import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboServicesMetadata; +import org.apache.dubbo.spring.boot.actuate.endpoint.metadata.DubboShutdownMetadata; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.web.client.RestTemplate; + +import java.util.Map; +import java.util.SortedMap; +import java.util.function.Supplier; + +/** + * {@link DubboEndpointAutoConfiguration} Test + * + * @since 2.7.0 + */ +@RunWith(SpringRunner.class) +@SpringBootTest( + classes = { + DubboEndpointAutoConfiguration.class, + DubboEndpointAutoConfigurationTest.class + }, + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + properties = { + "dubbo.service.version = 1.0.0", + "dubbo.application.id = my-application", + "dubbo.application.name = dubbo-demo-application", + "dubbo.module.id = my-module", + "dubbo.module.name = dubbo-demo-module", + "dubbo.registry.id = my-registry", + "dubbo.registry.address = N/A", + "dubbo.protocol.id=my-protocol", + "dubbo.protocol.name=dubbo", + "dubbo.protocol.port=20880", + "dubbo.provider.id=my-provider", + "dubbo.provider.host=127.0.0.1", + "dubbo.scan.basePackages=org.apache.dubbo.spring.boot.actuate.autoconfigure", + "endpoints.enabled = true", + "management.security.enabled = false", + "management.contextPath = /actuator", + "endpoints.dubbo.enabled = true", + "endpoints.dubbo.sensitive = false", + "endpoints.dubboshutdown.enabled = true", + "endpoints.dubboconfigs.enabled = true", + "endpoints.dubboservices.enabled = true", + "endpoints.dubboreferences.enabled = true", + "endpoints.dubboproperties.enabled = true", + }) +@EnableAutoConfiguration +@Ignore +public class DubboEndpointAutoConfigurationTest { + + @Autowired + private DubboEndpoint dubboEndpoint; + + @Autowired + private DubboConfigsMetadata dubboConfigsMetadata; + + @Autowired + private DubboPropertiesMetadata dubboProperties; + + @Autowired + private DubboReferencesMetadata dubboReferencesMetadata; + + @Autowired + private DubboServicesMetadata dubboServicesMetadata; + + @Autowired + private DubboShutdownMetadata dubboShutdownMetadata; + + private RestTemplate restTemplate = new RestTemplate(); + + @Autowired + private ObjectMapper objectMapper; + + @Value("http://127.0.0.1:${local.management.port}${management.contextPath:}") + private String actuatorBaseURL; + + @Test + public void testShutdown() throws Exception { + + Map value = dubboShutdownMetadata.shutdown(); + + Map shutdownCounts = (Map) value.get("shutdown.count"); + + Assert.assertEquals(0, shutdownCounts.get("registries")); + Assert.assertEquals(1, shutdownCounts.get("protocols")); + Assert.assertEquals(1, shutdownCounts.get("services")); + Assert.assertEquals(0, shutdownCounts.get("references")); + + } + + @Test + public void testConfigs() { + + Map>> configsMap = dubboConfigsMetadata.configs(); + + Map> beansMetadata = configsMap.get("ApplicationConfig"); + Assert.assertEquals("dubbo-demo-application", beansMetadata.get("my-application").get("name")); + + beansMetadata = configsMap.get("ConsumerConfig"); + Assert.assertTrue(beansMetadata.isEmpty()); + + beansMetadata = configsMap.get("MethodConfig"); + Assert.assertTrue(beansMetadata.isEmpty()); + + beansMetadata = configsMap.get("ModuleConfig"); + Assert.assertEquals("dubbo-demo-module", beansMetadata.get("my-module").get("name")); + + beansMetadata = configsMap.get("MonitorConfig"); + Assert.assertTrue(beansMetadata.isEmpty()); + + beansMetadata = configsMap.get("ProtocolConfig"); + Assert.assertEquals("dubbo", beansMetadata.get("my-protocol").get("name")); + + beansMetadata = configsMap.get("ProviderConfig"); + Assert.assertEquals("127.0.0.1", beansMetadata.get("my-provider").get("host")); + + beansMetadata = configsMap.get("ReferenceConfig"); + Assert.assertTrue(beansMetadata.isEmpty()); + + beansMetadata = configsMap.get("RegistryConfig"); + Assert.assertEquals("N/A", beansMetadata.get("my-registry").get("address")); + + beansMetadata = configsMap.get("ServiceConfig"); + Assert.assertFalse(beansMetadata.isEmpty()); + + } + + @Test + public void testServices() { + + Map> services = dubboServicesMetadata.services(); + + Assert.assertEquals(1, services.size()); + + Map demoServiceMeta = services.get("ServiceBean:org.apache.dubbo.spring.boot.actuate.autoconfigure.DubboEndpointAutoConfigurationTest$DemoService:1.0.0"); + + Assert.assertEquals("1.0.0", demoServiceMeta.get("version")); + + } + + @Test + public void testReferences() { + + Map> references = dubboReferencesMetadata.references(); + + Assert.assertTrue(references.isEmpty()); + + } + + @Test + public void testProperties() { + + SortedMap properties = dubboProperties.properties(); + + Assert.assertEquals("my-application", properties.get("dubbo.application.id")); + Assert.assertEquals("dubbo-demo-application", properties.get("dubbo.application.name")); + Assert.assertEquals("my-module", properties.get("dubbo.module.id")); + Assert.assertEquals("dubbo-demo-module", properties.get("dubbo.module.name")); + Assert.assertEquals("my-registry", properties.get("dubbo.registry.id")); + Assert.assertEquals("N/A", properties.get("dubbo.registry.address")); + Assert.assertEquals("my-protocol", properties.get("dubbo.protocol.id")); + Assert.assertEquals("dubbo", properties.get("dubbo.protocol.name")); + Assert.assertEquals("20880", properties.get("dubbo.protocol.port")); + Assert.assertEquals("my-provider", properties.get("dubbo.provider.id")); + Assert.assertEquals("127.0.0.1", properties.get("dubbo.provider.host")); + Assert.assertEquals("org.apache.dubbo.spring.boot.actuate.autoconfigure", properties.get("dubbo.scan.basePackages")); + } + + @Test + public void testHttpEndpoints() throws JsonProcessingException { +// testHttpEndpoint("/dubbo", dubboEndpoint::invoke); + testHttpEndpoint("/dubbo/configs", dubboConfigsMetadata::configs); + testHttpEndpoint("/dubbo/services", dubboServicesMetadata::services); + testHttpEndpoint("/dubbo/references", dubboReferencesMetadata::references); + testHttpEndpoint("/dubbo/properties", dubboProperties::properties); + } + + private void testHttpEndpoint(String actuatorURI, Supplier resultsSupplier) throws JsonProcessingException { + String actuatorURL = actuatorBaseURL + actuatorURI; + String response = restTemplate.getForObject(actuatorURL, String.class); + Assert.assertEquals(objectMapper.writeValueAsString(resultsSupplier.get()), response); + } + + + interface DemoService { + String sayHello(String name); + } + + @DubboService( + version = "${dubbo.service.version}", + application = "${dubbo.application.id}", + protocol = "${dubbo.protocol.id}", + registry = "${dubbo.registry.id}" + ) + static class DefaultDemoService implements DemoService { + + public String sayHello(String name) { + return "Hello, " + name + " (from Spring Boot)"; + } + + } + + +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/test/java/org/apache/dubbo/spring/boot/actuate/health/DubboHealthIndicatorTest.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/test/java/org/apache/dubbo/spring/boot/actuate/health/DubboHealthIndicatorTest.java index 0c55f7f5b2..130e21e8d8 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/test/java/org/apache/dubbo/spring/boot/actuate/health/DubboHealthIndicatorTest.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/test/java/org/apache/dubbo/spring/boot/actuate/health/DubboHealthIndicatorTest.java @@ -1,89 +1,89 @@ -/* - * 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.spring.boot.actuate.health; - -import org.apache.dubbo.config.spring.context.annotation.EnableDubboConfig; - -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit4.SpringRunner; - -import java.util.Map; - -/** - * {@link DubboHealthIndicator} Test - * - * @see DubboHealthIndicator - * @since 2.7.0 - */ -@RunWith(SpringRunner.class) -@TestPropertySource(properties = { - "dubbo.application.id = my-application-1", - "dubbo.application.name = dubbo-demo-application-1", - "dubbo.protocol.id = dubbo-protocol", - "dubbo.protocol.name = dubbo", - "dubbo.protocol.port = 12345", - "dubbo.protocol.status = registry", - "dubbo.provider.id = dubbo-provider", - "dubbo.provider.status = server", - "management.health.dubbo.status.defaults = memory", - "management.health.dubbo.status.extras = load,threadpool" -}) -@SpringBootTest( - classes = { - DubboHealthIndicator.class, - DubboHealthIndicatorTest.class - } -) -@EnableConfigurationProperties(DubboHealthIndicatorProperties.class) -@EnableDubboConfig -public class DubboHealthIndicatorTest { - - @Autowired - private DubboHealthIndicator dubboHealthIndicator; - - @Test - public void testResolveStatusCheckerNamesMap() { - - Map statusCheckerNamesMap = dubboHealthIndicator.resolveStatusCheckerNamesMap(); - - Assert.assertEquals(5, statusCheckerNamesMap.size()); - - Assert.assertEquals("dubbo-protocol@ProtocolConfig.getStatus()", statusCheckerNamesMap.get("registry")); - Assert.assertEquals("dubbo-provider@ProviderConfig.getStatus()", statusCheckerNamesMap.get("server")); - Assert.assertEquals("management.health.dubbo.status.defaults", statusCheckerNamesMap.get("memory")); - Assert.assertEquals("management.health.dubbo.status.extras", statusCheckerNamesMap.get("load")); - Assert.assertEquals("management.health.dubbo.status.extras", statusCheckerNamesMap.get("threadpool")); - - } - - @Test - public void testHealth() { - - Health health = dubboHealthIndicator.health(); - - Assert.assertEquals(Status.UNKNOWN, health.getStatus()); - - } -} +/* + * 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.spring.boot.actuate.health; + +import org.apache.dubbo.config.spring.context.annotation.EnableDubboConfig; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.health.Health; +import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.Map; + +/** + * {@link DubboHealthIndicator} Test + * + * @see DubboHealthIndicator + * @since 2.7.0 + */ +@RunWith(SpringRunner.class) +@TestPropertySource(properties = { + "dubbo.application.id = my-application-1", + "dubbo.application.name = dubbo-demo-application-1", + "dubbo.protocol.id = dubbo-protocol", + "dubbo.protocol.name = dubbo", + "dubbo.protocol.port = 12345", + "dubbo.protocol.status = registry", + "dubbo.provider.id = dubbo-provider", + "dubbo.provider.status = server", + "management.health.dubbo.status.defaults = memory", + "management.health.dubbo.status.extras = load,threadpool" +}) +@SpringBootTest( + classes = { + DubboHealthIndicator.class, + DubboHealthIndicatorTest.class + } +) +@EnableConfigurationProperties(DubboHealthIndicatorProperties.class) +@EnableDubboConfig +public class DubboHealthIndicatorTest { + + @Autowired + private DubboHealthIndicator dubboHealthIndicator; + + @Test + public void testResolveStatusCheckerNamesMap() { + + Map statusCheckerNamesMap = dubboHealthIndicator.resolveStatusCheckerNamesMap(); + + Assert.assertEquals(5, statusCheckerNamesMap.size()); + + Assert.assertEquals("dubbo-protocol@ProtocolConfig.getStatus()", statusCheckerNamesMap.get("registry")); + Assert.assertEquals("dubbo-provider@ProviderConfig.getStatus()", statusCheckerNamesMap.get("server")); + Assert.assertEquals("management.health.dubbo.status.defaults", statusCheckerNamesMap.get("memory")); + Assert.assertEquals("management.health.dubbo.status.extras", statusCheckerNamesMap.get("load")); + Assert.assertEquals("management.health.dubbo.status.extras", statusCheckerNamesMap.get("threadpool")); + + } + + @Test + public void testHealth() { + + Health health = dubboHealthIndicator.health(); + + Assert.assertEquals(Status.UNKNOWN, health.getStatus()); + + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/pom.xml b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/pom.xml index 488bc92017..e99f6b7f65 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/pom.xml +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/pom.xml @@ -1,88 +1,88 @@ - - - - - org.apache.dubbo - dubbo-spring-boot-compatible - ${revision} - ../pom.xml - - 4.0.0 - - dubbo-spring-boot-autoconfigure-compatible - Apache Dubbo Spring Boot Compatible for Spring Boot 1.x Auto-Configure - - - - - - org.springframework.boot - spring-boot-autoconfigure - true - - - - org.springframework.boot - spring-boot - true - - - - org.springframework.boot - spring-boot-starter-logging - true - - - - - org.springframework.boot - spring-boot-configuration-processor - true - - - - org.apache.dubbo - dubbo-common - ${revision} - true - - - - org.apache.dubbo - dubbo-config-spring - ${revision} - true - - - - org.apache.dubbo - dubbo - ${revision} - - - - - org.springframework.boot - spring-boot-starter-test - test - - - + + + + + org.apache.dubbo + dubbo-spring-boot-compatible + ${revision} + ../pom.xml + + 4.0.0 + + dubbo-spring-boot-autoconfigure-compatible + Apache Dubbo Spring Boot Compatible for Spring Boot 1.x Auto-Configure + + + + + + org.springframework.boot + spring-boot-autoconfigure + true + + + + org.springframework.boot + spring-boot + true + + + + org.springframework.boot + spring-boot-starter-logging + true + + + + + org.springframework.boot + spring-boot-configuration-processor + true + + + + org.apache.dubbo + dubbo-common + ${revision} + true + + + + org.apache.dubbo + dubbo-config-spring + ${revision} + true + + + + org.apache.dubbo + dubbo + ${revision} + + + + + org.springframework.boot + spring-boot-starter-test + test + + + \ No newline at end of file diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboAutoConfiguration.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboAutoConfiguration.java index 59ac13c2b1..4fb850c3f0 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboAutoConfiguration.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboAutoConfiguration.java @@ -1,114 +1,114 @@ -/* - * 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.spring.boot.autoconfigure; - -import org.apache.dubbo.config.annotation.DubboReference; -import org.apache.dubbo.config.annotation.DubboService; -import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor; -import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationPostProcessor; -import org.apache.dubbo.config.spring.context.DubboBootstrapApplicationListener; -import org.apache.dubbo.config.spring.context.DubboLifecycleComponentApplicationListener; -import org.apache.dubbo.config.spring.context.annotation.EnableDubboConfig; - -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; -import org.springframework.boot.autoconfigure.AutoConfigureAfter; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import java.util.Set; - -import static org.apache.dubbo.spring.boot.util.DubboUtils.BASE_PACKAGES_BEAN_NAME; -import static org.apache.dubbo.spring.boot.util.DubboUtils.BASE_PACKAGES_PROPERTY_NAME; -import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_PREFIX; -import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_SCAN_PREFIX; - -/** - * Dubbo Auto {@link Configuration} - * - * @see DubboReference - * @see DubboService - * @see ServiceAnnotationPostProcessor - * @see ReferenceAnnotationBeanPostProcessor - * @since 2.7.0 - */ -@ConditionalOnProperty(prefix = DUBBO_PREFIX, name = "enabled", matchIfMissing = true) -@Configuration -@AutoConfigureAfter(DubboRelaxedBindingAutoConfiguration.class) -@EnableConfigurationProperties(DubboConfigurationProperties.class) -@EnableDubboConfig -public class DubboAutoConfiguration implements ApplicationContextAware, BeanDefinitionRegistryPostProcessor { - - /** - * Creates {@link ServiceAnnotationPostProcessor} Bean - * - * @param packagesToScan the packages to scan - * @return {@link ServiceAnnotationPostProcessor} - */ - @ConditionalOnProperty(prefix = DUBBO_SCAN_PREFIX, name = BASE_PACKAGES_PROPERTY_NAME) - @ConditionalOnBean(name = BASE_PACKAGES_BEAN_NAME) - @ConditionalOnMissingBean - @Bean - public ServiceAnnotationPostProcessor serviceAnnotationBeanProcessor(@Qualifier(BASE_PACKAGES_BEAN_NAME) - Set packagesToScan) { - return new ServiceAnnotationPostProcessor(packagesToScan); - } - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - if (applicationContext instanceof ConfigurableApplicationContext) { - ConfigurableApplicationContext context = (ConfigurableApplicationContext) applicationContext; -// DubboLifecycleComponentApplicationListener dubboLifecycleComponentApplicationListener -// = new DubboLifecycleComponentApplicationListener(); -// dubboLifecycleComponentApplicationListener.setApplicationContext(applicationContext); -// context.addApplicationListener(dubboLifecycleComponentApplicationListener); - - DubboBootstrapApplicationListener dubboBootstrapApplicationListener = new DubboBootstrapApplicationListener(); - dubboBootstrapApplicationListener.setApplicationContext(applicationContext); - context.addApplicationListener(dubboBootstrapApplicationListener); - } - } - - @Override - public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { - // Remove the BeanDefinitions of ApplicationListener from DubboBeanUtils#registerCommonBeans(BeanDefinitionRegistry) - // TODO Refactoring in Dubbo 2.7.9 - removeBeanDefinition(registry, DubboLifecycleComponentApplicationListener.BEAN_NAME); - removeBeanDefinition(registry, DubboBootstrapApplicationListener.BEAN_NAME); - } - - private void removeBeanDefinition(BeanDefinitionRegistry registry, String beanName) { - if (registry.containsBeanDefinition(beanName)) { - registry.removeBeanDefinition(beanName); - } - } - - @Override - public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { - // DO NOTHING - } -} +/* + * 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.spring.boot.autoconfigure; + +import org.apache.dubbo.config.annotation.DubboReference; +import org.apache.dubbo.config.annotation.DubboService; +import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor; +import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationPostProcessor; +import org.apache.dubbo.config.spring.context.DubboBootstrapApplicationListener; +import org.apache.dubbo.config.spring.context.DubboLifecycleComponentApplicationListener; +import org.apache.dubbo.config.spring.context.annotation.EnableDubboConfig; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.Set; + +import static org.apache.dubbo.spring.boot.util.DubboUtils.BASE_PACKAGES_BEAN_NAME; +import static org.apache.dubbo.spring.boot.util.DubboUtils.BASE_PACKAGES_PROPERTY_NAME; +import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_PREFIX; +import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_SCAN_PREFIX; + +/** + * Dubbo Auto {@link Configuration} + * + * @see DubboReference + * @see DubboService + * @see ServiceAnnotationPostProcessor + * @see ReferenceAnnotationBeanPostProcessor + * @since 2.7.0 + */ +@ConditionalOnProperty(prefix = DUBBO_PREFIX, name = "enabled", matchIfMissing = true) +@Configuration +@AutoConfigureAfter(DubboRelaxedBindingAutoConfiguration.class) +@EnableConfigurationProperties(DubboConfigurationProperties.class) +@EnableDubboConfig +public class DubboAutoConfiguration implements ApplicationContextAware, BeanDefinitionRegistryPostProcessor { + + /** + * Creates {@link ServiceAnnotationPostProcessor} Bean + * + * @param packagesToScan the packages to scan + * @return {@link ServiceAnnotationPostProcessor} + */ + @ConditionalOnProperty(prefix = DUBBO_SCAN_PREFIX, name = BASE_PACKAGES_PROPERTY_NAME) + @ConditionalOnBean(name = BASE_PACKAGES_BEAN_NAME) + @ConditionalOnMissingBean + @Bean + public ServiceAnnotationPostProcessor serviceAnnotationBeanProcessor(@Qualifier(BASE_PACKAGES_BEAN_NAME) + Set packagesToScan) { + return new ServiceAnnotationPostProcessor(packagesToScan); + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + if (applicationContext instanceof ConfigurableApplicationContext) { + ConfigurableApplicationContext context = (ConfigurableApplicationContext) applicationContext; +// DubboLifecycleComponentApplicationListener dubboLifecycleComponentApplicationListener +// = new DubboLifecycleComponentApplicationListener(); +// dubboLifecycleComponentApplicationListener.setApplicationContext(applicationContext); +// context.addApplicationListener(dubboLifecycleComponentApplicationListener); + + DubboBootstrapApplicationListener dubboBootstrapApplicationListener = new DubboBootstrapApplicationListener(); + dubboBootstrapApplicationListener.setApplicationContext(applicationContext); + context.addApplicationListener(dubboBootstrapApplicationListener); + } + } + + @Override + public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { + // Remove the BeanDefinitions of ApplicationListener from DubboBeanUtils#registerCommonBeans(BeanDefinitionRegistry) + // TODO Refactoring in Dubbo 2.7.9 + removeBeanDefinition(registry, DubboLifecycleComponentApplicationListener.BEAN_NAME); + removeBeanDefinition(registry, DubboBootstrapApplicationListener.BEAN_NAME); + } + + private void removeBeanDefinition(BeanDefinitionRegistry registry, String beanName) { + if (registry.containsBeanDefinition(beanName)) { + registry.removeBeanDefinition(beanName); + } + } + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { + // DO NOTHING + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboConfigurationProperties.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboConfigurationProperties.java index f6cef20f73..e5c72baff1 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboConfigurationProperties.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboConfigurationProperties.java @@ -1,300 +1,300 @@ -/* - * 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.spring.boot.autoconfigure; - -import org.apache.dubbo.config.ApplicationConfig; -import org.apache.dubbo.config.ConsumerConfig; -import org.apache.dubbo.config.MetadataReportConfig; -import org.apache.dubbo.config.ModuleConfig; -import org.apache.dubbo.config.MonitorConfig; -import org.apache.dubbo.config.ProtocolConfig; -import org.apache.dubbo.config.ProviderConfig; -import org.apache.dubbo.config.RegistryConfig; -import org.apache.dubbo.config.spring.ConfigCenterBean; -import org.apache.dubbo.config.spring.context.annotation.EnableDubbo; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.context.properties.NestedConfigurationProperty; - -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; - -import static org.apache.dubbo.spring.boot.util.DubboUtils.DEFAULT_MULTIPLE_CONFIG_PROPERTY_VALUE; -import static org.apache.dubbo.spring.boot.util.DubboUtils.DEFAULT_OVERRIDE_CONFIG_PROPERTY_VALUE; -import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_PREFIX; - -/** - * Dubbo {@link ConfigurationProperties Config Properties} only used to generate JSON metadata(non-public class) - * - * @since 2.7.1 - */ -@ConfigurationProperties(DUBBO_PREFIX) -public class DubboConfigurationProperties { - - @NestedConfigurationProperty - private Config config = new Config(); - - @NestedConfigurationProperty - private Scan scan = new Scan(); - - // Single Config Bindings - @NestedConfigurationProperty - private ApplicationConfig application = new ApplicationConfig(); - - @NestedConfigurationProperty - private ModuleConfig module = new ModuleConfig(); - - @NestedConfigurationProperty - private RegistryConfig registry = new RegistryConfig(); - - @NestedConfigurationProperty - private ProtocolConfig protocol = new ProtocolConfig(); - - @NestedConfigurationProperty - private MonitorConfig monitor = new MonitorConfig(); - - @NestedConfigurationProperty - private ProviderConfig provider = new ProviderConfig(); - - @NestedConfigurationProperty - private ConsumerConfig consumer = new ConsumerConfig(); - - @NestedConfigurationProperty - private ConfigCenterBean configCenter = new ConfigCenterBean(); - - @NestedConfigurationProperty - private MetadataReportConfig metadataReport = new MetadataReportConfig(); - - // Multiple Config Bindings - - private Map modules = new LinkedHashMap<>(); - - private Map registries = new LinkedHashMap<>(); - - private Map protocols = new LinkedHashMap<>(); - - private Map monitors = new LinkedHashMap<>(); - - private Map providers = new LinkedHashMap<>(); - - private Map consumers = new LinkedHashMap<>(); - - private Map configCenters = new LinkedHashMap<>(); - - private Map metadataReports = new LinkedHashMap<>(); - - public Config getConfig() { - return config; - } - - public void setConfig(Config config) { - this.config = config; - } - - public Scan getScan() { - return scan; - } - - public void setScan(Scan scan) { - this.scan = scan; - } - - 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 registry; - } - - public void setRegistry(RegistryConfig registry) { - this.registry = registry; - } - - public ProtocolConfig getProtocol() { - return protocol; - } - - public void setProtocol(ProtocolConfig protocol) { - this.protocol = protocol; - } - - public MonitorConfig getMonitor() { - return monitor; - } - - public void setMonitor(MonitorConfig monitor) { - this.monitor = monitor; - } - - public ProviderConfig getProvider() { - return provider; - } - - public void setProvider(ProviderConfig provider) { - this.provider = provider; - } - - public ConsumerConfig getConsumer() { - return consumer; - } - - public void setConsumer(ConsumerConfig consumer) { - this.consumer = consumer; - } - - public ConfigCenterBean getConfigCenter() { - return configCenter; - } - - public void setConfigCenter(ConfigCenterBean configCenter) { - this.configCenter = configCenter; - } - - public MetadataReportConfig getMetadataReport() { - return metadataReport; - } - - public void setMetadataReport(MetadataReportConfig metadataReport) { - this.metadataReport = metadataReport; - } - - public Map getModules() { - return modules; - } - - public void setModules(Map modules) { - this.modules = modules; - } - - public Map getRegistries() { - return registries; - } - - public void setRegistries(Map registries) { - this.registries = registries; - } - - public Map getProtocols() { - return protocols; - } - - public void setProtocols(Map protocols) { - this.protocols = protocols; - } - - public Map getMonitors() { - return monitors; - } - - public void setMonitors(Map monitors) { - this.monitors = monitors; - } - - public Map getProviders() { - return providers; - } - - public void setProviders(Map providers) { - this.providers = providers; - } - - public Map getConsumers() { - return consumers; - } - - public void setConsumers(Map consumers) { - this.consumers = consumers; - } - - public Map getConfigCenters() { - return configCenters; - } - - public void setConfigCenters(Map configCenters) { - this.configCenters = configCenters; - } - - public Map getMetadataReports() { - return metadataReports; - } - - public void setMetadataReports(Map metadataReports) { - this.metadataReports = metadataReports; - } - - static class Config { - - /** - * Indicates multiple properties binding from externalized configuration or not. - */ - private boolean multiple = DEFAULT_MULTIPLE_CONFIG_PROPERTY_VALUE; - - /** - * The property name of override Dubbo config - */ - private boolean override = DEFAULT_OVERRIDE_CONFIG_PROPERTY_VALUE; - - public boolean isOverride() { - return override; - } - - public void setOverride(boolean override) { - this.override = override; - } - - public boolean isMultiple() { - return multiple; - } - - public void setMultiple(boolean multiple) { - this.multiple = multiple; - } - } - - static class Scan { - - /** - * The basePackages to scan , the multiple-value is delimited by comma - * - * @see EnableDubbo#scanBasePackages() - */ - private Set basePackages = new LinkedHashSet<>(); - - public Set getBasePackages() { - return basePackages; - } - - public void setBasePackages(Set basePackages) { - this.basePackages = basePackages; - } - } -} +/* + * 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.spring.boot.autoconfigure; + +import org.apache.dubbo.config.ApplicationConfig; +import org.apache.dubbo.config.ConsumerConfig; +import org.apache.dubbo.config.MetadataReportConfig; +import org.apache.dubbo.config.ModuleConfig; +import org.apache.dubbo.config.MonitorConfig; +import org.apache.dubbo.config.ProtocolConfig; +import org.apache.dubbo.config.ProviderConfig; +import org.apache.dubbo.config.RegistryConfig; +import org.apache.dubbo.config.spring.ConfigCenterBean; +import org.apache.dubbo.config.spring.context.annotation.EnableDubbo; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.NestedConfigurationProperty; + +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +import static org.apache.dubbo.spring.boot.util.DubboUtils.DEFAULT_MULTIPLE_CONFIG_PROPERTY_VALUE; +import static org.apache.dubbo.spring.boot.util.DubboUtils.DEFAULT_OVERRIDE_CONFIG_PROPERTY_VALUE; +import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_PREFIX; + +/** + * Dubbo {@link ConfigurationProperties Config Properties} only used to generate JSON metadata(non-public class) + * + * @since 2.7.1 + */ +@ConfigurationProperties(DUBBO_PREFIX) +public class DubboConfigurationProperties { + + @NestedConfigurationProperty + private Config config = new Config(); + + @NestedConfigurationProperty + private Scan scan = new Scan(); + + // Single Config Bindings + @NestedConfigurationProperty + private ApplicationConfig application = new ApplicationConfig(); + + @NestedConfigurationProperty + private ModuleConfig module = new ModuleConfig(); + + @NestedConfigurationProperty + private RegistryConfig registry = new RegistryConfig(); + + @NestedConfigurationProperty + private ProtocolConfig protocol = new ProtocolConfig(); + + @NestedConfigurationProperty + private MonitorConfig monitor = new MonitorConfig(); + + @NestedConfigurationProperty + private ProviderConfig provider = new ProviderConfig(); + + @NestedConfigurationProperty + private ConsumerConfig consumer = new ConsumerConfig(); + + @NestedConfigurationProperty + private ConfigCenterBean configCenter = new ConfigCenterBean(); + + @NestedConfigurationProperty + private MetadataReportConfig metadataReport = new MetadataReportConfig(); + + // Multiple Config Bindings + + private Map modules = new LinkedHashMap<>(); + + private Map registries = new LinkedHashMap<>(); + + private Map protocols = new LinkedHashMap<>(); + + private Map monitors = new LinkedHashMap<>(); + + private Map providers = new LinkedHashMap<>(); + + private Map consumers = new LinkedHashMap<>(); + + private Map configCenters = new LinkedHashMap<>(); + + private Map metadataReports = new LinkedHashMap<>(); + + public Config getConfig() { + return config; + } + + public void setConfig(Config config) { + this.config = config; + } + + public Scan getScan() { + return scan; + } + + public void setScan(Scan scan) { + this.scan = scan; + } + + 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 registry; + } + + public void setRegistry(RegistryConfig registry) { + this.registry = registry; + } + + public ProtocolConfig getProtocol() { + return protocol; + } + + public void setProtocol(ProtocolConfig protocol) { + this.protocol = protocol; + } + + public MonitorConfig getMonitor() { + return monitor; + } + + public void setMonitor(MonitorConfig monitor) { + this.monitor = monitor; + } + + public ProviderConfig getProvider() { + return provider; + } + + public void setProvider(ProviderConfig provider) { + this.provider = provider; + } + + public ConsumerConfig getConsumer() { + return consumer; + } + + public void setConsumer(ConsumerConfig consumer) { + this.consumer = consumer; + } + + public ConfigCenterBean getConfigCenter() { + return configCenter; + } + + public void setConfigCenter(ConfigCenterBean configCenter) { + this.configCenter = configCenter; + } + + public MetadataReportConfig getMetadataReport() { + return metadataReport; + } + + public void setMetadataReport(MetadataReportConfig metadataReport) { + this.metadataReport = metadataReport; + } + + public Map getModules() { + return modules; + } + + public void setModules(Map modules) { + this.modules = modules; + } + + public Map getRegistries() { + return registries; + } + + public void setRegistries(Map registries) { + this.registries = registries; + } + + public Map getProtocols() { + return protocols; + } + + public void setProtocols(Map protocols) { + this.protocols = protocols; + } + + public Map getMonitors() { + return monitors; + } + + public void setMonitors(Map monitors) { + this.monitors = monitors; + } + + public Map getProviders() { + return providers; + } + + public void setProviders(Map providers) { + this.providers = providers; + } + + public Map getConsumers() { + return consumers; + } + + public void setConsumers(Map consumers) { + this.consumers = consumers; + } + + public Map getConfigCenters() { + return configCenters; + } + + public void setConfigCenters(Map configCenters) { + this.configCenters = configCenters; + } + + public Map getMetadataReports() { + return metadataReports; + } + + public void setMetadataReports(Map metadataReports) { + this.metadataReports = metadataReports; + } + + static class Config { + + /** + * Indicates multiple properties binding from externalized configuration or not. + */ + private boolean multiple = DEFAULT_MULTIPLE_CONFIG_PROPERTY_VALUE; + + /** + * The property name of override Dubbo config + */ + private boolean override = DEFAULT_OVERRIDE_CONFIG_PROPERTY_VALUE; + + public boolean isOverride() { + return override; + } + + public void setOverride(boolean override) { + this.override = override; + } + + public boolean isMultiple() { + return multiple; + } + + public void setMultiple(boolean multiple) { + this.multiple = multiple; + } + } + + static class Scan { + + /** + * The basePackages to scan , the multiple-value is delimited by comma + * + * @see EnableDubbo#scanBasePackages() + */ + private Set basePackages = new LinkedHashSet<>(); + + public Set getBasePackages() { + return basePackages; + } + + public void setBasePackages(Set basePackages) { + this.basePackages = basePackages; + } + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboRelaxedBindingAutoConfiguration.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboRelaxedBindingAutoConfiguration.java index 3cefb46e98..fdd3209362 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboRelaxedBindingAutoConfiguration.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboRelaxedBindingAutoConfiguration.java @@ -1,73 +1,73 @@ -/* - * 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.spring.boot.autoconfigure; - -import com.alibaba.spring.context.config.ConfigurationBeanBinder; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.bind.RelaxedPropertyResolver; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Scope; -import org.springframework.core.env.Environment; -import org.springframework.core.env.PropertyResolver; - -import java.util.Set; - -import static java.util.Collections.emptySet; -import static org.apache.dubbo.spring.boot.util.DubboUtils.BASE_PACKAGES_BEAN_NAME; -import static org.apache.dubbo.spring.boot.util.DubboUtils.BASE_PACKAGES_PROPERTY_NAME; -import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_PREFIX; -import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_SCAN_PREFIX; -import static org.apache.dubbo.spring.boot.util.DubboUtils.RELAXED_DUBBO_CONFIG_BINDER_BEAN_NAME; -import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; - -/** - * Dubbo Relaxed Binding Auto-{@link Configuration} for Spring Boot 1.x - */ -@ConditionalOnProperty(prefix = DUBBO_PREFIX, name = "enabled", matchIfMissing = true) -@ConditionalOnClass(name = "org.springframework.boot.bind.RelaxedPropertyResolver") -@Configuration -public class DubboRelaxedBindingAutoConfiguration { - - public PropertyResolver dubboScanBasePackagesPropertyResolver(Environment environment) { - return new RelaxedPropertyResolver(environment, DUBBO_SCAN_PREFIX); - } - - /** - * The bean is used to scan the packages of Dubbo Service classes - * - * @param environment {@link Environment} instance - * @return non-null {@link Set} - * @since 2.7.8 - */ - @ConditionalOnMissingBean(name = BASE_PACKAGES_BEAN_NAME) - @Bean(name = BASE_PACKAGES_BEAN_NAME) - public Set dubboBasePackages(Environment environment) { - PropertyResolver propertyResolver = dubboScanBasePackagesPropertyResolver(environment); - return propertyResolver.getProperty(BASE_PACKAGES_PROPERTY_NAME, Set.class, emptySet()); - } - - @ConditionalOnMissingBean(name = RELAXED_DUBBO_CONFIG_BINDER_BEAN_NAME, value = ConfigurationBeanBinder.class) - @Bean(RELAXED_DUBBO_CONFIG_BINDER_BEAN_NAME) - @Scope(scopeName = SCOPE_PROTOTYPE) - public ConfigurationBeanBinder relaxedDubboConfigBinder() { - return new RelaxedDubboConfigBinder(); - } - -} +/* + * 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.spring.boot.autoconfigure; + +import com.alibaba.spring.context.config.ConfigurationBeanBinder; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.bind.RelaxedPropertyResolver; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Scope; +import org.springframework.core.env.Environment; +import org.springframework.core.env.PropertyResolver; + +import java.util.Set; + +import static java.util.Collections.emptySet; +import static org.apache.dubbo.spring.boot.util.DubboUtils.BASE_PACKAGES_BEAN_NAME; +import static org.apache.dubbo.spring.boot.util.DubboUtils.BASE_PACKAGES_PROPERTY_NAME; +import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_PREFIX; +import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_SCAN_PREFIX; +import static org.apache.dubbo.spring.boot.util.DubboUtils.RELAXED_DUBBO_CONFIG_BINDER_BEAN_NAME; +import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; + +/** + * Dubbo Relaxed Binding Auto-{@link Configuration} for Spring Boot 1.x + */ +@ConditionalOnProperty(prefix = DUBBO_PREFIX, name = "enabled", matchIfMissing = true) +@ConditionalOnClass(name = "org.springframework.boot.bind.RelaxedPropertyResolver") +@Configuration +public class DubboRelaxedBindingAutoConfiguration { + + public PropertyResolver dubboScanBasePackagesPropertyResolver(Environment environment) { + return new RelaxedPropertyResolver(environment, DUBBO_SCAN_PREFIX); + } + + /** + * The bean is used to scan the packages of Dubbo Service classes + * + * @param environment {@link Environment} instance + * @return non-null {@link Set} + * @since 2.7.8 + */ + @ConditionalOnMissingBean(name = BASE_PACKAGES_BEAN_NAME) + @Bean(name = BASE_PACKAGES_BEAN_NAME) + public Set dubboBasePackages(Environment environment) { + PropertyResolver propertyResolver = dubboScanBasePackagesPropertyResolver(environment); + return propertyResolver.getProperty(BASE_PACKAGES_PROPERTY_NAME, Set.class, emptySet()); + } + + @ConditionalOnMissingBean(name = RELAXED_DUBBO_CONFIG_BINDER_BEAN_NAME, value = ConfigurationBeanBinder.class) + @Bean(RELAXED_DUBBO_CONFIG_BINDER_BEAN_NAME) + @Scope(scopeName = SCOPE_PROTOTYPE) + public ConfigurationBeanBinder relaxedDubboConfigBinder() { + return new RelaxedDubboConfigBinder(); + } + +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/RelaxedDubboConfigBinder.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/RelaxedDubboConfigBinder.java index fcd461a789..40bc227047 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/RelaxedDubboConfigBinder.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/RelaxedDubboConfigBinder.java @@ -1,48 +1,48 @@ -/* - * 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.spring.boot.autoconfigure; - -import org.apache.dubbo.config.spring.context.properties.DubboConfigBinder; - -import com.alibaba.spring.context.config.ConfigurationBeanBinder; -import org.springframework.beans.MutablePropertyValues; -import org.springframework.boot.bind.RelaxedDataBinder; - -import java.util.Map; - - -/** - * Spring Boot Relaxed {@link DubboConfigBinder} implementation - * - * @since 2.7.0 - */ -class RelaxedDubboConfigBinder implements ConfigurationBeanBinder { - - @Override - public void bind(Map configurationProperties, boolean ignoreUnknownFields, - boolean ignoreInvalidFields, Object configurationBean) { - RelaxedDataBinder relaxedDataBinder = new RelaxedDataBinder(configurationBean); - // Set ignored* - relaxedDataBinder.setIgnoreInvalidFields(ignoreInvalidFields); - relaxedDataBinder.setIgnoreUnknownFields(ignoreUnknownFields); - // Get properties under specified prefix from PropertySources - // Convert Map to MutablePropertyValues - MutablePropertyValues propertyValues = new MutablePropertyValues(configurationProperties); - // Bind - relaxedDataBinder.bind(propertyValues); - } -} +/* + * 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.spring.boot.autoconfigure; + +import org.apache.dubbo.config.spring.context.properties.DubboConfigBinder; + +import com.alibaba.spring.context.config.ConfigurationBeanBinder; +import org.springframework.beans.MutablePropertyValues; +import org.springframework.boot.bind.RelaxedDataBinder; + +import java.util.Map; + + +/** + * Spring Boot Relaxed {@link DubboConfigBinder} implementation + * + * @since 2.7.0 + */ +class RelaxedDubboConfigBinder implements ConfigurationBeanBinder { + + @Override + public void bind(Map configurationProperties, boolean ignoreUnknownFields, + boolean ignoreInvalidFields, Object configurationBean) { + RelaxedDataBinder relaxedDataBinder = new RelaxedDataBinder(configurationBean); + // Set ignored* + relaxedDataBinder.setIgnoreInvalidFields(ignoreInvalidFields); + relaxedDataBinder.setIgnoreUnknownFields(ignoreUnknownFields); + // Get properties under specified prefix from PropertySources + // Convert Map to MutablePropertyValues + MutablePropertyValues propertyValues = new MutablePropertyValues(configurationProperties); + // Bind + relaxedDataBinder.bind(propertyValues); + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/beans/factory/config/ServiceBeanIdConflictProcessor.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/beans/factory/config/ServiceBeanIdConflictProcessor.java index 9b3ee16a1f..b6bf04be38 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/beans/factory/config/ServiceBeanIdConflictProcessor.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/beans/factory/config/ServiceBeanIdConflictProcessor.java @@ -1,115 +1,115 @@ -/* - * 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.spring.boot.beans.factory.config; - -import org.apache.dubbo.config.ServiceConfig; -import org.apache.dubbo.config.spring.ServiceBean; - -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.DisposableBean; -import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor; -import org.springframework.beans.factory.support.RootBeanDefinition; -import org.springframework.context.annotation.CommonAnnotationBeanPostProcessor; -import org.springframework.core.Ordered; -import org.springframework.core.PriorityOrdered; - -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Objects; -import java.util.Set; - -import static org.springframework.util.ClassUtils.getUserClass; -import static org.springframework.util.ClassUtils.isAssignable; - -/** - * The post-processor for resolving the id conflict of {@link ServiceBean} when an interface is - * implemented by multiple services with different groups or versions that are exported on one provider - *

- * Current implementation is a temporary resolution, and will be removed in the future. - * - * @see CommonAnnotationBeanPostProcessor - * @since 2.7.7 - * @deprecated - */ -public class ServiceBeanIdConflictProcessor implements MergedBeanDefinitionPostProcessor, DisposableBean, PriorityOrdered { - - /** - * The key is the class names of interfaces that were exported by {@link ServiceBean} - * The value is bean names of {@link ServiceBean} or {@link ServiceConfig}. - */ - private Map interfaceNamesToBeanNames = new HashMap<>(); - - /** - * Holds the bean names of {@link ServiceBean} or {@link ServiceConfig}. - */ - private Set conflictedBeanNames = new LinkedHashSet<>(); - - @Override - public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName) { - // Get raw bean type - Class rawBeanType = getUserClass(beanType); - if (isAssignable(ServiceConfig.class, rawBeanType)) { // ServiceConfig type or sub-type - String interfaceName = (String) beanDefinition.getPropertyValues().get("interface"); - String mappedBeanName = interfaceNamesToBeanNames.putIfAbsent(interfaceName, beanName); - // If mapped bean name exists and does not equal current bean name - if (mappedBeanName != null && !mappedBeanName.equals(beanName)) { - // conflictedBeanNames will record current bean name. - conflictedBeanNames.add(beanName); - } - } - } - - @Override - public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { - if (conflictedBeanNames.contains(beanName) && bean instanceof ServiceConfig) { - ServiceConfig serviceConfig = (ServiceConfig) bean; - if (isConflictedServiceConfig(serviceConfig)) { - // Set id as the bean name - serviceConfig.setId(beanName); - } - - } - return bean; - } - - private boolean isConflictedServiceConfig(ServiceConfig serviceConfig) { - return Objects.equals(serviceConfig.getId(), serviceConfig.getInterface()); - } - - @Override - public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { - return bean; - } - - /** - * Keep the order being higher than {@link CommonAnnotationBeanPostProcessor#getOrder()} that is - * {@link Ordered#LOWEST_PRECEDENCE} - * - * @return {@link Ordered#LOWEST_PRECEDENCE} +1 - */ - @Override - public int getOrder() { - return LOWEST_PRECEDENCE + 1; - } - - @Override - public void destroy() throws Exception { - interfaceNamesToBeanNames.clear(); - conflictedBeanNames.clear(); - } -} +/* + * 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.spring.boot.beans.factory.config; + +import org.apache.dubbo.config.ServiceConfig; +import org.apache.dubbo.config.spring.ServiceBean; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.context.annotation.CommonAnnotationBeanPostProcessor; +import org.springframework.core.Ordered; +import org.springframework.core.PriorityOrdered; + +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +import static org.springframework.util.ClassUtils.getUserClass; +import static org.springframework.util.ClassUtils.isAssignable; + +/** + * The post-processor for resolving the id conflict of {@link ServiceBean} when an interface is + * implemented by multiple services with different groups or versions that are exported on one provider + *

+ * Current implementation is a temporary resolution, and will be removed in the future. + * + * @see CommonAnnotationBeanPostProcessor + * @since 2.7.7 + * @deprecated + */ +public class ServiceBeanIdConflictProcessor implements MergedBeanDefinitionPostProcessor, DisposableBean, PriorityOrdered { + + /** + * The key is the class names of interfaces that were exported by {@link ServiceBean} + * The value is bean names of {@link ServiceBean} or {@link ServiceConfig}. + */ + private Map interfaceNamesToBeanNames = new HashMap<>(); + + /** + * Holds the bean names of {@link ServiceBean} or {@link ServiceConfig}. + */ + private Set conflictedBeanNames = new LinkedHashSet<>(); + + @Override + public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName) { + // Get raw bean type + Class rawBeanType = getUserClass(beanType); + if (isAssignable(ServiceConfig.class, rawBeanType)) { // ServiceConfig type or sub-type + String interfaceName = (String) beanDefinition.getPropertyValues().get("interface"); + String mappedBeanName = interfaceNamesToBeanNames.putIfAbsent(interfaceName, beanName); + // If mapped bean name exists and does not equal current bean name + if (mappedBeanName != null && !mappedBeanName.equals(beanName)) { + // conflictedBeanNames will record current bean name. + conflictedBeanNames.add(beanName); + } + } + } + + @Override + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + if (conflictedBeanNames.contains(beanName) && bean instanceof ServiceConfig) { + ServiceConfig serviceConfig = (ServiceConfig) bean; + if (isConflictedServiceConfig(serviceConfig)) { + // Set id as the bean name + serviceConfig.setId(beanName); + } + + } + return bean; + } + + private boolean isConflictedServiceConfig(ServiceConfig serviceConfig) { + return Objects.equals(serviceConfig.getId(), serviceConfig.getInterface()); + } + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + return bean; + } + + /** + * Keep the order being higher than {@link CommonAnnotationBeanPostProcessor#getOrder()} that is + * {@link Ordered#LOWEST_PRECEDENCE} + * + * @return {@link Ordered#LOWEST_PRECEDENCE} +1 + */ + @Override + public int getOrder() { + return LOWEST_PRECEDENCE + 1; + } + + @Override + public void destroy() throws Exception { + interfaceNamesToBeanNames.clear(); + conflictedBeanNames.clear(); + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/context/DubboApplicationContextInitializer.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/context/DubboApplicationContextInitializer.java index ed8c96c020..56f78b9970 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/context/DubboApplicationContextInitializer.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/context/DubboApplicationContextInitializer.java @@ -1,50 +1,50 @@ -/* - * 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.spring.boot.context; - -import org.springframework.context.ApplicationContextInitializer; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.core.Ordered; - -/** - * Dubbo {@link ApplicationContextInitializer} implementation - * - * @see ApplicationContextInitializer - * @since 2.7.1 - */ -public class DubboApplicationContextInitializer implements ApplicationContextInitializer, Ordered { - - @Override - public void initialize(ConfigurableApplicationContext applicationContext) { - overrideBeanDefinitions(applicationContext); - } - - private void overrideBeanDefinitions(ConfigurableApplicationContext applicationContext) { - // @since 2.7.8 OverrideBeanDefinitionRegistryPostProcessor has been removed - // applicationContext.addBeanFactoryPostProcessor(new OverrideBeanDefinitionRegistryPostProcessor()); - // @since 2.7.5 DubboConfigBeanDefinitionConflictProcessor has been removed - // @see {@link DubboConfigBeanDefinitionConflictApplicationListener} - // applicationContext.addBeanFactoryPostProcessor(new DubboConfigBeanDefinitionConflictProcessor()); - // TODO Add some components in the future ( after 2.7.8 ) - } - - @Override - public int getOrder() { - return HIGHEST_PRECEDENCE; - } - -} +/* + * 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.spring.boot.context; + +import org.springframework.context.ApplicationContextInitializer; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.core.Ordered; + +/** + * Dubbo {@link ApplicationContextInitializer} implementation + * + * @see ApplicationContextInitializer + * @since 2.7.1 + */ +public class DubboApplicationContextInitializer implements ApplicationContextInitializer, Ordered { + + @Override + public void initialize(ConfigurableApplicationContext applicationContext) { + overrideBeanDefinitions(applicationContext); + } + + private void overrideBeanDefinitions(ConfigurableApplicationContext applicationContext) { + // @since 2.7.8 OverrideBeanDefinitionRegistryPostProcessor has been removed + // applicationContext.addBeanFactoryPostProcessor(new OverrideBeanDefinitionRegistryPostProcessor()); + // @since 2.7.5 DubboConfigBeanDefinitionConflictProcessor has been removed + // @see {@link DubboConfigBeanDefinitionConflictApplicationListener} + // applicationContext.addBeanFactoryPostProcessor(new DubboConfigBeanDefinitionConflictProcessor()); + // TODO Add some components in the future ( after 2.7.8 ) + } + + @Override + public int getOrder() { + return HIGHEST_PRECEDENCE; + } + +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/context/event/AwaitingNonWebApplicationListener.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/context/event/AwaitingNonWebApplicationListener.java index a897a0fac1..8c0d59d488 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/context/event/AwaitingNonWebApplicationListener.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/context/event/AwaitingNonWebApplicationListener.java @@ -1,199 +1,199 @@ -/* - * 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.spring.boot.context.event; - -import org.apache.dubbo.common.lang.ShutdownHookCallbacks; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.boot.context.event.ApplicationReadyEvent; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationEvent; -import org.springframework.context.ApplicationListener; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.event.ContextClosedEvent; -import org.springframework.context.event.SmartApplicationListener; -import org.springframework.util.ClassUtils; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -import static java.util.concurrent.Executors.newSingleThreadExecutor; -import static org.springframework.util.ObjectUtils.containsElement; - -/** - * Awaiting Non-Web Spring Boot {@link ApplicationListener} - * - * @since 2.7.0 - */ -public class AwaitingNonWebApplicationListener implements SmartApplicationListener { - - private static final String[] WEB_APPLICATION_CONTEXT_CLASSES = new String[]{ - "org.springframework.web.context.WebApplicationContext", - "org.springframework.boot.web.reactive.context.ReactiveWebApplicationContext" - }; - - private static final Logger logger = LoggerFactory.getLogger(AwaitingNonWebApplicationListener.class); - - private static final Class[] SUPPORTED_APPLICATION_EVENTS = - of(ApplicationReadyEvent.class, ContextClosedEvent.class); - - private static final AtomicBoolean awaited = new AtomicBoolean(false); - - private static final Integer UNDEFINED_ID = Integer.valueOf(-1); - - /** - * Target the application id - */ - private static final AtomicInteger applicationContextId = new AtomicInteger(UNDEFINED_ID); - - private static final Lock lock = new ReentrantLock(); - - private static final Condition condition = lock.newCondition(); - - private static final ExecutorService executorService = newSingleThreadExecutor(); - - private static T[] of(T... values) { - return values; - } - - static AtomicBoolean getAwaited() { - return awaited; - } - - @Override - public boolean supportsEventType(Class eventType) { - return containsElement(SUPPORTED_APPLICATION_EVENTS, eventType); - } - - @Override - public boolean supportsSourceType(Class sourceType) { - return true; - } - - @Override - public void onApplicationEvent(ApplicationEvent event) { - if (event instanceof ApplicationReadyEvent) { - onApplicationReadyEvent((ApplicationReadyEvent) event); - } - } - - @Override - public int getOrder() { - return LOWEST_PRECEDENCE; - } - - protected void onApplicationReadyEvent(ApplicationReadyEvent event) { - - final ConfigurableApplicationContext applicationContext = event.getApplicationContext(); - - if (!isRootApplicationContext(applicationContext) || isWebApplication(applicationContext)) { - return; - } - - if (applicationContextId.compareAndSet(UNDEFINED_ID, applicationContext.hashCode())) { - await(); - releaseOnExit(); - } - } - - /** - * @since 2.7.8 - */ - private void releaseOnExit() { - ShutdownHookCallbacks.INSTANCE.addCallback(this::release); - } - - private boolean isRootApplicationContext(ApplicationContext applicationContext) { - return applicationContext.getParent() == null; - } - - private boolean isWebApplication(ApplicationContext applicationContext) { - boolean webApplication = false; - for (String contextClass : WEB_APPLICATION_CONTEXT_CLASSES) { - if (isAssignable(contextClass, applicationContext.getClass(), applicationContext.getClassLoader())) { - webApplication = true; - break; - } - } - return webApplication; - } - - private static boolean isAssignable(String target, Class type, ClassLoader classLoader) { - try { - return ClassUtils.resolveClassName(target, classLoader).isAssignableFrom(type); - } catch (Throwable ex) { - return false; - } - } - - protected void await() { - - // has been waited, return immediately - if (awaited.get()) { - return; - } - - if (!executorService.isShutdown()) { - executorService.execute(() -> executeMutually(() -> { - while (!awaited.get()) { - if (logger.isInfoEnabled()) { - logger.info(" [Dubbo] Current Spring Boot Application is await..."); - } - try { - condition.await(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - })); - } - } - - protected void release() { - executeMutually(() -> { - while (awaited.compareAndSet(false, true)) { - if (logger.isInfoEnabled()) { - logger.info(" [Dubbo] Current Spring Boot Application is about to shutdown..."); - } - condition.signalAll(); - // @since 2.7.8 method shutdown() is combined into the method release() - shutdown(); - } - }); - } - - private void shutdown() { - if (!executorService.isShutdown()) { - // Shutdown executorService - executorService.shutdown(); - } - } - - private void executeMutually(Runnable runnable) { - try { - lock.lock(); - runnable.run(); - } finally { - lock.unlock(); - } - } -} +/* + * 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.spring.boot.context.event; + +import org.apache.dubbo.common.lang.ShutdownHookCallbacks; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.event.ContextClosedEvent; +import org.springframework.context.event.SmartApplicationListener; +import org.springframework.util.ClassUtils; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +import static java.util.concurrent.Executors.newSingleThreadExecutor; +import static org.springframework.util.ObjectUtils.containsElement; + +/** + * Awaiting Non-Web Spring Boot {@link ApplicationListener} + * + * @since 2.7.0 + */ +public class AwaitingNonWebApplicationListener implements SmartApplicationListener { + + private static final String[] WEB_APPLICATION_CONTEXT_CLASSES = new String[]{ + "org.springframework.web.context.WebApplicationContext", + "org.springframework.boot.web.reactive.context.ReactiveWebApplicationContext" + }; + + private static final Logger logger = LoggerFactory.getLogger(AwaitingNonWebApplicationListener.class); + + private static final Class[] SUPPORTED_APPLICATION_EVENTS = + of(ApplicationReadyEvent.class, ContextClosedEvent.class); + + private static final AtomicBoolean awaited = new AtomicBoolean(false); + + private static final Integer UNDEFINED_ID = Integer.valueOf(-1); + + /** + * Target the application id + */ + private static final AtomicInteger applicationContextId = new AtomicInteger(UNDEFINED_ID); + + private static final Lock lock = new ReentrantLock(); + + private static final Condition condition = lock.newCondition(); + + private static final ExecutorService executorService = newSingleThreadExecutor(); + + private static T[] of(T... values) { + return values; + } + + static AtomicBoolean getAwaited() { + return awaited; + } + + @Override + public boolean supportsEventType(Class eventType) { + return containsElement(SUPPORTED_APPLICATION_EVENTS, eventType); + } + + @Override + public boolean supportsSourceType(Class sourceType) { + return true; + } + + @Override + public void onApplicationEvent(ApplicationEvent event) { + if (event instanceof ApplicationReadyEvent) { + onApplicationReadyEvent((ApplicationReadyEvent) event); + } + } + + @Override + public int getOrder() { + return LOWEST_PRECEDENCE; + } + + protected void onApplicationReadyEvent(ApplicationReadyEvent event) { + + final ConfigurableApplicationContext applicationContext = event.getApplicationContext(); + + if (!isRootApplicationContext(applicationContext) || isWebApplication(applicationContext)) { + return; + } + + if (applicationContextId.compareAndSet(UNDEFINED_ID, applicationContext.hashCode())) { + await(); + releaseOnExit(); + } + } + + /** + * @since 2.7.8 + */ + private void releaseOnExit() { + ShutdownHookCallbacks.INSTANCE.addCallback(this::release); + } + + private boolean isRootApplicationContext(ApplicationContext applicationContext) { + return applicationContext.getParent() == null; + } + + private boolean isWebApplication(ApplicationContext applicationContext) { + boolean webApplication = false; + for (String contextClass : WEB_APPLICATION_CONTEXT_CLASSES) { + if (isAssignable(contextClass, applicationContext.getClass(), applicationContext.getClassLoader())) { + webApplication = true; + break; + } + } + return webApplication; + } + + private static boolean isAssignable(String target, Class type, ClassLoader classLoader) { + try { + return ClassUtils.resolveClassName(target, classLoader).isAssignableFrom(type); + } catch (Throwable ex) { + return false; + } + } + + protected void await() { + + // has been waited, return immediately + if (awaited.get()) { + return; + } + + if (!executorService.isShutdown()) { + executorService.execute(() -> executeMutually(() -> { + while (!awaited.get()) { + if (logger.isInfoEnabled()) { + logger.info(" [Dubbo] Current Spring Boot Application is await..."); + } + try { + condition.await(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + })); + } + } + + protected void release() { + executeMutually(() -> { + while (awaited.compareAndSet(false, true)) { + if (logger.isInfoEnabled()) { + logger.info(" [Dubbo] Current Spring Boot Application is about to shutdown..."); + } + condition.signalAll(); + // @since 2.7.8 method shutdown() is combined into the method release() + shutdown(); + } + }); + } + + private void shutdown() { + if (!executorService.isShutdown()) { + // Shutdown executorService + executorService.shutdown(); + } + } + + private void executeMutually(Runnable runnable) { + try { + lock.lock(); + runnable.run(); + } finally { + lock.unlock(); + } + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/context/event/DubboConfigBeanDefinitionConflictApplicationListener.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/context/event/DubboConfigBeanDefinitionConflictApplicationListener.java index f18c8b2e4e..ab85b502db 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/context/event/DubboConfigBeanDefinitionConflictApplicationListener.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/context/event/DubboConfigBeanDefinitionConflictApplicationListener.java @@ -1,121 +1,121 @@ -/* - * 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.spring.boot.context.event; - -import org.apache.dubbo.config.ApplicationConfig; -import org.apache.dubbo.config.spring.context.annotation.EnableDubboConfig; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.BeanFactoryUtils; -import org.springframework.beans.factory.ListableBeanFactory; -import org.springframework.beans.factory.config.AutowireCapableBeanFactory; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationListener; -import org.springframework.context.event.ContextRefreshedEvent; -import org.springframework.core.Ordered; -import org.springframework.core.env.Environment; - -import java.util.Objects; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static org.springframework.beans.factory.BeanFactoryUtils.beanNamesForTypeIncludingAncestors; -import static org.springframework.context.ConfigurableApplicationContext.ENVIRONMENT_BEAN_NAME; - -/** - * The {@link ApplicationListener} class for Dubbo Config {@link BeanDefinition Bean Definition} to resolve conflict - * @see BeanDefinition - * @see ApplicationListener - * @since 2.7.5 - */ -public class DubboConfigBeanDefinitionConflictApplicationListener implements ApplicationListener, - Ordered { - - private final Logger logger = LoggerFactory.getLogger(getClass()); - - @Override - public void onApplicationEvent(ContextRefreshedEvent event) { - ApplicationContext applicationContext = event.getApplicationContext(); - BeanDefinitionRegistry registry = getBeanDefinitionRegistry(applicationContext); - resolveUniqueApplicationConfigBean(registry, applicationContext); - } - - private BeanDefinitionRegistry getBeanDefinitionRegistry(ApplicationContext applicationContext) { - AutowireCapableBeanFactory beanFactory = applicationContext.getAutowireCapableBeanFactory(); - if (beanFactory instanceof BeanDefinitionRegistry) { - return (BeanDefinitionRegistry) beanFactory; - } - throw new IllegalStateException(""); - } - - /** - * Resolve the unique {@link ApplicationConfig} Bean - * @param registry {@link BeanDefinitionRegistry} instance - * @param beanFactory {@link ConfigurableListableBeanFactory} instance - * @see EnableDubboConfig - */ - private void resolveUniqueApplicationConfigBean(BeanDefinitionRegistry registry, ListableBeanFactory beanFactory) { - - String[] beansNames = beanNamesForTypeIncludingAncestors(beanFactory, ApplicationConfig.class); - - if (beansNames.length < 2) { // If the number of ApplicationConfig beans is less than two, return immediately. - return; - } - - Environment environment = beanFactory.getBean(ENVIRONMENT_BEAN_NAME, Environment.class); - - // Remove ApplicationConfig Beans that are configured by "dubbo.application.*" - Stream.of(beansNames) - .filter(beansName -> isConfiguredApplicationConfigBeanName(environment, beansName)) - .forEach(registry::removeBeanDefinition); - - beansNames = beanNamesForTypeIncludingAncestors(beanFactory, ApplicationConfig.class); - - if (beansNames.length > 1) { - throw new IllegalStateException(String.format("There are more than one instances of %s, whose bean definitions : %s", - ApplicationConfig.class.getSimpleName(), - Stream.of(beansNames) - .map(registry::getBeanDefinition) - .collect(Collectors.toList())) - ); - } - } - - private boolean isConfiguredApplicationConfigBeanName(Environment environment, String beanName) { - boolean removed = BeanFactoryUtils.isGeneratedBeanName(beanName) - // Dubbo ApplicationConfig id as bean name - || Objects.equals(beanName, environment.getProperty("dubbo.application.id")); - - if (removed) { - if (logger.isDebugEnabled()) { - logger.debug("The {} bean [ name : {} ] has been removed!", ApplicationConfig.class.getSimpleName(), beanName); - } - } - - return removed; - } - - - @Override - public int getOrder() { - return LOWEST_PRECEDENCE; - } -} +/* + * 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.spring.boot.context.event; + +import org.apache.dubbo.config.ApplicationConfig; +import org.apache.dubbo.config.spring.context.annotation.EnableDubboConfig; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.BeanFactoryUtils; +import org.springframework.beans.factory.ListableBeanFactory; +import org.springframework.beans.factory.config.AutowireCapableBeanFactory; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ContextRefreshedEvent; +import org.springframework.core.Ordered; +import org.springframework.core.env.Environment; + +import java.util.Objects; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.springframework.beans.factory.BeanFactoryUtils.beanNamesForTypeIncludingAncestors; +import static org.springframework.context.ConfigurableApplicationContext.ENVIRONMENT_BEAN_NAME; + +/** + * The {@link ApplicationListener} class for Dubbo Config {@link BeanDefinition Bean Definition} to resolve conflict + * @see BeanDefinition + * @see ApplicationListener + * @since 2.7.5 + */ +public class DubboConfigBeanDefinitionConflictApplicationListener implements ApplicationListener, + Ordered { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + @Override + public void onApplicationEvent(ContextRefreshedEvent event) { + ApplicationContext applicationContext = event.getApplicationContext(); + BeanDefinitionRegistry registry = getBeanDefinitionRegistry(applicationContext); + resolveUniqueApplicationConfigBean(registry, applicationContext); + } + + private BeanDefinitionRegistry getBeanDefinitionRegistry(ApplicationContext applicationContext) { + AutowireCapableBeanFactory beanFactory = applicationContext.getAutowireCapableBeanFactory(); + if (beanFactory instanceof BeanDefinitionRegistry) { + return (BeanDefinitionRegistry) beanFactory; + } + throw new IllegalStateException(""); + } + + /** + * Resolve the unique {@link ApplicationConfig} Bean + * @param registry {@link BeanDefinitionRegistry} instance + * @param beanFactory {@link ConfigurableListableBeanFactory} instance + * @see EnableDubboConfig + */ + private void resolveUniqueApplicationConfigBean(BeanDefinitionRegistry registry, ListableBeanFactory beanFactory) { + + String[] beansNames = beanNamesForTypeIncludingAncestors(beanFactory, ApplicationConfig.class); + + if (beansNames.length < 2) { // If the number of ApplicationConfig beans is less than two, return immediately. + return; + } + + Environment environment = beanFactory.getBean(ENVIRONMENT_BEAN_NAME, Environment.class); + + // Remove ApplicationConfig Beans that are configured by "dubbo.application.*" + Stream.of(beansNames) + .filter(beansName -> isConfiguredApplicationConfigBeanName(environment, beansName)) + .forEach(registry::removeBeanDefinition); + + beansNames = beanNamesForTypeIncludingAncestors(beanFactory, ApplicationConfig.class); + + if (beansNames.length > 1) { + throw new IllegalStateException(String.format("There are more than one instances of %s, whose bean definitions : %s", + ApplicationConfig.class.getSimpleName(), + Stream.of(beansNames) + .map(registry::getBeanDefinition) + .collect(Collectors.toList())) + ); + } + } + + private boolean isConfiguredApplicationConfigBeanName(Environment environment, String beanName) { + boolean removed = BeanFactoryUtils.isGeneratedBeanName(beanName) + // Dubbo ApplicationConfig id as bean name + || Objects.equals(beanName, environment.getProperty("dubbo.application.id")); + + if (removed) { + if (logger.isDebugEnabled()) { + logger.debug("The {} bean [ name : {} ] has been removed!", ApplicationConfig.class.getSimpleName(), beanName); + } + } + + return removed; + } + + + @Override + public int getOrder() { + return LOWEST_PRECEDENCE; + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/context/event/WelcomeLogoApplicationListener.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/context/event/WelcomeLogoApplicationListener.java index 7aa0d8d3e9..8e9232c354 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/context/event/WelcomeLogoApplicationListener.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/context/event/WelcomeLogoApplicationListener.java @@ -1,94 +1,95 @@ -/* - * 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.spring.boot.context.event; - -import org.apache.dubbo.common.Version; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; -import org.springframework.context.ApplicationListener; -import org.springframework.core.Ordered; -import org.springframework.core.annotation.Order; - -import java.util.concurrent.atomic.AtomicBoolean; - -import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_GITHUB_URL; -import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_MAILING_LIST; -import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_SPRING_BOOT_GITHUB_URL; -import static org.apache.dubbo.spring.boot.util.DubboUtils.LINE_SEPARATOR; - -/** - * Dubbo Welcome Logo {@link ApplicationListener} - * - * @see ApplicationListener - * @since 2.7.0 - */ -@Order(Ordered.HIGHEST_PRECEDENCE + 20 + 1) // After LoggingApplicationListener#DEFAULT_ORDER -public class WelcomeLogoApplicationListener implements ApplicationListener { - - private static AtomicBoolean processed = new AtomicBoolean(false); - - @Override - public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) { - - // Skip if processed before, prevent duplicated execution in Hierarchical ApplicationContext - if (processed.get()) { - return; - } - - /** - * Gets Logger After LoggingSystem configuration ready - * @see LoggingApplicationListener - */ - final Logger logger = LoggerFactory.getLogger(getClass()); - - String bannerText = buildBannerText(); - - if (logger.isInfoEnabled()) { - logger.info(bannerText); - } else { - System.out.print(bannerText); - } - - // mark processed to be true - processed.compareAndSet(false, true); - } - - String buildBannerText() { - - StringBuilder bannerTextBuilder = new StringBuilder(); - - bannerTextBuilder - .append(LINE_SEPARATOR) - .append(LINE_SEPARATOR) - .append(" :: Dubbo Spring Boot (v").append(Version.getVersion(getClass(), Version.getVersion())).append(") : ") - .append(DUBBO_SPRING_BOOT_GITHUB_URL) - .append(LINE_SEPARATOR) - .append(" :: Dubbo (v").append(Version.getVersion()).append(") : ") - .append(DUBBO_GITHUB_URL) - .append(LINE_SEPARATOR) - .append(" :: Discuss group : ") - .append(DUBBO_MAILING_LIST) - .append(LINE_SEPARATOR) - ; - - return bannerTextBuilder.toString(); - - } - -} +/* + * 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.spring.boot.context.event; + +import org.apache.dubbo.common.Version; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; +import org.springframework.boot.logging.LoggingApplicationListener; +import org.springframework.context.ApplicationListener; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; + +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_GITHUB_URL; +import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_MAILING_LIST; +import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_SPRING_BOOT_GITHUB_URL; +import static org.apache.dubbo.spring.boot.util.DubboUtils.LINE_SEPARATOR; + +/** + * Dubbo Welcome Logo {@link ApplicationListener} + * + * @see ApplicationListener + * @since 2.7.0 + */ +@Order(Ordered.HIGHEST_PRECEDENCE + 20 + 1) // After LoggingApplicationListener#DEFAULT_ORDER +public class WelcomeLogoApplicationListener implements ApplicationListener { + + private static AtomicBoolean processed = new AtomicBoolean(false); + + @Override + public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) { + + // Skip if processed before, prevent duplicated execution in Hierarchical ApplicationContext + if (processed.get()) { + return; + } + + /** + * Gets Logger After LoggingSystem configuration ready + * @see LoggingApplicationListener + */ + final Logger logger = LoggerFactory.getLogger(getClass()); + + String bannerText = buildBannerText(); + + if (logger.isInfoEnabled()) { + logger.info(bannerText); + } else { + System.out.print(bannerText); + } + + // mark processed to be true + processed.compareAndSet(false, true); + } + + String buildBannerText() { + + StringBuilder bannerTextBuilder = new StringBuilder(); + + bannerTextBuilder + .append(LINE_SEPARATOR) + .append(LINE_SEPARATOR) + .append(" :: Dubbo Spring Boot (v").append(Version.getVersion(getClass(), Version.getVersion())).append(") : ") + .append(DUBBO_SPRING_BOOT_GITHUB_URL) + .append(LINE_SEPARATOR) + .append(" :: Dubbo (v").append(Version.getVersion()).append(") : ") + .append(DUBBO_GITHUB_URL) + .append(LINE_SEPARATOR) + .append(" :: Discuss group : ") + .append(DUBBO_MAILING_LIST) + .append(LINE_SEPARATOR) + ; + + return bannerTextBuilder.toString(); + + } + +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/env/DubboDefaultPropertiesEnvironmentPostProcessor.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/env/DubboDefaultPropertiesEnvironmentPostProcessor.java index 920c4c91d2..941c1ef3af 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/env/DubboDefaultPropertiesEnvironmentPostProcessor.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/env/DubboDefaultPropertiesEnvironmentPostProcessor.java @@ -1,136 +1,136 @@ -/* - * 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.spring.boot.env; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.env.EnvironmentPostProcessor; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.core.Ordered; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.core.env.Environment; -import org.springframework.core.env.MapPropertySource; -import org.springframework.core.env.MutablePropertySources; -import org.springframework.core.env.PropertySource; -import org.springframework.util.CollectionUtils; -import org.springframework.util.StringUtils; - -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; - -import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_APPLICATION_NAME_PROPERTY; -import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_APPLICATION_QOS_ENABLE_PROPERTY; -import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_CONFIG_MULTIPLE_PROPERTY; -import static org.apache.dubbo.spring.boot.util.DubboUtils.SPRING_APPLICATION_NAME_PROPERTY; - -/** - * The lowest precedence {@link EnvironmentPostProcessor} processes - * {@link SpringApplication#setDefaultProperties(Properties) Spring Boot default properties} for Dubbo - * as late as possible before {@link ConfigurableApplicationContext#refresh() application context refresh}. - */ -public class DubboDefaultPropertiesEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered { - - /** - * The name of default {@link PropertySource} defined in SpringApplication#configurePropertySources method. - */ - public static final String PROPERTY_SOURCE_NAME = "defaultProperties"; - - /** - * The property name of "spring.main.allow-bean-definition-overriding". - * Please refer to: https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.1-Release-Notes#bean-overriding - */ - public static final String ALLOW_BEAN_DEFINITION_OVERRIDING_PROPERTY = "spring.main.allow-bean-definition-overriding"; - - @Override - public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { - MutablePropertySources propertySources = environment.getPropertySources(); - Map defaultProperties = createDefaultProperties(environment); - if (!CollectionUtils.isEmpty(defaultProperties)) { - addOrReplace(propertySources, defaultProperties); - } - } - - @Override - public int getOrder() { - return LOWEST_PRECEDENCE; - } - - private Map createDefaultProperties(ConfigurableEnvironment environment) { - Map defaultProperties = new HashMap<>(); - setDubboApplicationNameProperty(environment, defaultProperties); - setDubboConfigMultipleProperty(defaultProperties); - setDubboApplicationQosEnableProperty(defaultProperties); - //setAllowBeanDefinitionOverriding(defaultProperties); - return defaultProperties; - } - - private void setDubboApplicationNameProperty(Environment environment, Map defaultProperties) { - String springApplicationName = environment.getProperty(SPRING_APPLICATION_NAME_PROPERTY); - if (StringUtils.hasLength(springApplicationName) - && !environment.containsProperty(DUBBO_APPLICATION_NAME_PROPERTY)) { - defaultProperties.put(DUBBO_APPLICATION_NAME_PROPERTY, springApplicationName); - } - } - - private void setDubboConfigMultipleProperty(Map defaultProperties) { - defaultProperties.put(DUBBO_CONFIG_MULTIPLE_PROPERTY, Boolean.TRUE.toString()); - } - - private void setDubboApplicationQosEnableProperty(Map defaultProperties) { - defaultProperties.put(DUBBO_APPLICATION_QOS_ENABLE_PROPERTY, Boolean.FALSE.toString()); - } - - /** - * Set {@link #ALLOW_BEAN_DEFINITION_OVERRIDING_PROPERTY "spring.main.allow-bean-definition-overriding"} to be - * true as default. - * - * @param defaultProperties the default {@link Properties properties} - * @see #ALLOW_BEAN_DEFINITION_OVERRIDING_PROPERTY - * @since 2.7.1 - */ - private void setAllowBeanDefinitionOverriding(Map defaultProperties) { - defaultProperties.put(ALLOW_BEAN_DEFINITION_OVERRIDING_PROPERTY, Boolean.TRUE.toString()); - } - - /** - * Copy from BusEnvironmentPostProcessor#addOrReplace(MutablePropertySources, Map) - * - * @param propertySources {@link MutablePropertySources} - * @param map Default Dubbo Properties - */ - private void addOrReplace(MutablePropertySources propertySources, - Map map) { - MapPropertySource target = null; - if (propertySources.contains(PROPERTY_SOURCE_NAME)) { - PropertySource source = propertySources.get(PROPERTY_SOURCE_NAME); - if (source instanceof MapPropertySource) { - target = (MapPropertySource) source; - for (String key : map.keySet()) { - if (!target.containsProperty(key)) { - target.getSource().put(key, map.get(key)); - } - } - } - } - if (target == null) { - target = new MapPropertySource(PROPERTY_SOURCE_NAME, map); - } - if (!propertySources.contains(PROPERTY_SOURCE_NAME)) { - propertySources.addLast(target); - } - } -} \ No newline at end of file +/* + * 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.spring.boot.env; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.env.EnvironmentPostProcessor; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.core.Ordered; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.Environment; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.MutablePropertySources; +import org.springframework.core.env.PropertySource; +import org.springframework.util.CollectionUtils; +import org.springframework.util.StringUtils; + +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_APPLICATION_NAME_PROPERTY; +import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_APPLICATION_QOS_ENABLE_PROPERTY; +import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_CONFIG_MULTIPLE_PROPERTY; +import static org.apache.dubbo.spring.boot.util.DubboUtils.SPRING_APPLICATION_NAME_PROPERTY; + +/** + * The lowest precedence {@link EnvironmentPostProcessor} processes + * {@link SpringApplication#setDefaultProperties(Properties) Spring Boot default properties} for Dubbo + * as late as possible before {@link ConfigurableApplicationContext#refresh() application context refresh}. + */ +public class DubboDefaultPropertiesEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered { + + /** + * The name of default {@link PropertySource} defined in SpringApplication#configurePropertySources method. + */ + public static final String PROPERTY_SOURCE_NAME = "defaultProperties"; + + /** + * The property name of "spring.main.allow-bean-definition-overriding". + * Please refer to: https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.1-Release-Notes#bean-overriding + */ + public static final String ALLOW_BEAN_DEFINITION_OVERRIDING_PROPERTY = "spring.main.allow-bean-definition-overriding"; + + @Override + public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { + MutablePropertySources propertySources = environment.getPropertySources(); + Map defaultProperties = createDefaultProperties(environment); + if (!CollectionUtils.isEmpty(defaultProperties)) { + addOrReplace(propertySources, defaultProperties); + } + } + + @Override + public int getOrder() { + return LOWEST_PRECEDENCE; + } + + private Map createDefaultProperties(ConfigurableEnvironment environment) { + Map defaultProperties = new HashMap<>(); + setDubboApplicationNameProperty(environment, defaultProperties); + setDubboConfigMultipleProperty(defaultProperties); + setDubboApplicationQosEnableProperty(defaultProperties); + //setAllowBeanDefinitionOverriding(defaultProperties); + return defaultProperties; + } + + private void setDubboApplicationNameProperty(Environment environment, Map defaultProperties) { + String springApplicationName = environment.getProperty(SPRING_APPLICATION_NAME_PROPERTY); + if (StringUtils.hasLength(springApplicationName) + && !environment.containsProperty(DUBBO_APPLICATION_NAME_PROPERTY)) { + defaultProperties.put(DUBBO_APPLICATION_NAME_PROPERTY, springApplicationName); + } + } + + private void setDubboConfigMultipleProperty(Map defaultProperties) { + defaultProperties.put(DUBBO_CONFIG_MULTIPLE_PROPERTY, Boolean.TRUE.toString()); + } + + private void setDubboApplicationQosEnableProperty(Map defaultProperties) { + defaultProperties.put(DUBBO_APPLICATION_QOS_ENABLE_PROPERTY, Boolean.FALSE.toString()); + } + + /** + * Set {@link #ALLOW_BEAN_DEFINITION_OVERRIDING_PROPERTY "spring.main.allow-bean-definition-overriding"} to be + * true as default. + * + * @param defaultProperties the default {@link Properties properties} + * @see #ALLOW_BEAN_DEFINITION_OVERRIDING_PROPERTY + * @since 2.7.1 + */ + private void setAllowBeanDefinitionOverriding(Map defaultProperties) { + defaultProperties.put(ALLOW_BEAN_DEFINITION_OVERRIDING_PROPERTY, Boolean.TRUE.toString()); + } + + /** + * Copy from BusEnvironmentPostProcessor#addOrReplace(MutablePropertySources, Map) + * + * @param propertySources {@link MutablePropertySources} + * @param map Default Dubbo Properties + */ + private void addOrReplace(MutablePropertySources propertySources, + Map map) { + MapPropertySource target = null; + if (propertySources.contains(PROPERTY_SOURCE_NAME)) { + PropertySource source = propertySources.get(PROPERTY_SOURCE_NAME); + if (source instanceof MapPropertySource) { + target = (MapPropertySource) source; + for (String key : map.keySet()) { + if (!target.containsProperty(key)) { + target.getSource().put(key, map.get(key)); + } + } + } + } + if (target == null) { + target = new MapPropertySource(PROPERTY_SOURCE_NAME, map); + } + if (!propertySources.contains(PROPERTY_SOURCE_NAME)) { + propertySources.addLast(target); + } + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/util/DubboUtils.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/util/DubboUtils.java index 186b6d6bc5..dae3d8211a 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/util/DubboUtils.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/util/DubboUtils.java @@ -1,184 +1,184 @@ -/* - * 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.spring.boot.util; - -import org.apache.dubbo.config.ApplicationConfig; -import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationPostProcessor; -import org.apache.dubbo.config.spring.context.annotation.EnableDubboConfig; -import org.apache.dubbo.config.spring.context.properties.DubboConfigBinder; - -import org.springframework.boot.context.ContextIdApplicationContextInitializer; -import org.springframework.core.env.PropertyResolver; - -import java.util.Set; - -/** - * The utilities class for Dubbo - * - * @since 2.7.0 - */ -public abstract class DubboUtils { - - /** - * line separator - */ - public static final String LINE_SEPARATOR = System.getProperty("line.separator"); - - - /** - * The separator of property name - */ - public static final String PROPERTY_NAME_SEPARATOR = "."; - - /** - * The prefix of property name of Dubbo - */ - public static final String DUBBO_PREFIX = "dubbo"; - - /** - * The prefix of property name for Dubbo scan - */ - public static final String DUBBO_SCAN_PREFIX = DUBBO_PREFIX + PROPERTY_NAME_SEPARATOR + "scan" + PROPERTY_NAME_SEPARATOR; - - /** - * The prefix of property name for Dubbo Config - */ - public static final String DUBBO_CONFIG_PREFIX = DUBBO_PREFIX + PROPERTY_NAME_SEPARATOR + "config" + PROPERTY_NAME_SEPARATOR; - - /** - * The property name of base packages to scan - *

- * The default value is empty set. - */ - public static final String BASE_PACKAGES_PROPERTY_NAME = "base-packages"; - - /** - * The property name of multiple properties binding from externalized configuration - *

- * The default value is {@link #DEFAULT_MULTIPLE_CONFIG_PROPERTY_VALUE} - * - * @deprecated 2.7.8 It will be remove in the future, {@link EnableDubboConfig} instead - */ - @Deprecated - public static final String MULTIPLE_CONFIG_PROPERTY_NAME = "multiple"; - - /** - * The default value of multiple properties binding from externalized configuration - * - * @deprecated 2.7.8 It will be remove in the future - */ - @Deprecated - public static final boolean DEFAULT_MULTIPLE_CONFIG_PROPERTY_VALUE = true; - - /** - * The property name of override Dubbo config - *

- * The default value is {@link #DEFAULT_OVERRIDE_CONFIG_PROPERTY_VALUE} - */ - public static final String OVERRIDE_CONFIG_FULL_PROPERTY_NAME = DUBBO_CONFIG_PREFIX + "override"; - - /** - * The default property value of override Dubbo config - */ - public static final boolean DEFAULT_OVERRIDE_CONFIG_PROPERTY_VALUE = true; - - - /** - * The github URL of Dubbo Spring Boot - */ - public static final String DUBBO_SPRING_BOOT_GITHUB_URL = "https://github.com/apache/dubbo-spring-boot-project"; - - /** - * The git URL of Dubbo Spring Boot - */ - public static final String DUBBO_SPRING_BOOT_GIT_URL = "https://github.com/apache/dubbo-spring-boot-project.git"; - - /** - * The issues of Dubbo Spring Boot - */ - public static final String DUBBO_SPRING_BOOT_ISSUES_URL = "https://github.com/apache/dubbo-spring-boot-project/issues"; - - /** - * The github URL of Dubbo - */ - public static final String DUBBO_GITHUB_URL = "https://github.com/apache/dubbo"; - - /** - * The google group URL of Dubbo - */ - public static final String DUBBO_MAILING_LIST = "dev@dubbo.apache.org"; - - /** - * The bean name of Relaxed-binding {@link DubboConfigBinder} - */ - public static final String RELAXED_DUBBO_CONFIG_BINDER_BEAN_NAME = "relaxedDubboConfigBinder"; - - /** - * The bean name of {@link PropertyResolver} for {@link ServiceAnnotationPostProcessor}'s base-packages - * - * @deprecated 2.7.8 It will be remove in the future, please use {@link #BASE_PACKAGES_BEAN_NAME} - */ - @Deprecated - public static final String BASE_PACKAGES_PROPERTY_RESOLVER_BEAN_NAME = "dubboScanBasePackagesPropertyResolver"; - - /** - * The bean name of {@link Set} presenting {@link ServiceAnnotationPostProcessor}'s base-packages - * - * @since 2.7.8 - */ - public static final String BASE_PACKAGES_BEAN_NAME = "dubbo-service-class-base-packages"; - - /** - * The property name of Spring Application - * - * @see ContextIdApplicationContextInitializer - * @since 2.7.1 - */ - public static final String SPRING_APPLICATION_NAME_PROPERTY = "spring.application.name"; - - /** - * The property id of {@link ApplicationConfig} Bean - * - * @see EnableDubboConfig - * @since 2.7.1 - */ - public static final String DUBBO_APPLICATION_ID_PROPERTY = "dubbo.application.id"; - - /** - * The property name of {@link ApplicationConfig} - * - * @see EnableDubboConfig - * @since 2.7.1 - */ - public static final String DUBBO_APPLICATION_NAME_PROPERTY = "dubbo.application.name"; - - /** - * The property name of {@link ApplicationConfig#getQosEnable() application's QOS enable} - * - * @since 2.7.1 - */ - public static final String DUBBO_APPLICATION_QOS_ENABLE_PROPERTY = "dubbo.application.qos-enable"; - - /** - * The property name of {@link EnableDubboConfig#multiple() @EnableDubboConfig.multiple()} - * - * @since 2.7.1 - */ - public static final String DUBBO_CONFIG_MULTIPLE_PROPERTY = "dubbo.config.multiple"; - - -} +/* + * 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.spring.boot.util; + +import org.apache.dubbo.config.ApplicationConfig; +import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationPostProcessor; +import org.apache.dubbo.config.spring.context.annotation.EnableDubboConfig; +import org.apache.dubbo.config.spring.context.properties.DubboConfigBinder; + +import org.springframework.boot.context.ContextIdApplicationContextInitializer; +import org.springframework.core.env.PropertyResolver; + +import java.util.Set; + +/** + * The utilities class for Dubbo + * + * @since 2.7.0 + */ +public abstract class DubboUtils { + + /** + * line separator + */ + public static final String LINE_SEPARATOR = System.getProperty("line.separator"); + + + /** + * The separator of property name + */ + public static final String PROPERTY_NAME_SEPARATOR = "."; + + /** + * The prefix of property name of Dubbo + */ + public static final String DUBBO_PREFIX = "dubbo"; + + /** + * The prefix of property name for Dubbo scan + */ + public static final String DUBBO_SCAN_PREFIX = DUBBO_PREFIX + PROPERTY_NAME_SEPARATOR + "scan" + PROPERTY_NAME_SEPARATOR; + + /** + * The prefix of property name for Dubbo Config + */ + public static final String DUBBO_CONFIG_PREFIX = DUBBO_PREFIX + PROPERTY_NAME_SEPARATOR + "config" + PROPERTY_NAME_SEPARATOR; + + /** + * The property name of base packages to scan + *

+ * The default value is empty set. + */ + public static final String BASE_PACKAGES_PROPERTY_NAME = "base-packages"; + + /** + * The property name of multiple properties binding from externalized configuration + *

+ * The default value is {@link #DEFAULT_MULTIPLE_CONFIG_PROPERTY_VALUE} + * + * @deprecated 2.7.8 It will be remove in the future, {@link EnableDubboConfig} instead + */ + @Deprecated + public static final String MULTIPLE_CONFIG_PROPERTY_NAME = "multiple"; + + /** + * The default value of multiple properties binding from externalized configuration + * + * @deprecated 2.7.8 It will be remove in the future + */ + @Deprecated + public static final boolean DEFAULT_MULTIPLE_CONFIG_PROPERTY_VALUE = true; + + /** + * The property name of override Dubbo config + *

+ * The default value is {@link #DEFAULT_OVERRIDE_CONFIG_PROPERTY_VALUE} + */ + public static final String OVERRIDE_CONFIG_FULL_PROPERTY_NAME = DUBBO_CONFIG_PREFIX + "override"; + + /** + * The default property value of override Dubbo config + */ + public static final boolean DEFAULT_OVERRIDE_CONFIG_PROPERTY_VALUE = true; + + + /** + * The github URL of Dubbo Spring Boot + */ + public static final String DUBBO_SPRING_BOOT_GITHUB_URL = "https://github.com/apache/dubbo-spring-boot-project"; + + /** + * The git URL of Dubbo Spring Boot + */ + public static final String DUBBO_SPRING_BOOT_GIT_URL = "https://github.com/apache/dubbo-spring-boot-project.git"; + + /** + * The issues of Dubbo Spring Boot + */ + public static final String DUBBO_SPRING_BOOT_ISSUES_URL = "https://github.com/apache/dubbo-spring-boot-project/issues"; + + /** + * The github URL of Dubbo + */ + public static final String DUBBO_GITHUB_URL = "https://github.com/apache/dubbo"; + + /** + * The google group URL of Dubbo + */ + public static final String DUBBO_MAILING_LIST = "dev@dubbo.apache.org"; + + /** + * The bean name of Relaxed-binding {@link DubboConfigBinder} + */ + public static final String RELAXED_DUBBO_CONFIG_BINDER_BEAN_NAME = "relaxedDubboConfigBinder"; + + /** + * The bean name of {@link PropertyResolver} for {@link ServiceAnnotationPostProcessor}'s base-packages + * + * @deprecated 2.7.8 It will be remove in the future, please use {@link #BASE_PACKAGES_BEAN_NAME} + */ + @Deprecated + public static final String BASE_PACKAGES_PROPERTY_RESOLVER_BEAN_NAME = "dubboScanBasePackagesPropertyResolver"; + + /** + * The bean name of {@link Set} presenting {@link ServiceAnnotationPostProcessor}'s base-packages + * + * @since 2.7.8 + */ + public static final String BASE_PACKAGES_BEAN_NAME = "dubbo-service-class-base-packages"; + + /** + * The property name of Spring Application + * + * @see ContextIdApplicationContextInitializer + * @since 2.7.1 + */ + public static final String SPRING_APPLICATION_NAME_PROPERTY = "spring.application.name"; + + /** + * The property id of {@link ApplicationConfig} Bean + * + * @see EnableDubboConfig + * @since 2.7.1 + */ + public static final String DUBBO_APPLICATION_ID_PROPERTY = "dubbo.application.id"; + + /** + * The property name of {@link ApplicationConfig} + * + * @see EnableDubboConfig + * @since 2.7.1 + */ + public static final String DUBBO_APPLICATION_NAME_PROPERTY = "dubbo.application.name"; + + /** + * The property name of {@link ApplicationConfig#getQosEnable() application's QOS enable} + * + * @since 2.7.1 + */ + public static final String DUBBO_APPLICATION_QOS_ENABLE_PROPERTY = "dubbo.application.qos-enable"; + + /** + * The property name of {@link EnableDubboConfig#multiple() @EnableDubboConfig.multiple()} + * + * @since 2.7.1 + */ + public static final String DUBBO_CONFIG_MULTIPLE_PROPERTY = "dubbo.config.multiple"; + + +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/resources/META-INF/spring.factories b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/resources/META-INF/spring.factories index 7de04eb6f7..9aacc99e12 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/resources/META-INF/spring.factories +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/resources/META-INF/spring.factories @@ -1,11 +1,11 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -org.apache.dubbo.spring.boot.autoconfigure.DubboAutoConfiguration,\ -org.apache.dubbo.spring.boot.autoconfigure.DubboRelaxedBindingAutoConfiguration -org.springframework.context.ApplicationListener=\ -org.apache.dubbo.spring.boot.context.event.DubboConfigBeanDefinitionConflictApplicationListener,\ -org.apache.dubbo.spring.boot.context.event.WelcomeLogoApplicationListener,\ -org.apache.dubbo.spring.boot.context.event.AwaitingNonWebApplicationListener -org.springframework.boot.env.EnvironmentPostProcessor=\ -org.apache.dubbo.spring.boot.env.DubboDefaultPropertiesEnvironmentPostProcessor -org.springframework.context.ApplicationContextInitializer=\ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ +org.apache.dubbo.spring.boot.autoconfigure.DubboAutoConfiguration,\ +org.apache.dubbo.spring.boot.autoconfigure.DubboRelaxedBindingAutoConfiguration +org.springframework.context.ApplicationListener=\ +org.apache.dubbo.spring.boot.context.event.DubboConfigBeanDefinitionConflictApplicationListener,\ +org.apache.dubbo.spring.boot.context.event.WelcomeLogoApplicationListener,\ +org.apache.dubbo.spring.boot.context.event.AwaitingNonWebApplicationListener +org.springframework.boot.env.EnvironmentPostProcessor=\ +org.apache.dubbo.spring.boot.env.DubboDefaultPropertiesEnvironmentPostProcessor +org.springframework.context.ApplicationContextInitializer=\ org.apache.dubbo.spring.boot.context.DubboApplicationContextInitializer \ No newline at end of file diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/TestSuite.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/TestSuite.java index 9dd185e000..e01131891f 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/TestSuite.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/TestSuite.java @@ -1,47 +1,47 @@ -/* - * 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.spring.boot; - -import org.apache.dubbo.spring.boot.autoconfigure.CompatibleDubboAutoConfigurationTest; -import org.apache.dubbo.spring.boot.autoconfigure.CompatibleDubboAutoConfigurationTestWithoutProperties; -import org.apache.dubbo.spring.boot.autoconfigure.DubboAutoConfigurationOnMultipleConfigTest; -import org.apache.dubbo.spring.boot.autoconfigure.DubboAutoConfigurationOnSingleConfigTest; -import org.apache.dubbo.spring.boot.autoconfigure.RelaxedDubboConfigBinderTest; -import org.apache.dubbo.spring.boot.context.event.AwaitingNonWebApplicationListenerTest; -import org.apache.dubbo.spring.boot.context.event.DubboConfigBeanDefinitionConflictApplicationListenerTest; -import org.apache.dubbo.spring.boot.context.event.WelcomeLogoApplicationListenerTest; -import org.apache.dubbo.spring.boot.env.DubboDefaultPropertiesEnvironmentPostProcessorTest; -import org.apache.dubbo.spring.boot.util.DubboUtilsTest; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; - -@RunWith(Suite.class) -@Suite.SuiteClasses({ - CompatibleDubboAutoConfigurationTest.class, - CompatibleDubboAutoConfigurationTestWithoutProperties.class, - DubboAutoConfigurationOnMultipleConfigTest.class, - DubboAutoConfigurationOnSingleConfigTest.class, - RelaxedDubboConfigBinderTest.class, - AwaitingNonWebApplicationListenerTest.class, - DubboConfigBeanDefinitionConflictApplicationListenerTest.class, - WelcomeLogoApplicationListenerTest.class, - DubboDefaultPropertiesEnvironmentPostProcessorTest.class, - DubboUtilsTest.class, -}) -public class TestSuite { -} +/* + * 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.spring.boot; + +import org.apache.dubbo.spring.boot.autoconfigure.CompatibleDubboAutoConfigurationTest; +import org.apache.dubbo.spring.boot.autoconfigure.CompatibleDubboAutoConfigurationTestWithoutProperties; +import org.apache.dubbo.spring.boot.autoconfigure.DubboAutoConfigurationOnMultipleConfigTest; +import org.apache.dubbo.spring.boot.autoconfigure.DubboAutoConfigurationOnSingleConfigTest; +import org.apache.dubbo.spring.boot.autoconfigure.RelaxedDubboConfigBinderTest; +import org.apache.dubbo.spring.boot.context.event.AwaitingNonWebApplicationListenerTest; +import org.apache.dubbo.spring.boot.context.event.DubboConfigBeanDefinitionConflictApplicationListenerTest; +import org.apache.dubbo.spring.boot.context.event.WelcomeLogoApplicationListenerTest; +import org.apache.dubbo.spring.boot.env.DubboDefaultPropertiesEnvironmentPostProcessorTest; +import org.apache.dubbo.spring.boot.util.DubboUtilsTest; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ + CompatibleDubboAutoConfigurationTest.class, + CompatibleDubboAutoConfigurationTestWithoutProperties.class, + DubboAutoConfigurationOnMultipleConfigTest.class, + DubboAutoConfigurationOnSingleConfigTest.class, + RelaxedDubboConfigBinderTest.class, + AwaitingNonWebApplicationListenerTest.class, + DubboConfigBeanDefinitionConflictApplicationListenerTest.class, + WelcomeLogoApplicationListenerTest.class, + DubboDefaultPropertiesEnvironmentPostProcessorTest.class, + DubboUtilsTest.class, +}) +public class TestSuite { +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/CompatibleDubboAutoConfigurationTest.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/CompatibleDubboAutoConfigurationTest.java index 3c94369409..6713deeb9b 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/CompatibleDubboAutoConfigurationTest.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/CompatibleDubboAutoConfigurationTest.java @@ -1,59 +1,59 @@ -/* - * 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.spring.boot.autoconfigure; - -import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor; -import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationPostProcessor; - -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.ObjectProvider; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.annotation.PropertySource; -import org.springframework.test.context.junit4.SpringRunner; - -/** - * {@link DubboAutoConfiguration} Test - * @see DubboAutoConfiguration - */ -@RunWith(SpringRunner.class) -@SpringBootTest(classes = { - CompatibleDubboAutoConfigurationTest.class -}, properties = { - "dubbo.scan.base-packages = org.apache.dubbo.spring.boot.autoconfigure" -}) -@EnableAutoConfiguration -@PropertySource(value = "classpath:/META-INF/dubbo.properties") -public class CompatibleDubboAutoConfigurationTest { - - @Autowired - private ObjectProvider serviceAnnotationPostProcessor; - - @Autowired - private ObjectProvider referenceAnnotationBeanPostProcessor; - - @Test - public void testBeans() { - Assert.assertNotNull(serviceAnnotationPostProcessor); - Assert.assertNotNull(serviceAnnotationPostProcessor.getIfAvailable()); - Assert.assertNotNull(referenceAnnotationBeanPostProcessor); - Assert.assertNotNull(referenceAnnotationBeanPostProcessor.getIfAvailable()); - } -} +/* + * 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.spring.boot.autoconfigure; + +import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor; +import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationPostProcessor; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.PropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +/** + * {@link DubboAutoConfiguration} Test + * @see DubboAutoConfiguration + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = { + CompatibleDubboAutoConfigurationTest.class +}, properties = { + "dubbo.scan.base-packages = org.apache.dubbo.spring.boot.autoconfigure" +}) +@EnableAutoConfiguration +@PropertySource(value = "classpath:/META-INF/dubbo.properties") +public class CompatibleDubboAutoConfigurationTest { + + @Autowired + private ObjectProvider serviceAnnotationPostProcessor; + + @Autowired + private ObjectProvider referenceAnnotationBeanPostProcessor; + + @Test + public void testBeans() { + Assert.assertNotNull(serviceAnnotationPostProcessor); + Assert.assertNotNull(serviceAnnotationPostProcessor.getIfAvailable()); + Assert.assertNotNull(referenceAnnotationBeanPostProcessor); + Assert.assertNotNull(referenceAnnotationBeanPostProcessor.getIfAvailable()); + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/CompatibleDubboAutoConfigurationTestWithoutProperties.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/CompatibleDubboAutoConfigurationTestWithoutProperties.java index bb1b236b15..2feb07477e 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/CompatibleDubboAutoConfigurationTestWithoutProperties.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/CompatibleDubboAutoConfigurationTestWithoutProperties.java @@ -1,66 +1,66 @@ -/* - * 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.spring.boot.autoconfigure; - -import org.apache.dubbo.config.bootstrap.DubboBootstrap; -import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor; -import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationPostProcessor; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -/** - * {@link DubboAutoConfiguration} Test - * - * @see DubboAutoConfiguration - */ -@RunWith(SpringRunner.class) -@SpringBootTest(classes = CompatibleDubboAutoConfigurationTestWithoutProperties.class, properties = { - "dubbo.application.name=demo" -}) -@EnableAutoConfiguration -public class CompatibleDubboAutoConfigurationTestWithoutProperties { - - @Autowired(required = false) - private ServiceAnnotationPostProcessor serviceAnnotationPostProcessor; - - @Autowired - private ReferenceAnnotationBeanPostProcessor referenceAnnotationBeanPostProcessor; - - @Before - public void init() { - DubboBootstrap.reset(); - } - - @After - public void destroy() { - DubboBootstrap.reset(); - } - - @Test - public void testBeans() { - Assert.assertNull(serviceAnnotationPostProcessor); - Assert.assertNotNull(referenceAnnotationBeanPostProcessor); - } -} +/* + * 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.spring.boot.autoconfigure; + +import org.apache.dubbo.config.bootstrap.DubboBootstrap; +import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor; +import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationPostProcessor; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +/** + * {@link DubboAutoConfiguration} Test + * + * @see DubboAutoConfiguration + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = CompatibleDubboAutoConfigurationTestWithoutProperties.class, properties = { + "dubbo.application.name=demo" +}) +@EnableAutoConfiguration +public class CompatibleDubboAutoConfigurationTestWithoutProperties { + + @Autowired(required = false) + private ServiceAnnotationPostProcessor serviceAnnotationPostProcessor; + + @Autowired + private ReferenceAnnotationBeanPostProcessor referenceAnnotationBeanPostProcessor; + + @Before + public void init() { + DubboBootstrap.reset(); + } + + @After + public void destroy() { + DubboBootstrap.reset(); + } + + @Test + public void testBeans() { + Assert.assertNull(serviceAnnotationPostProcessor); + Assert.assertNotNull(referenceAnnotationBeanPostProcessor); + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/DubboAutoConfigurationOnMultipleConfigTest.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/DubboAutoConfigurationOnMultipleConfigTest.java index 9dbb9e7142..b0fc8accf2 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/DubboAutoConfigurationOnMultipleConfigTest.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/DubboAutoConfigurationOnMultipleConfigTest.java @@ -1,280 +1,279 @@ -/* - * 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.spring.boot.autoconfigure; - -import org.apache.dubbo.config.ApplicationConfig; -import org.apache.dubbo.config.ConsumerConfig; -import org.apache.dubbo.config.ModuleConfig; -import org.apache.dubbo.config.MonitorConfig; -import org.apache.dubbo.config.ProtocolConfig; -import org.apache.dubbo.config.ProviderConfig; -import org.apache.dubbo.config.RegistryConfig; -import org.apache.dubbo.config.bootstrap.DubboBootstrap; -import org.apache.dubbo.rpc.model.ApplicationModel; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.ApplicationContext; -import org.springframework.core.env.Environment; -import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit4.SpringRunner; - -import java.util.LinkedHashMap; -import java.util.Map; - -import static org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors; - -/** - * {@link DubboAutoConfiguration} Test On multiple Dubbo Configuration - * - * @since 2.7.0 - */ -@Ignore -@RunWith(SpringRunner.class) -@TestPropertySource( - properties = { - "dubbo.applications.application1.NAME = dubbo-demo-application", - "dubbo.modules.module1.name = dubbo-demo-module", - "dubbo.registries.registry1.address = zookeeper://192.168.99.100:32770", - "dubbo.protocols.protocol1.name=dubbo", - "dubbo.protocols.protocol1.pORt=20880", - "dubbo.monitors.monitor1.Address=zookeeper://127.0.0.1:32770", - "dubbo.providers.provider1.host=127.0.0.1", - "dubbo.consumers.consumer1.client=netty", - "dubbo.config.multiple=true", - "dubbo.scan.basePackages=org.apache.dubbo.spring.boot.dubbo, org.apache.dubbo.spring.boot.condition" - } -) -@SpringBootTest( - classes = { - DubboAutoConfigurationOnMultipleConfigTest.class - } -) -@EnableAutoConfiguration -public class DubboAutoConfigurationOnMultipleConfigTest { - - @Autowired - private Environment environment; - - @Autowired - private ApplicationContext applicationContext; - - /** - * {@link ApplicationConfig} - */ - @Autowired - @Qualifier("application1") - private ApplicationConfig application; - - /** - * {@link ModuleConfig} - */ - @Autowired - @Qualifier("module1") - private ModuleConfig module; - - /** - * {@link RegistryConfig} - */ - @Autowired - @Qualifier("registry1") - private RegistryConfig registry; - - /** - * {@link ProtocolConfig} - */ - @Autowired - @Qualifier("protocol1") - private ProtocolConfig protocol; - - /** - * {@link MonitorConfig} - */ - @Autowired - @Qualifier("monitor1") - private MonitorConfig monitor; - - /** - * {@link ProviderConfig} - */ - @Autowired - @Qualifier("provider1") - private ProviderConfig provider; - - /** - * {@link ConsumerConfig} - */ - @Autowired - @Qualifier("consumer1") - private ConsumerConfig consumer; - - @Before - public void init() { - DubboBootstrap.reset(); - } - - @After - public void destroy() { - DubboBootstrap.reset(); - } - - @Autowired - private Map applications = new LinkedHashMap<>(); - - @Autowired - private Map modules = new LinkedHashMap<>(); - - @Autowired - private Map registries = new LinkedHashMap<>(); - - @Autowired - private Map protocols = new LinkedHashMap<>(); - - @Autowired - private Map monitors = new LinkedHashMap<>(); - - @Autowired - private Map providers = new LinkedHashMap<>(); - - @Autowired - private Map consumers = new LinkedHashMap<>(); - - @Test - public void testMultipleDubboConfigBindingProperties() { - - - Assert.assertEquals(1, applications.size()); - - Assert.assertEquals(1, modules.size()); - - Assert.assertEquals(1, registries.size()); - - Assert.assertEquals(1, protocols.size()); - - Assert.assertEquals(1, monitors.size()); - - Assert.assertEquals(1, providers.size()); - - Assert.assertEquals(1, consumers.size()); - - } - - @Test - public void testApplicationContext() { - - /** - * Multiple {@link ApplicationConfig} - */ - Map applications = beansOfTypeIncludingAncestors(applicationContext, ApplicationConfig.class); - - Assert.assertEquals(1, applications.size()); - - /** - * Multiple {@link ModuleConfig} - */ - Map modules = beansOfTypeIncludingAncestors(applicationContext, ModuleConfig.class); - - Assert.assertEquals(1, modules.size()); - - /** - * Multiple {@link RegistryConfig} - */ - Map registries = beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class); - - Assert.assertEquals(1, registries.size()); - - /** - * Multiple {@link ProtocolConfig} - */ - Map protocols = beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class); - - Assert.assertEquals(1, protocols.size()); - - /** - * Multiple {@link MonitorConfig} - */ - Map monitors = beansOfTypeIncludingAncestors(applicationContext, MonitorConfig.class); - - Assert.assertEquals(1, monitors.size()); - - /** - * Multiple {@link ProviderConfig} - */ - Map providers = beansOfTypeIncludingAncestors(applicationContext, ProviderConfig.class); - - Assert.assertEquals(1, providers.size()); - - /** - * Multiple {@link ConsumerConfig} - */ - Map consumers = beansOfTypeIncludingAncestors(applicationContext, ConsumerConfig.class); - - Assert.assertEquals(1, consumers.size()); - - } - - @Test - public void testApplicationConfig() { - - Assert.assertEquals("dubbo-demo-application", application.getName()); - - } - - @Test - public void testModuleConfig() { - - Assert.assertEquals("dubbo-demo-module", module.getName()); - - } - - @Test - public void testRegistryConfig() { - - Assert.assertEquals("zookeeper://192.168.99.100:32770", registry.getAddress()); - - } - - @Test - public void testMonitorConfig() { - - Assert.assertEquals("zookeeper://127.0.0.1:32770", monitor.getAddress()); - - } - - @Test - public void testProtocolConfig() { - - Assert.assertEquals("dubbo", protocol.getName()); - Assert.assertEquals(Integer.valueOf(20880), protocol.getPort()); - - } - - @Test - public void testConsumerConfig() { - - Assert.assertEquals("netty", consumer.getClient()); - - } -} +/* + * 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.spring.boot.autoconfigure; + +import org.apache.dubbo.config.ApplicationConfig; +import org.apache.dubbo.config.ConsumerConfig; +import org.apache.dubbo.config.ModuleConfig; +import org.apache.dubbo.config.MonitorConfig; +import org.apache.dubbo.config.ProtocolConfig; +import org.apache.dubbo.config.ProviderConfig; +import org.apache.dubbo.config.RegistryConfig; +import org.apache.dubbo.config.bootstrap.DubboBootstrap; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ApplicationContext; +import org.springframework.core.env.Environment; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.LinkedHashMap; +import java.util.Map; + +import static org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors; + +/** + * {@link DubboAutoConfiguration} Test On multiple Dubbo Configuration + * + * @since 2.7.0 + */ +@Ignore +@RunWith(SpringRunner.class) +@TestPropertySource( + properties = { + "dubbo.applications.application1.NAME = dubbo-demo-application", + "dubbo.modules.module1.name = dubbo-demo-module", + "dubbo.registries.registry1.address = zookeeper://192.168.99.100:32770", + "dubbo.protocols.protocol1.name=dubbo", + "dubbo.protocols.protocol1.pORt=20880", + "dubbo.monitors.monitor1.Address=zookeeper://127.0.0.1:32770", + "dubbo.providers.provider1.host=127.0.0.1", + "dubbo.consumers.consumer1.client=netty", + "dubbo.config.multiple=true", + "dubbo.scan.basePackages=org.apache.dubbo.spring.boot.dubbo, org.apache.dubbo.spring.boot.condition" + } +) +@SpringBootTest( + classes = { + DubboAutoConfigurationOnMultipleConfigTest.class + } +) +@EnableAutoConfiguration +public class DubboAutoConfigurationOnMultipleConfigTest { + + @Autowired + private Environment environment; + + @Autowired + private ApplicationContext applicationContext; + + /** + * {@link ApplicationConfig} + */ + @Autowired + @Qualifier("application1") + private ApplicationConfig application; + + /** + * {@link ModuleConfig} + */ + @Autowired + @Qualifier("module1") + private ModuleConfig module; + + /** + * {@link RegistryConfig} + */ + @Autowired + @Qualifier("registry1") + private RegistryConfig registry; + + /** + * {@link ProtocolConfig} + */ + @Autowired + @Qualifier("protocol1") + private ProtocolConfig protocol; + + /** + * {@link MonitorConfig} + */ + @Autowired + @Qualifier("monitor1") + private MonitorConfig monitor; + + /** + * {@link ProviderConfig} + */ + @Autowired + @Qualifier("provider1") + private ProviderConfig provider; + + /** + * {@link ConsumerConfig} + */ + @Autowired + @Qualifier("consumer1") + private ConsumerConfig consumer; + + @Before + public void init() { + DubboBootstrap.reset(); + } + + @After + public void destroy() { + DubboBootstrap.reset(); + } + + @Autowired + private Map applications = new LinkedHashMap<>(); + + @Autowired + private Map modules = new LinkedHashMap<>(); + + @Autowired + private Map registries = new LinkedHashMap<>(); + + @Autowired + private Map protocols = new LinkedHashMap<>(); + + @Autowired + private Map monitors = new LinkedHashMap<>(); + + @Autowired + private Map providers = new LinkedHashMap<>(); + + @Autowired + private Map consumers = new LinkedHashMap<>(); + + @Test + public void testMultipleDubboConfigBindingProperties() { + + + Assert.assertEquals(1, applications.size()); + + Assert.assertEquals(1, modules.size()); + + Assert.assertEquals(1, registries.size()); + + Assert.assertEquals(1, protocols.size()); + + Assert.assertEquals(1, monitors.size()); + + Assert.assertEquals(1, providers.size()); + + Assert.assertEquals(1, consumers.size()); + + } + + @Test + public void testApplicationContext() { + + /** + * Multiple {@link ApplicationConfig} + */ + Map applications = beansOfTypeIncludingAncestors(applicationContext, ApplicationConfig.class); + + Assert.assertEquals(1, applications.size()); + + /** + * Multiple {@link ModuleConfig} + */ + Map modules = beansOfTypeIncludingAncestors(applicationContext, ModuleConfig.class); + + Assert.assertEquals(1, modules.size()); + + /** + * Multiple {@link RegistryConfig} + */ + Map registries = beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class); + + Assert.assertEquals(1, registries.size()); + + /** + * Multiple {@link ProtocolConfig} + */ + Map protocols = beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class); + + Assert.assertEquals(1, protocols.size()); + + /** + * Multiple {@link MonitorConfig} + */ + Map monitors = beansOfTypeIncludingAncestors(applicationContext, MonitorConfig.class); + + Assert.assertEquals(1, monitors.size()); + + /** + * Multiple {@link ProviderConfig} + */ + Map providers = beansOfTypeIncludingAncestors(applicationContext, ProviderConfig.class); + + Assert.assertEquals(1, providers.size()); + + /** + * Multiple {@link ConsumerConfig} + */ + Map consumers = beansOfTypeIncludingAncestors(applicationContext, ConsumerConfig.class); + + Assert.assertEquals(1, consumers.size()); + + } + + @Test + public void testApplicationConfig() { + + Assert.assertEquals("dubbo-demo-application", application.getName()); + + } + + @Test + public void testModuleConfig() { + + Assert.assertEquals("dubbo-demo-module", module.getName()); + + } + + @Test + public void testRegistryConfig() { + + Assert.assertEquals("zookeeper://192.168.99.100:32770", registry.getAddress()); + + } + + @Test + public void testMonitorConfig() { + + Assert.assertEquals("zookeeper://127.0.0.1:32770", monitor.getAddress()); + + } + + @Test + public void testProtocolConfig() { + + Assert.assertEquals("dubbo", protocol.getName()); + Assert.assertEquals(Integer.valueOf(20880), protocol.getPort()); + + } + + @Test + public void testConsumerConfig() { + + Assert.assertEquals("netty", consumer.getClient()); + + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/DubboAutoConfigurationOnSingleConfigTest.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/DubboAutoConfigurationOnSingleConfigTest.java index 2aeb44cf31..db6d5a98c2 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/DubboAutoConfigurationOnSingleConfigTest.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/DubboAutoConfigurationOnSingleConfigTest.java @@ -1,154 +1,153 @@ -/* - * 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.spring.boot.autoconfigure; - -import org.apache.dubbo.config.ApplicationConfig; -import org.apache.dubbo.config.ConsumerConfig; -import org.apache.dubbo.config.ModuleConfig; -import org.apache.dubbo.config.MonitorConfig; -import org.apache.dubbo.config.ProtocolConfig; -import org.apache.dubbo.config.ProviderConfig; -import org.apache.dubbo.config.RegistryConfig; -import org.apache.dubbo.config.bootstrap.DubboBootstrap; -import org.apache.dubbo.rpc.model.ApplicationModel; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.ApplicationContext; -import org.springframework.core.env.Environment; -import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit4.SpringRunner; - -/** - * {@link DubboAutoConfiguration} Test On single Dubbo Configuration - * - * @since 2.7.0 - */ -@Ignore -@RunWith(SpringRunner.class) -@TestPropertySource( - properties = { - "dubbo.application.name = dubbo-demo-application", - "dubbo.module.name = dubbo-demo-module", - "dubbo.registry.address = zookeeper://192.168.99.100:32770", - "dubbo.protocol.name=dubbo", - "dubbo.protocol.port=20880", - "dubbo.monitor.address=zookeeper://127.0.0.1:32770", - "dubbo.provider.host=127.0.0.1", - "dubbo.consumer.client=netty" - } -) -@SpringBootTest( - classes = {DubboAutoConfigurationOnSingleConfigTest.class} -) -@EnableAutoConfiguration -public class DubboAutoConfigurationOnSingleConfigTest { - - @Autowired - private ApplicationConfig applicationConfig; - - @Autowired - private ModuleConfig moduleConfig; - - @Autowired - private RegistryConfig registryConfig; - - @Autowired - private MonitorConfig monitorConfig; - - @Autowired - private ProviderConfig providerConfig; - - @Autowired - private ConsumerConfig consumerConfig; - - @Autowired - private ProtocolConfig protocolConfig; - - @Autowired - private Environment environment; - - @Autowired - private ApplicationContext applicationContext; - - @Before - public void init() { - DubboBootstrap.reset(); - } - - @After - public void destroy() { - DubboBootstrap.reset(); - } - - @Test - public void testApplicationConfig() { - - Assert.assertEquals("dubbo-demo-application", applicationConfig.getName()); - - } - - @Test - public void testModuleConfig() { - - Assert.assertEquals("dubbo-demo-module", moduleConfig.getName()); - - } - - @Test - public void testRegistryConfig() { - - Assert.assertEquals("zookeeper://192.168.99.100:32770", registryConfig.getAddress()); - - } - - @Test - public void testMonitorConfig() { - - Assert.assertEquals("zookeeper://127.0.0.1:32770", monitorConfig.getAddress()); - - } - - @Test - public void testProtocolConfig() { - - Assert.assertEquals("dubbo", protocolConfig.getName()); - Assert.assertEquals(Integer.valueOf(20880), protocolConfig.getPort()); - - } - - @Test - public void testProviderConfig() { - - Assert.assertEquals("127.0.0.1", providerConfig.getHost()); - - } - - @Test - public void testConsumerConfig() { - - Assert.assertEquals("netty", consumerConfig.getClient()); - - } -} +/* + * 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.spring.boot.autoconfigure; + +import org.apache.dubbo.config.ApplicationConfig; +import org.apache.dubbo.config.ConsumerConfig; +import org.apache.dubbo.config.ModuleConfig; +import org.apache.dubbo.config.MonitorConfig; +import org.apache.dubbo.config.ProtocolConfig; +import org.apache.dubbo.config.ProviderConfig; +import org.apache.dubbo.config.RegistryConfig; +import org.apache.dubbo.config.bootstrap.DubboBootstrap; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ApplicationContext; +import org.springframework.core.env.Environment; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +/** + * {@link DubboAutoConfiguration} Test On single Dubbo Configuration + * + * @since 2.7.0 + */ +@Ignore +@RunWith(SpringRunner.class) +@TestPropertySource( + properties = { + "dubbo.application.name = dubbo-demo-application", + "dubbo.module.name = dubbo-demo-module", + "dubbo.registry.address = zookeeper://192.168.99.100:32770", + "dubbo.protocol.name=dubbo", + "dubbo.protocol.port=20880", + "dubbo.monitor.address=zookeeper://127.0.0.1:32770", + "dubbo.provider.host=127.0.0.1", + "dubbo.consumer.client=netty" + } +) +@SpringBootTest( + classes = {DubboAutoConfigurationOnSingleConfigTest.class} +) +@EnableAutoConfiguration +public class DubboAutoConfigurationOnSingleConfigTest { + + @Autowired + private ApplicationConfig applicationConfig; + + @Autowired + private ModuleConfig moduleConfig; + + @Autowired + private RegistryConfig registryConfig; + + @Autowired + private MonitorConfig monitorConfig; + + @Autowired + private ProviderConfig providerConfig; + + @Autowired + private ConsumerConfig consumerConfig; + + @Autowired + private ProtocolConfig protocolConfig; + + @Autowired + private Environment environment; + + @Autowired + private ApplicationContext applicationContext; + + @Before + public void init() { + DubboBootstrap.reset(); + } + + @After + public void destroy() { + DubboBootstrap.reset(); + } + + @Test + public void testApplicationConfig() { + + Assert.assertEquals("dubbo-demo-application", applicationConfig.getName()); + + } + + @Test + public void testModuleConfig() { + + Assert.assertEquals("dubbo-demo-module", moduleConfig.getName()); + + } + + @Test + public void testRegistryConfig() { + + Assert.assertEquals("zookeeper://192.168.99.100:32770", registryConfig.getAddress()); + + } + + @Test + public void testMonitorConfig() { + + Assert.assertEquals("zookeeper://127.0.0.1:32770", monitorConfig.getAddress()); + + } + + @Test + public void testProtocolConfig() { + + Assert.assertEquals("dubbo", protocolConfig.getName()); + Assert.assertEquals(Integer.valueOf(20880), protocolConfig.getPort()); + + } + + @Test + public void testProviderConfig() { + + Assert.assertEquals("127.0.0.1", providerConfig.getHost()); + + } + + @Test + public void testConsumerConfig() { + + Assert.assertEquals("netty", consumerConfig.getClient()); + + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/RelaxedDubboConfigBinderTest.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/RelaxedDubboConfigBinderTest.java index 4280a32d94..aebfb95deb 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/RelaxedDubboConfigBinderTest.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/RelaxedDubboConfigBinderTest.java @@ -1,90 +1,90 @@ -/* - * 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.spring.boot.autoconfigure; - -import org.apache.dubbo.config.ApplicationConfig; -import org.apache.dubbo.config.ProtocolConfig; -import org.apache.dubbo.config.RegistryConfig; -import org.apache.dubbo.config.bootstrap.DubboBootstrap; - -import com.alibaba.spring.context.config.ConfigurationBeanBinder; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit4.SpringRunner; - -import java.util.Map; - -import static com.alibaba.spring.util.PropertySourcesUtils.getSubProperties; - -/** - * {@link RelaxedDubboConfigBinder} Test - */ -@RunWith(SpringRunner.class) -@TestPropertySource(properties = { - "dubbo.application.NAME=hello", - "dubbo.application.owneR=world", - "dubbo.registry.Address=10.20.153.17", - "dubbo.protocol.pORt=20881", - "dubbo.service.invoke.timeout=2000", -}) -@ContextConfiguration(classes = RelaxedDubboConfigBinder.class) -public class RelaxedDubboConfigBinderTest { - - @Autowired - private ConfigurationBeanBinder dubboConfigBinder; - - @Autowired - private ConfigurableEnvironment environment; - - @Before - public void init() { - DubboBootstrap.reset(); - } - - @After - public void destroy() { - DubboBootstrap.reset(); - } - - @Test - public void testBinder() { - - ApplicationConfig applicationConfig = new ApplicationConfig(); - Map properties = getSubProperties(environment.getPropertySources(), "dubbo.application"); - dubboConfigBinder.bind(properties, true, true, applicationConfig); - Assert.assertEquals("hello", applicationConfig.getName()); - Assert.assertEquals("world", applicationConfig.getOwner()); - - RegistryConfig registryConfig = new RegistryConfig(); - properties = getSubProperties(environment.getPropertySources(), "dubbo.registry"); - dubboConfigBinder.bind(properties, true, true, registryConfig); - Assert.assertEquals("10.20.153.17", registryConfig.getAddress()); - - ProtocolConfig protocolConfig = new ProtocolConfig(); - properties = getSubProperties(environment.getPropertySources(), "dubbo.protocol"); - dubboConfigBinder.bind(properties, true, true, protocolConfig); - Assert.assertEquals(Integer.valueOf(20881), protocolConfig.getPort()); - - } -} +/* + * 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.spring.boot.autoconfigure; + +import org.apache.dubbo.config.ApplicationConfig; +import org.apache.dubbo.config.ProtocolConfig; +import org.apache.dubbo.config.RegistryConfig; +import org.apache.dubbo.config.bootstrap.DubboBootstrap; + +import com.alibaba.spring.context.config.ConfigurationBeanBinder; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.Map; + +import static com.alibaba.spring.util.PropertySourcesUtils.getSubProperties; + +/** + * {@link RelaxedDubboConfigBinder} Test + */ +@RunWith(SpringRunner.class) +@TestPropertySource(properties = { + "dubbo.application.NAME=hello", + "dubbo.application.owneR=world", + "dubbo.registry.Address=10.20.153.17", + "dubbo.protocol.pORt=20881", + "dubbo.service.invoke.timeout=2000", +}) +@ContextConfiguration(classes = RelaxedDubboConfigBinder.class) +public class RelaxedDubboConfigBinderTest { + + @Autowired + private ConfigurationBeanBinder dubboConfigBinder; + + @Autowired + private ConfigurableEnvironment environment; + + @Before + public void init() { + DubboBootstrap.reset(); + } + + @After + public void destroy() { + DubboBootstrap.reset(); + } + + @Test + public void testBinder() { + + ApplicationConfig applicationConfig = new ApplicationConfig(); + Map properties = getSubProperties(environment.getPropertySources(), "dubbo.application"); + dubboConfigBinder.bind(properties, true, true, applicationConfig); + Assert.assertEquals("hello", applicationConfig.getName()); + Assert.assertEquals("world", applicationConfig.getOwner()); + + RegistryConfig registryConfig = new RegistryConfig(); + properties = getSubProperties(environment.getPropertySources(), "dubbo.registry"); + dubboConfigBinder.bind(properties, true, true, registryConfig); + Assert.assertEquals("10.20.153.17", registryConfig.getAddress()); + + ProtocolConfig protocolConfig = new ProtocolConfig(); + properties = getSubProperties(environment.getPropertySources(), "dubbo.protocol"); + dubboConfigBinder.bind(properties, true, true, protocolConfig); + Assert.assertEquals(Integer.valueOf(20881), protocolConfig.getPort()); + + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/context/event/AwaitingNonWebApplicationListenerTest.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/context/event/AwaitingNonWebApplicationListenerTest.java index 73d0c45d39..5695e596ae 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/context/event/AwaitingNonWebApplicationListenerTest.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/context/event/AwaitingNonWebApplicationListenerTest.java @@ -1,75 +1,75 @@ -/* - * 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.spring.boot.context.event; - -import org.apache.dubbo.common.lang.ShutdownHookCallbacks; -import org.apache.dubbo.config.bootstrap.DubboBootstrap; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.springframework.boot.builder.SpringApplicationBuilder; - -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * {@link AwaitingNonWebApplicationListener} Test - */ -public class AwaitingNonWebApplicationListenerTest { - - @Before - public void before() { - DubboBootstrap.reset(); - } - - @After - public void after() { - DubboBootstrap.reset(); - } - - @Test - public void init() { - AtomicBoolean awaited = AwaitingNonWebApplicationListener.getAwaited(); - awaited.set(false); - } - - @Test - public void testSingleContextNonWebApplication() { - new SpringApplicationBuilder(Object.class) - .web(false) - .run() - .close(); - - ShutdownHookCallbacks.INSTANCE.addCallback(() -> { - AtomicBoolean awaited = AwaitingNonWebApplicationListener.getAwaited(); - Assert.assertTrue(awaited.get()); - System.out.println("Callback..."); - }); - } -// -// @Test -// public void testMultipleContextNonWebApplication() { -// new SpringApplicationBuilder(Object.class) -// .parent(Object.class) -// .web(false) -// .run().close(); -// AtomicBoolean awaited = AwaitingNonWebApplicationListener.getAwaited(); -// Assert.assertFalse(awaited.get()); -// } - -} +/* + * 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.spring.boot.context.event; + +import org.apache.dubbo.common.lang.ShutdownHookCallbacks; +import org.apache.dubbo.config.bootstrap.DubboBootstrap; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.springframework.boot.builder.SpringApplicationBuilder; + +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * {@link AwaitingNonWebApplicationListener} Test + */ +public class AwaitingNonWebApplicationListenerTest { + + @Before + public void before() { + DubboBootstrap.reset(); + } + + @After + public void after() { + DubboBootstrap.reset(); + } + + @Test + public void init() { + AtomicBoolean awaited = AwaitingNonWebApplicationListener.getAwaited(); + awaited.set(false); + } + + @Test + public void testSingleContextNonWebApplication() { + new SpringApplicationBuilder(Object.class) + .web(false) + .run() + .close(); + + ShutdownHookCallbacks.INSTANCE.addCallback(() -> { + AtomicBoolean awaited = AwaitingNonWebApplicationListener.getAwaited(); + Assert.assertTrue(awaited.get()); + System.out.println("Callback..."); + }); + } +// +// @Test +// public void testMultipleContextNonWebApplication() { +// new SpringApplicationBuilder(Object.class) +// .parent(Object.class) +// .web(false) +// .run().close(); +// AtomicBoolean awaited = AwaitingNonWebApplicationListener.getAwaited(); +// Assert.assertFalse(awaited.get()); +// } + +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/context/event/DubboConfigBeanDefinitionConflictApplicationListenerTest.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/context/event/DubboConfigBeanDefinitionConflictApplicationListenerTest.java index 1d464f999e..70f5e573d3 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/context/event/DubboConfigBeanDefinitionConflictApplicationListenerTest.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/context/event/DubboConfigBeanDefinitionConflictApplicationListenerTest.java @@ -1,104 +1,104 @@ -/* - * 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.spring.boot.context.event; - -import org.apache.dubbo.config.ApplicationConfig; -import org.apache.dubbo.config.bootstrap.DubboBootstrap; -import org.apache.dubbo.config.spring.context.annotation.EnableDubboConfig; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.springframework.context.annotation.ImportResource; -import org.springframework.context.annotation.PropertySource; - -import java.util.Map; - - -/** - * {@link DubboConfigBeanDefinitionConflictApplicationListener} Test - * - * @since 2.7.5 - */ -public class DubboConfigBeanDefinitionConflictApplicationListenerTest { - - @Before - public void init() { - DubboBootstrap.reset(); - //context.addApplicationListener(new DubboConfigBeanDefinitionConflictApplicationListener()); - } - - @After - public void destroy() { - DubboBootstrap.reset(); - - } - - //@Test - public void testNormalCase() { - - System.setProperty("dubbo.application.name", "test-dubbo-application"); - - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DubboConfig.class); - try { - context.start(); - - ApplicationConfig applicationConfig = context.getBean(ApplicationConfig.class); - - Assert.assertEquals("test-dubbo-application", applicationConfig.getName()); - } finally { - System.clearProperty("dubbo.application.name"); - context.close(); - } - } - - @Test - public void testDuplicatedConfigsCase() { - - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(PropertySourceConfig.class, DubboConfig.class, XmlConfig.class); - - try { - context.start(); - - Map beansMap = context.getBeansOfType(ApplicationConfig.class); - - ApplicationConfig applicationConfig = beansMap.get("dubbo-consumer-2.7.x"); - - Assert.assertEquals(1, beansMap.size()); - - Assert.assertEquals("dubbo-consumer-2.7.x", applicationConfig.getName()); - } finally { - context.close(); - } - } - - @EnableDubboConfig - static class DubboConfig { - - } - - @PropertySource("classpath:/META-INF/dubbo.properties") - static class PropertySourceConfig { - - } - - @ImportResource("classpath:/META-INF/spring/dubbo-context.xml") - static class XmlConfig { - } -} +/* + * 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.spring.boot.context.event; + +import org.apache.dubbo.config.ApplicationConfig; +import org.apache.dubbo.config.bootstrap.DubboBootstrap; +import org.apache.dubbo.config.spring.context.annotation.EnableDubboConfig; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.ImportResource; +import org.springframework.context.annotation.PropertySource; + +import java.util.Map; + + +/** + * {@link DubboConfigBeanDefinitionConflictApplicationListener} Test + * + * @since 2.7.5 + */ +public class DubboConfigBeanDefinitionConflictApplicationListenerTest { + + @Before + public void init() { + DubboBootstrap.reset(); + //context.addApplicationListener(new DubboConfigBeanDefinitionConflictApplicationListener()); + } + + @After + public void destroy() { + DubboBootstrap.reset(); + + } + + //@Test + public void testNormalCase() { + + System.setProperty("dubbo.application.name", "test-dubbo-application"); + + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DubboConfig.class); + try { + context.start(); + + ApplicationConfig applicationConfig = context.getBean(ApplicationConfig.class); + + Assert.assertEquals("test-dubbo-application", applicationConfig.getName()); + } finally { + System.clearProperty("dubbo.application.name"); + context.close(); + } + } + + @Test + public void testDuplicatedConfigsCase() { + + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(PropertySourceConfig.class, DubboConfig.class, XmlConfig.class); + + try { + context.start(); + + Map beansMap = context.getBeansOfType(ApplicationConfig.class); + + ApplicationConfig applicationConfig = beansMap.get("dubbo-consumer-2.7.x"); + + Assert.assertEquals(1, beansMap.size()); + + Assert.assertEquals("dubbo-consumer-2.7.x", applicationConfig.getName()); + } finally { + context.close(); + } + } + + @EnableDubboConfig + static class DubboConfig { + + } + + @PropertySource("classpath:/META-INF/dubbo.properties") + static class PropertySourceConfig { + + } + + @ImportResource("classpath:/META-INF/spring/dubbo-context.xml") + static class XmlConfig { + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/context/event/WelcomeLogoApplicationListenerTest.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/context/event/WelcomeLogoApplicationListenerTest.java index dd8dde8531..c006a7553e 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/context/event/WelcomeLogoApplicationListenerTest.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/context/event/WelcomeLogoApplicationListenerTest.java @@ -1,48 +1,48 @@ -/* - * 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.spring.boot.context.event; - -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -/** - * {@link WelcomeLogoApplicationListener} Test - * - * @see WelcomeLogoApplicationListener - * @since 2.7.0 - */ -@RunWith(SpringRunner.class) -@SpringBootTest( - classes = {WelcomeLogoApplicationListener.class} -) -public class WelcomeLogoApplicationListenerTest { - - @Autowired - private WelcomeLogoApplicationListener welcomeLogoApplicationListener; - - @Test - public void testOnApplicationEvent() { - - Assert.assertNotNull(welcomeLogoApplicationListener.buildBannerText()); - - } - -} +/* + * 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.spring.boot.context.event; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +/** + * {@link WelcomeLogoApplicationListener} Test + * + * @see WelcomeLogoApplicationListener + * @since 2.7.0 + */ +@RunWith(SpringRunner.class) +@SpringBootTest( + classes = {WelcomeLogoApplicationListener.class} +) +public class WelcomeLogoApplicationListenerTest { + + @Autowired + private WelcomeLogoApplicationListener welcomeLogoApplicationListener; + + @Test + public void testOnApplicationEvent() { + + Assert.assertNotNull(welcomeLogoApplicationListener.buildBannerText()); + + } + +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/env/DubboDefaultPropertiesEnvironmentPostProcessorTest.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/env/DubboDefaultPropertiesEnvironmentPostProcessorTest.java index 860bc2e8a3..9e2de9a822 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/env/DubboDefaultPropertiesEnvironmentPostProcessorTest.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/env/DubboDefaultPropertiesEnvironmentPostProcessorTest.java @@ -1,97 +1,97 @@ -/* - * 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.spring.boot.env; - -import org.junit.Assert; -import org.junit.Test; -import org.springframework.boot.SpringApplication; -import org.springframework.core.Ordered; -import org.springframework.core.env.MapPropertySource; -import org.springframework.core.env.MutablePropertySources; -import org.springframework.core.env.PropertySource; -import org.springframework.mock.env.MockEnvironment; - -import java.util.HashMap; - -/** - * {@link DubboDefaultPropertiesEnvironmentPostProcessor} Test - */ -public class DubboDefaultPropertiesEnvironmentPostProcessorTest { - - private DubboDefaultPropertiesEnvironmentPostProcessor instance = - new DubboDefaultPropertiesEnvironmentPostProcessor(); - - private SpringApplication springApplication = new SpringApplication(); - - @Test - public void testOrder() { - Assert.assertEquals(Ordered.LOWEST_PRECEDENCE, instance.getOrder()); - } - - @Test - public void testPostProcessEnvironment() { - MockEnvironment environment = new MockEnvironment(); - // Case 1 : Not Any property - instance.postProcessEnvironment(environment, springApplication); - // Get PropertySources - MutablePropertySources propertySources = environment.getPropertySources(); - // Nothing to change - PropertySource defaultPropertySource = propertySources.get("defaultProperties"); - Assert.assertNotNull(defaultPropertySource); - Assert.assertEquals("true", defaultPropertySource.getProperty("dubbo.config.multiple")); - Assert.assertEquals("false", defaultPropertySource.getProperty("dubbo.application.qos-enable")); - - // Case 2 : Only set property "spring.application.name" - environment.setProperty("spring.application.name", "demo-dubbo-application"); - instance.postProcessEnvironment(environment, springApplication); - defaultPropertySource = propertySources.get("defaultProperties"); - Object dubboApplicationName = defaultPropertySource.getProperty("dubbo.application.name"); - Assert.assertEquals("demo-dubbo-application", dubboApplicationName); - - // Case 3 : Only set property "dubbo.application.name" - // Rest environment - environment = new MockEnvironment(); - propertySources = environment.getPropertySources(); - environment.setProperty("dubbo.application.name", "demo-dubbo-application"); - instance.postProcessEnvironment(environment, springApplication); - defaultPropertySource = propertySources.get("defaultProperties"); - Assert.assertNotNull(defaultPropertySource); - dubboApplicationName = environment.getProperty("dubbo.application.name"); - Assert.assertEquals("demo-dubbo-application", dubboApplicationName); - - // Case 4 : If "defaultProperties" PropertySource is present in PropertySources - // Rest environment - environment = new MockEnvironment(); - propertySources = environment.getPropertySources(); - propertySources.addLast(new MapPropertySource("defaultProperties", new HashMap())); - environment.setProperty("spring.application.name", "demo-dubbo-application"); - instance.postProcessEnvironment(environment, springApplication); - defaultPropertySource = propertySources.get("defaultProperties"); - dubboApplicationName = defaultPropertySource.getProperty("dubbo.application.name"); - Assert.assertEquals("demo-dubbo-application", dubboApplicationName); - - // Case 5 : Rest dubbo.config.multiple and dubbo.application.qos-enable - environment = new MockEnvironment(); - propertySources = environment.getPropertySources(); - propertySources.addLast(new MapPropertySource("defaultProperties", new HashMap())); - environment.setProperty("dubbo.config.multiple", "false"); - environment.setProperty("dubbo.application.qos-enable", "true"); - instance.postProcessEnvironment(environment, springApplication); - Assert.assertEquals("false", environment.getProperty("dubbo.config.multiple")); - Assert.assertEquals("true", environment.getProperty("dubbo.application.qos-enable")); - } -} \ No newline at end of file +/* + * 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.spring.boot.env; + +import org.junit.Assert; +import org.junit.Test; +import org.springframework.boot.SpringApplication; +import org.springframework.core.Ordered; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.MutablePropertySources; +import org.springframework.core.env.PropertySource; +import org.springframework.mock.env.MockEnvironment; + +import java.util.HashMap; + +/** + * {@link DubboDefaultPropertiesEnvironmentPostProcessor} Test + */ +public class DubboDefaultPropertiesEnvironmentPostProcessorTest { + + private DubboDefaultPropertiesEnvironmentPostProcessor instance = + new DubboDefaultPropertiesEnvironmentPostProcessor(); + + private SpringApplication springApplication = new SpringApplication(); + + @Test + public void testOrder() { + Assert.assertEquals(Ordered.LOWEST_PRECEDENCE, instance.getOrder()); + } + + @Test + public void testPostProcessEnvironment() { + MockEnvironment environment = new MockEnvironment(); + // Case 1 : Not Any property + instance.postProcessEnvironment(environment, springApplication); + // Get PropertySources + MutablePropertySources propertySources = environment.getPropertySources(); + // Nothing to change + PropertySource defaultPropertySource = propertySources.get("defaultProperties"); + Assert.assertNotNull(defaultPropertySource); + Assert.assertEquals("true", defaultPropertySource.getProperty("dubbo.config.multiple")); + Assert.assertEquals("false", defaultPropertySource.getProperty("dubbo.application.qos-enable")); + + // Case 2 : Only set property "spring.application.name" + environment.setProperty("spring.application.name", "demo-dubbo-application"); + instance.postProcessEnvironment(environment, springApplication); + defaultPropertySource = propertySources.get("defaultProperties"); + Object dubboApplicationName = defaultPropertySource.getProperty("dubbo.application.name"); + Assert.assertEquals("demo-dubbo-application", dubboApplicationName); + + // Case 3 : Only set property "dubbo.application.name" + // Rest environment + environment = new MockEnvironment(); + propertySources = environment.getPropertySources(); + environment.setProperty("dubbo.application.name", "demo-dubbo-application"); + instance.postProcessEnvironment(environment, springApplication); + defaultPropertySource = propertySources.get("defaultProperties"); + Assert.assertNotNull(defaultPropertySource); + dubboApplicationName = environment.getProperty("dubbo.application.name"); + Assert.assertEquals("demo-dubbo-application", dubboApplicationName); + + // Case 4 : If "defaultProperties" PropertySource is present in PropertySources + // Rest environment + environment = new MockEnvironment(); + propertySources = environment.getPropertySources(); + propertySources.addLast(new MapPropertySource("defaultProperties", new HashMap())); + environment.setProperty("spring.application.name", "demo-dubbo-application"); + instance.postProcessEnvironment(environment, springApplication); + defaultPropertySource = propertySources.get("defaultProperties"); + dubboApplicationName = defaultPropertySource.getProperty("dubbo.application.name"); + Assert.assertEquals("demo-dubbo-application", dubboApplicationName); + + // Case 5 : Rest dubbo.config.multiple and dubbo.application.qos-enable + environment = new MockEnvironment(); + propertySources = environment.getPropertySources(); + propertySources.addLast(new MapPropertySource("defaultProperties", new HashMap())); + environment.setProperty("dubbo.config.multiple", "false"); + environment.setProperty("dubbo.application.qos-enable", "true"); + instance.postProcessEnvironment(environment, springApplication); + Assert.assertEquals("false", environment.getProperty("dubbo.config.multiple")); + Assert.assertEquals("true", environment.getProperty("dubbo.application.qos-enable")); + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/util/DubboUtilsTest.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/util/DubboUtilsTest.java index 7cf8299c21..b99113072f 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/util/DubboUtilsTest.java +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/util/DubboUtilsTest.java @@ -1,85 +1,85 @@ -/* - * 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.spring.boot.util; - -import org.junit.Assert; -import org.junit.Test; - -import static org.apache.dubbo.spring.boot.util.DubboUtils.BASE_PACKAGES_PROPERTY_NAME; -import static org.apache.dubbo.spring.boot.util.DubboUtils.DEFAULT_MULTIPLE_CONFIG_PROPERTY_VALUE; -import static org.apache.dubbo.spring.boot.util.DubboUtils.DEFAULT_OVERRIDE_CONFIG_PROPERTY_VALUE; -import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_APPLICATION_ID_PROPERTY; -import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_APPLICATION_NAME_PROPERTY; -import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_APPLICATION_QOS_ENABLE_PROPERTY; -import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_CONFIG_MULTIPLE_PROPERTY; -import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_CONFIG_PREFIX; -import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_GITHUB_URL; -import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_MAILING_LIST; -import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_PREFIX; -import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_SCAN_PREFIX; -import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_SPRING_BOOT_GITHUB_URL; -import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_SPRING_BOOT_GIT_URL; -import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_SPRING_BOOT_ISSUES_URL; -import static org.apache.dubbo.spring.boot.util.DubboUtils.MULTIPLE_CONFIG_PROPERTY_NAME; -import static org.apache.dubbo.spring.boot.util.DubboUtils.OVERRIDE_CONFIG_FULL_PROPERTY_NAME; -import static org.apache.dubbo.spring.boot.util.DubboUtils.SPRING_APPLICATION_NAME_PROPERTY; - -/** - * {@link DubboUtils} Test - * - * @see DubboUtils - * @since 2.7.0 - */ -public class DubboUtilsTest { - - @Test - public void testConstants() { - - Assert.assertEquals("dubbo", DUBBO_PREFIX); - - Assert.assertEquals("dubbo.scan.", DUBBO_SCAN_PREFIX); - - Assert.assertEquals("base-packages", BASE_PACKAGES_PROPERTY_NAME); - - Assert.assertEquals("dubbo.config.", DUBBO_CONFIG_PREFIX); - - Assert.assertEquals("multiple", MULTIPLE_CONFIG_PROPERTY_NAME); - - Assert.assertEquals("dubbo.config.override", OVERRIDE_CONFIG_FULL_PROPERTY_NAME); - - Assert.assertEquals("https://github.com/apache/dubbo-spring-boot-project", DUBBO_SPRING_BOOT_GITHUB_URL); - Assert.assertEquals("https://github.com/apache/dubbo-spring-boot-project.git", DUBBO_SPRING_BOOT_GIT_URL); - Assert.assertEquals("https://github.com/apache/dubbo-spring-boot-project/issues", DUBBO_SPRING_BOOT_ISSUES_URL); - - Assert.assertEquals("https://github.com/apache/dubbo", DUBBO_GITHUB_URL); - - Assert.assertEquals("dev@dubbo.apache.org", DUBBO_MAILING_LIST); - - Assert.assertEquals("spring.application.name", SPRING_APPLICATION_NAME_PROPERTY); - Assert.assertEquals("dubbo.application.id", DUBBO_APPLICATION_ID_PROPERTY); - Assert.assertEquals("dubbo.application.name", DUBBO_APPLICATION_NAME_PROPERTY); - Assert.assertEquals("dubbo.application.qos-enable", DUBBO_APPLICATION_QOS_ENABLE_PROPERTY); - Assert.assertEquals("dubbo.config.multiple", DUBBO_CONFIG_MULTIPLE_PROPERTY); - - Assert.assertTrue(DEFAULT_MULTIPLE_CONFIG_PROPERTY_VALUE); - - Assert.assertTrue(DEFAULT_OVERRIDE_CONFIG_PROPERTY_VALUE); - - - } - -} +/* + * 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.spring.boot.util; + +import org.junit.Assert; +import org.junit.Test; + +import static org.apache.dubbo.spring.boot.util.DubboUtils.BASE_PACKAGES_PROPERTY_NAME; +import static org.apache.dubbo.spring.boot.util.DubboUtils.DEFAULT_MULTIPLE_CONFIG_PROPERTY_VALUE; +import static org.apache.dubbo.spring.boot.util.DubboUtils.DEFAULT_OVERRIDE_CONFIG_PROPERTY_VALUE; +import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_APPLICATION_ID_PROPERTY; +import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_APPLICATION_NAME_PROPERTY; +import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_APPLICATION_QOS_ENABLE_PROPERTY; +import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_CONFIG_MULTIPLE_PROPERTY; +import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_CONFIG_PREFIX; +import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_GITHUB_URL; +import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_MAILING_LIST; +import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_PREFIX; +import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_SCAN_PREFIX; +import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_SPRING_BOOT_GITHUB_URL; +import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_SPRING_BOOT_GIT_URL; +import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_SPRING_BOOT_ISSUES_URL; +import static org.apache.dubbo.spring.boot.util.DubboUtils.MULTIPLE_CONFIG_PROPERTY_NAME; +import static org.apache.dubbo.spring.boot.util.DubboUtils.OVERRIDE_CONFIG_FULL_PROPERTY_NAME; +import static org.apache.dubbo.spring.boot.util.DubboUtils.SPRING_APPLICATION_NAME_PROPERTY; + +/** + * {@link DubboUtils} Test + * + * @see DubboUtils + * @since 2.7.0 + */ +public class DubboUtilsTest { + + @Test + public void testConstants() { + + Assert.assertEquals("dubbo", DUBBO_PREFIX); + + Assert.assertEquals("dubbo.scan.", DUBBO_SCAN_PREFIX); + + Assert.assertEquals("base-packages", BASE_PACKAGES_PROPERTY_NAME); + + Assert.assertEquals("dubbo.config.", DUBBO_CONFIG_PREFIX); + + Assert.assertEquals("multiple", MULTIPLE_CONFIG_PROPERTY_NAME); + + Assert.assertEquals("dubbo.config.override", OVERRIDE_CONFIG_FULL_PROPERTY_NAME); + + Assert.assertEquals("https://github.com/apache/dubbo-spring-boot-project", DUBBO_SPRING_BOOT_GITHUB_URL); + Assert.assertEquals("https://github.com/apache/dubbo-spring-boot-project.git", DUBBO_SPRING_BOOT_GIT_URL); + Assert.assertEquals("https://github.com/apache/dubbo-spring-boot-project/issues", DUBBO_SPRING_BOOT_ISSUES_URL); + + Assert.assertEquals("https://github.com/apache/dubbo", DUBBO_GITHUB_URL); + + Assert.assertEquals("dev@dubbo.apache.org", DUBBO_MAILING_LIST); + + Assert.assertEquals("spring.application.name", SPRING_APPLICATION_NAME_PROPERTY); + Assert.assertEquals("dubbo.application.id", DUBBO_APPLICATION_ID_PROPERTY); + Assert.assertEquals("dubbo.application.name", DUBBO_APPLICATION_NAME_PROPERTY); + Assert.assertEquals("dubbo.application.qos-enable", DUBBO_APPLICATION_QOS_ENABLE_PROPERTY); + Assert.assertEquals("dubbo.config.multiple", DUBBO_CONFIG_MULTIPLE_PROPERTY); + + Assert.assertTrue(DEFAULT_MULTIPLE_CONFIG_PROPERTY_VALUE); + + Assert.assertTrue(DEFAULT_OVERRIDE_CONFIG_PROPERTY_VALUE); + + + } + +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/resources/META-INF/dubbo.properties b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/resources/META-INF/dubbo.properties index f18569fd88..7796c2117f 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/resources/META-INF/dubbo.properties +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/resources/META-INF/dubbo.properties @@ -1 +1 @@ -dubbo.application.name = test-dubbo-application \ No newline at end of file +dubbo.application.name = test-dubbo-application diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/resources/META-INF/spring/dubbo-context.xml b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/resources/META-INF/spring/dubbo-context.xml index 268cf907fe..87b6505cf3 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/resources/META-INF/spring/dubbo-context.xml +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/resources/META-INF/spring/dubbo-context.xml @@ -1,14 +1,14 @@ - - - - - - - + + + + + + + \ No newline at end of file diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/pom.xml b/dubbo-spring-boot/dubbo-spring-boot-compatible/pom.xml index 06f277c356..9f4d8570fb 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-compatible/pom.xml +++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/pom.xml @@ -1,53 +1,53 @@ - - - - - org.apache.dubbo - dubbo-spring-boot - ${revision} - ../pom.xml - - 4.0.0 - - dubbo-spring-boot-compatible - pom - Apache Dubbo Spring Boot Compatible for Spring Boot 1.x - - - 1.5.22.RELEASE - - - - autoconfigure - actuator - - - - - - - spring-boot-1.4 - - 1.4.7.RELEASE - - - - + + + + + org.apache.dubbo + dubbo-spring-boot + ${revision} + ../pom.xml + + 4.0.0 + + dubbo-spring-boot-compatible + pom + Apache Dubbo Spring Boot Compatible for Spring Boot 1.x + + + 1.5.22.RELEASE + + + + autoconfigure + actuator + + + + + + + spring-boot-1.4 + + 1.4.7.RELEASE + + + + \ No newline at end of file diff --git a/dubbo-spring-boot/dubbo-spring-boot-starter/pom.xml b/dubbo-spring-boot/dubbo-spring-boot-starter/pom.xml index d3816464f2..763795bfb4 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-starter/pom.xml +++ b/dubbo-spring-boot/dubbo-spring-boot-starter/pom.xml @@ -1,49 +1,49 @@ - - - - - org.apache.dubbo - dubbo-spring-boot - ${revision} - ../pom.xml - - 4.0.0 - - dubbo-spring-boot-starter - jar - Apache Dubbo Spring Boot Starter - - - - - - org.springframework.boot - spring-boot-starter - true - - - - org.apache.dubbo - dubbo-spring-boot-autoconfigure - ${revision} - - - + + + + + org.apache.dubbo + dubbo-spring-boot + ${revision} + ../pom.xml + + 4.0.0 + + dubbo-spring-boot-starter + jar + Apache Dubbo Spring Boot Starter + + + + + + org.springframework.boot + spring-boot-starter + true + + + + org.apache.dubbo + dubbo-spring-boot-autoconfigure + ${revision} + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 63fb1da66b..86ebdcf4d9 100644 --- a/pom.xml +++ b/pom.xml @@ -125,6 +125,7 @@ 0.13 true + true true true 3.0.0-SNAPSHOT @@ -257,6 +258,7 @@ checkstyle false + false @@ -308,12 +310,34 @@ **/org/apache/dubbo/triple/TripleWrapper.java, **/istio/v1/auth/Ca.java, **/istio/v1/auth/IstioCertificateServiceGrpc.java, + **/generated/**/*, + **/target/**/*, check + + checkstyle-unix-validation + validate + + codestyle/checkstyle_unix.xml + UTF-8 + true + true + ${checkstyle_unix.skip} + + **/target/**/* + + + **/generated/**/* + + + + check + + @@ -610,6 +634,7 @@ .github/** compiler/** + **/generated/** **/mockito-extensions/*