This is an automated email from the ASF dual-hosted git repository.

albumenj pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/dubbo.git


The following commit(s) were added to refs/heads/master by this push:
     new 6acd5a2  fix #8378 parameter convert error (#8379)
6acd5a2 is described below

commit 6acd5a2a935c41c3f0b29ad9dce0d7e14586fded
Author: lmj <[email protected]>
AuthorDate: Sun Aug 15 22:18:00 2021 +0800

    fix #8378 parameter convert error (#8379)
---
 .../factory/annotation/ReferenceBeanBuilder.java   | 19 ++-----
 .../annotation/ServiceClassPostProcessor.java      | 23 +-------
 .../config/spring/util/DubboAnnotationUtils.java   | 64 +++++++++++++++++++++-
 .../factory/annotation/ParameterConvertTest.java   | 60 ++++++++++++++++++++
 4 files changed, 130 insertions(+), 36 deletions(-)

diff --git 
a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceBeanBuilder.java
 
b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceBeanBuilder.java
index 7d61ec9..285e51a 100644
--- 
a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceBeanBuilder.java
+++ 
b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceBeanBuilder.java
@@ -16,12 +16,12 @@
  */
 package org.apache.dubbo.config.spring.beans.factory.annotation;
 
-import org.apache.dubbo.common.utils.CollectionUtils;
 import org.apache.dubbo.config.ConsumerConfig;
 import org.apache.dubbo.config.MethodConfig;
 import org.apache.dubbo.config.annotation.Method;
 import org.apache.dubbo.config.annotation.Reference;
 import org.apache.dubbo.config.spring.ReferenceBean;
+import org.apache.dubbo.config.spring.util.DubboAnnotationUtils;
 import org.springframework.beans.propertyeditors.StringTrimmerEditor;
 import org.springframework.context.ApplicationContext;
 import org.springframework.core.annotation.AnnotationAttributes;
@@ -39,7 +39,6 @@ import static com.alibaba.spring.util.ObjectUtils.of;
 import static 
org.apache.dubbo.config.spring.util.DubboAnnotationUtils.resolveServiceInterfaceClass;
 import static 
org.apache.dubbo.config.spring.util.DubboBeanUtils.getOptionalBean;
 import static org.springframework.core.annotation.AnnotationAttributes.fromMap;
