Skip to content

Commit 553b98a

Browse files
committed
HADOOP-6578. Configuration should trim whitespace around a lot of value types. Contributed by Michele Catasta
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1054903 13f79535-47bb-0310-9956-ffa450edef68
1 parent a8f7063 commit 553b98a

File tree

3 files changed

+108
-8
lines changed

3 files changed

+108
-8
lines changed

CHANGES.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,9 @@ Release 0.22.0 - Unreleased
249249
HADOOP-6864. Provide a JNI-based implementation of ShellBasedUnixGroupsNetgroupMapping
250250
(implementation of GroupMappingServiceProvider) (Erik Seffl via boryas)
251251

252+
HADOOP-6578. Configuration should trim whitespace around a lot of value
253+
types. (Michele Catasta via eli)
254+
252255
OPTIMIZATIONS
253256

254257
HADOOP-6884. Add LOG.isDebugEnabled() guard for each LOG.debug(..).

src/java/org/apache/hadoop/conf/Configuration.java

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,29 @@ public String get(String name) {
544544
name = handleDeprecation(name);
545545
return substituteVars(getProps().getProperty(name));
546546
}
547+
548+
/**
549+
* Get the value of the <code>name</code> property as a trimmed <code>String</code>,
550+
* <code>null</code> if no such property exists.
551+
* If the key is deprecated, it returns the value of
552+
* the first key which replaces the deprecated key and is not null
553+
*
554+
* Values are processed for <a href="#VariableExpansion">variable expansion</a>
555+
* before being returned.
556+
*
557+
* @param name the property name.
558+
* @return the value of the <code>name</code> or its replacing property,
559+
* or null if no such property exists.
560+
*/
561+
public String getTrimmed(String name) {
562+
String value = get(name);
563+
564+
if (null == value) {
565+
return null;
566+
} else {
567+
return value.trim();
568+
}
569+
}
547570

