Repository: apache/dubbo (Java) — Bug Fix

Issue:
fail to parse config text with white space
- [ ] I have searched the [issues](https://github.com/apache/incubator-dubbo/issues) of this repository and believe that this is not a duplicate.
- [ ] I have checked the [FAQ](https://github.com/apache/incubator-dubbo/blob/master/FAQ.md) of this repository and believe that this is not a duplicate.

### Environment

* Dubbo version: 2.7.0
* Operating System version: Mac OS
* Java version: JDK1.8

### Steps to reproduce this issue

1. create `dubbo.properties` with trailing white space  
```properties
dubbo.provider.timeout=6666    
```
2. start dubbo provider  
3. will cause an exception: 
```java
java.lang.NumberFormatException: For input string: "6666   "
	at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
	at java.lang.Integer.parseInt(Integer.java:580)
	at java.lang.Integer.valueOf(Integer.java:766)
	at org.apache.dubbo.common.utils.ClassHelper.convertPrimitive(ClassHelper.java:277)
	at org.apache.dubbo.config.AbstractConfig.refresh(AbstractConfig.java:568)
	at java.util.concurrent.ConcurrentHashMap$ValuesView.forEach(ConcurrentHashMap.java:4707)
	at org.apache.dubbo.config.context.ConfigManager.refreshAll(ConfigManager.java:308)
	at org.apache.dubbo.config.AbstractInterfaceConfig.startConfigCenter(AbstractInterfaceConfig.java:241)
	at org.apache.dubbo.config.ServiceConfig.checkAndUpdateSubConfigs(ServiceConfig.java:267)
	at org.apache.dubbo.config.ServiceConfig.export(ServiceConfig.java:328)
	at org.apache.dubbo.config.spring.ServiceBean.onApplicationEvent(ServiceBean.java:104)
	at org.apache.dubbo.config.spring.ServiceBean.onApplicationEvent(ServiceBean.java:55)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
	at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:400)
	at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:354)
	at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:886)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.finishRefresh(ServletWebServerApplicationContext.java:161)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:386)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:307)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1242)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1230)
	at org.apache.dubbo.demo.DubboProviderApplication.main(DubboProviderApplication.java:13)
```

Pls. provide [GitHub address] to reproduce this issue.

### Expected Result

What do you expected from the above steps？

### Actual Result

What actually happens?

If there is an exception, please attach the exception trace:

```
Just put your stack trace here!
```



Discussion:
Deleting the space will succeed. I don't recommend enhancing the handling of the space here. What do you think?
There is a similar discussion in Springboot project 
https://github.com/spring-projects/spring-boot/issues/13602#issuecomment-402113151
White space should definitely be considered.

Resolving patch:
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/ConfigurationUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/ConfigurationUtils.java
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/ConfigurationUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/ConfigurationUtils.java
@@ -38,7 +38,7 @@ public class ConfigurationUtils {
     public static int getServerShutdownTimeout() {
         int timeout = Constants.DEFAULT_SERVER_SHUTDOWN_TIMEOUT;
         Configuration configuration = Environment.getInstance().getConfiguration();
-        String value = configuration.getString(Constants.SHUTDOWN_WAIT_KEY);
+        String value = StringUtils.trim(configuration.getString(Constants.SHUTDOWN_WAIT_KEY));
 
         if (value != null && value.length() > 0) {
             try {
@@ -47,7 +47,7 @@ public static int getServerShutdownTimeout() {
                 // ignore
             }
         } else {
-            value = configuration.getString(Constants.SHUTDOWN_WAIT_SECONDS_KEY);
+            value = StringUtils.trim(configuration.getString(Constants.SHUTDOWN_WAIT_SECONDS_KEY));
             if (value != null && value.length() > 0) {
                 try {
                     timeout = Integer.parseInt(value) * 1000;
@@ -64,7 +64,7 @@ public static String getProperty(String property) {
     }
 
     public static String getProperty(String property, String defaultValue) {
-        return Environment.getInstance().getConfiguration().getString(property, defaultValue);
+        return StringUtils.trim(Environment.getInstance().getConfiguration().getString(property, defaultValue));
     }
 
     public static Map<String, String> parseProperties(String content) throws IOException {
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
--- 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
@@ -789,4 +789,8 @@ public static String toArgumentString(Object[] args) {
         }
         return buf.toString();
     }
+
+    public static String trim(String str) {
+        return str == null ? null : str.trim();
+    }
 }
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java
@@ -557,7 +557,7 @@ public void refresh() {
             for (Method method : methods) {
                 if (ClassHelper.isSetter(method)) {
                     try {
-                        String value = compositeConfiguration.getString(extractPropertyName(getClass(), method));
+                        String value = StringUtils.trim(compositeConfiguration.getString(extractPropertyName(getClass(), method)));
                         // isTypeMatch() is called to avoid duplicate and incorrect update, for example, we have two 'setGeneric' methods in ReferenceConfig.
                         if (StringUtils.isNotEmpty(value) && ClassHelper.isTypeMatch(method.getParameterTypes()[0], value)) {
                             method.invoke(this, ClassHelper.convertPrimitive(method.getParameterTypes()[0], value));


Test patch:
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/config/ConfigurationUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/config/ConfigurationUtilsTest.java
new file mode 100644
--- /dev/null
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/config/ConfigurationUtilsTest.java
@@ -0,0 +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.common.config;
+
+import org.apache.dubbo.common.Constants;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+/**
+ *
+ */
+public class ConfigurationUtilsTest {
+
+    @Test
+    public void testGetServerShutdownTimeout () {
+        System.setProperty(Constants.SHUTDOWN_WAIT_KEY, " 10000");
+        Assertions.assertEquals(10000, ConfigurationUtils.getServerShutdownTimeout());
+        System.clearProperty(Constants.SHUTDOWN_WAIT_KEY);
+    }
+
+    @Test
+    public void testGetProperty () {
+        System.setProperty(Constants.SHUTDOWN_WAIT_KEY, " 10000");
+        Assertions.assertEquals("10000", ConfigurationUtils.getProperty(Constants.SHUTDOWN_WAIT_KEY));
+        System.clearProperty(Constants.SHUTDOWN_WAIT_KEY);
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/StringUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/StringUtilsTest.java
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/StringUtilsTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/StringUtilsTest.java
@@ -287,4 +287,12 @@ public void testToArgumentString() throws Exception {
         assertThat(s, containsString("0,"));
         assertThat(s, containsString("{\"enabled\":true}"));
     }
+
+    @Test
+    public void testTrim() {
+        assertEquals("left blank", StringUtils.trim(" left blank"));
+        assertEquals("right blank", StringUtils.trim("right blank "));
+        assertEquals("bi-side blank", StringUtils.trim(" bi-side blank "));
+
+    }
 }
\ No newline at end of file