-import static 
org.springframework.util.StringUtils.commaDelimitedListToStringArray;
 
 /**
  * {@link ReferenceBean} Builder
@@ -124,19 +123,11 @@ class ReferenceBeanBuilder extends 
AnnotatedInterfaceConfigBeanBuilder<Reference
         dataBinder.registerCustomEditor(String.class, "listener", new 
StringTrimmerEditor(true));
         dataBinder.registerCustomEditor(Map.class, "parameters", new 
PropertyEditorSupport() {
             @Override
-            public void setAsText(String text) throws 
java.lang.IllegalArgumentException {
-                // Trim all whitespace
-                String content = StringUtils.trimAllWhitespace(text);
-                if (!StringUtils.hasText(content)) { // No content , ignore 
directly
-                    return;
+            public void setValue(Object value) {
+                if (value instanceof String[]) {
+                    value = DubboAnnotationUtils.convertParameters((String[]) 
value);
                 }
-                // replace "=" to ","
-                content = StringUtils.replace(content, "=", ",");
-                // replace ":" to ","
-                content = StringUtils.replace(content, ":", ",");
-                // String[] to Map
-                Map<String, String> parameters = 
CollectionUtils.toStringMap(commaDelimitedListToStringArray(content));
-                setValue(parameters);
+                super.setValue(value);
             }
         });
 
diff --git 
a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceClassPostProcessor.java
 
b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceClassPostProcessor.java
index 3181ca1..7997fc1 100644
--- 
a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceClassPostProcessor.java
+++ 
b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceClassPostProcessor.java
@@ -18,7 +18,6 @@ package 
org.apache.dubbo.config.spring.beans.factory.annotation;
 
 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.config.MethodConfig;
 import org.apache.dubbo.config.annotation.DubboService;
 import org.apache.dubbo.config.annotation.Method;
@@ -27,7 +26,7 @@ import org.apache.dubbo.config.spring.ServiceBean;
 import 
org.apache.dubbo.config.spring.context.DubboBootstrapApplicationListener;
 import 
org.apache.dubbo.config.spring.context.annotation.DubboClassPathBeanDefinitionScanner;
 import org.apache.dubbo.config.spring.schema.AnnotationBeanDefinitionParser;
-
+import org.apache.dubbo.config.spring.util.DubboAnnotationUtils;
 import org.springframework.beans.BeansException;
 import org.springframework.beans.MutablePropertyValues;
 import org.springframework.beans.factory.BeanClassLoaderAware;
@@ -62,10 +61,8 @@ import org.springframework.util.StringUtils;
 import java.lang.annotation.Annotation;
 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.Objects;
 import java.util.Set;
 
@@ -414,7 +411,7 @@ public class ServiceClassPostProcessor implements 
BeanDefinitionRegistryPostProc
         // Set interface
         builder.addPropertyValue("interface", interfaceClass.getName());
         // Convert parameters into map
-        builder.addPropertyValue("parameters", 
convertParameters(serviceAnnotationAttributes.getStringArray("parameters")));
+        builder.addPropertyValue("parameters", 
DubboAnnotationUtils.convertParameters(serviceAnnotationAttributes.getStringArray("parameters")));
         // Add methods parameters
         List<MethodConfig> methodConfigs = 
convertMethodConfigs(serviceAnnotationAttributes.get("methods"));
         if (!methodConfigs.isEmpty()) {
@@ -511,22 +508,6 @@ public class ServiceClassPostProcessor implements 
BeanDefinitionRegistryPostProc
         builder.addPropertyReference(propertyName, resolvedBeanName);
     }
 
-    private Map<String, String> convertParameters(String[] parameters) {
-        if (ArrayUtils.isEmpty(parameters)) {
-            return null;
-        }
-
-        if (parameters.length % 2 != 0) {
-            throw new IllegalArgumentException("parameter attribute must be 
paired with key followed by value");
-        }
-
-        Map<String, String> map = new HashMap<>();
-        for (int i = 0; i < parameters.length; i += 2) {
-            map.put(parameters[i], parameters[i + 1]);
-        }
-        return map;
-    }
-
     @Override
     public void postProcessBeanFactory(ConfigurableListableBeanFactory 
beanFactory) throws BeansException {
 
diff --git 
a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/DubboAnnotationUtils.java
 
b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/DubboAnnotationUtils.java
index 0a4d3ad..1c4e50d 100644
--- 
a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/DubboAnnotationUtils.java
+++ 
b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/DubboAnnotationUtils.java
@@ -16,13 +16,20 @@
  */
 package org.apache.dubbo.config.spring.util;
 
+import org.apache.dubbo.common.utils.ArrayUtils;
+import org.apache.dubbo.common.utils.CollectionUtils;
 import org.apache.dubbo.config.annotation.Reference;
 import org.apache.dubbo.config.annotation.Service;
-
 import org.springframework.core.annotation.AnnotationAttributes;
 import org.springframework.util.Assert;
 import org.springframework.util.ClassUtils;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
 import static com.alibaba.spring.util.AnnotationUtils.getAttribute;
 import static org.springframework.util.ClassUtils.getAllInterfacesForClass;
 import static org.springframework.util.ClassUtils.resolveClassName;
@@ -147,4 +154,59 @@ public class DubboAnnotationUtils {
 
         return interfaceName;
     }