548571
/**
549572
* Get the value of the <code>name</code> property, without doing
@@ -644,7 +667,7 @@ public String get(String name, String defaultValue) {
644667
* or <code>defaultValue</code>.
645668
*/
646669
public int getInt(String name, int defaultValue) {
647-
String valueString = get(name);
670+
String valueString = getTrimmed(name);
648671
if (valueString == null)
649672
return defaultValue;
650673
try {
@@ -680,7 +703,7 @@ public void setInt(String name, int value) {
680703
* or <code>defaultValue</code>.
681704
*/
682705
public long getLong(String name, long defaultValue) {
683-
String valueString = get(name);
706+
String valueString = getTrimmed(name);
684707
if (valueString == null)
685708
return defaultValue;
686709
try {
@@ -733,7 +756,7 @@ public void setLong(String name, long value) {
733756
* or <code>defaultValue</code>.
734757
*/
735758
public float getFloat(String name, float defaultValue) {
736-
String valueString = get(name);
759+
String valueString = getTrimmed(name);
737760
if (valueString == null)
738761
return defaultValue;
739762
try {
@@ -763,7 +786,7 @@ public void setFloat(String name, float value) {
763786
* or <code>defaultValue</code>.
764787
*/
765788
public boolean getBoolean(String name, boolean defaultValue) {
766-
String valueString = get(name);
789+
String valueString = getTrimmed(name);
767790
if ("true".equals(valueString))
768791
return true;
769792
else if ("false".equals(valueString))
@@ -1079,7 +1102,7 @@ public Class<?> getClassByName(String name) throws ClassNotFoundException {
10791102
}
10801103
}
10811104

1082-
Class clazz = map.get(name);
1105+
Class<?> clazz = map.get(name);
10831106
if (clazz == null) {
10841107
clazz = Class.forName(name, true, classLoader);
10851108
if (clazz != null) {
@@ -1104,7 +1127,7 @@ public Class<?> getClassByName(String name) throws ClassNotFoundException {
11041127
* or <code>defaultValue</code>.
11051128
*/
11061129
public Class<?>[] getClasses(String name, Class<?> ... defaultValue) {
1107-
String[] classnames = getStrings(name);
1130+
String[] classnames = getTrimmedStrings(name);
11081131
if (classnames == null)
11091132
return defaultValue;
11101133
try {
@@ -1129,7 +1152,7 @@ public Class<?>[] getClasses(String name, Class<?> ... defaultValue) {
11291152
* or <code>defaultValue</code>.
11301153
*/
11311154
public Class<?> getClass(String name, Class<?> defaultValue) {
1132-
String valueString = get(name);
1155+
String valueString = getTrimmed(name);
11331156
if (valueString == null)
11341157
return defaultValue;
11351158
try {

src/test/core/org/apache/hadoop/conf/TestConfiguration.java

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.util.regex.Pattern;
3030

3131
import junit.framework.TestCase;
32+
import static org.junit.Assert.assertArrayEquals;
3233

3334
import org.apache.hadoop.fs.Path;
3435
import org.codehaus.jackson.map.ObjectMapper;
@@ -337,6 +338,7 @@ public void testIntegerValues() throws IOException{
337338
appendProperty("test.int1", "20");
338339
appendProperty("test.int2", "020");
339340
appendProperty("test.int3", "-20");
341+
appendProperty("test.int4", " -20 ");
340342
endConfig();
341343
Path fileResource = new Path(CONFIG);
342344
conf.addResource(fileResource);
@@ -346,8 +348,80 @@ public void testIntegerValues() throws IOException{
346348
assertEquals(20, conf.getLong("test.int2", 0));
347349
assertEquals(-20, conf.getInt("test.int3", 0));
348350
assertEquals(-20, conf.getLong("test.int3", 0));
351+
assertEquals(-20, conf.getInt("test.int4", 0));
352+
assertEquals(-20, conf.getLong("test.int4", 0));
349353
}
350-
354+
355+
public void testBooleanValues() throws IOException {
356+
out=new BufferedWriter(new FileWriter(CONFIG));
357+
startConfig();
358+
appendProperty("test.bool1", "true");
359+
appendProperty("test.bool2", "false");
360+
appendProperty("test.bool3", " true ");
361+
appendProperty("test.bool4", " false ");
362+
appendProperty("test.bool5", "foo");
363+
endConfig();
364+
Path fileResource = new Path(CONFIG);
365+
conf.addResource(fileResource);
366+
assertEquals(true, conf.getBoolean("test.bool1", false));
367+
assertEquals(false, conf.getBoolean("test.bool2", true));
368+
assertEquals(true, conf.getBoolean("test.bool3", false));
369+
assertEquals(false, conf.getBoolean("test.bool4", true));
370+
assertEquals(true, conf.getBoolean("test.bool5", true));
371+
}
372+
373+
public void testFloatValues() throws IOException {
374+
out=new BufferedWriter(new FileWriter(CONFIG));
375+
startConfig();
376+
appendProperty("test.float1", "3.1415");
377+
appendProperty("test.float2", "003.1415");
378+
appendProperty("test.float3", "-3.1415");
379+
appendProperty("test.float4", " -3.1415 ");
380+
endConfig();
381+
Path fileResource = new Path(CONFIG);
382+
conf.addResource(fileResource);
383+
assertEquals(3.1415f, conf.getFloat("test.float1", 0.0f));
384+
assertEquals(3.1415f, conf.getFloat("test.float2", 0.0f));
385+
assertEquals(-3.1415f, conf.getFloat("test.float3", 0.0f));
386+
assertEquals(-3.1415f, conf.getFloat("test.float4", 0.0f));
387+
}
388+
389+
public void testGetClass() throws IOException {
390+
out=new BufferedWriter(new FileWriter(CONFIG));
391+
startConfig();
392+
appendProperty("test.class1", "java.lang.Integer");
393+
appendProperty("test.class2", " java.lang.Integer ");
394+
endConfig();
395+
Path fileResource = new Path(CONFIG);
396+
conf.addResource(fileResource);
397+
assertEquals("java.lang.Integer", conf.getClass("test.class1", null).getCanonicalName());
398+
assertEquals("java.lang.Integer", conf.getClass("test.class2", null).getCanonicalName());
399+
}
400+
401+
public void testGetClasses() throws IOException {
402+
out=new BufferedWriter(new FileWriter(CONFIG));
403+
startConfig();
404+
appendProperty("test.classes1", "java.lang.Integer,java.lang.String");
405+
appendProperty("test.classes2", " java.lang.Integer , java.lang.String ");
406+
endConfig();
407+
Path fileResource = new Path(CONFIG);
408+
conf.addResource(fileResource);
409+
String[] expectedNames = {"java.lang.Integer", "java.lang.String"};
410+
Class<?>[] defaultClasses = {};
411+
Class<?>[] classes1 = conf.getClasses("test.classes1", defaultClasses);
412+
Class<?>[] classes2 = conf.getClasses("test.classes2", defaultClasses);
413+
assertArrayEquals(expectedNames, extractClassNames(classes1));
414+
assertArrayEquals(expectedNames, extractClassNames(classes2));
415+
}
416+
417+
private static String[] extractClassNames(Class<?>[] classes) {
418+
String[] classNames = new String[classes.length];
419+
for (int i = 0; i < classNames.length; i++) {
420+
classNames[i] = classes[i].getCanonicalName();
421+
}
422+
return classNames;
423+
}
424+
351425
enum Dingo { FOO, BAR };
352426
enum Yak { RAB, FOO };
353427
public void testEnum() throws IOException {

0 commit comments

Comments
 (0)