Skip to content

Commit

Permalink
fix #8378 parameter convert error
Browse files Browse the repository at this point in the history
  • Loading branch information
24kpure committed Aug 4, 2021
1 parent ca794b6 commit 51219ce
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 36 deletions.
Expand Up @@ -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;
Expand All @@ -39,7 +39,6 @@
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
Expand Down Expand Up @@ -124,19 +123,11 @@ protected void preConfigureBean(AnnotationAttributes attributes, ReferenceBean r
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);
}
});

Expand Down
Expand Up @@ -18,7 +18,6 @@

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;
Expand All @@ -27,7 +26,7 @@
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;
Expand Down Expand Up @@ -62,10 +61,8 @@
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;

Expand Down Expand Up @@ -414,7 +411,7 @@ private AbstractBeanDefinition buildServiceBeanDefinition(Annotation serviceAnno
// 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()) {
Expand Down Expand Up @@ -511,22 +508,6 @@ private void addPropertyReference(BeanDefinitionBuilder builder, String property
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 {

Expand Down
Expand Up @@ -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;
Expand Down Expand Up @@ -147,4 +154,59 @@ public static String resolveInterfaceName(Reference reference, Class<?> defaultI

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]));
}
}
@@ -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"}));
}
}

0 comments on commit 51219ce

Please sign in to comment.