+
+    /**
+     * Resolve the parameters of {@link 
org.apache.dubbo.config.annotation.DubboService}
+     * and {@link org.apache.dubbo.config.annotation.DubboReference} from the 
specified.
+     * It iterate elements in order.The former element plays as key or 
key&value role, it would be
+     * spilt if it contain specific string, for instance, ":" and "=". As for 
later element can't
+     * be split in anytime.It will throw IllegalArgumentException If converted 
array length isn't
+     * even number.
+     * The convert cases below work in right way,which are best practice.
+     * <p>
+     * (array->map)
+     * ["a","b"] ==> {a=b}
+     * [" a "," b "] ==> {a=b}
+     * ["a=b"] ==>{a=b}
+     * ["a:b"] ==>{a=b}
+     * ["a=b","c","d"] ==>{a=b,c=d}
+     * ["a","a:b"] ==>{a=a:b}
+     * </p>
+     *
+     * @param parameters
+     * @return
+     */
+    public static Map<String, String> convertParameters(String[] parameters) {
+        if (ArrayUtils.isEmpty(parameters)) {
+            return null;
+        }
+
+        List<String> compatibleParameterArray = Arrays.stream(parameters)
+                .map(String::trim)
+                .reduce(new ArrayList<>(parameters.length), (list, parameter) 
->
+                        {
+                            if (list.size() % 2 == 1) {
+                                //value doesn't split
+                                list.add(parameter);
+                                return list;
+                            }
+
+                            String[] sp1 = parameter.split(":");
+                            if (sp1.length > 0 && sp1.length % 2 == 0) {
+                                //key split
+                                
list.addAll(Arrays.stream(sp1).map(String::trim).collect(Collectors.toList()));
+                                return list;
+                            }
+                            sp1 = parameter.split("=");
+                            if (sp1.length > 0 && sp1.length % 2 == 0) {
+                                
list.addAll(Arrays.stream(sp1).map(String::trim).collect(Collectors.toList()));
+                                return list;
+                            }
+                            list.add(parameter);
+                            return list;
+                        }
+                        , (a, b) -> a);
+
+        return 
CollectionUtils.toStringMap(compatibleParameterArray.toArray(new String[0]));
+    }
 }
diff --git 
a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ParameterConvertTest.java
 
b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ParameterConvertTest.java
new file mode 100644
index 0000000..d32e4ec
--- /dev/null
+++ 
b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ParameterConvertTest.java
@@ -0,0 +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.config.spring.beans.factory.annotation;
+
+import org.apache.dubbo.config.spring.util.DubboAnnotationUtils;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.test.annotation.DirtiesContext;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * {@link DubboAnnotationUtils#convertParameters} Test
+ */
+@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
+public class ParameterConvertTest {
+
+    @Test
+    public void test() {
+        /**
+         *     (array->map)
+         *     ["a","b"] ==> {a=b}
+         *     [" a "," b "] ==> {a=b}
+         *     ["a=b"] ==>{a=b}
+         *     ["a:b"] ==>{a=b}
+         *     ["a=b","c","d"] ==>{a=b,c=d}
+         *     ["a=b","c:d"] ==>{a=b,c=d}
+         *     ["a","a:b"] ==>{a=a:b}
+         */
+        Map<String, String> parametersMap = new HashMap<>();
+        parametersMap.put("a", "b");
+        Assertions.assertEquals(parametersMap, 
DubboAnnotationUtils.convertParameters(new String[]{"a", "b"}));
+        Assertions.assertEquals(parametersMap, 
DubboAnnotationUtils.convertParameters(new String[]{" a ", " b "}));
+        Assertions.assertEquals(parametersMap, 
DubboAnnotationUtils.convertParameters(new String[]{"a=b"}));
+        Assertions.assertEquals(parametersMap, 
DubboAnnotationUtils.convertParameters(new String[]{"a:b"}));
+
+        parametersMap.put("c", "d");
+        Assertions.assertEquals(parametersMap, 
DubboAnnotationUtils.convertParameters(new String[]{"a=b", "c", "d"}));
+        Assertions.assertEquals(parametersMap, 
DubboAnnotationUtils.convertParameters(new String[]{"a:b", "c=d"}));
+
+        parametersMap.clear();
+        parametersMap.put("a", "a:b");
+        Assertions.assertEquals(parametersMap, 
DubboAnnotationUtils.convertParameters(new String[]{"a", "a:b"}));
+    }
+}

Reply via email to