summaryrefslogtreecommitdiff
path: root/spring-core/src/test/java/org/springframework
diff options
context:
space:
mode:
authorEmmanuel Bourg <ebourg@apache.org>2014-12-03 14:31:16 +0100
committerEmmanuel Bourg <ebourg@apache.org>2014-12-03 14:31:16 +0100
commitc56370beb0a2bfa263e125fce107dceccee89fd3 (patch)
tree7ee611ceb0acbbdf7f83abcd72adb854b7d77225 /spring-core/src/test/java/org/springframework
parentaa5221b73661fa728dc4e62e1230e9104528c4eb (diff)
Imported Upstream version 3.2.12
Diffstat (limited to 'spring-core/src/test/java/org/springframework')
-rw-r--r--spring-core/src/test/java/org/springframework/core/AbstractControlFlowTests.java90
-rw-r--r--spring-core/src/test/java/org/springframework/core/AbstractGenericsTests.java51
-rw-r--r--spring-core/src/test/java/org/springframework/core/AttributeAccessorSupportTests.java72
-rw-r--r--spring-core/src/test/java/org/springframework/core/BridgeMethodResolverTests.java1315
-rw-r--r--spring-core/src/test/java/org/springframework/core/CollectionFactoryTests.java74
-rw-r--r--spring-core/src/test/java/org/springframework/core/ConstantsTests.java272
-rw-r--r--spring-core/src/test/java/org/springframework/core/ConventionsTests.java74
-rw-r--r--spring-core/src/test/java/org/springframework/core/DefaultControlFlowTests.java38
-rw-r--r--spring-core/src/test/java/org/springframework/core/ExceptionDepthComparatorTests.java110
-rw-r--r--spring-core/src/test/java/org/springframework/core/GenericCollectionTypeResolverTests.java149
-rw-r--r--spring-core/src/test/java/org/springframework/core/GenericTypeResolverTests.java316
-rw-r--r--spring-core/src/test/java/org/springframework/core/Jdk14ControlFlowTests.java38
-rw-r--r--spring-core/src/test/java/org/springframework/core/LocalVariableTableParameterNameDiscovererTests.java314
-rw-r--r--spring-core/src/test/java/org/springframework/core/MethodParameterTests.java84
-rw-r--r--spring-core/src/test/java/org/springframework/core/NestedExceptionTests.java106
-rw-r--r--spring-core/src/test/java/org/springframework/core/OrderComparatorTests.java74
-rw-r--r--spring-core/src/test/java/org/springframework/core/ParameterizedTypeReferenceTests.java63
-rw-r--r--spring-core/src/test/java/org/springframework/core/PrioritizedParameterNameDiscovererTests.java88
-rw-r--r--spring-core/src/test/java/org/springframework/core/annotation/AnnotationAttributesTests.java110
-rw-r--r--spring-core/src/test/java/org/springframework/core/annotation/AnnotationAwareOrderComparatorTests.java90
-rw-r--r--spring-core/src/test/java/org/springframework/core/annotation/AnnotationUtilsTests.java441
-rw-r--r--spring-core/src/test/java/org/springframework/core/convert/TypeDescriptorTests.java890
-rw-r--r--spring-core/src/test/java/org/springframework/core/convert/converter/ConvertingComparatorTests.java148
-rw-r--r--spring-core/src/test/java/org/springframework/core/convert/support/CollectionToCollectionConverterTests.java338
-rw-r--r--spring-core/src/test/java/org/springframework/core/convert/support/DefaultConversionTests.java876
-rw-r--r--spring-core/src/test/java/org/springframework/core/convert/support/GenericConversionServiceTests.java1020
-rw-r--r--spring-core/src/test/java/org/springframework/core/convert/support/MapToMapConverterTests.java227
-rw-r--r--spring-core/src/test/java/org/springframework/core/enums/LabeledEnumTests.java192
-rw-r--r--spring-core/src/test/java/org/springframework/core/enums/StandAloneStaticLabeledEnum.java36
-rw-r--r--spring-core/src/test/java/org/springframework/core/env/CustomEnvironmentTests.java108
-rw-r--r--spring-core/src/test/java/org/springframework/core/env/DummyEnvironment.java75
-rw-r--r--spring-core/src/test/java/org/springframework/core/env/JOptCommandLinePropertySourceTests.java165
-rw-r--r--spring-core/src/test/java/org/springframework/core/env/MutablePropertySourcesTests.java158
-rw-r--r--spring-core/src/test/java/org/springframework/core/env/PropertySourceTests.java120
-rw-r--r--spring-core/src/test/java/org/springframework/core/env/PropertySourcesPropertyResolverTests.java441
-rw-r--r--spring-core/src/test/java/org/springframework/core/env/SimpleCommandLineParserTests.java114
-rw-r--r--spring-core/src/test/java/org/springframework/core/env/SimpleCommandLinePropertySourceTests.java126
-rw-r--r--spring-core/src/test/java/org/springframework/core/env/StandardEnvironmentTests.java550
-rw-r--r--spring-core/src/test/java/org/springframework/core/env/SystemEnvironmentPropertySourceTests.java104
-rw-r--r--spring-core/src/test/java/org/springframework/core/io/ClassPathResourceTests.java126
-rw-r--r--spring-core/src/test/java/org/springframework/core/io/ResourceEditorTests.java90
-rw-r--r--spring-core/src/test/java/org/springframework/core/io/ResourceTests.java254
-rw-r--r--spring-core/src/test/java/org/springframework/core/io/example.properties1
-rw-r--r--spring-core/src/test/java/org/springframework/core/io/example.xml6
-rw-r--r--spring-core/src/test/java/org/springframework/core/io/support/DummyFactory.java28
-rw-r--r--spring-core/src/test/java/org/springframework/core/io/support/MyDummyFactory1.java33
-rw-r--r--spring-core/src/test/java/org/springframework/core/io/support/MyDummyFactory2.java33
-rw-r--r--spring-core/src/test/java/org/springframework/core/io/support/PathMatchingResourcePatternResolverTests.java165
-rw-r--r--spring-core/src/test/java/org/springframework/core/io/support/ResourceArrayPropertyEditorTests.java85
-rw-r--r--spring-core/src/test/java/org/springframework/core/io/support/ResourcePropertySourceTests.java102
-rw-r--r--spring-core/src/test/java/org/springframework/core/serializer/SerializationConverterTests.java85
-rw-r--r--spring-core/src/test/java/org/springframework/core/style/ToStringCreatorTests.java127
-rw-r--r--spring-core/src/test/java/org/springframework/core/task/SimpleAsyncTaskExecutorTests.java141
-rw-r--r--spring-core/src/test/java/org/springframework/core/type/AbstractClassMetadataMemberClassTests.java76
-rw-r--r--spring-core/src/test/java/org/springframework/core/type/AnnotationMetadataTests.java224
-rw-r--r--spring-core/src/test/java/org/springframework/core/type/AnnotationTypeFilterTests.java153
-rw-r--r--spring-core/src/test/java/org/springframework/core/type/AspectJTypeFilterTests.java164
-rw-r--r--spring-core/src/test/java/org/springframework/core/type/AssignableTypeFilterTests.java105
-rw-r--r--spring-core/src/test/java/org/springframework/core/type/CachingMetadataReaderLeakTest.java82
-rw-r--r--spring-core/src/test/java/org/springframework/core/type/ClassloadingAssertions.java45
-rw-r--r--spring-core/src/test/java/org/springframework/core/type/Scope.java36
-rw-r--r--spring-core/src/test/java/org/springframework/core/type/StandardClassMetadataMemberClassTests.java32
-rw-r--r--spring-core/src/test/java/org/springframework/core/type/TestAutowired.java34
-rw-r--r--spring-core/src/test/java/org/springframework/core/type/TestQualifier.java34
-rw-r--r--spring-core/src/test/java/org/springframework/core/type/classreading/ClassMetadataReadingVisitorMemberClassTests.java43
-rw-r--r--spring-core/src/test/java/org/springframework/mock/env/MockPropertySource.java104
-rw-r--r--spring-core/src/test/java/org/springframework/stereotype/Component.java54
-rw-r--r--spring-core/src/test/java/org/springframework/tests/Assume.java112
-rw-r--r--spring-core/src/test/java/org/springframework/tests/BuildTests.java36
-rw-r--r--spring-core/src/test/java/org/springframework/tests/JavaVersion.java96
-rw-r--r--spring-core/src/test/java/org/springframework/tests/JavaVersionTests.java43
-rw-r--r--spring-core/src/test/java/org/springframework/tests/Matchers.java67
-rw-r--r--spring-core/src/test/java/org/springframework/tests/MockitoUtils.java88
-rw-r--r--spring-core/src/test/java/org/springframework/tests/TestGroup.java96
-rw-r--r--spring-core/src/test/java/org/springframework/tests/TestGroupTests.java75
-rw-r--r--spring-core/src/test/java/org/springframework/tests/TestResourceUtils.java46
-rw-r--r--spring-core/src/test/java/org/springframework/tests/TimeStamped.java34
-rw-r--r--spring-core/src/test/java/org/springframework/tests/package-info.java22
-rw-r--r--spring-core/src/test/java/org/springframework/tests/sample/objects/DerivedTestObject.java24
-rw-r--r--spring-core/src/test/java/org/springframework/tests/sample/objects/GenericObject.java36
-rw-r--r--spring-core/src/test/java/org/springframework/tests/sample/objects/ITestInterface.java24
-rw-r--r--spring-core/src/test/java/org/springframework/tests/sample/objects/ITestObject.java33
-rw-r--r--spring-core/src/test/java/org/springframework/tests/sample/objects/TestObject.java72
-rw-r--r--spring-core/src/test/java/org/springframework/tests/sample/objects/package-info.java4
-rw-r--r--spring-core/src/test/java/org/springframework/util/AntPathMatcherTests.java556
-rw-r--r--spring-core/src/test/java/org/springframework/util/AssertTests.java176
-rw-r--r--spring-core/src/test/java/org/springframework/util/AutoPopulatingListTests.java95
-rw-r--r--spring-core/src/test/java/org/springframework/util/CachingMapDecoratorTests.java116
-rw-r--r--spring-core/src/test/java/org/springframework/util/ClassUtilsTests.java401
-rw-r--r--spring-core/src/test/java/org/springframework/util/CollectionUtilsTests.java241
-rw-r--r--spring-core/src/test/java/org/springframework/util/CompositeIteratorTests.java129
-rw-r--r--spring-core/src/test/java/org/springframework/util/ConcurrentReferenceHashMapTests.java674
-rw-r--r--spring-core/src/test/java/org/springframework/util/DigestUtilsTests.java56
-rw-r--r--spring-core/src/test/java/org/springframework/util/FileCopyUtilsTests.java82
-rw-r--r--spring-core/src/test/java/org/springframework/util/FileSystemUtilsTests.java89
-rw-r--r--spring-core/src/test/java/org/springframework/util/LinkedCaseInsensitiveMapTests.java58
-rw-r--r--spring-core/src/test/java/org/springframework/util/LinkedMultiValueMapTests.java84
-rw-r--r--spring-core/src/test/java/org/springframework/util/Log4jConfigurerTests.java100
-rw-r--r--spring-core/src/test/java/org/springframework/util/MethodInvokerTests.java292
-rw-r--r--spring-core/src/test/java/org/springframework/util/MockLog4jAppender.java62
-rw-r--r--spring-core/src/test/java/org/springframework/util/NumberUtilsTests.java348
-rw-r--r--spring-core/src/test/java/org/springframework/util/ObjectUtilsTests.java763
-rw-r--r--spring-core/src/test/java/org/springframework/util/PatternMatchUtilsTests.java81
-rw-r--r--spring-core/src/test/java/org/springframework/util/PropertiesPersisterTests.java125
-rw-r--r--spring-core/src/test/java/org/springframework/util/PropertyPlaceholderHelperTests.java116
-rw-r--r--spring-core/src/test/java/org/springframework/util/ReflectionUtilsTests.java457
-rw-r--r--spring-core/src/test/java/org/springframework/util/ResourceUtilsTests.java72
-rw-r--r--spring-core/src/test/java/org/springframework/util/SerializationTestUtils.java65
-rw-r--r--spring-core/src/test/java/org/springframework/util/SerializationUtilsTests.java74
-rw-r--r--spring-core/src/test/java/org/springframework/util/StopWatchTests.java144
-rw-r--r--spring-core/src/test/java/org/springframework/util/StreamUtilsTests.java125
-rw-r--r--spring-core/src/test/java/org/springframework/util/StringUtilsTests.java703
-rw-r--r--spring-core/src/test/java/org/springframework/util/SystemPropertyUtilsTests.java137
-rw-r--r--spring-core/src/test/java/org/springframework/util/TypeUtilsTests.java128
-rw-r--r--spring-core/src/test/java/org/springframework/util/comparator/BooleanComparatorTests.java63
-rw-r--r--spring-core/src/test/java/org/springframework/util/comparator/ComparableComparatorTests.java57
-rw-r--r--spring-core/src/test/java/org/springframework/util/comparator/CompoundComparatorTests.java44
-rw-r--r--spring-core/src/test/java/org/springframework/util/comparator/InstanceComparatorTests.java92
-rw-r--r--spring-core/src/test/java/org/springframework/util/comparator/InvertibleComparatorTests.java81
-rw-r--r--spring-core/src/test/java/org/springframework/util/comparator/NullSafeComparatorTests.java49
-rw-r--r--spring-core/src/test/java/org/springframework/util/xml/AbstractStaxContentHandlerTestCase.java66
-rw-r--r--spring-core/src/test/java/org/springframework/util/xml/AbstractStaxXMLReaderTestCase.java267
-rw-r--r--spring-core/src/test/java/org/springframework/util/xml/DomContentHandlerTest.java95
-rw-r--r--spring-core/src/test/java/org/springframework/util/xml/SimpleNamespaceContextTests.java121
-rw-r--r--spring-core/src/test/java/org/springframework/util/xml/StaxEventContentHandlerTests.java30
-rw-r--r--spring-core/src/test/java/org/springframework/util/xml/StaxEventXMLReaderTests.java55
-rw-r--r--spring-core/src/test/java/org/springframework/util/xml/StaxResultTests.java77
-rw-r--r--spring-core/src/test/java/org/springframework/util/xml/StaxSourceTests.java108
-rw-r--r--spring-core/src/test/java/org/springframework/util/xml/StaxStreamContentHandlerTests.java30
-rw-r--r--spring-core/src/test/java/org/springframework/util/xml/StaxStreamXMLReaderTests.java69
-rw-r--r--spring-core/src/test/java/org/springframework/util/xml/StaxUtilsTest.java93
-rw-r--r--spring-core/src/test/java/org/springframework/util/xml/TransformerUtilsTests.java157
-rw-r--r--spring-core/src/test/java/org/springframework/util/xml/XMLEventStreamReaderTests.java63
-rw-r--r--spring-core/src/test/java/org/springframework/util/xml/XMLEventStreamWriterTests.java64
134 files changed, 21257 insertions, 0 deletions
diff --git a/spring-core/src/test/java/org/springframework/core/AbstractControlFlowTests.java b/spring-core/src/test/java/org/springframework/core/AbstractControlFlowTests.java
new file mode 100644
index 00000000..56e59e2d
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/AbstractControlFlowTests.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Rod Johnson
+ */
+public abstract class AbstractControlFlowTests extends TestCase {
+
+ protected abstract ControlFlow createControlFlow();
+
+ /*
+ * Class to test for boolean under(Class)
+ */
+ public void testUnderClassAndMethod() {
+ new One().test();
+ new Two().testing();
+ new Three().test();
+ }
+
+ /*
+ public void testUnderPackage() {
+ ControlFlow cflow = new ControlFlow();
+ assertFalse(cflow.underPackage("org.springframework.aop"));
+ assertTrue(cflow.underPackage("org.springframework.aop.support"));
+ assertFalse(cflow.underPackage("com.interface21"));
+ }
+ */
+
+
+ public class One {
+
+ public void test() {
+ ControlFlow cflow = createControlFlow();
+ assertTrue(cflow.under(One.class));
+ assertTrue(cflow.under(AbstractControlFlowTests.class));
+ assertFalse(cflow.under(Two.class));
+ assertTrue(cflow.under(One.class, "test"));
+ assertFalse(cflow.under(One.class, "hashCode"));
+ }
+
+ }
+
+
+ public class Two {
+
+ public void testing() {
+ ControlFlow cflow = createControlFlow();
+ assertTrue(cflow.under(Two.class));
+ assertTrue(cflow.under(AbstractControlFlowTests.class));
+ assertFalse(cflow.under(One.class));
+ assertFalse(cflow.under(Two.class, "test"));
+ assertTrue(cflow.under(Two.class, "testing"));
+ }
+ }
+
+
+ public class Three {
+
+ public void test() {
+ testing();
+ }
+
+ private void testing() {
+ ControlFlow cflow = createControlFlow();
+ assertTrue(cflow.under(Three.class));
+ assertTrue(cflow.under(AbstractControlFlowTests.class));
+ assertFalse(cflow.under(One.class));
+ assertTrue(cflow.under(Three.class, "test"));
+ assertTrue(cflow.under(Three.class, "testing"));
+ }
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/AbstractGenericsTests.java b/spring-core/src/test/java/org/springframework/core/AbstractGenericsTests.java
new file mode 100644
index 00000000..3d85742f
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/AbstractGenericsTests.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Serge Bogatyrjov
+ */
+public abstract class AbstractGenericsTests extends TestCase {
+
+ protected Class<?> targetClass;
+
+ protected String methods[];
+
+ protected Type expectedResults[];
+
+ protected void executeTest() throws NoSuchMethodException {
+ String methodName = getName().substring(4);
+ methodName = methodName.substring(0, 1).toLowerCase() + methodName.substring(1);
+ for (int i = 0; i < this.methods.length; i++) {
+ if (methodName.equals(this.methods[i])) {
+ Method method = this.targetClass.getMethod(methodName);
+ Type type = getType(method);
+ assertEquals(this.expectedResults[i], type);
+ return;
+ }
+ }
+ throw new IllegalStateException("Bad test data");
+ }
+
+ protected abstract Type getType(Method method);
+
+} \ No newline at end of file
diff --git a/spring-core/src/test/java/org/springframework/core/AttributeAccessorSupportTests.java b/spring-core/src/test/java/org/springframework/core/AttributeAccessorSupportTests.java
new file mode 100644
index 00000000..3a92c77c
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/AttributeAccessorSupportTests.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core;
+
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+
+/**
+ * @author Rob Harrop
+ * @since 2.0
+ */
+public class AttributeAccessorSupportTests extends TestCase {
+
+ private static final String NAME = "foo";
+
+ private static final String VALUE = "bar";
+
+ private AttributeAccessor attributeAccessor;
+
+ @Override
+ @SuppressWarnings("serial")
+ protected void setUp() throws Exception {
+ this.attributeAccessor = new AttributeAccessorSupport() {
+ };
+ }
+
+ public void testSetAndGet() throws Exception {
+ this.attributeAccessor.setAttribute(NAME, VALUE);
+ assertEquals(VALUE, this.attributeAccessor.getAttribute(NAME));
+ }
+
+ public void testSetAndHas() throws Exception {
+ assertFalse(this.attributeAccessor.hasAttribute(NAME));
+ this.attributeAccessor.setAttribute(NAME, VALUE);
+ assertTrue(this.attributeAccessor.hasAttribute(NAME));
+ }
+
+ public void testRemove() throws Exception {
+ assertFalse(this.attributeAccessor.hasAttribute(NAME));
+ this.attributeAccessor.setAttribute(NAME, VALUE);
+ assertEquals(VALUE, this.attributeAccessor.removeAttribute(NAME));
+ assertFalse(this.attributeAccessor.hasAttribute(NAME));
+ }
+
+ public void testAttributeNames() throws Exception {
+ this.attributeAccessor.setAttribute(NAME, VALUE);
+ this.attributeAccessor.setAttribute("abc", "123");
+ String[] attributeNames = this.attributeAccessor.attributeNames();
+ Arrays.sort(attributeNames);
+ assertTrue(Arrays.binarySearch(attributeNames, NAME) > -1);
+ assertTrue(Arrays.binarySearch(attributeNames, "abc") > -1);
+ }
+ @Override
+ protected void tearDown() throws Exception {
+ this.attributeAccessor.removeAttribute(NAME);
+ }
+}
diff --git a/spring-core/src/test/java/org/springframework/core/BridgeMethodResolverTests.java b/spring-core/src/test/java/org/springframework/core/BridgeMethodResolverTests.java
new file mode 100644
index 00000000..dbca8b7b
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/BridgeMethodResolverTests.java
@@ -0,0 +1,1315 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.concurrent.DelayQueue;
+import java.util.concurrent.Delayed;
+
+import static org.junit.Assert.*;
+import org.junit.Test;
+
+import org.springframework.util.ReflectionUtils;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ * @author Chris Beams
+ */
+public class BridgeMethodResolverTests {
+
+ private static TypeVariable<?> findTypeVariable(Class<?> clazz, String name) {
+ TypeVariable<?>[] variables = clazz.getTypeParameters();
+ for (TypeVariable<?> variable : variables) {
+ if (variable.getName().equals(name)) {
+ return variable;
+ }
+ }
+ return null;
+ }
+
+ private static Method findMethodWithReturnType(String name, Class<?> returnType, Class<SettingsDaoImpl> targetType) {
+ Method[] methods = targetType.getMethods();
+ for (Method m : methods) {
+ if (m.getName().equals(name) && m.getReturnType().equals(returnType)) {
+ return m;
+ }
+ }
+ return null;
+ }
+
+
+ @Test
+ public void testFindBridgedMethod() throws Exception {
+ Method unbridged = MyFoo.class.getDeclaredMethod("someMethod", String.class, Object.class);
+ Method bridged = MyFoo.class.getDeclaredMethod("someMethod", Serializable.class, Object.class);
+ assertFalse(unbridged.isBridge());
+ assertTrue(bridged.isBridge());
+
+ assertEquals("Unbridged method not returned directly", unbridged, BridgeMethodResolver.findBridgedMethod(unbridged));
+ assertEquals("Incorrect bridged method returned", unbridged, BridgeMethodResolver.findBridgedMethod(bridged));
+ }
+
+ @Test
+ public void testFindBridgedVarargMethod() throws Exception {
+ Method unbridged = MyFoo.class.getDeclaredMethod("someVarargMethod", String.class, Object[].class);
+ Method bridged = MyFoo.class.getDeclaredMethod("someVarargMethod", Serializable.class, Object[].class);
+ assertFalse(unbridged.isBridge());
+ assertTrue(bridged.isBridge());
+
+ assertEquals("Unbridged method not returned directly", unbridged, BridgeMethodResolver.findBridgedMethod(unbridged));
+ assertEquals("Incorrect bridged method returned", unbridged, BridgeMethodResolver.findBridgedMethod(bridged));
+ }
+
+ @Test
+ public void testFindBridgedMethodInHierarchy() throws Exception {
+ Method bridgeMethod = DateAdder.class.getMethod("add", Object.class);
+ assertTrue(bridgeMethod.isBridge());
+ Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(bridgeMethod);
+ assertFalse(bridgedMethod.isBridge());
+ assertEquals("add", bridgedMethod.getName());
+ assertEquals(1, bridgedMethod.getParameterTypes().length);
+ assertEquals(Date.class, bridgedMethod.getParameterTypes()[0]);
+ }
+
+ @Test
+ public void testIsBridgeMethodFor() throws Exception {
+ Map<TypeVariable, Type> typeParameterMap = GenericTypeResolver.getTypeVariableMap(MyBar.class);
+ Method bridged = MyBar.class.getDeclaredMethod("someMethod", String.class, Object.class);
+ Method other = MyBar.class.getDeclaredMethod("someMethod", Integer.class, Object.class);
+ Method bridge = MyBar.class.getDeclaredMethod("someMethod", Object.class, Object.class);
+
+ assertTrue("Should be bridge method", BridgeMethodResolver.isBridgeMethodFor(bridge, bridged, typeParameterMap));
+ assertFalse("Should not be bridge method", BridgeMethodResolver.isBridgeMethodFor(bridge, other, typeParameterMap));
+ }
+
+ @Test
+ public void testCreateTypeVariableMap() throws Exception {
+ Map<TypeVariable, Type> typeVariableMap = GenericTypeResolver.getTypeVariableMap(MyBar.class);
+ TypeVariable<?> barT = findTypeVariable(InterBar.class, "T");
+ assertEquals(String.class, typeVariableMap.get(barT));
+
+ typeVariableMap = GenericTypeResolver.getTypeVariableMap(MyFoo.class);
+ TypeVariable<?> fooT = findTypeVariable(Foo.class, "T");
+ assertEquals(String.class, typeVariableMap.get(fooT));
+
+ typeVariableMap = GenericTypeResolver.getTypeVariableMap(ExtendsEnclosing.ExtendsEnclosed.ExtendsReallyDeepNow.class);
+ TypeVariable<?> r = findTypeVariable(Enclosing.Enclosed.ReallyDeepNow.class, "R");
+ TypeVariable<?> s = findTypeVariable(Enclosing.Enclosed.class, "S");
+ TypeVariable<?> t = findTypeVariable(Enclosing.class, "T");
+ assertEquals(Long.class, typeVariableMap.get(r));
+ assertEquals(Integer.class, typeVariableMap.get(s));
+ assertEquals(String.class, typeVariableMap.get(t));
+ }
+
+ @Test
+ public void testDoubleParameterization() throws Exception {
+ Method objectBridge = MyBoo.class.getDeclaredMethod("foo", Object.class);
+ Method serializableBridge = MyBoo.class.getDeclaredMethod("foo", Serializable.class);
+
+ Method stringFoo = MyBoo.class.getDeclaredMethod("foo", String.class);
+ Method integerFoo = MyBoo.class.getDeclaredMethod("foo", Integer.class);
+
+ assertEquals("foo(String) not resolved.", stringFoo, BridgeMethodResolver.findBridgedMethod(objectBridge));
+ assertEquals("foo(Integer) not resolved.", integerFoo, BridgeMethodResolver.findBridgedMethod(serializableBridge));
+ }
+
+ @Test
+ public void testFindBridgedMethodFromMultipleBridges() throws Exception {
+ Method loadWithObjectReturn = findMethodWithReturnType("load", Object.class, SettingsDaoImpl.class);
+ assertNotNull(loadWithObjectReturn);
+
+ Method loadWithSettingsReturn = findMethodWithReturnType("load", Settings.class, SettingsDaoImpl.class);
+ assertNotNull(loadWithSettingsReturn);
+ assertNotSame(loadWithObjectReturn, loadWithSettingsReturn);
+
+ Method method = SettingsDaoImpl.class.getMethod("load");
+ assertEquals(method, BridgeMethodResolver.findBridgedMethod(loadWithObjectReturn));
+ assertEquals(method, BridgeMethodResolver.findBridgedMethod(loadWithSettingsReturn));
+ }
+
+ @Test
+ public void testFindBridgedMethodFromParent() throws Exception {
+ Method loadFromParentBridge = SettingsDaoImpl.class.getMethod("loadFromParent");
+ assertTrue(loadFromParentBridge.isBridge());
+
+ Method loadFromParent = AbstractDaoImpl.class.getMethod("loadFromParent");
+ assertFalse(loadFromParent.isBridge());
+
+ assertEquals(loadFromParent, BridgeMethodResolver.findBridgedMethod(loadFromParentBridge));
+ }
+
+ @Test
+ public void testWithSingleBoundParameterizedOnInstantiate() throws Exception {
+ Method bridgeMethod = DelayQueue.class.getMethod("add", Object.class);
+ assertTrue(bridgeMethod.isBridge());
+ Method actualMethod = DelayQueue.class.getMethod("add", Delayed.class);
+ assertFalse(actualMethod.isBridge());
+ assertEquals(actualMethod, BridgeMethodResolver.findBridgedMethod(bridgeMethod));
+ }
+
+ @Test
+ public void testWithDoubleBoundParameterizedOnInstantiate() throws Exception {
+ Method bridgeMethod = SerializableBounded.class.getMethod("boundedOperation", Object.class);
+ assertTrue(bridgeMethod.isBridge());
+ Method actualMethod = SerializableBounded.class.getMethod("boundedOperation", HashMap.class);
+ assertFalse(actualMethod.isBridge());
+ assertEquals(actualMethod, BridgeMethodResolver.findBridgedMethod(bridgeMethod));
+ }
+
+ @Test
+ public void testWithGenericParameter() throws Exception {
+ Method[] methods = StringGenericParameter.class.getMethods();
+ Method bridgeMethod = null;
+ Method bridgedMethod = null;
+ for (Method method : methods) {
+ if ("getFor".equals(method.getName()) && !method.getParameterTypes()[0].equals(Integer.class)) {
+ if (method.getReturnType().equals(Object.class)) {
+ bridgeMethod = method;
+ }
+ else {
+ bridgedMethod = method;
+ }
+ }
+ }
+ assertTrue(bridgeMethod != null && bridgeMethod.isBridge());
+ assertTrue(bridgedMethod != null && !bridgedMethod.isBridge());
+ assertEquals(bridgedMethod, BridgeMethodResolver.findBridgedMethod(bridgeMethod));
+ }
+
+ @Test
+ public void testOnAllMethods() throws Exception {
+ Method[] methods = StringList.class.getMethods();
+ for (Method method : methods) {
+ assertNotNull(BridgeMethodResolver.findBridgedMethod(method));
+ }
+ }
+
+ @Test
+ public void testSPR2583() throws Exception {
+ Method bridgedMethod = MessageBroadcasterImpl.class.getMethod("receive", MessageEvent.class);
+ assertFalse(bridgedMethod.isBridge());
+ Method bridgeMethod = MessageBroadcasterImpl.class.getMethod("receive", Event.class);
+ assertTrue(bridgeMethod.isBridge());
+
+ Method otherMethod = MessageBroadcasterImpl.class.getMethod("receive", NewMessageEvent.class);
+ assertFalse(otherMethod.isBridge());
+
+ Map<TypeVariable, Type> typeVariableMap = GenericTypeResolver.getTypeVariableMap(MessageBroadcasterImpl.class);
+ assertFalse("Match identified incorrectly", BridgeMethodResolver.isBridgeMethodFor(bridgeMethod, otherMethod, typeVariableMap));
+ assertTrue("Match not found correctly", BridgeMethodResolver.isBridgeMethodFor(bridgeMethod, bridgedMethod, typeVariableMap));
+
+ assertEquals(bridgedMethod, BridgeMethodResolver.findBridgedMethod(bridgeMethod));
+ }
+
+ @Test
+ public void testSPR2454() throws Exception {
+ Map<TypeVariable, Type> typeVariableMap = GenericTypeResolver.getTypeVariableMap(YourHomer.class);
+ TypeVariable<?> variable = findTypeVariable(MyHomer.class, "L");
+ assertEquals(AbstractBounded.class, ((ParameterizedType) typeVariableMap.get(variable)).getRawType());
+ }
+
+ @Test
+ public void testSPR2603() throws Exception {
+ Method objectBridge = YourHomer.class.getDeclaredMethod("foo", Bounded.class);
+ Method abstractBoundedFoo = YourHomer.class.getDeclaredMethod("foo", AbstractBounded.class);
+
+ Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(objectBridge);
+ assertEquals("foo(AbstractBounded) not resolved.", abstractBoundedFoo, bridgedMethod);
+ }
+
+ @Test
+ public void testSPR2648() throws Exception {
+ Method bridgeMethod = ReflectionUtils.findMethod(GenericSqlMapIntegerDao.class, "saveOrUpdate", Object.class);
+ assertTrue(bridgeMethod != null && bridgeMethod.isBridge());
+ Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(bridgeMethod);
+ assertFalse(bridgedMethod.isBridge());
+ assertEquals("saveOrUpdate", bridgedMethod.getName());
+ }
+
+ @Test
+ public void testSPR2763() throws Exception {
+ Method bridgedMethod = AbstractDao.class.getDeclaredMethod("save", Object.class);
+ assertFalse(bridgedMethod.isBridge());
+
+ Method bridgeMethod = UserDaoImpl.class.getDeclaredMethod("save", User.class);
+ assertTrue(bridgeMethod.isBridge());
+
+ assertEquals(bridgedMethod, BridgeMethodResolver.findBridgedMethod(bridgeMethod));
+ }
+
+ @Test
+ public void testSPR3041() throws Exception {
+ Method bridgedMethod = BusinessDao.class.getDeclaredMethod("save", Business.class);
+ assertFalse(bridgedMethod.isBridge());
+
+ Method bridgeMethod = BusinessDao.class.getDeclaredMethod("save", Object.class);
+ assertTrue(bridgeMethod.isBridge());
+
+ assertEquals(bridgedMethod, BridgeMethodResolver.findBridgedMethod(bridgeMethod));
+ }
+
+ @Test
+ public void testSPR3173() throws Exception {
+ Method bridgedMethod = UserDaoImpl.class.getDeclaredMethod("saveVararg", User.class, Object[].class);
+ assertFalse(bridgedMethod.isBridge());
+
+ Method bridgeMethod = UserDaoImpl.class.getDeclaredMethod("saveVararg", Object.class, Object[].class);
+ assertTrue(bridgeMethod.isBridge());
+
+ assertEquals(bridgedMethod, BridgeMethodResolver.findBridgedMethod(bridgeMethod));
+ }
+
+ @Test
+ public void testSPR3304() throws Exception {
+ Method bridgedMethod = MegaMessageProducerImpl.class.getDeclaredMethod("receive", MegaMessageEvent.class);
+ assertFalse(bridgedMethod.isBridge());
+
+ Method bridgeMethod = MegaMessageProducerImpl.class.getDeclaredMethod("receive", MegaEvent.class);
+ assertTrue(bridgeMethod.isBridge());
+
+ assertEquals(bridgedMethod, BridgeMethodResolver.findBridgedMethod(bridgeMethod));
+ }
+
+ @Test
+ public void testSPR3324() throws Exception {
+ Method bridgedMethod = BusinessDao.class.getDeclaredMethod("get", Long.class);
+ assertFalse(bridgedMethod.isBridge());
+
+ Method bridgeMethod = BusinessDao.class.getDeclaredMethod("get", Object.class);
+ assertTrue(bridgeMethod.isBridge());
+
+ assertEquals(bridgedMethod, BridgeMethodResolver.findBridgedMethod(bridgeMethod));
+ }
+
+ @Test
+ public void testSPR3357() throws Exception {
+ Method bridgedMethod = ExtendsAbstractImplementsInterface.class.getDeclaredMethod(
+ "doSomething", DomainObjectExtendsSuper.class, Object.class);
+ assertFalse(bridgedMethod.isBridge());
+
+ Method bridgeMethod = ExtendsAbstractImplementsInterface.class.getDeclaredMethod(
+ "doSomething", DomainObjectSuper.class, Object.class);
+ assertTrue(bridgeMethod.isBridge());
+
+ assertEquals(bridgedMethod, BridgeMethodResolver.findBridgedMethod(bridgeMethod));
+ }
+
+ @Test
+ public void testSPR3485() throws Exception {
+ Method bridgedMethod = DomainObject.class.getDeclaredMethod(
+ "method2", ParameterType.class, byte[].class);
+ assertFalse(bridgedMethod.isBridge());
+
+ Method bridgeMethod = DomainObject.class.getDeclaredMethod(
+ "method2", Serializable.class, Object.class);
+ assertTrue(bridgeMethod.isBridge());
+
+ assertEquals(bridgedMethod, BridgeMethodResolver.findBridgedMethod(bridgeMethod));
+ }
+
+ @Test
+ public void testSPR3534() throws Exception {
+ Method bridgeMethod = ReflectionUtils.findMethod(TestEmailProvider.class, "findBy", Object.class);
+ assertTrue(bridgeMethod != null && bridgeMethod.isBridge());
+ Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(bridgeMethod);
+ assertFalse(bridgedMethod.isBridge());
+ assertEquals("findBy", bridgedMethod.getName());
+ }
+
+
+ public static interface Foo<T extends Serializable> {
+
+ void someMethod(T theArg, Object otherArg);
+
+ void someVarargMethod(T theArg, Object... otherArg);
+ }
+
+
+ public static class MyFoo implements Foo<String> {
+
+ public void someMethod(Integer theArg, Object otherArg) {
+ }
+
+ @Override
+ public void someMethod(String theArg, Object otherArg) {
+ }
+
+ @Override
+ public void someVarargMethod(String theArg, Object... otherArgs) {
+ }
+ }
+
+
+ public static abstract class Bar<T> {
+
+ void someMethod(Map<?, ?> m, Object otherArg) {
+ }
+
+ void someMethod(T theArg, Map<?, ?> m) {
+ }
+
+ abstract void someMethod(T theArg, Object otherArg);
+ }
+
+
+ public static abstract class InterBar<T> extends Bar<T> {
+
+ }
+
+
+ public static class MyBar extends InterBar<String> {
+
+ @Override
+ public void someMethod(String theArg, Object otherArg) {
+ }
+
+ public void someMethod(Integer theArg, Object otherArg) {
+ }
+ }
+
+
+ public interface Adder<T> {
+
+ void add(T item);
+ }
+
+
+ public abstract class AbstractDateAdder implements Adder<Date> {
+
+ @Override
+ public abstract void add(Date date);
+ }
+
+
+ public class DateAdder extends AbstractDateAdder {
+
+ @Override
+ public void add(Date date) {
+ }
+ }
+
+
+ public class Enclosing<T> {
+
+ public class Enclosed<S> {
+
+ public class ReallyDeepNow<R> {
+
+ void someMethod(S s, T t, R r) {
+ }
+ }
+ }
+ }
+
+
+ public class ExtendsEnclosing extends Enclosing<String> {
+
+ public class ExtendsEnclosed extends Enclosed<Integer> {
+
+ public class ExtendsReallyDeepNow extends ReallyDeepNow<Long> {
+
+ @Override
+ void someMethod(Integer s, String t, Long r) {
+ throw new UnsupportedOperationException();
+ }
+ }
+ }
+ }
+
+
+ public interface Boo<E, T extends Serializable> {
+
+ void foo(E e);
+
+ void foo(T t);
+ }
+
+
+ public class MyBoo implements Boo<String, Integer> {
+
+ @Override
+ public void foo(String e) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void foo(Integer t) {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+
+ public interface Settings {
+
+ }
+
+
+ public interface ConcreteSettings extends Settings {
+
+ }
+
+
+ public interface Dao<T, S> {
+
+ T load();
+
+ S loadFromParent();
+ }
+
+
+ public interface SettingsDao<T extends Settings, S> extends Dao<T, S> {
+
+ @Override
+ T load();
+ }
+
+
+ public interface ConcreteSettingsDao extends SettingsDao<ConcreteSettings, String> {
+
+ @Override
+ String loadFromParent();
+ }
+
+
+ abstract class AbstractDaoImpl<T, S> implements Dao<T, S> {
+
+ protected T object;
+
+ protected S otherObject;
+
+ protected AbstractDaoImpl(T object, S otherObject) {
+ this.object = object;
+ this.otherObject = otherObject;
+ }
+
+ //@Transactional(readOnly = true)
+ @Override
+ public S loadFromParent() {
+ return otherObject;
+ }
+ }
+
+
+ class SettingsDaoImpl extends AbstractDaoImpl<ConcreteSettings, String> implements ConcreteSettingsDao {
+
+ protected SettingsDaoImpl(ConcreteSettings object) {
+ super(object, "From Parent");
+ }
+
+ //@Transactional(readOnly = true)
+ @Override
+ public ConcreteSettings load() {
+ return super.object;
+ }
+ }
+
+
+ public static interface Bounded<E> {
+
+ boolean boundedOperation(E e);
+ }
+
+
+ private static class AbstractBounded<E> implements Bounded<E> {
+
+ @Override
+ public boolean boundedOperation(E myE) {
+ return true;
+ }
+ }
+
+
+ private static class SerializableBounded<E extends HashMap & Delayed> extends AbstractBounded<E> {
+
+ @Override
+ public boolean boundedOperation(E myE) {
+ return false;
+ }
+ }
+
+
+ public static interface GenericParameter<T> {
+
+ T getFor(Class<T> cls);
+ }
+
+
+ @SuppressWarnings("unused")
+ private static class StringGenericParameter implements GenericParameter<String> {
+
+ @Override
+ public String getFor(Class<String> cls) {
+ return "foo";
+ }
+
+ public String getFor(Integer integer) {
+ return "foo";
+ }
+ }
+
+
+ private static class StringList implements List<String> {
+
+ @Override
+ public int size() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Iterator<String> iterator() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Object[] toArray() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public <T> T[] toArray(T[] a) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean add(String o) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean containsAll(Collection<?> c) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends String> c) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean addAll(int index, Collection<? extends String> c) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void clear() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String get(int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String set(int index, String element) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void add(int index, String element) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String remove(int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int indexOf(Object o) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int lastIndexOf(Object o) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ListIterator<String> listIterator() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ListIterator<String> listIterator(int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public List<String> subList(int fromIndex, int toIndex) {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+
+ public interface Event {
+
+ int getPriority();
+ }
+
+
+ public class GenericEvent implements Event {
+
+ private int priority;
+
+ @Override
+ public int getPriority() {
+ return priority;
+ }
+
+ /**
+ * Constructor that takes an event priority
+ */
+ public GenericEvent(int priority) {
+ this.priority = priority;
+ }
+
+ /**
+ * Default Constructor
+ */
+ public GenericEvent() {
+ }
+ }
+
+
+ public interface UserInitiatedEvent {
+
+ //public Session getInitiatorSession();
+ }
+
+
+ public abstract class BaseUserInitiatedEvent extends GenericEvent implements UserInitiatedEvent {
+
+ }
+
+
+ public class MessageEvent extends BaseUserInitiatedEvent {
+
+ }
+
+
+ public interface Channel<E extends Event> {
+
+ void send(E event);
+
+ void subscribe(final Receiver<E> receiver, Class<E> event);
+
+ void unsubscribe(final Receiver<E> receiver, Class<E> event);
+ }
+
+
+ public interface Broadcaster {
+ }
+
+
+ public interface EventBroadcaster extends Broadcaster {
+
+ public void subscribe();
+
+ public void unsubscribe();
+
+ public void setChannel(Channel<?> channel);
+ }
+
+
+ public class GenericBroadcasterImpl implements Broadcaster {
+
+ }
+
+
+ public abstract class GenericEventBroadcasterImpl<T extends Event> extends GenericBroadcasterImpl
+ implements EventBroadcaster {
+
+ private Class<T>[] subscribingEvents;
+
+ private Channel<T> channel;
+
+ /**
+ * Abstract method to retrieve instance of subclass
+ *
+ * @return receiver instance
+ */
+ public abstract Receiver<T> getInstance();
+
+ @Override
+ public void setChannel(Channel channel) {
+ this.channel = channel;
+ }
+
+ private String beanName;
+
+ public void setBeanName(String name) {
+ this.beanName = name;
+ }
+
+ @Override
+ public void subscribe() {
+
+ }
+
+ @Override
+ public void unsubscribe() {
+
+ }
+
+ public GenericEventBroadcasterImpl(Class<? extends T>... events) {
+
+ }
+ }
+
+
+ public interface Receiver<E extends Event> {
+
+ void receive(E event);
+ }
+
+
+ public interface MessageBroadcaster extends Receiver<MessageEvent> {
+
+ }
+
+
+ public class RemovedMessageEvent extends MessageEvent {
+
+ }
+
+
+ public class NewMessageEvent extends MessageEvent {
+
+ }
+
+
+ public class ModifiedMessageEvent extends MessageEvent {
+
+ }
+
+
+ public class MessageBroadcasterImpl extends GenericEventBroadcasterImpl<MessageEvent>
+ implements MessageBroadcaster {
+
+ public MessageBroadcasterImpl() {
+ super(NewMessageEvent.class);
+ }
+
+ @Override
+ public void receive(MessageEvent event) {
+ throw new UnsupportedOperationException("should not be called, use subclassed events");
+ }
+
+ public void receive(NewMessageEvent event) {
+ }
+
+ @Override
+ public Receiver<MessageEvent> getInstance() {
+ return null;
+ }
+
+ public void receive(RemovedMessageEvent event) {
+ }
+
+ public void receive(ModifiedMessageEvent event) {
+ }
+ }
+
+
+ //-----------------------------
+ // SPR-2454 Test Classes
+ //-----------------------------
+
+ public interface SimpleGenericRepository<T> {
+
+ public Class<T> getPersistentClass();
+
+ List<T> findByQuery();
+
+ List<T> findAll();
+
+ T refresh(T entity);
+
+ T saveOrUpdate(T entity);
+
+ void delete(Collection<T> entities);
+ }
+
+
+ public interface RepositoryRegistry {
+
+ <T> SimpleGenericRepository<T> getFor(Class<T> entityType);
+ }
+
+
+ public class SettableRepositoryRegistry<R extends SimpleGenericRepository<?>>
+ implements RepositoryRegistry {
+
+ protected void injectInto(R rep) {
+ }
+
+ public void register(R rep) {
+ }
+
+ public void register(R... reps) {
+ }
+
+ public void setRepos(R... reps) {
+ }
+
+ @Override
+ public <T> SimpleGenericRepository<T> getFor(Class<T> entityType) {
+ return null;
+ }
+
+ public void afterPropertiesSet() throws Exception {
+ }
+ }
+
+
+ public interface ConvenientGenericRepository<T, ID extends Serializable> extends SimpleGenericRepository<T> {
+
+ T findById(ID id, boolean lock);
+
+ List<T> findByExample(T exampleInstance);
+
+ void delete(ID id);
+
+ void delete(T entity);
+ }
+
+
+ public class GenericHibernateRepository<T, ID extends Serializable>
+ implements ConvenientGenericRepository<T, ID> {
+
+ /**
+ * @param c Mandatory. The domain class this repository is responsible for.
+ */
+ // Since it is impossible to determine the actual type of a type
+ // parameter (!), we resort to requiring the caller to provide the
+ // actual type as parameter, too.
+ // Not set in a constructor to enable easy CGLIB-proxying (passing
+ // constructor arguments to Spring AOP proxies is quite cumbersome).
+ public void setPersistentClass(Class<T> c) {
+ }
+
+ @Override
+ public Class<T> getPersistentClass() {
+ return null;
+ }
+
+ @Override
+ public T findById(ID id, boolean lock) {
+ return null;
+ }
+
+ @Override
+ public List<T> findAll() {
+ return null;
+ }
+
+ @Override
+ public List<T> findByExample(T exampleInstance) {
+ return null;
+ }
+
+ @Override
+ public List<T> findByQuery() {
+ return null;
+ }
+
+ @Override
+ public T saveOrUpdate(T entity) {
+ return null;
+ }
+
+ @Override
+ public void delete(T entity) {
+ }
+
+ @Override
+ public T refresh(T entity) {
+ return null;
+ }
+
+ @Override
+ public void delete(ID id) {
+ }
+
+ @Override
+ public void delete(Collection<T> entities) {
+ }
+ }
+
+
+ public class HibernateRepositoryRegistry extends SettableRepositoryRegistry<GenericHibernateRepository<?, ?>> {
+
+ @Override
+ public void injectInto(GenericHibernateRepository<?, ?> rep) {
+ }
+
+ @Override
+ public <T> GenericHibernateRepository<T, ?> getFor(Class<T> entityType) {
+ return null;
+ }
+ }
+
+
+ //-------------------
+ // SPR-2603 classes
+ //-------------------
+
+ public interface Homer<E> {
+
+ void foo(E e);
+ }
+
+
+ public class MyHomer<T extends Bounded<T>, L extends T> implements Homer<L> {
+
+ @Override
+ public void foo(L t) {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+
+ public class YourHomer<T extends AbstractBounded<T>, L extends T> extends MyHomer<T, L> {
+
+ @Override
+ public void foo(L t) {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+
+ public interface GenericDao<T> {
+
+ public void saveOrUpdate(T t);
+ }
+
+
+ public interface ConvenienceGenericDao<T> extends GenericDao<T> {
+ }
+
+
+ public class GenericSqlMapDao<T extends Serializable> implements ConvenienceGenericDao<T> {
+
+ @Override
+ public void saveOrUpdate(T t) {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+
+ public class GenericSqlMapIntegerDao<T extends Number> extends GenericSqlMapDao<T> {
+
+ @Override
+ public void saveOrUpdate(T t) {
+ }
+ }
+
+
+ public class Permission {
+ }
+
+
+ public class User {
+ }
+
+
+ public interface UserDao {
+
+ //@Transactional
+ void save(User user);
+
+ //@Transactional
+ void save(Permission perm);
+ }
+
+
+ public abstract class AbstractDao<T> {
+
+ public void save(T t) {
+ }
+
+ public void saveVararg(T t, Object... args) {
+ }
+ }
+
+
+ public class UserDaoImpl extends AbstractDao<User> implements UserDao {
+
+ @Override
+ public void save(Permission perm) {
+ }
+
+ @Override
+ public void saveVararg(User user, Object... args) {
+ }
+ }
+
+
+ public interface DaoInterface<T,P> {
+ T get(P id);
+ }
+
+
+ public abstract class BusinessGenericDao<T, PK extends Serializable> implements DaoInterface<T, PK> {
+
+ public void save(T object) {
+ }
+ }
+
+
+ public class Business<T> {
+ }
+
+
+ public class BusinessDao extends BusinessGenericDao<Business<?>, Long> {
+
+ @Override
+ public void save(Business<?> business) {
+ }
+
+ @Override
+ public Business<?> get(Long id) {
+ return null;
+ }
+
+ public Business<?> get(String code) {
+ return null;
+ }
+ }
+
+
+ //-------------------
+ // SPR-3304 classes
+ //-------------------
+
+ private static class MegaEvent {
+ }
+
+
+ private static class MegaMessageEvent extends MegaEvent {
+ }
+
+
+ private static class NewMegaMessageEvent extends MegaEvent {
+ }
+
+
+ private static class ModifiedMegaMessageEvent extends MegaEvent {
+ }
+
+
+ public static interface MegaReceiver<E extends MegaEvent> {
+
+ void receive(E event);
+ }
+
+
+ public static interface MegaMessageProducer extends MegaReceiver<MegaMessageEvent> {
+ }
+
+
+ private static class Other<S,E> {
+ }
+
+
+ @SuppressWarnings("unused")
+ private static class MegaMessageProducerImpl extends Other<Long, String> implements MegaMessageProducer {
+
+ public void receive(NewMegaMessageEvent event) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void receive(ModifiedMegaMessageEvent event) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void receive(MegaMessageEvent event) {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+
+ //-------------------
+ // SPR-3357 classes
+ //-------------------
+
+ private static class DomainObjectSuper {
+ }
+
+
+ private static class DomainObjectExtendsSuper extends DomainObjectSuper {
+ }
+
+
+ public interface IGenericInterface<D extends DomainObjectSuper> {
+
+ <T> void doSomething(final D domainObject, final T value);
+ }
+
+
+ @SuppressWarnings("unused")
+ private static abstract class AbstractImplementsInterface<D extends DomainObjectSuper> implements IGenericInterface<D> {
+
+ @Override
+ public <T> void doSomething(D domainObject, T value) {
+ }
+
+ public void anotherBaseMethod() {
+ }
+ }
+
+
+ private static class ExtendsAbstractImplementsInterface extends AbstractImplementsInterface<DomainObjectExtendsSuper> {
+
+ @Override
+ public <T> void doSomething(DomainObjectExtendsSuper domainObject, T value) {
+ super.doSomething(domainObject, value);
+ }
+ }
+
+
+ //-------------------
+ // SPR-3485 classes
+ //-------------------
+
+ @SuppressWarnings("serial")
+ private static class ParameterType implements Serializable {
+ }
+
+
+ private static class AbstractDomainObject<P extends Serializable, R> {
+
+ public R method1(P p) {
+ return null;
+ }
+
+ public void method2(P p, R r) {
+ }
+ }
+
+
+ private static class DomainObject extends AbstractDomainObject<ParameterType, byte[]> {
+
+ @Override
+ public byte[] method1(ParameterType p) {
+ return super.method1(p);
+ }
+
+ @Override
+ public void method2(ParameterType p, byte[] r) {
+ super.method2(p, r);
+ }
+ }
+
+
+ //-------------------
+ // SPR-3534 classes
+ //-------------------
+
+ public interface SearchProvider<RETURN_TYPE, CONDITIONS_TYPE> {
+
+ Collection<RETURN_TYPE> findBy(CONDITIONS_TYPE conditions);
+ }
+
+
+ public static class SearchConditions {
+ }
+
+
+ public interface IExternalMessageProvider<S extends ExternalMessage, T extends ExternalMessageSearchConditions<?>>
+ extends SearchProvider<S, T> {
+ }
+
+
+ public static class ExternalMessage {
+ }
+
+
+ public static class ExternalMessageSearchConditions<T extends ExternalMessage> extends SearchConditions {
+ }
+
+
+ public static class ExternalMessageProvider<S extends ExternalMessage, T extends ExternalMessageSearchConditions<S>>
+ implements IExternalMessageProvider<S, T> {
+
+ @Override
+ public Collection<S> findBy(T conditions) {
+ return null;
+ }
+ }
+
+
+ public static class EmailMessage extends ExternalMessage {
+ }
+
+
+ public static class EmailSearchConditions extends ExternalMessageSearchConditions<EmailMessage> {
+ }
+
+
+ public static class EmailMessageProvider extends ExternalMessageProvider<EmailMessage, EmailSearchConditions> {
+ }
+
+
+ public static class TestEmailProvider extends EmailMessageProvider {
+
+ @Override
+ public Collection<EmailMessage> findBy(EmailSearchConditions conditions) {
+ return null;
+ }
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/CollectionFactoryTests.java b/spring-core/src/test/java/org/springframework/core/CollectionFactoryTests.java
new file mode 100644
index 00000000..45b27e2d
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/CollectionFactoryTests.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core;
+
+import java.util.IdentityHashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+import org.springframework.util.MultiValueMap;
+
+/**
+ * @author Darren Davison
+ * @author Juergen Hoeller
+ * @author Dave Syer
+ */
+public class CollectionFactoryTests extends TestCase {
+
+ @SuppressWarnings("deprecation")
+ public void testLinkedSet() {
+ Set set = CollectionFactory.createLinkedSetIfPossible(16);
+ assertTrue(set instanceof LinkedHashSet);
+ }
+
+ @SuppressWarnings("deprecation")
+ public void testLinkedMap() {
+ Map map = CollectionFactory.createLinkedMapIfPossible(16);
+ assertTrue(map instanceof LinkedHashMap);
+ }
+
+ @SuppressWarnings("deprecation")
+ public void testIdentityMap() {
+ Map map = CollectionFactory.createIdentityMapIfPossible(16);
+ assertTrue(map instanceof IdentityHashMap);
+ }
+
+ @SuppressWarnings("deprecation")
+ public void testConcurrentMap() {
+ Map map = CollectionFactory.createConcurrentMapIfPossible(16);
+ assertTrue(map.getClass().getName().endsWith("ConcurrentHashMap"));
+ }
+
+ public void testMultiValueMap() {
+ Map map = CollectionFactory.createMap(MultiValueMap.class, 16);
+ assertTrue(map.getClass().getName().endsWith("MultiValueMap"));
+ }
+
+ @SuppressWarnings("deprecation")
+ public void testConcurrentMapWithExplicitInterface() {
+ ConcurrentMap map = CollectionFactory.createConcurrentMap(16);
+ assertTrue(map.getClass().getSuperclass().getName().endsWith("ConcurrentHashMap"));
+ map.putIfAbsent("key", "value1");
+ map.putIfAbsent("key", "value2");
+ assertEquals("value1", map.get("key"));
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/ConstantsTests.java b/spring-core/src/test/java/org/springframework/core/ConstantsTests.java
new file mode 100644
index 00000000..2dc85aae
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/ConstantsTests.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core;
+
+import java.util.Locale;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ * @author Rick Evans
+ * @since 28.04.2003
+ */
+public class ConstantsTests extends TestCase {
+
+ public void testConstants() {
+ Constants c = new Constants(A.class);
+ assertEquals(A.class.getName(), c.getClassName());
+ assertEquals(9, c.getSize());
+
+ assertEquals(c.asNumber("DOG").intValue(), A.DOG);
+ assertEquals(c.asNumber("dog").intValue(), A.DOG);
+ assertEquals(c.asNumber("cat").intValue(), A.CAT);
+
+ try {
+ c.asNumber("bogus");
+ fail("Can't get bogus field");
+ }
+ catch (ConstantException expected) {
+ }
+
+ assertTrue(c.asString("S1").equals(A.S1));
+ try {
+ c.asNumber("S1");
+ fail("Wrong type");
+ }
+ catch (ConstantException expected) {
+ }
+ }
+
+ public void testGetNames() {
+ Constants c = new Constants(A.class);
+
+ Set<?> names = c.getNames("");
+ assertEquals(c.getSize(), names.size());
+ assertTrue(names.contains("DOG"));
+ assertTrue(names.contains("CAT"));
+ assertTrue(names.contains("S1"));
+
+ names = c.getNames("D");
+ assertEquals(1, names.size());
+ assertTrue(names.contains("DOG"));
+
+ names = c.getNames("d");
+ assertEquals(1, names.size());
+ assertTrue(names.contains("DOG"));
+ }
+
+ public void testGetValues() {
+ Constants c = new Constants(A.class);
+
+ Set<?> values = c.getValues("");
+ assertEquals(7, values.size());
+ assertTrue(values.contains(new Integer(0)));
+ assertTrue(values.contains(new Integer(66)));
+ assertTrue(values.contains(""));
+
+ values = c.getValues("D");
+ assertEquals(1, values.size());
+ assertTrue(values.contains(new Integer(0)));
+
+ values = c.getValues("prefix");
+ assertEquals(2, values.size());
+ assertTrue(values.contains(new Integer(1)));
+ assertTrue(values.contains(new Integer(2)));
+
+ values = c.getValuesForProperty("myProperty");
+ assertEquals(2, values.size());
+ assertTrue(values.contains(new Integer(1)));
+ assertTrue(values.contains(new Integer(2)));
+ }
+
+ public void testGetValuesInTurkey() {
+ Locale oldLocale = Locale.getDefault();
+ Locale.setDefault(new Locale("tr", ""));
+ try {
+ Constants c = new Constants(A.class);
+
+ Set<?> values = c.getValues("");
+ assertEquals(7, values.size());
+ assertTrue(values.contains(new Integer(0)));
+ assertTrue(values.contains(new Integer(66)));
+ assertTrue(values.contains(""));
+
+ values = c.getValues("D");
+ assertEquals(1, values.size());
+ assertTrue(values.contains(new Integer(0)));
+
+ values = c.getValues("prefix");
+ assertEquals(2, values.size());
+ assertTrue(values.contains(new Integer(1)));
+ assertTrue(values.contains(new Integer(2)));
+
+ values = c.getValuesForProperty("myProperty");
+ assertEquals(2, values.size());
+ assertTrue(values.contains(new Integer(1)));
+ assertTrue(values.contains(new Integer(2)));
+ }
+ finally {
+ Locale.setDefault(oldLocale);
+ }
+ }
+
+ public void testSuffixAccess() {
+ Constants c = new Constants(A.class);
+
+ Set<?> names = c.getNamesForSuffix("_PROPERTY");
+ assertEquals(2, names.size());
+ assertTrue(names.contains("NO_PROPERTY"));
+ assertTrue(names.contains("YES_PROPERTY"));
+
+ Set<?> values = c.getValuesForSuffix("_PROPERTY");
+ assertEquals(2, values.size());
+ assertTrue(values.contains(new Integer(3)));
+ assertTrue(values.contains(new Integer(4)));
+ }
+
+ public void testToCode() {
+ Constants c = new Constants(A.class);
+
+ assertEquals(c.toCode(new Integer(0), ""), "DOG");
+ assertEquals(c.toCode(new Integer(0), "D"), "DOG");
+ assertEquals(c.toCode(new Integer(0), "DO"), "DOG");
+ assertEquals(c.toCode(new Integer(0), "DoG"), "DOG");
+ assertEquals(c.toCode(new Integer(0), null), "DOG");
+ assertEquals(c.toCode(new Integer(66), ""), "CAT");
+ assertEquals(c.toCode(new Integer(66), "C"), "CAT");
+ assertEquals(c.toCode(new Integer(66), "ca"), "CAT");
+ assertEquals(c.toCode(new Integer(66), "cAt"), "CAT");
+ assertEquals(c.toCode(new Integer(66), null), "CAT");
+ assertEquals(c.toCode("", ""), "S1");
+ assertEquals(c.toCode("", "s"), "S1");
+ assertEquals(c.toCode("", "s1"), "S1");
+ assertEquals(c.toCode("", null), "S1");
+ try {
+ c.toCode("bogus", "bogus");
+ fail("Should have thrown ConstantException");
+ }
+ catch (ConstantException expected) {
+ }
+ try {
+ c.toCode("bogus", null);
+ fail("Should have thrown ConstantException");
+ }
+ catch (ConstantException expected) {
+ }
+
+ assertEquals(c.toCodeForProperty(new Integer(1), "myProperty"), "MY_PROPERTY_NO");
+ assertEquals(c.toCodeForProperty(new Integer(2), "myProperty"), "MY_PROPERTY_YES");
+ try {
+ c.toCodeForProperty("bogus", "bogus");
+ fail("Should have thrown ConstantException");
+ }
+ catch (ConstantException expected) {
+ }
+
+ assertEquals(c.toCodeForSuffix(new Integer(0), ""), "DOG");
+ assertEquals(c.toCodeForSuffix(new Integer(0), "G"), "DOG");
+ assertEquals(c.toCodeForSuffix(new Integer(0), "OG"), "DOG");
+ assertEquals(c.toCodeForSuffix(new Integer(0), "DoG"), "DOG");
+ assertEquals(c.toCodeForSuffix(new Integer(0), null), "DOG");
+ assertEquals(c.toCodeForSuffix(new Integer(66), ""), "CAT");
+ assertEquals(c.toCodeForSuffix(new Integer(66), "T"), "CAT");
+ assertEquals(c.toCodeForSuffix(new Integer(66), "at"), "CAT");
+ assertEquals(c.toCodeForSuffix(new Integer(66), "cAt"), "CAT");
+ assertEquals(c.toCodeForSuffix(new Integer(66), null), "CAT");
+ assertEquals(c.toCodeForSuffix("", ""), "S1");
+ assertEquals(c.toCodeForSuffix("", "1"), "S1");
+ assertEquals(c.toCodeForSuffix("", "s1"), "S1");
+ assertEquals(c.toCodeForSuffix("", null), "S1");
+ try {
+ c.toCodeForSuffix("bogus", "bogus");
+ fail("Should have thrown ConstantException");
+ }
+ catch (ConstantException expected) {
+ }
+ try {
+ c.toCodeForSuffix("bogus", null);
+ fail("Should have thrown ConstantException");
+ }
+ catch (ConstantException expected) {
+ }
+ }
+
+ public void testGetValuesWithNullPrefix() throws Exception {
+ Constants c = new Constants(A.class);
+ Set<?> values = c.getValues(null);
+ assertEquals("Must have returned *all* public static final values", 7, values.size());
+ }
+
+ public void testGetValuesWithEmptyStringPrefix() throws Exception {
+ Constants c = new Constants(A.class);
+ Set<Object> values = c.getValues("");
+ assertEquals("Must have returned *all* public static final values", 7, values.size());
+ }
+
+ public void testGetValuesWithWhitespacedStringPrefix() throws Exception {
+ Constants c = new Constants(A.class);
+ Set<?> values = c.getValues(" ");
+ assertEquals("Must have returned *all* public static final values", 7, values.size());
+ }
+
+ public void testWithClassThatExposesNoConstants() throws Exception {
+ Constants c = new Constants(NoConstants.class);
+ assertEquals(0, c.getSize());
+ final Set<?> values = c.getValues("");
+ assertNotNull(values);
+ assertEquals(0, values.size());
+ }
+
+ public void testCtorWithNullClass() throws Exception {
+ try {
+ new Constants(null);
+ fail("Must have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException expected) {}
+ }
+
+
+ private static final class NoConstants {
+ }
+
+
+ @SuppressWarnings("unused")
+ private static final class A {
+
+ public static final int DOG = 0;
+ public static final int CAT = 66;
+ public static final String S1 = "";
+
+ public static final int PREFIX_NO = 1;
+ public static final int PREFIX_YES = 2;
+
+ public static final int MY_PROPERTY_NO = 1;
+ public static final int MY_PROPERTY_YES = 2;
+
+ public static final int NO_PROPERTY = 3;
+ public static final int YES_PROPERTY = 4;
+
+ /** ignore these */
+ protected static final int P = -1;
+ protected boolean f;
+ static final Object o = new Object();
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/ConventionsTests.java b/spring-core/src/test/java/org/springframework/core/ConventionsTests.java
new file mode 100644
index 00000000..cdc94380
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/ConventionsTests.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+import org.springframework.tests.sample.objects.TestObject;
+
+/**
+ * @author Rob Harrop
+ */
+public class ConventionsTests extends TestCase {
+
+ public void testSimpleObject() {
+ TestObject testObject = new TestObject();
+ assertEquals("Incorrect singular variable name", "testObject", Conventions.getVariableName(testObject));
+ }
+
+ public void testArray() {
+ TestObject[] testObjects = new TestObject[0];
+ assertEquals("Incorrect plural array form", "testObjectList", Conventions.getVariableName(testObjects));
+ }
+
+ public void testCollections() {
+ List<TestObject> list = new ArrayList<TestObject>();
+ list.add(new TestObject());
+ assertEquals("Incorrect plural List form", "testObjectList", Conventions.getVariableName(list));
+
+ Set<TestObject> set = new HashSet<TestObject>();
+ set.add(new TestObject());
+ assertEquals("Incorrect plural Set form", "testObjectList", Conventions.getVariableName(set));
+
+ List<?> emptyList = new ArrayList<Object>();
+ try {
+ Conventions.getVariableName(emptyList);
+ fail("Should not be able to generate name for empty collection");
+ }
+ catch(IllegalArgumentException ex) {
+ // success
+ }
+ }
+
+ public void testAttributeNameToPropertyName() throws Exception {
+ assertEquals("transactionManager", Conventions.attributeNameToPropertyName("transaction-manager"));
+ assertEquals("pointcutRef", Conventions.attributeNameToPropertyName("pointcut-ref"));
+ assertEquals("lookupOnStartup", Conventions.attributeNameToPropertyName("lookup-on-startup"));
+ }
+
+ public void testGetQualifiedAttributeName() throws Exception {
+ String baseName = "foo";
+ Class<String> cls = String.class;
+ String desiredResult = "java.lang.String.foo";
+ assertEquals(desiredResult, Conventions.getQualifiedAttributeName(cls, baseName));
+ }
+}
diff --git a/spring-core/src/test/java/org/springframework/core/DefaultControlFlowTests.java b/spring-core/src/test/java/org/springframework/core/DefaultControlFlowTests.java
new file mode 100644
index 00000000..a3929896
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/DefaultControlFlowTests.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core;
+
+/**
+ * Tests with ControlFlowFactory return.
+ *
+ * @author Rod Johnson
+ */
+public class DefaultControlFlowTests extends AbstractControlFlowTests {
+
+ /**
+ * Necessary only because Eclipse won't run test suite unless
+ * it declares some methods as well as inherited methods.
+ */
+ public void testThisClassPlease() {
+ }
+
+ @Override
+ protected ControlFlow createControlFlow() {
+ return ControlFlowFactory.createControlFlow();
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/ExceptionDepthComparatorTests.java b/spring-core/src/test/java/org/springframework/core/ExceptionDepthComparatorTests.java
new file mode 100644
index 00000000..5de3f4b6
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/ExceptionDepthComparatorTests.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core;
+
+import java.util.Arrays;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author Juergen Hoeller
+ * @author Chris Shepperd
+ */
+public class ExceptionDepthComparatorTests {
+
+ @Test
+ public void targetBeforeSameDepth() throws Exception {
+ Class<? extends Throwable> foundClass = findClosestMatch(TargetException.class, SameDepthException.class);
+ assertEquals(TargetException.class, foundClass);
+ }
+
+ @Test
+ public void sameDepthBeforeTarget() throws Exception {
+ Class<? extends Throwable> foundClass = findClosestMatch(SameDepthException.class, TargetException.class);
+ assertEquals(TargetException.class, foundClass);
+ }
+
+ @Test
+ public void lowestDepthBeforeTarget() throws Exception {
+ Class<? extends Throwable> foundClass = findClosestMatch(LowestDepthException.class, TargetException.class);
+ assertEquals(TargetException.class, foundClass);
+ }
+
+ @Test
+ public void targetBeforeLowestDepth() throws Exception {
+ Class<? extends Throwable> foundClass = findClosestMatch(TargetException.class, LowestDepthException.class);
+ assertEquals(TargetException.class, foundClass);
+ }
+
+ @Test
+ public void noDepthBeforeTarget() throws Exception {
+ Class<? extends Throwable> foundClass = findClosestMatch(NoDepthException.class, TargetException.class);
+ assertEquals(TargetException.class, foundClass);
+ }
+
+ @Test
+ public void noDepthBeforeHighestDepth() throws Exception {
+ Class<? extends Throwable> foundClass = findClosestMatch(NoDepthException.class, HighestDepthException.class);
+ assertEquals(HighestDepthException.class, foundClass);
+ }
+
+ @Test
+ public void highestDepthBeforeNoDepth() throws Exception {
+ Class<? extends Throwable> foundClass = findClosestMatch(HighestDepthException.class, NoDepthException.class);
+ assertEquals(HighestDepthException.class, foundClass);
+ }
+
+ @Test
+ public void highestDepthBeforeLowestDepth() throws Exception {
+ Class<? extends Throwable> foundClass = findClosestMatch(HighestDepthException.class, LowestDepthException.class);
+ assertEquals(LowestDepthException.class, foundClass);
+ }
+
+ @Test
+ public void lowestDepthBeforeHighestDepth() throws Exception {
+ Class<? extends Throwable> foundClass = findClosestMatch(LowestDepthException.class, HighestDepthException.class);
+ assertEquals(LowestDepthException.class, foundClass);
+ }
+
+ private Class<? extends Throwable> findClosestMatch(
+ Class<? extends Throwable>... classes) {
+ return ExceptionDepthComparator.findClosestMatch(Arrays.asList(classes), new TargetException());
+ }
+
+ @SuppressWarnings("serial")
+ public class HighestDepthException extends Throwable {
+ }
+
+ @SuppressWarnings("serial")
+ public class LowestDepthException extends HighestDepthException {
+ }
+
+ @SuppressWarnings("serial")
+ public class TargetException extends LowestDepthException {
+ }
+
+ @SuppressWarnings("serial")
+ public class SameDepthException extends LowestDepthException {
+ }
+
+ @SuppressWarnings("serial")
+ public class NoDepthException extends TargetException {
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/GenericCollectionTypeResolverTests.java b/spring-core/src/test/java/org/springframework/core/GenericCollectionTypeResolverTests.java
new file mode 100644
index 00000000..08fbaa96
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/GenericCollectionTypeResolverTests.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.AbstractMap;
+import java.util.AbstractSet;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.springframework.core.io.Resource;
+import org.springframework.tests.sample.objects.GenericObject;
+
+/**
+ * @author Serge Bogatyrjov
+ * @author Juergen Hoeller
+ */
+public class GenericCollectionTypeResolverTests extends AbstractGenericsTests {
+
+ @Override
+ protected void setUp() throws Exception {
+ this.targetClass = Foo.class;
+ this.methods = new String[] {"a", "b", "b2", "b3", "c", "d", "d2", "d3", "e", "e2", "e3"};
+ this.expectedResults = new Class[] {
+ Integer.class, null, Set.class, Set.class, null, Integer.class,
+ Integer.class, Integer.class, Integer.class, Integer.class, Integer.class};
+ }
+
+ @Override
+ protected Type getType(Method method) {
+ return GenericCollectionTypeResolver.getMapValueReturnType(method);
+ }
+
+ public void testA() throws Exception {
+ executeTest();
+ }
+
+ public void testB() throws Exception {
+ executeTest();
+ }
+
+ public void testB2() throws Exception {
+ executeTest();
+ }
+
+ public void testB3() throws Exception {
+ executeTest();
+ }
+
+ public void testC() throws Exception {
+ executeTest();
+ }
+
+ public void testD() throws Exception {
+ executeTest();
+ }
+
+ public void testD2() throws Exception {
+ executeTest();
+ }
+
+ public void testD3() throws Exception {
+ executeTest();
+ }
+
+ public void testE() throws Exception {
+ executeTest();
+ }
+
+ public void testE2() throws Exception {
+ executeTest();
+ }
+
+ public void testE3() throws Exception {
+ executeTest();
+ }
+
+ public void testProgrammaticListIntrospection() throws Exception {
+ Method setter = GenericObject.class.getMethod("setResourceList", List.class);
+ assertEquals(Resource.class,
+ GenericCollectionTypeResolver.getCollectionParameterType(new MethodParameter(setter, 0)));
+
+ Method getter = GenericObject.class.getMethod("getResourceList");
+ assertEquals(Resource.class,
+ GenericCollectionTypeResolver.getCollectionReturnType(getter));
+ }
+
+ public void testClassResolution() {
+ assertEquals(String.class, GenericCollectionTypeResolver.getCollectionType(CustomSet.class));
+ assertEquals(String.class, GenericCollectionTypeResolver.getMapKeyType(CustomMap.class));
+ assertEquals(Integer.class, GenericCollectionTypeResolver.getMapValueType(CustomMap.class));
+ }
+
+
+ private abstract class CustomSet<T> extends AbstractSet<String> {
+ }
+
+
+ private abstract class CustomMap<T> extends AbstractMap<String, Integer> {
+ }
+
+
+ private abstract class OtherCustomMap<T> implements Map<String, Integer> {
+ }
+
+
+ private interface Foo {
+
+ Map<String, Integer> a();
+
+ Map<?, ?> b();
+
+ Map<?, ? extends Set> b2();
+
+ Map<?, ? super Set> b3();
+
+ Map c();
+
+ CustomMap<Date> d();
+
+ CustomMap<?> d2();
+
+ CustomMap d3();
+
+ OtherCustomMap<Date> e();
+
+ OtherCustomMap<?> e2();
+
+ OtherCustomMap e3();
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/GenericTypeResolverTests.java b/spring-core/src/test/java/org/springframework/core/GenericTypeResolverTests.java
new file mode 100644
index 00000000..ca335500
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/GenericTypeResolverTests.java
@@ -0,0 +1,316 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Test;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+import static org.springframework.core.GenericTypeResolver.*;
+import static org.springframework.util.ReflectionUtils.*;
+
+/**
+ * @author Juergen Hoeller
+ * @author Sam Brannen
+ */
+public class GenericTypeResolverTests {
+
+ @Test
+ public void simpleInterfaceType() {
+ assertEquals(String.class, resolveTypeArgument(MySimpleInterfaceType.class, MyInterfaceType.class));
+ }
+
+ @Test
+ public void simpleCollectionInterfaceType() {
+ assertEquals(Collection.class, resolveTypeArgument(MyCollectionInterfaceType.class, MyInterfaceType.class));
+ }
+
+ @Test
+ public void simpleSuperclassType() {
+ assertEquals(String.class, resolveTypeArgument(MySimpleSuperclassType.class, MySuperclassType.class));
+ }
+
+ @Test
+ public void simpleCollectionSuperclassType() {
+ assertEquals(Collection.class, resolveTypeArgument(MyCollectionSuperclassType.class, MySuperclassType.class));
+ }
+
+ @Test
+ public void nullIfNotResolvable() {
+ GenericClass<String> obj = new GenericClass<String>();
+ assertNull(resolveTypeArgument(obj.getClass(), GenericClass.class));
+ }
+
+ @Test
+ public void methodReturnTypes() {
+ assertEquals(Integer.class,
+ resolveReturnTypeArgument(findMethod(MyTypeWithMethods.class, "integer"), MyInterfaceType.class));
+ assertEquals(String.class,
+ resolveReturnTypeArgument(findMethod(MyTypeWithMethods.class, "string"), MyInterfaceType.class));
+ assertEquals(null, resolveReturnTypeArgument(findMethod(MyTypeWithMethods.class, "raw"), MyInterfaceType.class));
+ assertEquals(null,
+ resolveReturnTypeArgument(findMethod(MyTypeWithMethods.class, "object"), MyInterfaceType.class));
+ }
+
+ @Test
+ public void testResolveType() {
+ Method intMessageMethod = findMethod(MyTypeWithMethods.class, "readIntegerInputMessage", MyInterfaceType.class);
+ MethodParameter intMessageMethodParam = new MethodParameter(intMessageMethod, 0);
+ assertEquals(MyInterfaceType.class,
+ resolveType(intMessageMethodParam.getGenericParameterType(), new HashMap<TypeVariable, Type>()));
+
+ Method intArrMessageMethod = findMethod(MyTypeWithMethods.class, "readIntegerArrayInputMessage",
+ MyInterfaceType[].class);
+ MethodParameter intArrMessageMethodParam = new MethodParameter(intArrMessageMethod, 0);
+ assertEquals(MyInterfaceType[].class,
+ resolveType(intArrMessageMethodParam.getGenericParameterType(), new HashMap<TypeVariable, Type>()));
+
+ Method genericArrMessageMethod = findMethod(MySimpleTypeWithMethods.class, "readGenericArrayInputMessage",
+ Object[].class);
+ MethodParameter genericArrMessageMethodParam = new MethodParameter(genericArrMessageMethod, 0);
+ Map<TypeVariable, Type> varMap = getTypeVariableMap(MySimpleTypeWithMethods.class);
+ assertEquals(Integer[].class, resolveType(genericArrMessageMethodParam.getGenericParameterType(), varMap));
+ }
+
+ @Test
+ public void testBoundParameterizedType() {
+ assertEquals(B.class, resolveTypeArgument(TestImpl.class, ITest.class));
+ }
+
+ @Test
+ public void testGetTypeVariableMap() throws Exception {
+ Map<TypeVariable, Type> map;
+
+ map = GenericTypeResolver.getTypeVariableMap(MySimpleInterfaceType.class);
+ assertThat(map.toString(), equalTo("{T=class java.lang.String}"));
+
+ map = GenericTypeResolver.getTypeVariableMap(MyCollectionInterfaceType.class);
+ assertThat(map.toString(), equalTo("{T=java.util.Collection<java.lang.String>}"));
+
+ map = GenericTypeResolver.getTypeVariableMap(MyCollectionSuperclassType.class);
+ assertThat(map.toString(), equalTo("{T=java.util.Collection<java.lang.String>}"));
+
+ map = GenericTypeResolver.getTypeVariableMap(MySimpleTypeWithMethods.class);
+ assertThat(map.toString(), equalTo("{T=class java.lang.Integer}"));
+
+ map = GenericTypeResolver.getTypeVariableMap(TopLevelClass.class);
+ assertThat(map.toString(), equalTo("{}"));
+
+ map = GenericTypeResolver.getTypeVariableMap(TypedTopLevelClass.class);
+ assertThat(map.toString(), equalTo("{T=class java.lang.Integer}"));
+
+ map = GenericTypeResolver.getTypeVariableMap(TypedTopLevelClass.TypedNested.class);
+ assertThat(map.size(), equalTo(2));
+ Type t = null;
+ Type x = null;
+ for (Map.Entry<TypeVariable, Type> entry : map.entrySet()) {
+ if(entry.getKey().toString().equals("T")) {
+ t = entry.getValue();
+ }
+ else {
+ x = entry.getValue();
+ }
+ }
+ assertThat(t, equalTo((Type) Integer.class));
+ assertThat(x, equalTo((Type) Long.class));
+ }
+
+ @Test
+ public void getGenericsCannotBeResolved() throws Exception {
+ // SPR-11030
+ Class<?>[] resolved = GenericTypeResolver.resolveTypeArguments(List.class, Iterable.class);
+ // Note: to be changed to return null in Spring 4.0
+ assertThat(resolved, equalTo(new Class[] {Object.class}));
+ }
+
+ @Test
+ public void getRawMapTypeCannotBeResolved() throws Exception {
+ // SPR-11052
+ Class<?>[] resolved = GenericTypeResolver.resolveTypeArguments(Map.class, Map.class);
+ assertNull(resolved);
+ }
+
+ @Test
+ public void getGenericsOnArrayFromParamCannotBeResolved() throws Exception {
+ // SPR-11044
+ MethodParameter methodParameter = MethodParameter.forMethodOrConstructor(
+ WithArrayBase.class.getDeclaredMethod("array", Object[].class), 0);
+ Class<?> resolved = GenericTypeResolver.resolveParameterType(methodParameter, WithArray.class);
+ assertThat(resolved, equalTo((Class) Object[].class));
+ }
+
+ @Test
+ public void getGenericsOnArrayFromReturnCannotBeResolved() throws Exception {
+ // SPR-11044
+ Class<?> resolved = GenericTypeResolver.resolveReturnType(
+ WithArrayBase.class.getDeclaredMethod("array", Object[].class),
+ WithArray.class);
+ assertThat(resolved, equalTo((Class) Object[].class));
+ }
+
+ public interface MyInterfaceType<T> {
+ }
+
+ public class MySimpleInterfaceType implements MyInterfaceType<String> {
+ }
+
+ public class MyCollectionInterfaceType implements MyInterfaceType<Collection<String>> {
+ }
+
+ public abstract class MySuperclassType<T> {
+ }
+
+ public class MySimpleSuperclassType extends MySuperclassType<String> {
+ }
+
+ public class MyCollectionSuperclassType extends MySuperclassType<Collection<String>> {
+ }
+
+ public static class MyTypeWithMethods<T> {
+
+ public MyInterfaceType<Integer> integer() {
+ return null;
+ }
+
+ public MySimpleInterfaceType string() {
+ return null;
+ }
+
+ public Object object() {
+ return null;
+ }
+
+ @SuppressWarnings("rawtypes")
+ public MyInterfaceType raw() {
+ return null;
+ }
+
+ public String notParameterized() {
+ return null;
+ }
+
+ public String notParameterizedWithArguments(Integer x, Boolean b) {
+ return null;
+ }
+
+ /**
+ * Simulates a factory method that wraps the supplied object in a proxy of the
+ * same type.
+ */
+ public static <T> T createProxy(T object) {
+ return null;
+ }
+
+ /**
+ * Similar to {@link #createProxy(Object)} but adds an additional argument before
+ * the argument of type {@code T}. Note that they may potentially be of the same
+ * time when invoked!
+ */
+ public static <T> T createNamedProxy(String name, T object) {
+ return null;
+ }
+
+ /**
+ * Simulates factory methods found in libraries such as Mockito and EasyMock.
+ */
+ public static <MOCK> MOCK createMock(Class<MOCK> toMock) {
+ return null;
+ }
+
+ /**
+ * Similar to {@link #createMock(Class)} but adds an additional method argument
+ * before the parameterized argument.
+ */
+ public static <T> T createNamedMock(String name, Class<T> toMock) {
+ return null;
+ }
+
+ /**
+ * Similar to {@link #createNamedMock(String, Class)} but adds an additional
+ * parameterized type.
+ */
+ public static <V extends Object, T> T createVMock(V name, Class<T> toMock) {
+ return null;
+ }
+
+ /**
+ * Extract some value of the type supported by the interface (i.e., by a concrete,
+ * non-generic implementation of the interface).
+ */
+ public static <T> T extractValueFrom(MyInterfaceType<T> myInterfaceType) {
+ return null;
+ }
+
+ /**
+ * Extract some magic value from the supplied map.
+ */
+ public static <K, V> V extractMagicValue(Map<K, V> map) {
+ return null;
+ }
+
+ public void readIntegerInputMessage(MyInterfaceType<Integer> message) {
+ }
+
+ public void readIntegerArrayInputMessage(MyInterfaceType<Integer>[] message) {
+ }
+
+ public void readGenericArrayInputMessage(T[] message) {
+ }
+ }
+
+ public static class MySimpleTypeWithMethods extends MyTypeWithMethods<Integer> {
+ }
+
+ static class GenericClass<T> {
+ }
+
+ class A{}
+
+ class B<T>{}
+
+ class ITest<T>{}
+
+ class TestImpl<I extends A, T extends B<I>> extends ITest<T>{
+ }
+
+ static class TopLevelClass<T> {
+ class Nested<X> {
+ }
+ }
+
+ static class TypedTopLevelClass extends TopLevelClass<Integer> {
+ class TypedNested extends Nested<Long> {
+ }
+ }
+
+ static abstract class WithArrayBase<T> {
+
+ public abstract T[] array(T... args);
+ }
+
+ static abstract class WithArray<T> extends WithArrayBase<T> {
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/Jdk14ControlFlowTests.java b/spring-core/src/test/java/org/springframework/core/Jdk14ControlFlowTests.java
new file mode 100644
index 00000000..66f1e4f7
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/Jdk14ControlFlowTests.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core;
+
+/**
+ * Tests with ControlFlowFactory return.
+ *
+ * @author Rod Johnson
+ */
+public class Jdk14ControlFlowTests extends AbstractControlFlowTests {
+
+ /**
+ * Necessary only because Eclipse won't run test suite unless it declares
+ * some methods as well as inherited methods
+ */
+ public void testThisClassPlease() {
+ }
+
+ @Override
+ protected ControlFlow createControlFlow() {
+ return ControlFlowFactory.createControlFlow();
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/LocalVariableTableParameterNameDiscovererTests.java b/spring-core/src/test/java/org/springframework/core/LocalVariableTableParameterNameDiscovererTests.java
new file mode 100644
index 00000000..bc659f61
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/LocalVariableTableParameterNameDiscovererTests.java
@@ -0,0 +1,314 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core;
+
+import java.awt.Component;
+import java.io.PrintStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.Date;
+
+import junit.framework.TestCase;
+
+import org.junit.Ignore;
+import org.springframework.tests.sample.objects.TestObject;
+
+/**
+ * @author Adrian Colyer
+ */
+public class LocalVariableTableParameterNameDiscovererTests extends TestCase {
+
+ private LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();
+
+ public void testMethodParameterNameDiscoveryNoArgs() throws NoSuchMethodException {
+ Method getName = TestObject.class.getMethod("getName", new Class[0]);
+ String[] names = discoverer.getParameterNames(getName);
+ assertNotNull("should find method info", names);
+ assertEquals("no argument names", 0, names.length);
+ }
+
+ public void testMethodParameterNameDiscoveryWithArgs() throws NoSuchMethodException {
+ Method setName = TestObject.class.getMethod("setName", new Class[] { String.class });
+ String[] names = discoverer.getParameterNames(setName);
+ assertNotNull("should find method info", names);
+ assertEquals("one argument", 1, names.length);
+ assertEquals("name", names[0]);
+ }
+
+ public void testConsParameterNameDiscoveryNoArgs() throws NoSuchMethodException {
+ Constructor<TestObject> noArgsCons = TestObject.class.getConstructor(new Class[0]);
+ String[] names = discoverer.getParameterNames(noArgsCons);
+ assertNotNull("should find cons info", names);
+ assertEquals("no argument names", 0, names.length);
+ }
+
+ public void testConsParameterNameDiscoveryArgs() throws NoSuchMethodException {
+ Constructor<TestObject> twoArgCons = TestObject.class.getConstructor(new Class[] { String.class, int.class });
+ String[] names = discoverer.getParameterNames(twoArgCons);
+ assertNotNull("should find cons info", names);
+ assertEquals("one argument", 2, names.length);
+ assertEquals("name", names[0]);
+ assertEquals("age", names[1]);
+ }
+
+ public void testStaticMethodParameterNameDiscoveryNoArgs() throws NoSuchMethodException {
+ Method m = getClass().getMethod("staticMethodNoLocalVars", new Class[0]);
+ String[] names = discoverer.getParameterNames(m);
+ assertNotNull("should find method info", names);
+ assertEquals("no argument names", 0, names.length);
+ }
+
+ public void testOverloadedStaticMethod() throws Exception {
+ Class<? extends LocalVariableTableParameterNameDiscovererTests> clazz = this.getClass();
+
+ Method m1 = clazz.getMethod("staticMethod", new Class[] { Long.TYPE, Long.TYPE });
+ String[] names = discoverer.getParameterNames(m1);
+ assertNotNull("should find method info", names);
+ assertEquals("two arguments", 2, names.length);
+ assertEquals("x", names[0]);
+ assertEquals("y", names[1]);
+
+ Method m2 = clazz.getMethod("staticMethod", new Class[] { Long.TYPE, Long.TYPE, Long.TYPE });
+ names = discoverer.getParameterNames(m2);
+ assertNotNull("should find method info", names);
+ assertEquals("three arguments", 3, names.length);
+ assertEquals("x", names[0]);
+ assertEquals("y", names[1]);
+ assertEquals("z", names[2]);
+ }
+
+ public void testOverloadedStaticMethodInInnerClass() throws Exception {
+ Class<InnerClass> clazz = InnerClass.class;
+
+ Method m1 = clazz.getMethod("staticMethod", new Class[] { Long.TYPE });
+ String[] names = discoverer.getParameterNames(m1);
+ assertNotNull("should find method info", names);
+ assertEquals("one argument", 1, names.length);
+ assertEquals("x", names[0]);
+
+ Method m2 = clazz.getMethod("staticMethod", new Class[] { Long.TYPE, Long.TYPE });
+ names = discoverer.getParameterNames(m2);
+ assertNotNull("should find method info", names);
+ assertEquals("two arguments", 2, names.length);
+ assertEquals("x", names[0]);
+ assertEquals("y", names[1]);
+ }
+
+ public void testOverloadedMethod() throws Exception {
+ Class<? extends LocalVariableTableParameterNameDiscovererTests> clazz = this.getClass();
+
+ Method m1 = clazz.getMethod("instanceMethod", new Class[] { Double.TYPE, Double.TYPE });
+ String[] names = discoverer.getParameterNames(m1);
+ assertNotNull("should find method info", names);
+ assertEquals("two arguments", 2, names.length);
+ assertEquals("x", names[0]);
+ assertEquals("y", names[1]);
+
+ Method m2 = clazz.getMethod("instanceMethod", new Class[] { Double.TYPE, Double.TYPE, Double.TYPE });
+ names = discoverer.getParameterNames(m2);
+ assertNotNull("should find method info", names);
+ assertEquals("three arguments", 3, names.length);
+ assertEquals("x", names[0]);
+ assertEquals("y", names[1]);
+ assertEquals("z", names[2]);
+ }
+
+ public void testOverloadedMethodInInnerClass() throws Exception {
+ Class<InnerClass> clazz = InnerClass.class;
+
+ Method m1 = clazz.getMethod("instanceMethod", new Class[] { String.class });
+ String[] names = discoverer.getParameterNames(m1);
+ assertNotNull("should find method info", names);
+ assertEquals("one argument", 1, names.length);
+ assertEquals("aa", names[0]);
+
+ Method m2 = clazz.getMethod("instanceMethod", new Class[] { String.class, String.class });
+ names = discoverer.getParameterNames(m2);
+ assertNotNull("should find method info", names);
+ assertEquals("two arguments", 2, names.length);
+ assertEquals("aa", names[0]);
+ assertEquals("bb", names[1]);
+ }
+
+ public void testGenerifiedClass() throws Exception {
+ Class<?> clazz = (Class<?>)GenerifiedClass.class;
+
+ Constructor<?> ctor = clazz.getDeclaredConstructor(Object.class);
+ String[] names = discoverer.getParameterNames(ctor);
+ assertEquals(1, names.length);
+ assertEquals("key", names[0]);
+
+ ctor = clazz.getDeclaredConstructor(Object.class, Object.class);
+ names = discoverer.getParameterNames(ctor);
+ assertEquals(2, names.length);
+ assertEquals("key", names[0]);
+ assertEquals("value", names[1]);
+
+ Method m = clazz.getMethod("generifiedStaticMethod", Object.class);
+ names = discoverer.getParameterNames(m);
+ assertEquals(1, names.length);
+ assertEquals("param", names[0]);
+
+ m = clazz.getMethod("generifiedMethod", Object.class, long.class, Object.class, Object.class);
+ names = discoverer.getParameterNames(m);
+ assertEquals(4, names.length);
+ assertEquals("param", names[0]);
+ assertEquals("x", names[1]);
+ assertEquals("key", names[2]);
+ assertEquals("value", names[3]);
+
+ m = clazz.getMethod("voidStaticMethod", Object.class, long.class, int.class);
+ names = discoverer.getParameterNames(m);
+ assertEquals(3, names.length);
+ assertEquals("obj", names[0]);
+ assertEquals("x", names[1]);
+ assertEquals("i", names[2]);
+
+ m = clazz.getMethod("nonVoidStaticMethod", Object.class, long.class, int.class);
+ names = discoverer.getParameterNames(m);
+ assertEquals(3, names.length);
+ assertEquals("obj", names[0]);
+ assertEquals("x", names[1]);
+ assertEquals("i", names[2]);
+
+ m = clazz.getMethod("getDate");
+ names = discoverer.getParameterNames(m);
+ assertEquals(0, names.length);
+
+ //System.in.read();
+ }
+
+ /**
+ * Ignored because Ubuntu packages OpenJDK with debug symbols enabled.
+ * See SPR-8078.
+ */
+ @Ignore
+ public void ignore_testClassesWithoutDebugSymbols() throws Exception {
+ // JDK classes don't have debug information (usually)
+ Class<Component> clazz = Component.class;
+ String methodName = "list";
+
+ Method m = clazz.getMethod(methodName);
+ String[] names = discoverer.getParameterNames(m);
+ assertNull(names);
+
+ m = clazz.getMethod(methodName, PrintStream.class);
+ names = discoverer.getParameterNames(m);
+ assertNull(names);
+
+ m = clazz.getMethod(methodName, PrintStream.class, int.class);
+ names = discoverer.getParameterNames(m);
+ assertNull(names);
+
+ //System.in.read();
+ }
+
+ public static void staticMethodNoLocalVars() {
+ }
+
+ public static long staticMethod(long x, long y) {
+ long u = x * y;
+ return u;
+ }
+
+ public static long staticMethod(long x, long y, long z) {
+ long u = x * y * z;
+ return u;
+ }
+
+ public double instanceMethod(double x, double y) {
+ double u = x * y;
+ return u;
+ }
+
+ public double instanceMethod(double x, double y, double z) {
+ double u = x * y * z;
+ return u;
+ }
+
+ public static class InnerClass {
+
+ public int waz = 0;
+
+ public InnerClass() {
+ }
+
+ public InnerClass(String firstArg, long secondArg, Object thirdArg) {
+ long foo = 0;
+ short bar = 10;
+ this.waz = (int) (foo + bar);
+ }
+
+ public String instanceMethod(String aa) {
+ return aa;
+ }
+
+ public String instanceMethod(String aa, String bb) {
+ return aa + bb;
+ }
+
+ public static long staticMethod(long x) {
+ long u = x;
+ return u;
+ }
+
+ public static long staticMethod(long x, long y) {
+ long u = x * y;
+ return u;
+ }
+ }
+
+ public static class GenerifiedClass<K, V> {
+ private static long date;
+
+ static {
+ // some custom static bloc or <clinit>
+ date = new Date().getTime();
+ }
+
+ public GenerifiedClass() {
+ this(null, null);
+ }
+
+ public GenerifiedClass(K key) {
+ this(key, null);
+ }
+
+ public GenerifiedClass(K key, V value) {
+ }
+
+ public static <P> long generifiedStaticMethod(P param) {
+ return date;
+ }
+
+ public <P> void generifiedMethod(P param, long x, K key, V value) {
+ // nothing
+ }
+
+ public static void voidStaticMethod(Object obj, long x, int i) {
+ // nothing
+ }
+
+ public static long nonVoidStaticMethod(Object obj, long x, int i) {
+ return date;
+ }
+
+ public static long getDate() {
+ return date;
+ }
+ }
+}
diff --git a/spring-core/src/test/java/org/springframework/core/MethodParameterTests.java b/spring-core/src/test/java/org/springframework/core/MethodParameterTests.java
new file mode 100644
index 00000000..c3c3e7d1
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/MethodParameterTests.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core;
+
+import java.lang.reflect.Method;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author Arjen Poutsma
+ */
+public class MethodParameterTests {
+
+ private MethodParameter stringParameter;
+
+ private MethodParameter longParameter;
+
+ private MethodParameter intReturnType;
+
+
+ @Before
+ public void setUp() throws NoSuchMethodException {
+ Method method = getClass().getMethod("method", String.class, Long.TYPE);
+ stringParameter = new MethodParameter(method, 0);
+ longParameter = new MethodParameter(method, 1);
+ intReturnType = new MethodParameter(method, -1);
+ }
+
+ @Test
+ public void testEquals() throws NoSuchMethodException {
+ assertEquals(stringParameter, stringParameter);
+ assertEquals(longParameter, longParameter);
+ assertEquals(intReturnType, intReturnType);
+
+ assertFalse(stringParameter.equals(longParameter));
+ assertFalse(stringParameter.equals(intReturnType));
+ assertFalse(longParameter.equals(stringParameter));
+ assertFalse(longParameter.equals(intReturnType));
+ assertFalse(intReturnType.equals(stringParameter));
+ assertFalse(intReturnType.equals(longParameter));
+
+ Method method = getClass().getMethod("method", String.class, Long.TYPE);
+ MethodParameter methodParameter = new MethodParameter(method, 0);
+ assertEquals(stringParameter, methodParameter);
+ assertEquals(methodParameter, stringParameter);
+ assertFalse(longParameter.equals(methodParameter));
+ assertFalse(methodParameter.equals(longParameter));
+ }
+
+ @Test
+ public void testHashCode() throws NoSuchMethodException {
+ assertEquals(stringParameter.hashCode(), stringParameter.hashCode());
+ assertEquals(longParameter.hashCode(), longParameter.hashCode());
+ assertEquals(intReturnType.hashCode(), intReturnType.hashCode());
+
+ Method method = getClass().getMethod("method", String.class, Long.TYPE);
+ MethodParameter methodParameter = new MethodParameter(method, 0);
+ assertEquals(stringParameter.hashCode(), methodParameter.hashCode());
+ assertTrue(longParameter.hashCode() != methodParameter.hashCode());
+ }
+
+
+ public int method(String p1, long p2) {
+ return 42;
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/NestedExceptionTests.java b/spring-core/src/test/java/org/springframework/core/NestedExceptionTests.java
new file mode 100644
index 00000000..dff42909
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/NestedExceptionTests.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintWriter;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ */
+public class NestedExceptionTests extends TestCase {
+
+ @SuppressWarnings("serial")
+ public void testNestedRuntimeExceptionWithNoRootCause() {
+ String mesg = "mesg of mine";
+ // Making a class abstract doesn't _really_ prevent instantiation :-)
+ NestedRuntimeException nex = new NestedRuntimeException(mesg) {};
+ assertNull(nex.getCause());
+ assertEquals(nex.getMessage(), mesg);
+
+ // Check printStackTrace
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ PrintWriter pw = new PrintWriter(baos);
+ nex.printStackTrace(pw);
+ pw.flush();
+ String stackTrace = new String(baos.toByteArray());
+ assertFalse(stackTrace.indexOf(mesg) == -1);
+ }
+
+ @SuppressWarnings("serial")
+ public void testNestedRuntimeExceptionWithRootCause() {
+ String myMessage = "mesg for this exception";
+ String rootCauseMesg = "this is the obscure message of the root cause";
+ Exception rootCause = new Exception(rootCauseMesg);
+ // Making a class abstract doesn't _really_ prevent instantiation :-)
+ NestedRuntimeException nex = new NestedRuntimeException(myMessage, rootCause) {};
+ assertEquals(nex.getCause(), rootCause);
+ assertTrue(nex.getMessage().indexOf(myMessage) != -1);
+ assertTrue(nex.getMessage().indexOf(rootCauseMesg) != -1);
+
+ // check PrintStackTrace
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ PrintWriter pw = new PrintWriter(baos);
+ nex.printStackTrace(pw);
+ pw.flush();
+ String stackTrace = new String(baos.toByteArray());
+ assertFalse(stackTrace.indexOf(rootCause.getClass().getName()) == -1);
+ assertFalse(stackTrace.indexOf(rootCauseMesg) == -1);
+ }
+
+ @SuppressWarnings("serial")
+ public void testNestedCheckedExceptionWithNoRootCause() {
+ String mesg = "mesg of mine";
+ // Making a class abstract doesn't _really_ prevent instantiation :-)
+ NestedCheckedException nex = new NestedCheckedException(mesg) {};
+ assertNull(nex.getCause());
+ assertEquals(nex.getMessage(), mesg);
+
+ // Check printStackTrace
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ PrintWriter pw = new PrintWriter(baos);
+ nex.printStackTrace(pw);
+ pw.flush();
+ String stackTrace = new String(baos.toByteArray());
+ assertFalse(stackTrace.indexOf(mesg) == -1);
+ }
+
+ @SuppressWarnings("serial")
+ public void testNestedCheckedExceptionWithRootCause() {
+ String myMessage = "mesg for this exception";
+ String rootCauseMesg = "this is the obscure message of the root cause";
+ Exception rootCause = new Exception(rootCauseMesg);
+ // Making a class abstract doesn't _really_ prevent instantiation :-)
+ NestedCheckedException nex = new NestedCheckedException(myMessage, rootCause) {};
+ assertEquals(nex.getCause(), rootCause);
+ assertTrue(nex.getMessage().indexOf(myMessage) != -1);
+ assertTrue(nex.getMessage().indexOf(rootCauseMesg) != -1);
+
+ // check PrintStackTrace
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ PrintWriter pw = new PrintWriter(baos);
+ nex.printStackTrace(pw);
+ pw.flush();
+ String stackTrace = new String(baos.toByteArray());
+ assertFalse(stackTrace.indexOf(rootCause.getClass().getName()) == -1);
+ assertFalse(stackTrace.indexOf(rootCauseMesg) == -1);
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/OrderComparatorTests.java b/spring-core/src/test/java/org/springframework/core/OrderComparatorTests.java
new file mode 100644
index 00000000..d93649a0
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/OrderComparatorTests.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core;
+
+import junit.framework.TestCase;
+
+import java.util.Comparator;
+
+/**
+ * Unit tests for the {@link OrderComparator} class.
+ *
+ * @author Rick Evans
+ */
+public final class OrderComparatorTests extends TestCase {
+
+ private Comparator comparator;
+
+
+ @Override
+ protected void setUp() throws Exception {
+ this.comparator = new OrderComparator();
+ }
+
+
+ public void testCompareOrderedInstancesBefore() throws Exception {
+ assertEquals(-1, this.comparator.compare(
+ new StubOrdered(100), new StubOrdered(2000)));
+ }
+
+ public void testCompareOrderedInstancesSame() throws Exception {
+ assertEquals(0, this.comparator.compare(
+ new StubOrdered(100), new StubOrdered(100)));
+ }
+
+ public void testCompareOrderedInstancesAfter() throws Exception {
+ assertEquals(1, this.comparator.compare(
+ new StubOrdered(982300), new StubOrdered(100)));
+ }
+
+ public void testCompareTwoNonOrderedInstancesEndsUpAsSame() throws Exception {
+ assertEquals(0, this.comparator.compare(new Object(), new Object()));
+ }
+
+
+ private static final class StubOrdered implements Ordered {
+
+ private final int order;
+
+
+ public StubOrdered(int order) {
+ this.order = order;
+ }
+
+ @Override
+ public int getOrder() {
+ return this.order;
+ }
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/ParameterizedTypeReferenceTests.java b/spring-core/src/test/java/org/springframework/core/ParameterizedTypeReferenceTests.java
new file mode 100644
index 00000000..56060b24
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/ParameterizedTypeReferenceTests.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core;
+
+import java.lang.reflect.Type;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Test fixture for {@link ParameterizedTypeReference}.
+ *
+ * @author Arjen Poutsma
+ * @author Rossen Stoyanchev
+ */
+public class ParameterizedTypeReferenceTests {
+
+ @Test
+ public void map() throws NoSuchMethodException {
+ Type mapType = getClass().getMethod("mapMethod").getGenericReturnType();
+ ParameterizedTypeReference<Map<Object,String>> mapTypeReference = new ParameterizedTypeReference<Map<Object,String>>() {};
+ assertEquals(mapType, mapTypeReference.getType());
+ }
+
+ @Test
+ public void list() throws NoSuchMethodException {
+ Type mapType = getClass().getMethod("listMethod").getGenericReturnType();
+ ParameterizedTypeReference<List<String>> mapTypeReference = new ParameterizedTypeReference<List<String>>() {};
+ assertEquals(mapType, mapTypeReference.getType());
+ }
+
+ @Test
+ public void string() {
+ ParameterizedTypeReference<String> typeReference = new ParameterizedTypeReference<String>() {};
+ assertEquals(String.class, typeReference.getType());
+ }
+
+ public static Map<Object, String> mapMethod() {
+ return null;
+ }
+
+ public static List<String> listMethod() {
+ return null;
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/PrioritizedParameterNameDiscovererTests.java b/spring-core/src/test/java/org/springframework/core/PrioritizedParameterNameDiscovererTests.java
new file mode 100644
index 00000000..19c16d15
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/PrioritizedParameterNameDiscovererTests.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+
+import org.springframework.tests.sample.objects.TestObject;
+
+public class PrioritizedParameterNameDiscovererTests extends TestCase {
+
+ private static final String[] FOO_BAR = new String[] { "foo", "bar" };
+
+ private static final String[] SOMETHING_ELSE = new String[] { "something", "else" };
+
+ ParameterNameDiscoverer returnsFooBar = new ParameterNameDiscoverer() {
+ @Override
+ public String[] getParameterNames(Method m) {
+ return FOO_BAR;
+ }
+ @Override
+ public String[] getParameterNames(Constructor ctor) {
+ return FOO_BAR;
+ }
+ };
+
+ ParameterNameDiscoverer returnsSomethingElse = new ParameterNameDiscoverer() {
+ @Override
+ public String[] getParameterNames(Method m) {
+ return SOMETHING_ELSE;
+ }
+ @Override
+ public String[] getParameterNames(Constructor ctor) {
+ return SOMETHING_ELSE;
+ }
+ };
+
+ private final Method anyMethod;
+ private final Class anyClass = Object.class;
+
+ public PrioritizedParameterNameDiscovererTests() throws SecurityException, NoSuchMethodException {
+ anyMethod = TestObject.class.getMethod("getAge", (Class[]) null);
+ }
+
+ public void testNoParametersDiscoverers() {
+ ParameterNameDiscoverer pnd = new PrioritizedParameterNameDiscoverer();
+ assertNull(pnd.getParameterNames(anyMethod));
+ assertNull(pnd.getParameterNames((Constructor) null));
+ }
+
+ public void testOrderedParameterDiscoverers1() {
+ PrioritizedParameterNameDiscoverer pnd = new PrioritizedParameterNameDiscoverer();
+ pnd.addDiscoverer(returnsFooBar);
+ assertTrue(Arrays.equals(FOO_BAR, pnd.getParameterNames(anyMethod)));
+ assertTrue(Arrays.equals(FOO_BAR, pnd.getParameterNames((Constructor) null)));
+ pnd.addDiscoverer(returnsSomethingElse);
+ assertTrue(Arrays.equals(FOO_BAR, pnd.getParameterNames(anyMethod)));
+ assertTrue(Arrays.equals(FOO_BAR, pnd.getParameterNames((Constructor) null)));
+ }
+
+ public void testOrderedParameterDiscoverers2() {
+ PrioritizedParameterNameDiscoverer pnd = new PrioritizedParameterNameDiscoverer();
+ pnd.addDiscoverer(returnsSomethingElse);
+ assertTrue(Arrays.equals(SOMETHING_ELSE, pnd.getParameterNames(anyMethod)));
+ assertTrue(Arrays.equals(SOMETHING_ELSE, pnd.getParameterNames((Constructor) null)));
+ pnd.addDiscoverer(returnsFooBar);
+ assertTrue(Arrays.equals(SOMETHING_ELSE, pnd.getParameterNames(anyMethod)));
+ assertTrue(Arrays.equals(SOMETHING_ELSE, pnd.getParameterNames((Constructor) null)));
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/annotation/AnnotationAttributesTests.java b/spring-core/src/test/java/org/springframework/core/annotation/AnnotationAttributesTests.java
new file mode 100644
index 00000000..487b3399
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/annotation/AnnotationAttributesTests.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.annotation;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link AnnotationAttributes}.
+ *
+ * @author Chris Beams
+ * @since 3.1.1
+ */
+public class AnnotationAttributesTests {
+
+ enum Color { RED, WHITE, BLUE }
+
+ @Test
+ public void testTypeSafeAttributeAccess() {
+ AnnotationAttributes a = new AnnotationAttributes();
+ a.put("name", "dave");
+ a.put("names", new String[] { "dave", "frank", "hal" });
+ a.put("bool1", true);
+ a.put("bool2", false);
+ a.put("color", Color.RED);
+ a.put("clazz", Integer.class);
+ a.put("classes", new Class<?>[] { Number.class, Short.class, Integer.class });
+ a.put("number", 42);
+ a.put("numbers", new int[] { 42, 43 });
+ AnnotationAttributes anno = new AnnotationAttributes();
+ anno.put("value", 10);
+ anno.put("name", "algernon");
+ a.put("anno", anno);
+ a.put("annoArray", new AnnotationAttributes[] { anno });
+
+ assertThat(a.getString("name"), equalTo("dave"));
+ assertThat(a.getStringArray("names"), equalTo(new String[] { "dave", "frank", "hal" }));
+ assertThat(a.getBoolean("bool1"), equalTo(true));
+ assertThat(a.getBoolean("bool2"), equalTo(false));
+ assertThat(a.<Color>getEnum("color"), equalTo(Color.RED));
+ assertTrue(a.getClass("clazz").equals(Integer.class));
+ assertThat(a.getClassArray("classes"), equalTo(new Class[] { Number.class, Short.class, Integer.class }));
+ assertThat(a.<Integer>getNumber("number"), equalTo(42));
+ assertThat(a.getAnnotation("anno").<Integer>getNumber("value"), equalTo(10));
+ assertThat(a.getAnnotationArray("annoArray")[0].getString("name"), equalTo("algernon"));
+ }
+
+ @Test
+ public void getEnum_emptyAttributeName() {
+ AnnotationAttributes a = new AnnotationAttributes();
+ a.put("color", "RED");
+ try {
+ a.getEnum("");
+ fail();
+ } catch (IllegalArgumentException ex) {
+ assertThat(ex.getMessage(), equalTo("attributeName must not be null or empty"));
+ }
+ try {
+ a.getEnum(null);
+ fail();
+ } catch (IllegalArgumentException ex) {
+ assertThat(ex.getMessage(), equalTo("attributeName must not be null or empty"));
+ }
+ }
+
+ @Test
+ public void getEnum_notFound() {
+ AnnotationAttributes a = new AnnotationAttributes();
+ a.put("color", "RED");
+ try {
+ a.getEnum("colour");
+ fail();
+ } catch (IllegalArgumentException ex) {
+ assertThat(ex.getMessage(), equalTo("Attribute 'colour' not found"));
+ }
+ }
+
+ @Test
+ public void getEnum_typeMismatch() {
+ AnnotationAttributes a = new AnnotationAttributes();
+ a.put("color", "RED");
+ try {
+ a.getEnum("color");
+ fail();
+ } catch (IllegalArgumentException ex) {
+ String expected =
+ "Attribute 'color' is of type [String], but [Enum] was expected";
+ assertThat(ex.getMessage().substring(0, expected.length()), equalTo(expected));
+ }
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/annotation/AnnotationAwareOrderComparatorTests.java b/spring-core/src/test/java/org/springframework/core/annotation/AnnotationAwareOrderComparatorTests.java
new file mode 100644
index 00000000..df656655
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/annotation/AnnotationAwareOrderComparatorTests.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.annotation;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author Juergen Hoeller
+ * @author Oliver Gierke
+ */
+public class AnnotationAwareOrderComparatorTests {
+
+ @Test
+ public void instanceVariableIsAnAnnotationAwareOrderComparator() {
+ assertThat(AnnotationAwareOrderComparator.INSTANCE, is(instanceOf(AnnotationAwareOrderComparator.class)));
+ }
+
+ @Test
+ public void sortInstances() {
+ List<Object> list = new ArrayList<>();
+ list.add(new B());
+ list.add(new A());
+ AnnotationAwareOrderComparator.sort(list);
+ assertTrue(list.get(0) instanceof A);
+ assertTrue(list.get(1) instanceof B);
+ }
+
+ @Test
+ public void sortInstancesWithSubclass() {
+ List<Object> list = new ArrayList<>();
+ list.add(new B());
+ list.add(new C());
+ AnnotationAwareOrderComparator.sort(list);
+ assertTrue(list.get(0) instanceof C);
+ assertTrue(list.get(1) instanceof B);
+ }
+
+ @Test
+ public void sortClasses() {
+ List<Object> list = new ArrayList<>();
+ list.add(B.class);
+ list.add(A.class);
+ AnnotationAwareOrderComparator.sort(list);
+ assertEquals(A.class, list.get(0));
+ assertEquals(B.class, list.get(1));
+ }
+
+ @Test
+ public void sortClassesWithSubclass() {
+ List<Object> list = new ArrayList<>();
+ list.add(B.class);
+ list.add(C.class);
+ AnnotationAwareOrderComparator.sort(list);
+ assertEquals(C.class, list.get(0));
+ assertEquals(B.class, list.get(1));
+ }
+
+
+ @Order(1)
+ private static class A {
+ }
+
+ @Order(2)
+ private static class B {
+ }
+
+ private static class C extends A {
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/annotation/AnnotationUtilsTests.java b/spring-core/src/test/java/org/springframework/core/annotation/AnnotationUtilsTests.java
new file mode 100644
index 00000000..d4b6d5ee
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/annotation/AnnotationUtilsTests.java
@@ -0,0 +1,441 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.annotation;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+
+import org.springframework.core.Ordered;
+import org.springframework.stereotype.Component;
+
+import static org.junit.Assert.*;
+import static org.springframework.core.annotation.AnnotationUtils.*;
+
+/**
+ * Unit tests for {@link AnnotationUtils}.
+ *
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ * @author Sam Brannen
+ * @author Chris Beams
+ */
+public class AnnotationUtilsTests {
+
+ @Test
+ public void findMethodAnnotationOnLeaf() throws Exception {
+ Method m = Leaf.class.getMethod("annotatedOnLeaf", (Class[]) null);
+ assertNotNull(m.getAnnotation(Order.class));
+ assertNotNull(getAnnotation(m, Order.class));
+ assertNotNull(findAnnotation(m, Order.class));
+ }
+
+ @Test
+ public void findMethodAnnotationOnRoot() throws Exception {
+ Method m = Leaf.class.getMethod("annotatedOnRoot", (Class[]) null);
+ assertNotNull(m.getAnnotation(Order.class));
+ assertNotNull(getAnnotation(m, Order.class));
+ assertNotNull(findAnnotation(m, Order.class));
+ }
+
+ @Test
+ public void findMethodAnnotationOnRootButOverridden() throws Exception {
+ Method m = Leaf.class.getMethod("overrideWithoutNewAnnotation", (Class[]) null);
+ assertNull(m.getAnnotation(Order.class));
+ assertNull(getAnnotation(m, Order.class));
+ assertNotNull(findAnnotation(m, Order.class));
+ }
+
+ @Test
+ public void findMethodAnnotationNotAnnotated() throws Exception {
+ Method m = Leaf.class.getMethod("notAnnotated", (Class[]) null);
+ assertNull(findAnnotation(m, Order.class));
+ }
+
+ @Test
+ public void findMethodAnnotationOnBridgeMethod() throws Exception {
+ Method m = SimpleFoo.class.getMethod("something", Object.class);
+ assertTrue(m.isBridge());
+ assertNull(m.getAnnotation(Order.class));
+ assertNull(getAnnotation(m, Order.class));
+ assertNotNull(findAnnotation(m, Order.class));
+ // TODO: actually found on OpenJDK 8 b99! assertNull(m.getAnnotation(Transactional.class));
+ assertNotNull(getAnnotation(m, Transactional.class));
+ assertNotNull(findAnnotation(m, Transactional.class));
+ }
+
+ // TODO consider whether we want this to handle annotations on interfaces
+ // public void findMethodAnnotationFromInterfaceImplementedByRoot()
+ // throws Exception {
+ // Method m = Leaf.class.getMethod("fromInterfaceImplementedByRoot",
+ // (Class[]) null);
+ // Order o = findAnnotation(Order.class, m, Leaf.class);
+ // assertNotNull(o);
+ // }
+
+ @Test
+ public void testFindAnnotationDeclaringClass() throws Exception {
+ // no class-level annotation
+ assertNull(findAnnotationDeclaringClass(Transactional.class, NonAnnotatedInterface.class));
+ assertNull(findAnnotationDeclaringClass(Transactional.class, NonAnnotatedClass.class));
+
+ // inherited class-level annotation; note: @Transactional is inherited
+ assertEquals(InheritedAnnotationInterface.class,
+ findAnnotationDeclaringClass(Transactional.class, InheritedAnnotationInterface.class));
+ assertNull(findAnnotationDeclaringClass(Transactional.class, SubInheritedAnnotationInterface.class));
+ assertEquals(InheritedAnnotationClass.class,
+ findAnnotationDeclaringClass(Transactional.class, InheritedAnnotationClass.class));
+ assertEquals(InheritedAnnotationClass.class,
+ findAnnotationDeclaringClass(Transactional.class, SubInheritedAnnotationClass.class));
+
+ // non-inherited class-level annotation; note: @Order is not inherited,
+ // but findAnnotationDeclaringClass() should still find it on classes.
+ assertEquals(NonInheritedAnnotationInterface.class,
+ findAnnotationDeclaringClass(Order.class, NonInheritedAnnotationInterface.class));
+ assertNull(findAnnotationDeclaringClass(Order.class, SubNonInheritedAnnotationInterface.class));
+ assertEquals(NonInheritedAnnotationClass.class,
+ findAnnotationDeclaringClass(Order.class, NonInheritedAnnotationClass.class));
+ assertEquals(NonInheritedAnnotationClass.class,
+ findAnnotationDeclaringClass(Order.class, SubNonInheritedAnnotationClass.class));
+ }
+
+ @Test
+ public void findAnnotationDeclaringClassForTypesWithSingleCandidateType() {
+ // no class-level annotation
+ List<Class<? extends Annotation>> transactionalCandidateList = Arrays.<Class<? extends Annotation>> asList(Transactional.class);
+ assertNull(findAnnotationDeclaringClassForTypes(transactionalCandidateList, NonAnnotatedInterface.class));
+ assertNull(findAnnotationDeclaringClassForTypes(transactionalCandidateList, NonAnnotatedClass.class));
+
+ // inherited class-level annotation; note: @Transactional is inherited
+ assertEquals(InheritedAnnotationInterface.class,
+ findAnnotationDeclaringClassForTypes(transactionalCandidateList, InheritedAnnotationInterface.class));
+ assertNull(findAnnotationDeclaringClassForTypes(transactionalCandidateList, SubInheritedAnnotationInterface.class));
+ assertEquals(InheritedAnnotationClass.class,
+ findAnnotationDeclaringClassForTypes(transactionalCandidateList, InheritedAnnotationClass.class));
+ assertEquals(InheritedAnnotationClass.class,
+ findAnnotationDeclaringClassForTypes(transactionalCandidateList, SubInheritedAnnotationClass.class));
+
+ // non-inherited class-level annotation; note: @Order is not inherited,
+ // but findAnnotationDeclaringClassForTypes() should still find it on classes.
+ List<Class<? extends Annotation>> orderCandidateList = Arrays.<Class<? extends Annotation>> asList(Order.class);
+ assertEquals(NonInheritedAnnotationInterface.class,
+ findAnnotationDeclaringClassForTypes(orderCandidateList, NonInheritedAnnotationInterface.class));
+ assertNull(findAnnotationDeclaringClassForTypes(orderCandidateList, SubNonInheritedAnnotationInterface.class));
+ assertEquals(NonInheritedAnnotationClass.class,
+ findAnnotationDeclaringClassForTypes(orderCandidateList, NonInheritedAnnotationClass.class));
+ assertEquals(NonInheritedAnnotationClass.class,
+ findAnnotationDeclaringClassForTypes(orderCandidateList, SubNonInheritedAnnotationClass.class));
+ }
+
+ @Test
+ public void findAnnotationDeclaringClassForTypesWithMultipleCandidateTypes() {
+ List<Class<? extends Annotation>> candidates = Arrays.<Class<? extends Annotation>> asList(Transactional.class, Order.class);
+
+ // no class-level annotation
+ assertNull(findAnnotationDeclaringClassForTypes(candidates, NonAnnotatedInterface.class));
+ assertNull(findAnnotationDeclaringClassForTypes(candidates, NonAnnotatedClass.class));
+
+ // inherited class-level annotation; note: @Transactional is inherited
+ assertEquals(InheritedAnnotationInterface.class,
+ findAnnotationDeclaringClassForTypes(candidates, InheritedAnnotationInterface.class));
+ assertNull(findAnnotationDeclaringClassForTypes(candidates, SubInheritedAnnotationInterface.class));
+ assertEquals(InheritedAnnotationClass.class,
+ findAnnotationDeclaringClassForTypes(candidates, InheritedAnnotationClass.class));
+ assertEquals(InheritedAnnotationClass.class,
+ findAnnotationDeclaringClassForTypes(candidates, SubInheritedAnnotationClass.class));
+
+ // non-inherited class-level annotation; note: @Order is not inherited,
+ // but findAnnotationDeclaringClassForTypes() should still find it on classes.
+ assertEquals(NonInheritedAnnotationInterface.class,
+ findAnnotationDeclaringClassForTypes(candidates, NonInheritedAnnotationInterface.class));
+ assertNull(findAnnotationDeclaringClassForTypes(candidates, SubNonInheritedAnnotationInterface.class));
+ assertEquals(NonInheritedAnnotationClass.class,
+ findAnnotationDeclaringClassForTypes(candidates, NonInheritedAnnotationClass.class));
+ assertEquals(NonInheritedAnnotationClass.class,
+ findAnnotationDeclaringClassForTypes(candidates, SubNonInheritedAnnotationClass.class));
+
+ // class hierarchy mixed with @Transactional and @Order declarations
+ assertEquals(TransactionalClass.class,
+ findAnnotationDeclaringClassForTypes(candidates, TransactionalClass.class));
+ assertEquals(TransactionalAndOrderedClass.class,
+ findAnnotationDeclaringClassForTypes(candidates, TransactionalAndOrderedClass.class));
+ assertEquals(TransactionalAndOrderedClass.class,
+ findAnnotationDeclaringClassForTypes(candidates, SubTransactionalAndOrderedClass.class));
+ }
+
+ @Test
+ public void testIsAnnotationDeclaredLocally() throws Exception {
+ // no class-level annotation
+ assertFalse(isAnnotationDeclaredLocally(Transactional.class, NonAnnotatedInterface.class));
+ assertFalse(isAnnotationDeclaredLocally(Transactional.class, NonAnnotatedClass.class));
+
+ // inherited class-level annotation; note: @Transactional is inherited
+ assertTrue(isAnnotationDeclaredLocally(Transactional.class, InheritedAnnotationInterface.class));
+ assertFalse(isAnnotationDeclaredLocally(Transactional.class, SubInheritedAnnotationInterface.class));
+ assertTrue(isAnnotationDeclaredLocally(Transactional.class, InheritedAnnotationClass.class));
+ assertFalse(isAnnotationDeclaredLocally(Transactional.class, SubInheritedAnnotationClass.class));
+
+ // non-inherited class-level annotation; note: @Order is not inherited
+ assertTrue(isAnnotationDeclaredLocally(Order.class, NonInheritedAnnotationInterface.class));
+ assertFalse(isAnnotationDeclaredLocally(Order.class, SubNonInheritedAnnotationInterface.class));
+ assertTrue(isAnnotationDeclaredLocally(Order.class, NonInheritedAnnotationClass.class));
+ assertFalse(isAnnotationDeclaredLocally(Order.class, SubNonInheritedAnnotationClass.class));
+ }
+
+ @Test
+ public void testIsAnnotationInherited() throws Exception {
+ // no class-level annotation
+ assertFalse(isAnnotationInherited(Transactional.class, NonAnnotatedInterface.class));
+ assertFalse(isAnnotationInherited(Transactional.class, NonAnnotatedClass.class));
+
+ // inherited class-level annotation; note: @Transactional is inherited
+ assertFalse(isAnnotationInherited(Transactional.class, InheritedAnnotationInterface.class));
+ // isAnnotationInherited() does not currently traverse interface
+ // hierarchies. Thus the following, though perhaps counter intuitive,
+ // must be false:
+ assertFalse(isAnnotationInherited(Transactional.class, SubInheritedAnnotationInterface.class));
+ assertFalse(isAnnotationInherited(Transactional.class, InheritedAnnotationClass.class));
+ assertTrue(isAnnotationInherited(Transactional.class, SubInheritedAnnotationClass.class));
+
+ // non-inherited class-level annotation; note: @Order is not inherited
+ assertFalse(isAnnotationInherited(Order.class, NonInheritedAnnotationInterface.class));
+ assertFalse(isAnnotationInherited(Order.class, SubNonInheritedAnnotationInterface.class));
+ assertFalse(isAnnotationInherited(Order.class, NonInheritedAnnotationClass.class));
+ assertFalse(isAnnotationInherited(Order.class, SubNonInheritedAnnotationClass.class));
+ }
+
+ @Test
+ public void getValueFromAnnotation() throws Exception {
+ Method method = SimpleFoo.class.getMethod("something", Object.class);
+ Order order = findAnnotation(method, Order.class);
+
+ assertEquals(1, AnnotationUtils.getValue(order, AnnotationUtils.VALUE));
+ assertEquals(1, AnnotationUtils.getValue(order));
+ }
+
+ @Test
+ public void getValueFromNonPublicAnnotation() throws Exception {
+ Method method = SimpleFoo.class.getMethod("something", Object.class);
+ Order order = findAnnotation(method, Order.class);
+
+ assertEquals(Ordered.LOWEST_PRECEDENCE, AnnotationUtils.getDefaultValue(order, AnnotationUtils.VALUE));
+ assertEquals(Ordered.LOWEST_PRECEDENCE, AnnotationUtils.getDefaultValue(order));
+ }
+
+ @Test
+ public void getDefaultValueFromAnnotation() throws Exception {
+ Method method = SimpleFoo.class.getMethod("something", Object.class);
+ Order order = findAnnotation(method, Order.class);
+
+ assertEquals(Ordered.LOWEST_PRECEDENCE, AnnotationUtils.getDefaultValue(order, AnnotationUtils.VALUE));
+ assertEquals(Ordered.LOWEST_PRECEDENCE, AnnotationUtils.getDefaultValue(order));
+ }
+
+ @Test
+ public void getDefaultValueFromNonPublicAnnotation() throws Exception {
+ Method method = ImplementsInterfaceWithAnnotatedMethod.class.getMethod("foo");
+ Order order = findAnnotation(method, Order.class);
+ assertNotNull(order);
+ }
+
+ @Test
+ public void findAnnotationFromInterfaceOnSuper() throws Exception {
+ Method method = SubOfImplementsInterfaceWithAnnotatedMethod.class.getMethod("foo");
+ Order order = findAnnotation(method, Order.class);
+ assertNotNull(order);
+ }
+
+ @Test
+ public void findAnnotationFromInterfaceWhenSuperDoesNotImplementMethod() throws Exception {
+ Method method = SubOfAbstractImplementsInterfaceWithAnnotatedMethod.class.getMethod("foo");
+ Order order = findAnnotation(method, Order.class);
+ assertNotNull(order);
+ }
+
+
+ @Component(value = "meta1")
+ @Retention(RetentionPolicy.RUNTIME)
+ @interface Meta1 {
+ }
+
+ @Component(value = "meta2")
+ @Retention(RetentionPolicy.RUNTIME)
+ @interface Meta2 {
+ }
+
+ @Meta1
+ @Component(value = "local")
+ @Meta2
+ static class HasLocalAndMetaComponentAnnotation {
+ }
+
+ public static interface AnnotatedInterface {
+
+ @Order(0)
+ void fromInterfaceImplementedByRoot();
+ }
+
+ public static class Root implements AnnotatedInterface {
+
+ @Order(27)
+ public void annotatedOnRoot() {
+
+ }
+
+ public void overrideToAnnotate() {
+
+ }
+
+ @Order(27)
+ public void overrideWithoutNewAnnotation() {
+
+ }
+
+ public void notAnnotated() {
+
+ }
+
+ @Override
+ public void fromInterfaceImplementedByRoot() {
+
+ }
+ }
+
+ public static class Leaf extends Root {
+
+ @Order(25)
+ public void annotatedOnLeaf() {
+
+ }
+
+ @Override
+ @Order(1)
+ public void overrideToAnnotate() {
+
+ }
+
+ @Override
+ public void overrideWithoutNewAnnotation() {
+
+ }
+ }
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Inherited
+ @interface Transactional {
+
+ }
+
+ public static abstract class Foo<T> {
+
+ @Order(1)
+ public abstract void something(T arg);
+ }
+
+ public static class SimpleFoo extends Foo<String> {
+
+ @Override
+ @Transactional
+ public void something(final String arg) {
+
+ }
+ }
+
+ @Transactional
+ public static interface InheritedAnnotationInterface {
+ }
+
+ public static interface SubInheritedAnnotationInterface extends InheritedAnnotationInterface {
+ }
+
+ @Order
+ public static interface NonInheritedAnnotationInterface {
+ }
+
+ public static interface SubNonInheritedAnnotationInterface extends NonInheritedAnnotationInterface {
+ }
+
+ public static class NonAnnotatedClass {
+ }
+
+ public static interface NonAnnotatedInterface {
+ }
+
+ @Transactional
+ public static class InheritedAnnotationClass {
+ }
+
+ public static class SubInheritedAnnotationClass extends InheritedAnnotationClass {
+ }
+
+ @Order
+ public static class NonInheritedAnnotationClass {
+ }
+
+ public static class SubNonInheritedAnnotationClass extends NonInheritedAnnotationClass {
+ }
+
+ @Transactional
+ public static class TransactionalClass {
+ }
+
+ @Order
+ public static class TransactionalAndOrderedClass {
+ }
+
+ public static class SubTransactionalAndOrderedClass extends TransactionalAndOrderedClass {
+ }
+
+ public static interface InterfaceWithAnnotatedMethod {
+
+ @Order
+ void foo();
+ }
+
+ public static class ImplementsInterfaceWithAnnotatedMethod implements InterfaceWithAnnotatedMethod {
+
+ @Override
+ public void foo() {
+ }
+ }
+
+ public static class SubOfImplementsInterfaceWithAnnotatedMethod extends ImplementsInterfaceWithAnnotatedMethod {
+
+ @Override
+ public void foo() {
+ }
+ }
+
+ public abstract static class AbstractDoesNotImplementInterfaceWithAnnotatedMethod implements
+ InterfaceWithAnnotatedMethod {
+ }
+
+ public static class SubOfAbstractImplementsInterfaceWithAnnotatedMethod extends
+ AbstractDoesNotImplementInterfaceWithAnnotatedMethod {
+
+ @Override
+ public void foo() {
+ }
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/convert/TypeDescriptorTests.java b/spring-core/src/test/java/org/springframework/core/convert/TypeDescriptorTests.java
new file mode 100644
index 00000000..7af9d19f
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/convert/TypeDescriptorTests.java
@@ -0,0 +1,890 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.convert;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Test;
+import org.springframework.core.MethodParameter;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author Keith Donald
+ * @author Andy Clement
+ * @author Phillip Webb
+ */
+@SuppressWarnings("rawtypes")
+public class TypeDescriptorTests {
+
+ public List<String> listOfString;
+
+ public List<List<String>> listOfListOfString = new ArrayList<List<String>>();
+
+ public List<List> listOfListOfUnknown = new ArrayList<List>();
+
+ public int[] intArray;
+
+ public List<String>[] arrayOfListOfString;
+
+ public List<Integer> listField = new ArrayList<Integer>();
+
+ public Map<String, Integer> mapField = new HashMap<String, Integer>();
+
+ public Map<String, List<Integer>> nestedMapField = new HashMap<String, List<Integer>>();
+
+ @Test
+ public void parameterPrimitive() throws Exception {
+ TypeDescriptor desc = new TypeDescriptor(new MethodParameter(getClass().getMethod("testParameterPrimitive", int.class), 0));
+ assertEquals(int.class, desc.getType());
+ assertEquals(Integer.class, desc.getObjectType());
+ assertEquals("int", desc.getName());
+ assertEquals("int", desc.toString());
+ assertTrue(desc.isPrimitive());
+ assertEquals(0, desc.getAnnotations().length);
+ assertFalse(desc.isCollection());
+ assertFalse(desc.isMap());
+ }
+
+ public void testParameterPrimitive(int primitive) {
+
+ }
+
+ @Test
+ public void parameterScalar() throws Exception {
+ TypeDescriptor desc = new TypeDescriptor(new MethodParameter(getClass().getMethod("testParameterScalar", String.class), 0));
+ assertEquals(String.class, desc.getType());
+ assertEquals(String.class, desc.getObjectType());
+ assertEquals("java.lang.String", desc.getName());
+ assertEquals("java.lang.String", desc.toString());
+ assertTrue(!desc.isPrimitive());
+ assertEquals(0, desc.getAnnotations().length);
+ assertFalse(desc.isCollection());
+ assertFalse(desc.isArray());
+ assertFalse(desc.isMap());
+ }
+
+ public void testParameterScalar(String value) {
+
+ }
+
+ @Test
+ public void parameterList() throws Exception {
+ MethodParameter methodParameter = new MethodParameter(getClass().getMethod("testParameterList", List.class), 0);
+ TypeDescriptor desc = new TypeDescriptor(methodParameter);
+ assertEquals(List.class, desc.getType());
+ assertEquals(List.class, desc.getObjectType());
+ assertEquals("java.util.List", desc.getName());
+ assertEquals("java.util.List<java.util.List<java.util.Map<java.lang.Integer, java.lang.Enum>>>", desc.toString());
+ assertTrue(!desc.isPrimitive());
+ assertEquals(0, desc.getAnnotations().length);
+ assertTrue(desc.isCollection());
+ assertFalse(desc.isArray());
+ assertEquals(List.class, desc.getElementTypeDescriptor().getType());
+ assertEquals(TypeDescriptor.nested(methodParameter, 1), desc.getElementTypeDescriptor());
+ assertEquals(TypeDescriptor.nested(methodParameter, 2), desc.getElementTypeDescriptor().getElementTypeDescriptor());
+ assertEquals(TypeDescriptor.nested(methodParameter, 3), desc.getElementTypeDescriptor().getElementTypeDescriptor().getMapValueTypeDescriptor());
+ assertEquals(Integer.class, desc.getElementTypeDescriptor().getElementTypeDescriptor().getMapKeyTypeDescriptor().getType());
+ assertEquals(Enum.class, desc.getElementTypeDescriptor().getElementTypeDescriptor().getMapValueTypeDescriptor().getType());
+ assertFalse(desc.isMap());
+ }
+
+ public void testParameterList(List<List<Map<Integer, Enum<?>>>> list) {
+
+ }
+
+ @Test
+ public void parameterListNoParamTypes() throws Exception {
+ MethodParameter methodParameter = new MethodParameter(getClass().getMethod("testParameterListNoParamTypes", List.class), 0);
+ TypeDescriptor desc = new TypeDescriptor(methodParameter);
+ assertEquals(List.class, desc.getType());
+ assertEquals(List.class, desc.getObjectType());
+ assertEquals("java.util.List", desc.getName());
+ assertEquals("java.util.List<?>", desc.toString());
+ assertTrue(!desc.isPrimitive());
+ assertEquals(0, desc.getAnnotations().length);
+ assertTrue(desc.isCollection());
+ assertFalse(desc.isArray());
+ assertNull(desc.getElementTypeDescriptor());
+ assertFalse(desc.isMap());
+ }
+
+ public void testParameterListNoParamTypes(List list) {
+
+ }
+
+ @Test
+ public void parameterArray() throws Exception {
+ MethodParameter methodParameter = new MethodParameter(getClass().getMethod("testParameterArray", Integer[].class), 0);
+ TypeDescriptor desc = new TypeDescriptor(methodParameter);
+ assertEquals(Integer[].class, desc.getType());
+ assertEquals(Integer[].class, desc.getObjectType());
+ assertEquals("java.lang.Integer[]", desc.getName());
+ assertEquals("java.lang.Integer[]", desc.toString());
+ assertTrue(!desc.isPrimitive());
+ assertEquals(0, desc.getAnnotations().length);
+ assertFalse(desc.isCollection());
+ assertTrue(desc.isArray());
+ assertEquals(Integer.class, desc.getElementTypeDescriptor().getType());
+ assertEquals(TypeDescriptor.valueOf(Integer.class), desc.getElementTypeDescriptor());
+ assertFalse(desc.isMap());
+ }
+
+ public void testParameterArray(Integer[] array) {
+
+ }
+
+ @Test
+ public void parameterMap() throws Exception {
+ MethodParameter methodParameter = new MethodParameter(getClass().getMethod("testParameterMap", Map.class), 0);
+ TypeDescriptor desc = new TypeDescriptor(methodParameter);
+ assertEquals(Map.class, desc.getType());
+ assertEquals(Map.class, desc.getObjectType());
+ assertEquals("java.util.Map", desc.getName());
+ assertEquals("java.util.Map<java.lang.Integer, java.util.List<java.lang.String>>", desc.toString());
+ assertTrue(!desc.isPrimitive());
+ assertEquals(0, desc.getAnnotations().length);
+ assertFalse(desc.isCollection());
+ assertFalse(desc.isArray());
+ assertTrue(desc.isMap());
+ assertEquals(TypeDescriptor.nested(methodParameter, 1), desc.getMapValueTypeDescriptor());
+ assertEquals(TypeDescriptor.nested(methodParameter, 2), desc.getMapValueTypeDescriptor().getElementTypeDescriptor());
+ assertEquals(Integer.class, desc.getMapKeyTypeDescriptor().getType());
+ assertEquals(List.class, desc.getMapValueTypeDescriptor().getType());
+ assertEquals(String.class, desc.getMapValueTypeDescriptor().getElementTypeDescriptor().getType());
+ }
+
+ public void testParameterMap(Map<Integer, List<String>> map) {
+
+ }
+
+ @Test
+ public void parameterAnnotated() throws Exception {
+ TypeDescriptor t1 = new TypeDescriptor(new MethodParameter(getClass().getMethod("testAnnotatedMethod", String.class), 0));
+ assertEquals(String.class, t1.getType());
+ assertEquals(1, t1.getAnnotations().length);
+ assertNotNull(t1.getAnnotation(ParameterAnnotation.class));
+ assertTrue(t1.hasAnnotation(ParameterAnnotation.class));
+ assertEquals(123, t1.getAnnotation(ParameterAnnotation.class).value());
+ }
+
+ @Target({ElementType.PARAMETER})
+ @Retention(RetentionPolicy.RUNTIME)
+ public @interface ParameterAnnotation {
+ int value();
+ }
+
+ public void testAnnotatedMethod(@ParameterAnnotation(123) String parameter) {
+
+ }
+
+ @Test
+ public void propertyComplex() throws Exception {
+ Property property = new Property(getClass(), getClass().getMethod("getComplexProperty"), getClass().getMethod("setComplexProperty", Map.class));
+ TypeDescriptor desc = new TypeDescriptor(property);
+ assertEquals(String.class, desc.getMapKeyTypeDescriptor().getType());
+ assertEquals(Integer.class, desc.getMapValueTypeDescriptor().getElementTypeDescriptor().getElementTypeDescriptor().getType());
+ }
+
+ public Map<String, List<List<Integer>>> getComplexProperty() {
+ return null;
+ }
+
+ public void setComplexProperty(Map<String, List<List<Integer>>> complexProperty) {
+
+ }
+
+ @Test
+ public void propertyGenericType() throws Exception {
+ GenericType<Integer> genericBean = new IntegerType();
+ Property property = new Property(getClass(), genericBean.getClass().getMethod("getProperty"), genericBean.getClass().getMethod("setProperty", Integer.class));
+ TypeDescriptor desc = new TypeDescriptor(property);
+ assertEquals(Integer.class, desc.getType());
+ }
+
+ @Test
+ public void propertyTypeCovariance() throws Exception {
+ GenericType<Number> genericBean = new NumberType();
+ Property property = new Property(getClass(), genericBean.getClass().getMethod("getProperty"), genericBean.getClass().getMethod("setProperty", Number.class));
+ TypeDescriptor desc = new TypeDescriptor(property);
+ assertEquals(Integer.class, desc.getType());
+ }
+
+ @Test
+ public void propertyGenericTypeList() throws Exception {
+ GenericType<Integer> genericBean = new IntegerType();
+ Property property = new Property(getClass(), genericBean.getClass().getMethod("getListProperty"), genericBean.getClass().getMethod("setListProperty", List.class));
+ TypeDescriptor desc = new TypeDescriptor(property);
+ assertEquals(List.class, desc.getType());
+ assertEquals(Integer.class, desc.getElementTypeDescriptor().getType());
+ }
+
+ public interface GenericType<T> {
+ T getProperty();
+
+ void setProperty(T t);
+
+ List<T> getListProperty();
+
+ void setListProperty(List<T> t);
+
+ }
+
+ public class IntegerType implements GenericType<Integer> {
+
+ @Override
+ public Integer getProperty() {
+ return null;
+ }
+
+ @Override
+ public void setProperty(Integer t) {
+ }
+
+ @Override
+ public List<Integer> getListProperty() {
+ return null;
+ }
+
+ @Override
+ public void setListProperty(List<Integer> t) {
+ }
+ }
+
+ public class NumberType implements GenericType<Number> {
+
+ @Override
+ public Integer getProperty() {
+ return null;
+ }
+
+ @Override
+ public void setProperty(Number t) {
+ }
+
+ @Override
+ public List<Number> getListProperty() {
+ return null;
+ }
+
+ @Override
+ public void setListProperty(List<Number> t) {
+ }
+ }
+
+ @Test
+ public void propertyGenericClassList() throws Exception {
+ IntegerClass genericBean = new IntegerClass();
+ Property property = new Property(genericBean.getClass(), genericBean.getClass().getMethod("getListProperty"), genericBean.getClass().getMethod("setListProperty", List.class));
+ TypeDescriptor desc = new TypeDescriptor(property);
+ assertEquals(List.class, desc.getType());
+ assertEquals(Integer.class, desc.getElementTypeDescriptor().getType());
+ assertNotNull(desc.getAnnotation(MethodAnnotation1.class));
+ assertTrue(desc.hasAnnotation(MethodAnnotation1.class));
+ }
+
+ public static class GenericClass<T> {
+
+ public T getProperty() {
+ return null;
+ }
+
+ public void setProperty(T t) {
+ }
+
+ @MethodAnnotation1
+ public List<T> getListProperty() {
+ return null;
+ }
+
+ public void setListProperty(List<T> t) {
+ }
+
+ }
+
+ public static class IntegerClass extends GenericClass<Integer> {
+
+ }
+
+ @Test
+ public void property() throws Exception {
+ Property property = new Property(getClass(), getClass().getMethod("getProperty"), getClass().getMethod("setProperty", Map.class));
+ TypeDescriptor desc = new TypeDescriptor(property);
+ assertEquals(Map.class, desc.getType());
+ assertEquals(Integer.class, desc.getMapKeyTypeDescriptor().getElementTypeDescriptor().getType());
+ assertEquals(Long.class, desc.getMapValueTypeDescriptor().getElementTypeDescriptor().getType());
+ assertNotNull(desc.getAnnotation(MethodAnnotation1.class));
+ assertNotNull(desc.getAnnotation(MethodAnnotation2.class));
+ assertNotNull(desc.getAnnotation(MethodAnnotation3.class));
+ }
+
+ @MethodAnnotation1
+ public Map<List<Integer>, List<Long>> getProperty() {
+ return property;
+ }
+
+ @MethodAnnotation2
+ public void setProperty(Map<List<Integer>, List<Long>> property) {
+ this.property = property;
+ }
+
+ @MethodAnnotation3
+ private Map<List<Integer>, List<Long>> property;
+
+ @Target({ElementType.METHOD})
+ @Retention(RetentionPolicy.RUNTIME)
+ public @interface MethodAnnotation1 {
+
+ }
+
+ @Target({ElementType.METHOD})
+ @Retention(RetentionPolicy.RUNTIME)
+ public @interface MethodAnnotation2 {
+
+ }
+
+ @Target({ElementType.FIELD})
+ @Retention(RetentionPolicy.RUNTIME)
+ public @interface MethodAnnotation3 {
+
+ }
+
+ @Test
+ public void fieldScalar() throws Exception {
+ TypeDescriptor typeDescriptor = new TypeDescriptor(getClass().getField("fieldScalar"));
+ assertFalse(typeDescriptor.isPrimitive());
+ assertFalse(typeDescriptor.isArray());
+ assertFalse(typeDescriptor.isCollection());
+ assertFalse(typeDescriptor.isMap());
+ assertEquals(Integer.class, typeDescriptor.getType());
+ assertEquals(Integer.class, typeDescriptor.getObjectType());
+ }
+
+ public Integer fieldScalar;
+
+ @Test
+ public void fieldList() throws Exception {
+ TypeDescriptor typeDescriptor = new TypeDescriptor(TypeDescriptorTests.class.getDeclaredField("listOfString"));
+ assertFalse(typeDescriptor.isArray());
+ assertEquals(List.class, typeDescriptor.getType());
+ assertEquals(String.class, typeDescriptor.getElementTypeDescriptor().getType());
+ assertEquals("java.util.List<java.lang.String>", typeDescriptor.toString());
+ }
+
+ @Test
+ public void fieldListOfListOfString() throws Exception {
+ TypeDescriptor typeDescriptor = new TypeDescriptor(TypeDescriptorTests.class.getDeclaredField("listOfListOfString"));
+ assertFalse(typeDescriptor.isArray());
+ assertEquals(List.class, typeDescriptor.getType());
+ assertEquals(List.class, typeDescriptor.getElementTypeDescriptor().getType());
+ assertEquals(String.class, typeDescriptor.getElementTypeDescriptor().getElementTypeDescriptor().getType());
+ assertEquals("java.util.List<java.util.List<java.lang.String>>", typeDescriptor.toString());
+ }
+
+ @Test
+ public void fieldListOfListUnknown() throws Exception {
+ TypeDescriptor typeDescriptor = new TypeDescriptor(TypeDescriptorTests.class.getDeclaredField("listOfListOfUnknown"));
+ assertFalse(typeDescriptor.isArray());
+ assertEquals(List.class, typeDescriptor.getType());
+ assertEquals(List.class, typeDescriptor.getElementTypeDescriptor().getType());
+ assertNull(typeDescriptor.getElementTypeDescriptor().getElementTypeDescriptor());
+ assertEquals("java.util.List<java.util.List<?>>", typeDescriptor.toString());
+ }
+
+ @Test
+ public void fieldArray() throws Exception {
+ TypeDescriptor typeDescriptor = new TypeDescriptor(TypeDescriptorTests.class.getDeclaredField("intArray"));
+ assertTrue(typeDescriptor.isArray());
+ assertEquals(Integer.TYPE,typeDescriptor.getElementTypeDescriptor().getType());
+ assertEquals("int[]",typeDescriptor.toString());
+ }
+
+ @Test
+ public void fieldComplexTypeDescriptor() throws Exception {
+ TypeDescriptor typeDescriptor = new TypeDescriptor(TypeDescriptorTests.class.getDeclaredField("arrayOfListOfString"));
+ assertTrue(typeDescriptor.isArray());
+ assertEquals(List.class,typeDescriptor.getElementTypeDescriptor().getType());
+ assertEquals(String.class, typeDescriptor.getElementTypeDescriptor().getElementTypeDescriptor().getType());
+ assertEquals("java.util.List[]",typeDescriptor.toString());
+ }
+
+ @Test
+ public void fieldComplexTypeDescriptor2() throws Exception {
+ TypeDescriptor typeDescriptor = new TypeDescriptor(TypeDescriptorTests.class.getDeclaredField("nestedMapField"));
+ assertTrue(typeDescriptor.isMap());
+ assertEquals(String.class,typeDescriptor.getMapKeyTypeDescriptor().getType());
+ assertEquals(List.class, typeDescriptor.getMapValueTypeDescriptor().getType());
+ assertEquals(Integer.class, typeDescriptor.getMapValueTypeDescriptor().getElementTypeDescriptor().getType());
+ assertEquals("java.util.Map<java.lang.String, java.util.List<java.lang.Integer>>", typeDescriptor.toString());
+ }
+
+ @Test
+ public void fieldMap() throws Exception {
+ TypeDescriptor desc = new TypeDescriptor(TypeDescriptorTests.class.getField("fieldMap"));
+ assertTrue(desc.isMap());
+ assertEquals(Integer.class, desc.getMapKeyTypeDescriptor().getElementTypeDescriptor().getType());
+ assertEquals(Long.class, desc.getMapValueTypeDescriptor().getElementTypeDescriptor().getType());
+ }
+
+ public Map<List<Integer>, List<Long>> fieldMap;
+
+ @Test
+ public void fieldAnnotated() throws Exception {
+ TypeDescriptor typeDescriptor = new TypeDescriptor(getClass().getField("fieldAnnotated"));
+ assertEquals(1, typeDescriptor.getAnnotations().length);
+ assertNotNull(typeDescriptor.getAnnotation(FieldAnnotation.class));
+ }
+
+ @FieldAnnotation
+ public List<String> fieldAnnotated;
+
+ @Target({ElementType.FIELD})
+ @Retention(RetentionPolicy.RUNTIME)
+ public @interface FieldAnnotation {
+
+ }
+
+ @Test
+ public void valueOfScalar() {
+ TypeDescriptor typeDescriptor = TypeDescriptor.valueOf(Integer.class);
+ assertFalse(typeDescriptor.isPrimitive());
+ assertFalse(typeDescriptor.isArray());
+ assertFalse(typeDescriptor.isCollection());
+ assertFalse(typeDescriptor.isMap());
+ assertEquals(Integer.class, typeDescriptor.getType());
+ assertEquals(Integer.class, typeDescriptor.getObjectType());
+ }
+
+ @Test
+ public void valueOfPrimitive() {
+ TypeDescriptor typeDescriptor = TypeDescriptor.valueOf(int.class);
+ assertTrue(typeDescriptor.isPrimitive());
+ assertFalse(typeDescriptor.isArray());
+ assertFalse(typeDescriptor.isCollection());
+ assertFalse(typeDescriptor.isMap());
+ assertEquals(Integer.TYPE, typeDescriptor.getType());
+ assertEquals(Integer.class, typeDescriptor.getObjectType());
+ }
+
+ @Test
+ public void valueOfArray() throws Exception {
+ TypeDescriptor typeDescriptor = TypeDescriptor.valueOf(int[].class);
+ assertTrue(typeDescriptor.isArray());
+ assertFalse(typeDescriptor.isCollection());
+ assertFalse(typeDescriptor.isMap());
+ assertEquals(Integer.TYPE, typeDescriptor.getElementTypeDescriptor().getType());
+ }
+
+ @Test
+ public void valueOfCollection() throws Exception {
+ TypeDescriptor typeDescriptor = TypeDescriptor.valueOf(Collection.class);
+ assertTrue(typeDescriptor.isCollection());
+ assertFalse(typeDescriptor.isArray());
+ assertFalse(typeDescriptor.isMap());
+ assertNull(typeDescriptor.getElementTypeDescriptor());
+ }
+
+ @Test
+ public void forObject() {
+ TypeDescriptor desc = TypeDescriptor.forObject("3");
+ assertEquals(String.class, desc.getType());
+ }
+
+ @Test
+ public void forObjectNullTypeDescriptor() {
+ TypeDescriptor desc = TypeDescriptor.forObject(null);
+ assertNull(desc);
+ }
+
+ @Test
+ public void nestedMethodParameterType2Levels() throws Exception {
+ TypeDescriptor t1 = TypeDescriptor.nested(new MethodParameter(getClass().getMethod("test2", List.class), 0), 2);
+ assertEquals(String.class, t1.getType());
+ }
+
+ @Test
+ public void nestedMethodParameterTypeMap() throws Exception {
+ TypeDescriptor t1 = TypeDescriptor.nested(new MethodParameter(getClass().getMethod("test3", Map.class), 0), 1);
+ assertEquals(String.class, t1.getType());
+ }
+
+ @Test
+ public void nestedMethodParameterTypeMapTwoLevels() throws Exception {
+ TypeDescriptor t1 = TypeDescriptor.nested(new MethodParameter(getClass().getMethod("test4", List.class), 0), 2);
+ assertEquals(String.class, t1.getType());
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void nestedMethodParameterNot1NestedLevel() throws Exception {
+ TypeDescriptor.nested(new MethodParameter(getClass().getMethod("test4", List.class), 0, 2), 2);
+ }
+
+ @Test(expected=IllegalStateException.class)
+ public void nestedTooManyLevels() throws Exception {
+ TypeDescriptor t1 = TypeDescriptor.nested(new MethodParameter(getClass().getMethod("test4", List.class), 0), 3);
+ assertEquals(String.class, t1.getType());
+ }
+
+ @Test(expected=IllegalStateException.class)
+ public void nestedMethodParameterTypeNotNestable() throws Exception {
+ TypeDescriptor.nested(new MethodParameter(getClass().getMethod("test5", String.class), 0), 2);
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void nestedMethodParameterTypeInvalidNestingLevel() throws Exception {
+ TypeDescriptor.nested(new MethodParameter(getClass().getMethod("test5", String.class), 0, 2), 2);
+ }
+
+ public void test1(List<String> param1) {
+
+ }
+
+ public void test2(List<List<String>> param1) {
+
+ }
+
+ public void test3(Map<Integer, String> param1) {
+
+ }
+
+ public void test4(List<Map<Integer, String>> param1) {
+
+ }
+
+ public void test5(String param1) {
+
+ }
+
+ @Test
+ public void nestedNotParameterized() throws Exception {
+ TypeDescriptor t1 = TypeDescriptor.nested(new MethodParameter(getClass().getMethod("test6", List.class), 0), 1);
+ assertEquals(List.class,t1.getType());
+ assertEquals("java.util.List<?>", t1.toString());
+ TypeDescriptor t2 = TypeDescriptor.nested(new MethodParameter(getClass().getMethod("test6", List.class), 0), 2);
+ assertNull(t2);
+ }
+
+ public void test6(List<List> param1) {
+
+ }
+
+ @Test
+ public void nestedFieldTypeMapTwoLevels() throws Exception {
+ TypeDescriptor t1 = TypeDescriptor.nested(getClass().getField("test4"), 2);
+ assertEquals(String.class, t1.getType());
+ }
+
+ public List<Map<Integer, String>> test4;
+
+ @Test
+ public void nestedPropertyTypeMapTwoLevels() throws Exception {
+ Property property = new Property(getClass(), getClass().getMethod("getTest4"), getClass().getMethod("setTest4", List.class));
+ TypeDescriptor t1 = TypeDescriptor.nested(property, 2);
+ assertEquals(String.class, t1.getType());
+ }
+
+ public List<Map<Integer, String>> getTest4() {
+ return null;
+ }
+
+ public void setTest4(List<Map<Integer, String>> test4) {
+
+ }
+
+ @Test
+ public void collection() {
+ TypeDescriptor desc = TypeDescriptor.collection(List.class, TypeDescriptor.valueOf(Integer.class));
+ assertEquals(List.class, desc.getType());
+ assertEquals(List.class, desc.getObjectType());
+ assertEquals("java.util.List", desc.getName());
+ assertEquals("java.util.List<java.lang.Integer>", desc.toString());
+ assertTrue(!desc.isPrimitive());
+ assertEquals(0, desc.getAnnotations().length);
+ assertTrue(desc.isCollection());
+ assertFalse(desc.isArray());
+ assertEquals(Integer.class, desc.getElementTypeDescriptor().getType());
+ assertEquals(TypeDescriptor.valueOf(Integer.class), desc.getElementTypeDescriptor());
+ assertFalse(desc.isMap());
+ }
+
+ @Test
+ public void collectionNested() {
+ TypeDescriptor desc = TypeDescriptor.collection(List.class, TypeDescriptor.collection(List.class, TypeDescriptor.valueOf(Integer.class)));
+ assertEquals(List.class, desc.getType());
+ assertEquals(List.class, desc.getObjectType());
+ assertEquals("java.util.List", desc.getName());
+ assertEquals("java.util.List<java.util.List<java.lang.Integer>>", desc.toString());
+ assertTrue(!desc.isPrimitive());
+ assertEquals(0, desc.getAnnotations().length);
+ assertTrue(desc.isCollection());
+ assertFalse(desc.isArray());
+ assertEquals(List.class, desc.getElementTypeDescriptor().getType());
+ assertEquals(TypeDescriptor.valueOf(Integer.class), desc.getElementTypeDescriptor().getElementTypeDescriptor());
+ assertFalse(desc.isMap());
+ }
+
+ @Test
+ public void map() {
+ TypeDescriptor desc = TypeDescriptor.map(Map.class, TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(Integer.class));
+ assertEquals(Map.class, desc.getType());
+ assertEquals(Map.class, desc.getObjectType());
+ assertEquals("java.util.Map", desc.getName());
+ assertEquals("java.util.Map<java.lang.String, java.lang.Integer>", desc.toString());
+ assertTrue(!desc.isPrimitive());
+ assertEquals(0, desc.getAnnotations().length);
+ assertFalse(desc.isCollection());
+ assertFalse(desc.isArray());
+ assertTrue(desc.isMap());
+ assertEquals(String.class, desc.getMapKeyTypeDescriptor().getType());
+ assertEquals(Integer.class, desc.getMapValueTypeDescriptor().getType());
+ }
+
+ @Test
+ public void mapNested() {
+ TypeDescriptor desc = TypeDescriptor.map(Map.class, TypeDescriptor.valueOf(String.class),
+ TypeDescriptor.map(Map.class, TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(Integer.class)));
+ assertEquals(Map.class, desc.getType());
+ assertEquals(Map.class, desc.getObjectType());
+ assertEquals("java.util.Map", desc.getName());
+ assertEquals("java.util.Map<java.lang.String, java.util.Map<java.lang.String, java.lang.Integer>>", desc.toString());
+ assertTrue(!desc.isPrimitive());
+ assertEquals(0, desc.getAnnotations().length);
+ assertFalse(desc.isCollection());
+ assertFalse(desc.isArray());
+ assertTrue(desc.isMap());
+ assertEquals(String.class, desc.getMapKeyTypeDescriptor().getType());
+ assertEquals(String.class, desc.getMapValueTypeDescriptor().getMapKeyTypeDescriptor().getType());
+ assertEquals(Integer.class, desc.getMapValueTypeDescriptor().getMapValueTypeDescriptor().getType());
+ }
+
+ @Test
+ public void narrow() {
+ TypeDescriptor desc = TypeDescriptor.valueOf(Number.class);
+ Integer value = new Integer(3);
+ desc = desc.narrow(value);
+ assertEquals(Integer.class, desc.getType());
+ }
+
+ @Test
+ public void elementType() {
+ TypeDescriptor desc = TypeDescriptor.valueOf(List.class);
+ Integer value = new Integer(3);
+ desc = desc.elementTypeDescriptor(value);
+ assertEquals(Integer.class, desc.getType());
+ }
+
+ @Test
+ public void elementTypePreserveContext() throws Exception {
+ TypeDescriptor desc = new TypeDescriptor(getClass().getField("listPreserveContext"));
+ assertEquals(Integer.class, desc.getElementTypeDescriptor().getElementTypeDescriptor().getType());
+ List<Integer> value = new ArrayList<Integer>(3);
+ desc = desc.elementTypeDescriptor(value);
+ assertEquals(Integer.class, desc.getElementTypeDescriptor().getType());
+ assertNotNull(desc.getAnnotation(FieldAnnotation.class));
+ }
+
+ @FieldAnnotation
+ public List<List<Integer>> listPreserveContext;
+
+ @Test
+ public void mapKeyType() {
+ TypeDescriptor desc = TypeDescriptor.valueOf(Map.class);
+ Integer value = new Integer(3);
+ desc = desc.getMapKeyTypeDescriptor(value);
+ assertEquals(Integer.class, desc.getType());
+ }
+
+ @Test
+ public void mapKeyTypePreserveContext() throws Exception {
+ TypeDescriptor desc = new TypeDescriptor(getClass().getField("mapPreserveContext"));
+ assertEquals(Integer.class, desc.getMapKeyTypeDescriptor().getElementTypeDescriptor().getType());
+ List<Integer> value = new ArrayList<Integer>(3);
+ desc = desc.getMapKeyTypeDescriptor(value);
+ assertEquals(Integer.class, desc.getElementTypeDescriptor().getType());
+ assertNotNull(desc.getAnnotation(FieldAnnotation.class));
+ }
+
+ @FieldAnnotation
+ public Map<List<Integer>, List<Integer>> mapPreserveContext;
+
+ @Test
+ public void mapValueType() {
+ TypeDescriptor desc = TypeDescriptor.valueOf(Map.class);
+ Integer value = new Integer(3);
+ desc = desc.getMapValueTypeDescriptor(value);
+ assertEquals(Integer.class, desc.getType());
+ }
+
+ @Test
+ public void mapValueTypePreserveContext() throws Exception {
+ TypeDescriptor desc = new TypeDescriptor(getClass().getField("mapPreserveContext"));
+ assertEquals(Integer.class, desc.getMapValueTypeDescriptor().getElementTypeDescriptor().getType());
+ List<Integer> value = new ArrayList<Integer>(3);
+ desc = desc.getMapValueTypeDescriptor(value);
+ assertEquals(Integer.class, desc.getElementTypeDescriptor().getType());
+ assertNotNull(desc.getAnnotation(FieldAnnotation.class));
+ }
+
+ @Test
+ public void equals() throws Exception {
+ TypeDescriptor t1 = TypeDescriptor.valueOf(String.class);
+ TypeDescriptor t2 = TypeDescriptor.valueOf(String.class);
+ TypeDescriptor t3 = TypeDescriptor.valueOf(Date.class);
+ TypeDescriptor t4 = TypeDescriptor.valueOf(Date.class);
+ TypeDescriptor t5 = TypeDescriptor.valueOf(List.class);
+ TypeDescriptor t6 = TypeDescriptor.valueOf(List.class);
+ TypeDescriptor t7 = TypeDescriptor.valueOf(Map.class);
+ TypeDescriptor t8 = TypeDescriptor.valueOf(Map.class);
+ assertEquals(t1, t2);
+ assertEquals(t3, t4);
+ assertEquals(t5, t6);
+ assertEquals(t7, t8);
+
+ TypeDescriptor t9 = new TypeDescriptor(getClass().getField("listField"));
+ TypeDescriptor t10 = new TypeDescriptor(getClass().getField("listField"));
+ assertEquals(t9, t10);
+
+ TypeDescriptor t11 = new TypeDescriptor(getClass().getField("mapField"));
+ TypeDescriptor t12 = new TypeDescriptor(getClass().getField("mapField"));
+ assertEquals(t11, t12);
+ }
+
+ @Test
+ public void isAssignableTypes() {
+ assertTrue(TypeDescriptor.valueOf(Integer.class).isAssignableTo(TypeDescriptor.valueOf(Number.class)));
+ assertFalse(TypeDescriptor.valueOf(Number.class).isAssignableTo(TypeDescriptor.valueOf(Integer.class)));
+ assertFalse(TypeDescriptor.valueOf(String.class).isAssignableTo(TypeDescriptor.valueOf(String[].class)));
+ }
+
+ @Test
+ public void isAssignableElementTypes() throws Exception {
+ assertTrue(new TypeDescriptor(getClass().getField("listField")).isAssignableTo(new TypeDescriptor(getClass().getField("listField"))));
+ assertTrue(new TypeDescriptor(getClass().getField("notGenericList")).isAssignableTo(new TypeDescriptor(getClass().getField("listField"))));
+ assertTrue(new TypeDescriptor(getClass().getField("listField")).isAssignableTo(new TypeDescriptor(getClass().getField("notGenericList"))));
+ assertFalse(new TypeDescriptor(getClass().getField("isAssignableElementTypes")).isAssignableTo(new TypeDescriptor(getClass().getField("listField"))));
+ assertTrue(TypeDescriptor.valueOf(List.class).isAssignableTo(new TypeDescriptor(getClass().getField("listField"))));
+ }
+
+ public List notGenericList;
+
+ public List<Number> isAssignableElementTypes;
+
+ @Test
+ public void isAssignableMapKeyValueTypes() throws Exception {
+ assertTrue(new TypeDescriptor(getClass().getField("mapField")).isAssignableTo(new TypeDescriptor(getClass().getField("mapField"))));
+ assertTrue(new TypeDescriptor(getClass().getField("notGenericMap")).isAssignableTo(new TypeDescriptor(getClass().getField("mapField"))));
+ assertTrue(new TypeDescriptor(getClass().getField("mapField")).isAssignableTo(new TypeDescriptor(getClass().getField("notGenericMap"))));
+ assertFalse(new TypeDescriptor(getClass().getField("isAssignableMapKeyValueTypes")).isAssignableTo(new TypeDescriptor(getClass().getField("mapField"))));
+ assertTrue(TypeDescriptor.valueOf(Map.class).isAssignableTo(new TypeDescriptor(getClass().getField("mapField"))));
+ }
+
+ public Map notGenericMap;
+
+ public Map<CharSequence, Number> isAssignableMapKeyValueTypes;
+
+ @Test
+ public void testUpCast() throws Exception {
+ Property property = new Property(getClass(), getClass().getMethod("getProperty"),
+ getClass().getMethod("setProperty", Map.class));
+ TypeDescriptor typeDescriptor = new TypeDescriptor(property);
+ TypeDescriptor upCast = typeDescriptor.upcast(Object.class);
+ assertTrue(upCast.getAnnotation(MethodAnnotation1.class) != null);
+ }
+
+ @Test
+ public void testUpCastNotSuper() throws Exception {
+ Property property = new Property(getClass(), getClass().getMethod("getProperty"),
+ getClass().getMethod("setProperty", Map.class));
+ TypeDescriptor typeDescriptor = new TypeDescriptor(property);
+ try {
+ typeDescriptor.upcast(Collection.class);
+ fail("Did not throw");
+ } catch(IllegalArgumentException e) {
+ assertEquals("interface java.util.Map is not assignable to interface java.util.Collection", e.getMessage());
+ }
+ }
+
+ @Test
+ public void elementTypeForCollectionSubclass() throws Exception {
+ @SuppressWarnings("serial")
+ class CustomSet extends HashSet<String> {
+ }
+
+ assertEquals(TypeDescriptor.valueOf(CustomSet.class).getElementTypeDescriptor(), TypeDescriptor.valueOf(String.class));
+ assertEquals(TypeDescriptor.forObject(new CustomSet()).getElementTypeDescriptor(), TypeDescriptor.valueOf(String.class));
+ }
+
+ @Test
+ public void elementTypeForMapSubclass() throws Exception {
+ @SuppressWarnings("serial")
+ class CustomMap extends HashMap<String, Integer> {
+ }
+
+ assertEquals(TypeDescriptor.valueOf(CustomMap.class).getMapKeyTypeDescriptor(), TypeDescriptor.valueOf(String.class));
+ assertEquals(TypeDescriptor.valueOf(CustomMap.class).getMapValueTypeDescriptor(), TypeDescriptor.valueOf(Integer.class));
+ assertEquals(TypeDescriptor.forObject(new CustomMap()).getMapKeyTypeDescriptor(), TypeDescriptor.valueOf(String.class));
+ assertEquals(TypeDescriptor.forObject(new CustomMap()).getMapValueTypeDescriptor(), TypeDescriptor.valueOf(Integer.class));
+ }
+
+ @Test
+ public void createMapArray() throws Exception {
+ TypeDescriptor mapType = TypeDescriptor.map(LinkedHashMap.class, TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(Integer.class));
+ TypeDescriptor arrayType = TypeDescriptor.array(mapType);
+ assertEquals(arrayType.getType(), LinkedHashMap[].class);
+ assertEquals(arrayType.getElementTypeDescriptor(), mapType);
+ }
+
+
+ @Test
+ public void createStringArray() throws Exception {
+ TypeDescriptor arrayType = TypeDescriptor.array(TypeDescriptor.valueOf(String.class));
+ assertEquals(arrayType, TypeDescriptor.valueOf(String[].class));
+ }
+
+ @Test
+ public void createNullArray() throws Exception {
+ assertNull(TypeDescriptor.array(null));
+ }
+
+ @Test
+ public void serializable() throws Exception {
+ TypeDescriptor typeDescriptor = TypeDescriptor.forObject("");
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ObjectOutputStream outputStream = new ObjectOutputStream(out);
+ outputStream.writeObject(typeDescriptor);
+ ObjectInputStream inputStream = new ObjectInputStream(new ByteArrayInputStream(
+ out.toByteArray()));
+ TypeDescriptor readObject = (TypeDescriptor) inputStream.readObject();
+ assertThat(readObject, equalTo(typeDescriptor));
+ }
+}
diff --git a/spring-core/src/test/java/org/springframework/core/convert/converter/ConvertingComparatorTests.java b/spring-core/src/test/java/org/springframework/core/convert/converter/ConvertingComparatorTests.java
new file mode 100644
index 00000000..4cadfe74
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/convert/converter/ConvertingComparatorTests.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.convert.converter;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.junit.Test;
+
+import org.springframework.core.convert.ConversionService;
+import org.springframework.core.convert.support.DefaultConversionService;
+import org.springframework.util.comparator.ComparableComparator;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+/**
+ * Tests for {@link ConvertingComparator}.
+ *
+ * @author Phillip Webb
+ */
+public class ConvertingComparatorTests {
+
+ private final StringToInteger converter = new StringToInteger();
+
+ private final ConversionService conversionService = new DefaultConversionService();
+
+ private final TestComparator comparator = new TestComparator();
+
+ @Test(expected=IllegalArgumentException.class)
+ public void shouldThrowOnNullComparator() throws Exception {
+ new ConvertingComparator<String, Integer>(null, this.converter);
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void shouldThrowOnNullConverter() throws Exception {
+ new ConvertingComparator<String, Integer>(this.comparator, null);
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void shouldThrowOnNullConversionService() throws Exception {
+ new ConvertingComparator<String, Integer>(this.comparator, null, Integer.class);
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void shouldThrowOnNullType() throws Exception {
+ new ConvertingComparator<String, Integer>(this.comparator,
+ this.conversionService, null);
+ }
+
+ @Test
+ public void shouldUseConverterOnCompare() throws Exception {
+ ConvertingComparator<String, Integer> convertingComparator = new ConvertingComparator<String, Integer>(
+ this.comparator, this.converter);
+ testConversion(convertingComparator);
+ }
+
+ @Test
+ public void shouldUseConversionServiceOnCompare() throws Exception {
+ ConvertingComparator<String, Integer> convertingComparator = new ConvertingComparator<String, Integer>(
+ comparator, conversionService, Integer.class);
+ testConversion(convertingComparator);
+ }
+
+ @Test
+ public void shouldGetForConverter() throws Exception {
+ testConversion(new ConvertingComparator<String, Integer>(comparator, converter));
+ }
+
+ private void testConversion(ConvertingComparator<String, Integer> convertingComparator) {
+ assertThat(convertingComparator.compare("0", "0"), is(0));
+ assertThat(convertingComparator.compare("0", "1"), is(-1));
+ assertThat(convertingComparator.compare("1", "0"), is(1));
+ comparator.assertCalled();
+ }
+
+ @Test
+ public void shouldGetMapEntryKeys() throws Exception {
+ ArrayList<Entry<String, Integer>> list = createReverseOrderMapEntryList();
+ Comparator<Map.Entry<String, Integer>> comparator = ConvertingComparator.mapEntryKeys(new ComparableComparator<String>());
+ Collections.sort(list, comparator);
+ assertThat(list.get(0).getKey(), is("a"));
+ }
+
+ @Test
+ public void shouldGetMapEntryValues() throws Exception {
+ ArrayList<Entry<String, Integer>> list = createReverseOrderMapEntryList();
+ Comparator<Map.Entry<String, Integer>> comparator = ConvertingComparator.mapEntryValues(new ComparableComparator<Integer>());
+ Collections.sort(list, comparator);
+ assertThat(list.get(0).getValue(), is(1));
+ }
+
+ private ArrayList<Entry<String, Integer>> createReverseOrderMapEntryList() {
+ Map<String, Integer> map = new LinkedHashMap<String, Integer>();
+ map.put("b", 2);
+ map.put("a", 1);
+ ArrayList<Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(
+ map.entrySet());
+ assertThat(list.get(0).getKey(), is("b"));
+ return list;
+ }
+
+ private static class StringToInteger implements Converter<String, Integer> {
+
+ @Override
+ public Integer convert(String source) {
+ return new Integer(source);
+ }
+
+ }
+
+
+ private static class TestComparator extends ComparableComparator<Integer> {
+
+ private boolean called;
+
+ @Override
+ public int compare(Integer o1, Integer o2) {
+ assertThat(o1, instanceOf(Integer.class));
+ assertThat(o2, instanceOf(Integer.class));
+ this.called = true;
+ return super.compare(o1, o2);
+ };
+
+ public void assertCalled() {
+ assertThat(this.called, is(true));
+ }
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/convert/support/CollectionToCollectionConverterTests.java b/spring-core/src/test/java/org/springframework/core/convert/support/CollectionToCollectionConverterTests.java
new file mode 100644
index 00000000..00bf054a
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/convert/support/CollectionToCollectionConverterTests.java
@@ -0,0 +1,338 @@
+/*
+ * Copyright 2002-2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.convert.support;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Vector;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.springframework.core.convert.ConversionFailedException;
+import org.springframework.core.convert.ConverterNotFoundException;
+import org.springframework.core.convert.TypeDescriptor;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.core.io.Resource;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author Keith Donald
+ * @author Juergen Hoeller
+ * @author Stephane Nicoll
+ */
+public class CollectionToCollectionConverterTests {
+
+ private GenericConversionService conversionService = new GenericConversionService();
+
+
+ @Before
+ public void setUp() {
+ conversionService.addConverter(new CollectionToCollectionConverter(conversionService));
+ }
+
+
+ @Test
+ public void scalarList() throws Exception {
+ List<String> list = new ArrayList<String>();
+ list.add("9");
+ list.add("37");
+ TypeDescriptor sourceType = TypeDescriptor.forObject(list);
+ TypeDescriptor targetType = new TypeDescriptor(getClass().getField("scalarListTarget"));
+ assertTrue(conversionService.canConvert(sourceType, targetType));
+ try {
+ conversionService.convert(list, sourceType, targetType);
+ }
+ catch (ConversionFailedException ex) {
+ assertTrue(ex.getCause() instanceof ConverterNotFoundException);
+ }
+ conversionService.addConverterFactory(new StringToNumberConverterFactory());
+ assertTrue(conversionService.canConvert(sourceType, targetType));
+ @SuppressWarnings("unchecked")
+ List<String> result = (List<String>) conversionService.convert(list, sourceType, targetType);
+ assertFalse(list.equals(result));
+ assertEquals(9, result.get(0));
+ assertEquals(37, result.get(1));
+ }
+
+ @Test
+ public void emptyListToList() throws Exception {
+ conversionService.addConverter(new CollectionToCollectionConverter(conversionService));
+ conversionService.addConverterFactory(new StringToNumberConverterFactory());
+ List<String> list = new ArrayList<String>();
+ TypeDescriptor sourceType = TypeDescriptor.forObject(list);
+ TypeDescriptor targetType = new TypeDescriptor(getClass().getField("emptyListTarget"));
+ assertTrue(conversionService.canConvert(sourceType, targetType));
+ assertEquals(list, conversionService.convert(list, sourceType, targetType));
+ }
+
+ @Test
+ public void emptyListToListDifferentTargetType() throws Exception {
+ conversionService.addConverter(new CollectionToCollectionConverter(conversionService));
+ conversionService.addConverterFactory(new StringToNumberConverterFactory());
+ List<String> list = new ArrayList<String>();
+ TypeDescriptor sourceType = TypeDescriptor.forObject(list);
+ TypeDescriptor targetType = new TypeDescriptor(getClass().getField("emptyListDifferentTarget"));
+ assertTrue(conversionService.canConvert(sourceType, targetType));
+ @SuppressWarnings("unchecked")
+ LinkedList<Integer> result = (LinkedList<Integer>) conversionService.convert(list, sourceType, targetType);
+ assertEquals(LinkedList.class, result.getClass());
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void collectionToObjectInteraction() throws Exception {
+ List<List<String>> list = new ArrayList<List<String>>();
+ list.add(Arrays.asList("9", "12"));
+ list.add(Arrays.asList("37", "23"));
+ conversionService.addConverter(new CollectionToObjectConverter(conversionService));
+ assertTrue(conversionService.canConvert(List.class, List.class));
+ assertSame(list, conversionService.convert(list, List.class));
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void arrayCollectionToObjectInteraction() throws Exception {
+ List<String>[] array = new List[2];
+ array[0] = Arrays.asList("9", "12");
+ array[1] = Arrays.asList("37", "23");
+ conversionService.addConverter(new ArrayToCollectionConverter(conversionService));
+ conversionService.addConverter(new CollectionToObjectConverter(conversionService));
+ assertTrue(conversionService.canConvert(String[].class, List.class));
+ assertEquals(Arrays.asList(array), conversionService.convert(array, List.class));
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void objectToCollection() throws Exception {
+ List<List<String>> list = new ArrayList<List<String>>();
+ list.add(Arrays.asList("9", "12"));
+ list.add(Arrays.asList("37", "23"));
+ conversionService.addConverterFactory(new StringToNumberConverterFactory());
+ conversionService.addConverter(new ObjectToCollectionConverter(conversionService));
+ conversionService.addConverter(new CollectionToObjectConverter(conversionService));
+ TypeDescriptor sourceType = TypeDescriptor.forObject(list);
+ TypeDescriptor targetType = new TypeDescriptor(getClass().getField("objectToCollection"));
+ assertTrue(conversionService.canConvert(sourceType, targetType));
+ List<List<List<Integer>>> result = (List<List<List<Integer>>>) conversionService.convert(list, sourceType, targetType);
+ assertEquals((Integer) 9, result.get(0).get(0).get(0));
+ assertEquals((Integer) 12, result.get(0).get(1).get(0));
+ assertEquals((Integer) 37, result.get(1).get(0).get(0));
+ assertEquals((Integer) 23, result.get(1).get(1).get(0));
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void stringToCollection() throws Exception {
+ List<List<String>> list = new ArrayList<List<String>>();
+ list.add(Arrays.asList("9,12"));
+ list.add(Arrays.asList("37,23"));
+ conversionService.addConverterFactory(new StringToNumberConverterFactory());
+ conversionService.addConverter(new StringToCollectionConverter(conversionService));
+ conversionService.addConverter(new ObjectToCollectionConverter(conversionService));
+ conversionService.addConverter(new CollectionToObjectConverter(conversionService));
+ TypeDescriptor sourceType = TypeDescriptor.forObject(list);
+ TypeDescriptor targetType = new TypeDescriptor(getClass().getField("objectToCollection"));
+ assertTrue(conversionService.canConvert(sourceType, targetType));
+ List<List<List<Integer>>> result = (List<List<List<Integer>>>) conversionService.convert(list, sourceType, targetType);
+ assertEquals((Integer) 9, result.get(0).get(0).get(0));
+ assertEquals((Integer) 12, result.get(0).get(0).get(1));
+ assertEquals((Integer) 37, result.get(1).get(0).get(0));
+ assertEquals((Integer) 23, result.get(1).get(0).get(1));
+ }
+
+ @Test
+ public void convertEmptyVector_shouldReturnEmptyArrayList() {
+ Vector<String> vector = new Vector<String>();
+ vector.add("Element");
+ testCollectionConversionToArrayList(vector);
+ }
+
+ @Test
+ public void convertNonEmptyVector_shouldReturnNonEmptyArrayList() {
+ Vector<String> vector = new Vector<String>();
+ vector.add("Element");
+ testCollectionConversionToArrayList(vector);
+ }
+
+ @Test
+ public void testCollectionsEmptyList() throws Exception {
+ CollectionToCollectionConverter converter = new CollectionToCollectionConverter(new GenericConversionService());
+ TypeDescriptor type = new TypeDescriptor(getClass().getField("list"));
+ converter.convert(list, type, TypeDescriptor.valueOf(Class.forName("java.util.Collections$EmptyList")));
+ }
+
+ @SuppressWarnings("rawtypes")
+ private void testCollectionConversionToArrayList(Collection<String> aSource) {
+ Object myConverted = (new CollectionToCollectionConverter(new GenericConversionService())).convert(
+ aSource, TypeDescriptor.forObject(aSource), TypeDescriptor.forObject(new ArrayList()));
+ assertTrue(myConverted instanceof ArrayList<?>);
+ assertEquals(aSource.size(), ((ArrayList<?>) myConverted).size());
+ }
+
+ @Test
+ public void listToCollectionNoCopyRequired() throws NoSuchFieldException {
+ List<?> input = new ArrayList<String>(Arrays.asList("foo", "bar"));
+ assertSame(input, conversionService.convert(input, TypeDescriptor.forObject(input),
+ new TypeDescriptor(getClass().getField("wildCardCollection"))));
+ }
+
+ @Test
+ public void differentImpls() throws Exception {
+ List<Resource> resources = new ArrayList<Resource>();
+ resources.add(new ClassPathResource("test"));
+ resources.add(new FileSystemResource("test"));
+ resources.add(new TestResource());
+ TypeDescriptor sourceType = TypeDescriptor.forObject(resources);
+ assertSame(resources, conversionService.convert(resources, sourceType, new TypeDescriptor(getClass().getField("resources"))));
+ }
+
+ @Test
+ public void mixedInNulls() throws Exception {
+ List<Resource> resources = new ArrayList<Resource>();
+ resources.add(new ClassPathResource("test"));
+ resources.add(null);
+ resources.add(new FileSystemResource("test"));
+ resources.add(new TestResource());
+ TypeDescriptor sourceType = TypeDescriptor.forObject(resources);
+ assertSame(resources, conversionService.convert(resources, sourceType, new TypeDescriptor(getClass().getField("resources"))));
+ }
+
+ @Test
+ public void allNulls() throws Exception {
+ List<Resource> resources = new ArrayList<Resource>();
+ resources.add(null);
+ resources.add(null);
+ TypeDescriptor sourceType = TypeDescriptor.forObject(resources);
+ assertSame(resources, conversionService.convert(resources, sourceType, new TypeDescriptor(getClass().getField("resources"))));
+ }
+
+ @Test(expected=ConverterNotFoundException.class)
+ public void elementTypesNotConvertible() throws Exception {
+ List<String> resources = new ArrayList<String>();
+ resources.add(null);
+ resources.add(null);
+ TypeDescriptor sourceType = new TypeDescriptor(getClass().getField("strings"));
+ assertEquals(resources, conversionService.convert(resources, sourceType, new TypeDescriptor(getClass().getField("resources"))));
+ }
+
+ @Test(expected=ConversionFailedException.class)
+ public void nothingInCommon() throws Exception {
+ List<Object> resources = new ArrayList<Object>();
+ resources.add(new ClassPathResource("test"));
+ resources.add(3);
+ TypeDescriptor sourceType = TypeDescriptor.forObject(resources);
+ assertEquals(resources, conversionService.convert(resources, sourceType, new TypeDescriptor(getClass().getField("resources"))));
+ }
+
+
+ public ArrayList<Integer> scalarListTarget;
+
+ public List<Integer> emptyListTarget;
+
+ public LinkedList<Integer> emptyListDifferentTarget;
+
+ public List<List<List<Integer>>> objectToCollection;
+
+ public List<String> strings;
+
+ public List list = Collections.emptyList();
+
+ public Collection<?> wildCardCollection = Collections.emptyList();
+
+ public List<Resource> resources;
+
+
+ public static abstract class BaseResource implements Resource {
+
+ @Override
+ public InputStream getInputStream() throws IOException {
+ return null;
+ }
+
+ @Override
+ public boolean exists() {
+ return false;
+ }
+
+ @Override
+ public boolean isReadable() {
+ return false;
+ }
+
+ @Override
+ public boolean isOpen() {
+ return false;
+ }
+
+ @Override
+ public URL getURL() throws IOException {
+ return null;
+ }
+
+ @Override
+ public URI getURI() throws IOException {
+ return null;
+ }
+
+ @Override
+ public File getFile() throws IOException {
+ return null;
+ }
+
+ @Override
+ public long contentLength() throws IOException {
+ return 0;
+ }
+
+ @Override
+ public long lastModified() throws IOException {
+ return 0;
+ }
+
+ @Override
+ public Resource createRelative(String relativePath) throws IOException {
+ return null;
+ }
+
+ @Override
+ public String getFilename() {
+ return null;
+ }
+
+ @Override
+ public String getDescription() {
+ return null;
+ }
+ }
+
+
+ public static class TestResource extends BaseResource {
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/convert/support/DefaultConversionTests.java b/spring-core/src/test/java/org/springframework/core/convert/support/DefaultConversionTests.java
new file mode 100644
index 00000000..f3498894
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/convert/support/DefaultConversionTests.java
@@ -0,0 +1,876 @@
+/*
+ * Copyright 2002-2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.convert.support;
+
+import java.awt.Color;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.AbstractList;
+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.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import org.junit.Test;
+
+import org.springframework.core.MethodParameter;
+import org.springframework.core.convert.ConversionFailedException;
+import org.springframework.core.convert.ConverterNotFoundException;
+import org.springframework.core.convert.TypeDescriptor;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.core.convert.converter.ConverterRegistry;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author Keith Donald
+ * @author Juergen Hoeller
+ */
+public class DefaultConversionTests {
+
+ private final DefaultConversionService conversionService = new DefaultConversionService();
+
+
+ @Test
+ public void testStringToCharacter() {
+ assertEquals(Character.valueOf('1'), conversionService.convert("1", Character.class));
+ }
+
+ @Test
+ public void testStringToCharacterEmptyString() {
+ assertEquals(null, conversionService.convert("", Character.class));
+ }
+
+ @Test(expected=ConversionFailedException.class)
+ public void testStringToCharacterInvalidString() {
+ conversionService.convert("invalid", Character.class);
+ }
+
+ @Test
+ public void testCharacterToString() {
+ assertEquals("3", conversionService.convert('3', String.class));
+ }
+
+ @Test
+ public void testStringToBooleanTrue() {
+ assertEquals(Boolean.valueOf(true), conversionService.convert("true", Boolean.class));
+ assertEquals(Boolean.valueOf(true), conversionService.convert("on", Boolean.class));
+ assertEquals(Boolean.valueOf(true), conversionService.convert("yes", Boolean.class));
+ assertEquals(Boolean.valueOf(true), conversionService.convert("1", Boolean.class));
+ assertEquals(Boolean.valueOf(true), conversionService.convert("TRUE", Boolean.class));
+ assertEquals(Boolean.valueOf(true), conversionService.convert("ON", Boolean.class));
+ assertEquals(Boolean.valueOf(true), conversionService.convert("YES", Boolean.class));
+ }
+
+ @Test
+ public void testStringToBooleanFalse() {
+ assertEquals(Boolean.valueOf(false), conversionService.convert("false", Boolean.class));
+ assertEquals(Boolean.valueOf(false), conversionService.convert("off", Boolean.class));
+ assertEquals(Boolean.valueOf(false), conversionService.convert("no", Boolean.class));
+ assertEquals(Boolean.valueOf(false), conversionService.convert("0", Boolean.class));
+ assertEquals(Boolean.valueOf(false), conversionService.convert("FALSE", Boolean.class));
+ assertEquals(Boolean.valueOf(false), conversionService.convert("OFF", Boolean.class));
+ assertEquals(Boolean.valueOf(false), conversionService.convert("NO", Boolean.class));
+ }
+
+ @Test
+ public void testStringToBooleanEmptyString() {
+ assertEquals(null, conversionService.convert("", Boolean.class));
+ }
+
+ @Test(expected=ConversionFailedException.class)
+ public void testStringToBooleanInvalidString() {
+ conversionService.convert("invalid", Boolean.class);
+ }
+
+ @Test
+ public void testBooleanToString() {
+ assertEquals("true", conversionService.convert(true, String.class));
+ }
+
+ @Test
+ public void testStringToByte() throws Exception {
+ assertEquals(Byte.valueOf("1"), conversionService.convert("1", Byte.class));
+ }
+
+ @Test
+ public void testByteToString() {
+ assertEquals("65", conversionService.convert(new String("A").getBytes()[0], String.class));
+ }
+
+ @Test
+ public void testStringToShort() {
+ assertEquals(Short.valueOf("1"), conversionService.convert("1", Short.class));
+ }
+
+ @Test
+ public void testShortToString() {
+ short three = 3;
+ assertEquals("3", conversionService.convert(three, String.class));
+ }
+
+ @Test
+ public void testStringToInteger() {
+ assertEquals(Integer.valueOf("1"), conversionService.convert("1", Integer.class));
+ }
+
+ @Test
+ public void testIntegerToString() {
+ assertEquals("3", conversionService.convert(3, String.class));
+ }
+
+ @Test
+ public void testStringToLong() {
+ assertEquals(Long.valueOf("1"), conversionService.convert("1", Long.class));
+ }
+
+ @Test
+ public void testLongToString() {
+ assertEquals("3", conversionService.convert(3L, String.class));
+ }
+
+ @Test
+ public void testStringToFloat() {
+ assertEquals(Float.valueOf("1.0"), conversionService.convert("1.0", Float.class));
+ }
+
+ @Test
+ public void testFloatToString() {
+ assertEquals("1.0", conversionService.convert(new Float("1.0"), String.class));
+ }
+
+ @Test
+ public void testStringToDouble() {
+ assertEquals(Double.valueOf("1.0"), conversionService.convert("1.0", Double.class));
+ }
+
+ @Test
+ public void testDoubleToString() {
+ assertEquals("1.0", conversionService.convert(new Double("1.0"), String.class));
+ }
+
+ @Test
+ public void testStringToBigInteger() {
+ assertEquals(new BigInteger("1"), conversionService.convert("1", BigInteger.class));
+ }
+
+ @Test
+ public void testBigIntegerToString() {
+ assertEquals("100", conversionService.convert(new BigInteger("100"), String.class));
+ }
+
+ @Test
+ public void testStringToBigDecimal() {
+ assertEquals(new BigDecimal("1.0"), conversionService.convert("1.0", BigDecimal.class));
+ }
+
+ @Test
+ public void testBigDecimalToString() {
+ assertEquals("100.00", conversionService.convert(new BigDecimal("100.00"), String.class));
+ }
+
+ @Test
+ public void testStringToNumber() {
+ assertEquals(new BigDecimal("1.0"), conversionService.convert("1.0", Number.class));
+ }
+
+ @Test
+ public void testStringToNumberEmptyString() {
+ assertEquals(null, conversionService.convert("", Number.class));
+ }
+
+ @Test
+ public void testStringToEnum() throws Exception {
+ assertEquals(Foo.BAR, conversionService.convert("BAR", Foo.class));
+ }
+
+ @Test
+ public void testStringToEnumWithSubclass() throws Exception {
+ assertEquals(SubFoo.BAZ, conversionService.convert("BAZ", SubFoo.BAR.getClass()));
+ }
+
+ @Test
+ public void testStringToEnumEmptyString() {
+ assertEquals(null, conversionService.convert("", Foo.class));
+ }
+
+ @Test
+ public void testEnumToString() {
+ assertEquals("BAR", conversionService.convert(Foo.BAR, String.class));
+ }
+
+ public static enum Foo {
+ BAR, BAZ
+ }
+
+ public static enum SubFoo {
+
+ BAR {
+ @Override
+ String s() {
+ return "x";
+ }
+ },
+ BAZ {
+ @Override
+ String s() {
+ return "y";
+ }
+ };
+
+ abstract String s();
+ }
+
+ @Test
+ public void testStringToLocale() {
+ assertEquals(Locale.ENGLISH, conversionService.convert("en", Locale.class));
+ }
+
+ @Test
+ public void testStringToString() {
+ String str = "test";
+ assertSame(str, conversionService.convert(str, String.class));
+ }
+
+ @Test
+ public void testNumberToNumber() {
+ assertEquals(Long.valueOf(1), conversionService.convert(Integer.valueOf(1), Long.class));
+ }
+
+ @Test(expected=ConversionFailedException.class)
+ public void testNumberToNumberNotSupportedNumber() {
+ conversionService.convert(Integer.valueOf(1), CustomNumber.class);
+ }
+
+ @SuppressWarnings("serial")
+ public static class CustomNumber extends Number {
+
+ @Override
+ public double doubleValue() {
+ return 0;
+ }
+
+ @Override
+ public float floatValue() {
+ return 0;
+ }
+
+ @Override
+ public int intValue() {
+ return 0;
+ }
+
+ @Override
+ public long longValue() {
+ return 0;
+ }
+
+ }
+
+ @Test
+ public void testNumberToCharacter() {
+ assertEquals(Character.valueOf('A'), conversionService.convert(Integer.valueOf(65), Character.class));
+ }
+
+ @Test
+ public void testCharacterToNumber() {
+ assertEquals(new Integer(65), conversionService.convert('A', Integer.class));
+ }
+
+ // collection conversion
+
+ @Test
+ public void convertArrayToCollectionInterface() {
+ List<?> result = conversionService.convert(new String[] { "1", "2", "3" }, List.class);
+ assertEquals("1", result.get(0));
+ assertEquals("2", result.get(1));
+ assertEquals("3", result.get(2));
+ }
+
+ public List<Integer> genericList = new ArrayList<Integer>();
+
+ @Test
+ public void convertArrayToCollectionGenericTypeConversion() throws Exception {
+ List<Integer> result = (List<Integer>) conversionService.convert(new String[] { "1", "2", "3" }, TypeDescriptor
+ .valueOf(String[].class), new TypeDescriptor(getClass().getDeclaredField("genericList")));
+ assertEquals(new Integer("1"), result.get(0));
+ assertEquals(new Integer("2"), result.get(1));
+ assertEquals(new Integer("3"), result.get(2));
+ }
+
+ @Test
+ public void testSpr7766() throws Exception {
+ ConverterRegistry registry = (conversionService);
+ registry.addConverter(new ColorConverter());
+ List<Color> colors = (List<Color>) conversionService.convert(new String[] { "ffffff", "#000000" }, TypeDescriptor.valueOf(String[].class), new TypeDescriptor(new MethodParameter(getClass().getMethod("handlerMethod", List.class), 0)));
+ assertEquals(2, colors.size());
+ assertEquals(Color.WHITE, colors.get(0));
+ assertEquals(Color.BLACK, colors.get(1));
+ }
+
+ public class ColorConverter implements Converter<String, Color> {
+ @Override
+ public Color convert(String source) { if (!source.startsWith("#")) source = "#" + source; return Color.decode(source); }
+ }
+
+ public void handlerMethod(List<Color> color) {
+
+ }
+
+ @Test
+ public void convertArrayToCollectionImpl() {
+ LinkedList<?> result = conversionService.convert(new String[] { "1", "2", "3" }, LinkedList.class);
+ assertEquals("1", result.get(0));
+ assertEquals("2", result.get(1));
+ assertEquals("3", result.get(2));
+ }
+
+ @Test(expected = ConversionFailedException.class)
+ public void convertArrayToAbstractCollection() {
+ conversionService.convert(new String[] { "1", "2", "3" }, AbstractList.class);
+ }
+
+ public static enum FooEnum {
+ BAR, BAZ
+ }
+
+ @Test
+ public void convertArrayToString() {
+ String result = conversionService.convert(new String[] { "1", "2", "3" }, String.class);
+ assertEquals("1,2,3", result);
+ }
+
+ @Test
+ public void convertArrayToStringWithElementConversion() {
+ String result = conversionService.convert(new Integer[] { 1, 2, 3 }, String.class);
+ assertEquals("1,2,3", result);
+ }
+
+ @Test
+ public void convertEmptyArrayToString() {
+ String result = conversionService.convert(new String[0], String.class);
+ assertEquals("", result);
+ }
+
+ @Test
+ public void convertStringToArray() {
+ String[] result = conversionService.convert("1,2,3", String[].class);
+ assertEquals(3, result.length);
+ assertEquals("1", result[0]);
+ assertEquals("2", result[1]);
+ assertEquals("3", result[2]);
+ }
+
+ @Test
+ public void convertStringToArrayWithElementConversion() {
+ Integer[] result = conversionService.convert("1,2,3", Integer[].class);
+ assertEquals(3, result.length);
+ assertEquals(new Integer(1), result[0]);
+ assertEquals(new Integer(2), result[1]);
+ assertEquals(new Integer(3), result[2]);
+ }
+
+ @Test
+ public void convertStringToPrimitiveArrayWithElementConversion() {
+ int[] result = conversionService.convert("1,2,3", int[].class);
+ assertEquals(3, result.length);
+ assertEquals(1, result[0]);
+ assertEquals(2, result[1]);
+ assertEquals(3, result[2]);
+ }
+
+ @Test
+ public void convertEmptyStringToArray() {
+ String[] result = conversionService.convert("", String[].class);
+ assertEquals(0, result.length);
+ }
+
+ @Test
+ public void convertArrayToObject() {
+ Object[] array = new Object[] { 3L };
+ Object result = conversionService.convert(array, Long.class);
+ assertEquals(3L, result);
+ }
+
+ @Test
+ public void convertArrayToObjectWithElementConversion() {
+ String[] array = new String[] { "3" };
+ Integer result = conversionService.convert(array, Integer.class);
+ assertEquals(new Integer(3), result);
+ }
+
+ @Test
+ public void convertArrayToObjectAssignableTargetType() {
+ Long[] array = new Long[] { 3L };
+ Long[] result = (Long[]) conversionService.convert(array, Object.class);
+ assertArrayEquals(array, result);
+ }
+
+ @Test
+ public void convertObjectToArray() {
+ Object[] result = conversionService.convert(3L, Object[].class);
+ assertEquals(1, result.length);
+ assertEquals(3L, result[0]);
+ }
+
+ @Test
+ public void convertObjectToArrayWithElementConversion() {
+ Integer[] result = conversionService.convert(3L, Integer[].class);
+ assertEquals(1, result.length);
+ assertEquals(new Integer(3), result[0]);
+ }
+
+ @Test
+ public void convertCollectionToArray() {
+ List<String> list = new ArrayList<String>();
+ list.add("1");
+ list.add("2");
+ list.add("3");
+ String[] result = conversionService.convert(list, String[].class);
+ assertEquals("1", result[0]);
+ assertEquals("2", result[1]);
+ assertEquals("3", result[2]);
+ }
+
+ @Test
+ public void convertCollectionToArrayWithElementConversion() {
+ List<String> list = new ArrayList<String>();
+ list.add("1");
+ list.add("2");
+ list.add("3");
+ Integer[] result = conversionService.convert(list, Integer[].class);
+ assertEquals(new Integer(1), result[0]);
+ assertEquals(new Integer(2), result[1]);
+ assertEquals(new Integer(3), result[2]);
+ }
+
+ @Test
+ public void convertCollectionToString() {
+ List<String> list = Arrays.asList(new String[] { "foo", "bar" });
+ String result = conversionService.convert(list, String.class);
+ assertEquals("foo,bar", result);
+ }
+
+ @Test
+ public void convertCollectionToStringWithElementConversion() throws Exception {
+ List<Integer> list = Arrays.asList(new Integer[] { 3, 5 });
+ String result = (String) conversionService.convert(list,
+ new TypeDescriptor(getClass().getField("genericList")), TypeDescriptor.valueOf(String.class));
+ assertEquals("3,5", result);
+ }
+
+ @Test
+ public void convertStringToCollection() {
+ List result = conversionService.convert("1,2,3", List.class);
+ assertEquals(3, result.size());
+ assertEquals("1", result.get(0));
+ assertEquals("2", result.get(1));
+ assertEquals("3", result.get(2));
+ }
+
+ @Test
+ public void convertStringToCollectionWithElementConversion() throws Exception {
+ List result = (List) conversionService.convert("1,2,3", TypeDescriptor.valueOf(String.class),
+ new TypeDescriptor(getClass().getField("genericList")));
+ assertEquals(3, result.size());
+ assertEquals(new Integer(1), result.get(0));
+ assertEquals(new Integer(2), result.get(1));
+ assertEquals(new Integer(3), result.get(2));
+ }
+
+ @Test
+ public void convertEmptyStringToCollection() {
+ Collection result = conversionService.convert("", Collection.class);
+ assertEquals(0, result.size());
+ }
+
+ @Test
+ public void convertCollectionToObject() {
+ List<Long> list = Collections.singletonList(3L);
+ Long result = conversionService.convert(list, Long.class);
+ assertEquals(new Long(3), result);
+ }
+
+ @Test
+ public void convertCollectionToObjectWithElementConversion() {
+ List<String> list = Collections.singletonList("3");
+ Integer result = conversionService.convert(list, Integer.class);
+ assertEquals(new Integer(3), result);
+ }
+
+ @Test
+ public void convertCollectionToObjectAssignableTarget() throws Exception {
+ Collection<String> source = new ArrayList<String>();
+ source.add("foo");
+ Object result = conversionService.convert(source, new TypeDescriptor(getClass().getField("assignableTarget")));
+ assertEquals(source, result);
+ }
+
+ @Test
+ public void convertCollectionToObjectWithCustomConverter() throws Exception {
+ List<String> source = new ArrayList<String>();
+ source.add("A");
+ source.add("B");
+ conversionService.addConverter(new Converter<List, ListWrapper>() {
+ @Override
+ public ListWrapper convert(List source) {
+ return new ListWrapper(source);
+ }
+ });
+ ListWrapper result = conversionService.convert(source, ListWrapper.class);
+ assertSame(source, result.getList());
+ }
+
+ @Test
+ public void convertObjectToCollection() {
+ List<String> result = (List<String>) conversionService.convert(3L, List.class);
+ assertEquals(1, result.size());
+ assertEquals(3L, result.get(0));
+ }
+
+ @Test
+ public void convertObjectToCollectionWithElementConversion() throws Exception {
+ List<Integer> result = (List<Integer>) conversionService.convert(3L, TypeDescriptor.valueOf(Long.class),
+ new TypeDescriptor(getClass().getField("genericList")));
+ assertEquals(1, result.size());
+ assertEquals(new Integer(3), result.get(0));
+ }
+
+ @Test
+ public void convertArrayToArray() {
+ Integer[] result = conversionService.convert(new String[] { "1", "2", "3" }, Integer[].class);
+ assertEquals(new Integer(1), result[0]);
+ assertEquals(new Integer(2), result[1]);
+ assertEquals(new Integer(3), result[2]);
+ }
+
+ @Test
+ public void convertArrayToPrimitiveArray() {
+ int[] result = conversionService.convert(new String[] { "1", "2", "3" }, int[].class);
+ assertEquals(1, result[0]);
+ assertEquals(2, result[1]);
+ assertEquals(3, result[2]);
+ }
+
+ @Test
+ public void convertArrayToArrayAssignable() {
+ int[] result = conversionService.convert(new int[] { 1, 2, 3 }, int[].class);
+ assertEquals(1, result[0]);
+ assertEquals(2, result[1]);
+ assertEquals(3, result[2]);
+ }
+
+ @Test
+ public void convertCollectionToCollection() throws Exception {
+ Set<String> foo = new LinkedHashSet<String>();
+ foo.add("1");
+ foo.add("2");
+ foo.add("3");
+ List<Integer> bar = (List<Integer>) conversionService.convert(foo, TypeDescriptor.forObject(foo),
+ new TypeDescriptor(getClass().getField("genericList")));
+ assertEquals(new Integer(1), bar.get(0));
+ assertEquals(new Integer(2), bar.get(1));
+ assertEquals(new Integer(3), bar.get(2));
+ }
+
+ @Test
+ public void convertCollectionToCollectionNull() throws Exception {
+ List<Integer> bar = (List<Integer>) conversionService.convert(null,
+ TypeDescriptor.valueOf(LinkedHashSet.class), new TypeDescriptor(getClass().getField("genericList")));
+ assertNull(bar);
+ }
+
+ @Test
+ public void convertCollectionToCollectionNotGeneric() throws Exception {
+ Set<String> foo = new LinkedHashSet<String>();
+ foo.add("1");
+ foo.add("2");
+ foo.add("3");
+ List bar = (List) conversionService.convert(foo, TypeDescriptor.valueOf(LinkedHashSet.class), TypeDescriptor
+ .valueOf(List.class));
+ assertEquals("1", bar.get(0));
+ assertEquals("2", bar.get(1));
+ assertEquals("3", bar.get(2));
+ }
+
+ @Test
+ public void convertCollectionToCollectionSpecialCaseSourceImpl() throws Exception {
+ Map map = new LinkedHashMap();
+ map.put("1", "1");
+ map.put("2", "2");
+ map.put("3", "3");
+ Collection values = map.values();
+ List<Integer> bar = (List<Integer>) conversionService.convert(values,
+ TypeDescriptor.forObject(values), new TypeDescriptor(getClass().getField("genericList")));
+ assertEquals(3, bar.size());
+ assertEquals(new Integer(1), bar.get(0));
+ assertEquals(new Integer(2), bar.get(1));
+ assertEquals(new Integer(3), bar.get(2));
+ }
+
+ @Test
+ public void collection() {
+ List<String> strings = new ArrayList<String>();
+ strings.add("3");
+ strings.add("9");
+ List<Integer> integers = (List<Integer>) conversionService.convert(strings, TypeDescriptor.collection(List.class, TypeDescriptor.valueOf(Integer.class)));
+ assertEquals(new Integer(3), integers.get(0));
+ assertEquals(new Integer(9), integers.get(1));
+ }
+
+ public Map<Integer, FooEnum> genericMap = new HashMap<Integer, FooEnum>();
+
+ @Test
+ public void convertMapToMap() throws Exception {
+ Map<String, String> foo = new HashMap<String, String>();
+ foo.put("1", "BAR");
+ foo.put("2", "BAZ");
+ Map<String, FooEnum> map = (Map<String, FooEnum>) conversionService.convert(foo,
+ TypeDescriptor.forObject(foo), new TypeDescriptor(getClass().getField("genericMap")));
+ assertEquals(FooEnum.BAR, map.get(1));
+ assertEquals(FooEnum.BAZ, map.get(2));
+ }
+
+ @Test
+ public void map() {
+ Map<String, String> strings = new HashMap<String, String>();
+ strings.put("3", "9");
+ strings.put("6", "31");
+ Map<Integer, Integer> integers = (Map<Integer, Integer>) conversionService.convert(strings, TypeDescriptor.map(Map.class, TypeDescriptor.valueOf(Integer.class), TypeDescriptor.valueOf(Integer.class)));
+ assertEquals(new Integer(9), integers.get(3));
+ assertEquals(new Integer(31), integers.get(6));
+ }
+
+ @Test
+ public void convertPropertiesToString() {
+ Properties foo = new Properties();
+ foo.setProperty("1", "BAR");
+ foo.setProperty("2", "BAZ");
+ String result = conversionService.convert(foo, String.class);
+ assertTrue(result.contains("1=BAR"));
+ assertTrue(result.contains("2=BAZ"));
+ }
+
+ @Test
+ public void convertStringToProperties() {
+ Properties result = conversionService.convert("a=b\nc=2\nd=", Properties.class);
+ assertEquals(3, result.size());
+ assertEquals("b", result.getProperty("a"));
+ assertEquals("2", result.getProperty("c"));
+ assertEquals("", result.getProperty("d"));
+ }
+
+ @Test
+ public void convertStringToPropertiesWithSpaces() {
+ Properties result = conversionService.convert(" foo=bar\n bar=baz\n baz=boop", Properties.class);
+ assertEquals("bar", result.get("foo"));
+ assertEquals("baz", result.get("bar"));
+ assertEquals("boop", result.get("baz"));
+ }
+
+ // generic object conversion
+
+ @Test
+ public void convertObjectToStringValueOfMethodPresent() {
+ assertEquals("123456789", conversionService.convert(ISBN.valueOf("123456789"), String.class));
+ }
+
+ @Test
+ public void convertObjectToStringStringConstructorPresent() {
+ assertEquals("123456789", conversionService.convert(new SSN("123456789"), String.class));
+ }
+
+ @Test
+ public void convertObjectToStringNotSupported() {
+ assertFalse(conversionService.canConvert(TestEntity.class, String.class));
+ }
+
+ @Test
+ public void convertObjectToObjectValueOfMethod() {
+ assertEquals(ISBN.valueOf("123456789"), conversionService.convert("123456789", ISBN.class));
+ }
+
+ @Test
+ public void convertObjectToObjectConstructor() {
+ assertEquals(new SSN("123456789"), conversionService.convert("123456789", SSN.class));
+ assertEquals("123456789", conversionService.convert(new SSN("123456789"), String.class));
+ }
+
+ @Test(expected=ConverterNotFoundException.class)
+ public void convertObjectToObjectNoValueOFMethodOrConstructor() {
+ conversionService.convert(new Long(3), SSN.class);
+ }
+
+ @Test
+ public void convertObjectToObjectFinderMethod() {
+ TestEntity e = conversionService.convert(1L, TestEntity.class);
+ assertEquals(new Long(1), e.getId());
+ }
+
+ @Test
+ public void convertObjectToObjectFinderMethodWithNull() {
+ TestEntity e = (TestEntity) conversionService.convert(null, TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(TestEntity.class));
+ assertNull(e);
+ }
+
+ @Test
+ public void convertObjectToObjectFinderMethodWithIdConversion() {
+ TestEntity e = conversionService.convert("1", TestEntity.class);
+ assertEquals(new Long(1), e.getId());
+ }
+
+ @Test
+ public void convertCharArrayToString() throws Exception {
+ String converted = conversionService.convert(new char[] { 'a', 'b', 'c' }, String.class);
+ assertThat(converted, equalTo("a,b,c"));
+ }
+
+ @Test
+ public void convertStringToCharArray() throws Exception {
+ char[] converted = conversionService.convert("a,b,c", char[].class);
+ assertThat(converted, equalTo(new char[] { 'a', 'b', 'c' }));
+ }
+
+ @Test
+ public void convertStringToCustomCharArray() throws Exception {
+ conversionService.addConverter(new Converter<String, char[]>() {
+ @Override
+ public char[] convert(String source) {
+ return source.toCharArray();
+ }
+ });
+ char[] converted = conversionService.convert("abc", char[].class);
+ assertThat(converted, equalTo(new char[] { 'a', 'b', 'c' }));
+ }
+
+ @Test
+ public void multidimensionalArrayToListConversionShouldConvertEntriesCorrectly() {
+ String[][] grid = new String[][] { new String[] { "1", "2", "3", "4" }, new String[] { "5", "6", "7", "8" },
+ new String[] { "9", "10", "11", "12" } };
+ List<String[]> converted = conversionService.convert(grid, List.class);
+ String[][] convertedBack = conversionService.convert(converted, String[][].class);
+ assertArrayEquals(grid, convertedBack);
+ }
+
+
+ public static class TestEntity {
+
+ private Long id;
+
+ public TestEntity(Long id) {
+ this.id = id;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public static TestEntity findTestEntity(Long id) {
+ return new TestEntity(id);
+ }
+ }
+
+
+ private static class ListWrapper {
+
+ private List<?> list;
+
+ public ListWrapper(List<?> list) {
+ this.list = list;
+ }
+
+ public List<?> getList() {
+ return list;
+ }
+ }
+
+
+ public Object assignableTarget;
+
+
+ private static class SSN {
+
+ private String value;
+
+ public SSN(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof SSN)) {
+ return false;
+ }
+ SSN ssn = (SSN) o;
+ return this.value.equals(ssn.value);
+ }
+
+ @Override
+ public int hashCode() {
+ return value.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+ }
+
+
+ private static class ISBN {
+
+ private String value;
+
+ private ISBN(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof ISBN)) {
+ return false;
+ }
+ ISBN isbn = (ISBN) o;
+ return this.value.equals(isbn.value);
+ }
+
+ @Override
+ public int hashCode() {
+ return value.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+
+ public static ISBN valueOf(String value) {
+ return new ISBN(value);
+ }
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/convert/support/GenericConversionServiceTests.java b/spring-core/src/test/java/org/springframework/core/convert/support/GenericConversionServiceTests.java
new file mode 100644
index 00000000..8af4f860
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/convert/support/GenericConversionServiceTests.java
@@ -0,0 +1,1020 @@
+/*
+ * Copyright 2002-2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.convert.support;
+
+import java.awt.Color;
+import java.awt.SystemColor;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+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.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+import org.junit.Test;
+
+import org.springframework.core.convert.ConversionFailedException;
+import org.springframework.core.convert.ConverterNotFoundException;
+import org.springframework.core.convert.TypeDescriptor;
+import org.springframework.core.convert.converter.ConditionalConverter;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.core.convert.converter.ConverterFactory;
+import org.springframework.core.convert.converter.GenericConverter;
+import org.springframework.core.io.DescriptiveResource;
+import org.springframework.core.io.Resource;
+import org.springframework.tests.Assume;
+import org.springframework.tests.TestGroup;
+import org.springframework.util.StopWatch;
+import org.springframework.util.StringUtils;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author Keith Donald
+ * @author Juergen Hoeller
+ * @author Phillip Webb
+ * @author David Haraburda
+ */
+public class GenericConversionServiceTests {
+
+ private GenericConversionService conversionService = new GenericConversionService();
+
+
+ @Test
+ public void canConvert() {
+ assertFalse(conversionService.canConvert(String.class, Integer.class));
+ conversionService.addConverterFactory(new StringToNumberConverterFactory());
+ assertTrue(conversionService.canConvert(String.class, Integer.class));
+ }
+
+ @Test
+ public void canConvertAssignable() {
+ assertTrue(conversionService.canConvert(String.class, String.class));
+ assertTrue(conversionService.canConvert(Integer.class, Number.class));
+ assertTrue(conversionService.canConvert(boolean.class, boolean.class));
+ assertTrue(conversionService.canConvert(boolean.class, Boolean.class));
+ }
+
+ @Test
+ public void canConvertIllegalArgumentNullTargetType() {
+ try {
+ assertFalse(conversionService.canConvert(String.class, null));
+ fail("Should have failed");
+ }
+ catch (IllegalArgumentException ex) {
+ }
+ try {
+ assertFalse(conversionService.canConvert(TypeDescriptor.valueOf(String.class), null));
+ fail("Should have failed");
+ }
+ catch (IllegalArgumentException ex) {
+ }
+ }
+
+ @Test
+ public void canConvertNullSourceType() {
+ assertTrue(conversionService.canConvert(null, Integer.class));
+ assertTrue(conversionService.canConvert(null, TypeDescriptor.valueOf(Integer.class)));
+ }
+
+ @Test
+ public void convert() {
+ conversionService.addConverterFactory(new StringToNumberConverterFactory());
+ assertEquals(new Integer(3), conversionService.convert("3", Integer.class));
+ }
+
+ @Test
+ public void convertNullSource() {
+ assertEquals(null, conversionService.convert(null, Integer.class));
+ }
+
+ @Test(expected=ConversionFailedException.class)
+ public void convertNullSourcePrimitiveTarget() {
+ assertEquals(null, conversionService.convert(null, int.class));
+ }
+
+ @Test(expected=ConversionFailedException.class)
+ public void convertNullSourcePrimitiveTargetTypeDescriptor() {
+ conversionService.convert(null, TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(int.class));
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void convertNotNullSourceNullSourceTypeDescriptor() {
+ conversionService.convert("3", null, TypeDescriptor.valueOf(int.class));
+ }
+
+ @Test
+ public void convertAssignableSource() {
+ assertEquals(Boolean.FALSE, conversionService.convert(false, boolean.class));
+ assertEquals(Boolean.FALSE, conversionService.convert(false, Boolean.class));
+ }
+
+ @Test
+ public void converterNotFound() {
+ try {
+ conversionService.convert("3", Integer.class);
+ fail("Should have thrown an exception");
+ }
+ catch (ConverterNotFoundException e) {
+ }
+ }
+
+ @Test
+ @SuppressWarnings("rawtypes")
+ public void addConverterNoSourceTargetClassInfoAvailable() {
+ try {
+ conversionService.addConverter(new Converter() {
+ @Override
+ public Object convert(Object source) {
+ return source;
+ }
+ });
+ fail("Should have failed");
+ }
+ catch (IllegalArgumentException ex) {
+ }
+ }
+
+ @Test
+ public void sourceTypeIsVoid() {
+ GenericConversionService conversionService = new GenericConversionService();
+ assertFalse(conversionService.canConvert(void.class, String.class));
+ }
+
+ @Test
+ public void targetTypeIsVoid() {
+ GenericConversionService conversionService = new GenericConversionService();
+ assertFalse(conversionService.canConvert(String.class, void.class));
+ }
+
+ @Test
+ public void convertNull() {
+ assertNull(conversionService.convert(null, Integer.class));
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void convertNullTargetClass() {
+ assertNull(conversionService.convert("3", (Class<?>) null));
+ assertNull(conversionService.convert("3", TypeDescriptor.valueOf(String.class), null));
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void convertNullTypeDescriptor() {
+ assertNull(conversionService.convert("3", TypeDescriptor.valueOf(String.class), null));
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void convertWrongSourceTypeDescriptor() {
+ conversionService.convert("3", TypeDescriptor.valueOf(Integer.class), TypeDescriptor.valueOf(Long.class));
+ }
+
+ @Test
+ public void convertWrongTypeArgument() {
+ conversionService.addConverterFactory(new StringToNumberConverterFactory());
+ try {
+ conversionService.convert("BOGUS", Integer.class);
+ fail("Should have failed");
+ }
+ catch (ConversionFailedException e) {
+
+ }
+ }
+
+ @Test
+ public void convertSuperSourceType() {
+ conversionService.addConverter(new Converter<CharSequence, Integer>() {
+ @Override
+ public Integer convert(CharSequence source) {
+ return Integer.valueOf(source.toString());
+ }
+ });
+ Integer result = conversionService.convert("3", Integer.class);
+ assertEquals(new Integer(3), result);
+ }
+
+ // SPR-8718
+
+ @Test(expected=ConverterNotFoundException.class)
+ public void convertSuperTarget() {
+ conversionService.addConverter(new ColorConverter());
+ conversionService.convert("#000000", SystemColor.class);
+ }
+
+ public class ColorConverter implements Converter<String, Color> {
+ @Override
+ public Color convert(String source) { if (!source.startsWith("#")) source = "#" + source; return Color.decode(source); }
+ }
+
+ @Test
+ public void convertObjectToPrimitive() {
+ assertFalse(conversionService.canConvert(String.class, boolean.class));
+ conversionService.addConverter(new StringToBooleanConverter());
+ assertTrue(conversionService.canConvert(String.class, boolean.class));
+ Boolean b = conversionService.convert("true", boolean.class);
+ assertEquals(Boolean.TRUE, b);
+ assertTrue(conversionService.canConvert(TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(boolean.class)));
+ b = (Boolean) conversionService.convert("true", TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(boolean.class));
+ assertEquals(Boolean.TRUE, b);
+ }
+
+ @Test
+ public void convertObjectToPrimitiveViaConverterFactory() {
+ assertFalse(conversionService.canConvert(String.class, int.class));
+ conversionService.addConverterFactory(new StringToNumberConverterFactory());
+ assertTrue(conversionService.canConvert(String.class, int.class));
+ Integer three = conversionService.convert("3", int.class);
+ assertEquals(3, three.intValue());
+ }
+
+ @Test
+ public void genericConverterDelegatingBackToConversionServiceConverterNotFound() {
+ conversionService.addConverter(new ObjectToArrayConverter(conversionService));
+ assertFalse(conversionService.canConvert(String.class, Integer[].class));
+ try {
+ conversionService.convert("3,4,5", Integer[].class);
+ fail("should have failed");
+ }
+ catch (ConverterNotFoundException ex) {
+ }
+ }
+
+ @Test
+ public void testListToIterableConversion() {
+ GenericConversionService conversionService = new GenericConversionService();
+ List<Object> raw = new ArrayList<Object>();
+ raw.add("one");
+ raw.add("two");
+ Object converted = conversionService.convert(raw, Iterable.class);
+ assertSame(raw, converted);
+ }
+
+ @Test
+ public void testListToObjectConversion() {
+ GenericConversionService conversionService = new GenericConversionService();
+ List<Object> raw = new ArrayList<Object>();
+ raw.add("one");
+ raw.add("two");
+ Object converted = conversionService.convert(raw, Object.class);
+ assertSame(raw, converted);
+ }
+
+ @Test
+ public void testMapToObjectConversion() {
+ GenericConversionService conversionService = new GenericConversionService();
+ Map<Object, Object> raw = new HashMap<Object, Object>();
+ raw.put("key", "value");
+ Object converted = conversionService.convert(raw, Object.class);
+ assertSame(raw, converted);
+ }
+
+ @Test
+ public void testInterfaceToString() {
+ GenericConversionService conversionService = new GenericConversionService();
+ conversionService.addConverter(new MyBaseInterfaceConverter());
+ conversionService.addConverter(new ObjectToStringConverter());
+ Object converted = conversionService.convert(new MyInterfaceImplementer(), String.class);
+ assertEquals("RESULT", converted);
+ }
+
+ @Test
+ public void testInterfaceArrayToStringArray() {
+ GenericConversionService conversionService = new GenericConversionService();
+ conversionService.addConverter(new MyBaseInterfaceConverter());
+ conversionService.addConverter(new ArrayToArrayConverter(conversionService));
+ String[] converted = conversionService.convert(new MyInterface[] {new MyInterfaceImplementer()}, String[].class);
+ assertEquals("RESULT", converted[0]);
+ }
+
+ @Test
+ public void testObjectArrayToStringArray() {
+ GenericConversionService conversionService = new GenericConversionService();
+ conversionService.addConverter(new MyBaseInterfaceConverter());
+ conversionService.addConverter(new ArrayToArrayConverter(conversionService));
+ String[] converted = conversionService.convert(new MyInterfaceImplementer[] {new MyInterfaceImplementer()}, String[].class);
+ assertEquals("RESULT", converted[0]);
+ }
+
+ @Test
+ public void testStringArrayToResourceArray() {
+ GenericConversionService conversionService = new DefaultConversionService();
+ conversionService.addConverter(new MyStringArrayToResourceArrayConverter());
+ Resource[] converted = conversionService.convert(new String[] {"x1", "z3"}, Resource[].class);
+ assertEquals(2, converted.length);
+ assertEquals("1", converted[0].getDescription());
+ assertEquals("3", converted[1].getDescription());
+ }
+
+ @Test
+ public void testStringArrayToIntegerArray() {
+ GenericConversionService conversionService = new DefaultConversionService();
+ conversionService.addConverter(new MyStringArrayToIntegerArrayConverter());
+ Integer[] converted = conversionService.convert(new String[] {"x1", "z3"}, Integer[].class);
+ assertEquals(2, converted.length);
+ assertEquals(1, converted[0].intValue());
+ assertEquals(3, converted[1].intValue());
+ }
+
+ @Test
+ public void testStringToIntegerArray() {
+ GenericConversionService conversionService = new DefaultConversionService();
+ conversionService.addConverter(new MyStringToIntegerArrayConverter());
+ Integer[] converted = conversionService.convert("x1,z3", Integer[].class);
+ assertEquals(2, converted.length);
+ assertEquals(1, converted[0].intValue());
+ assertEquals(3, converted[1].intValue());
+ }
+
+ @Test
+ public void testWildcardMap() throws Exception {
+ GenericConversionService conversionService = new DefaultConversionService();
+ Map<String, String> input = new LinkedHashMap<String, String>();
+ input.put("key", "value");
+ Object converted = conversionService.convert(input, TypeDescriptor.forObject(input), new TypeDescriptor(getClass().getField("wildcardMap")));
+ assertEquals(input, converted);
+ }
+
+ @Test
+ public void testListOfList() {
+ GenericConversionService service = new DefaultConversionService();
+ List<String> list1 = Arrays.asList("Foo", "Bar");
+ List<String> list2 = Arrays.asList("Baz", "Boop");
+ List<List<String>> list = Arrays.asList(list1, list2);
+ String result = service.convert(list, String.class);
+ assertNotNull(result);
+ assertEquals("Foo,Bar,Baz,Boop", result);
+ }
+
+ @Test
+ public void testStringToString() {
+ GenericConversionService service = new DefaultConversionService();
+ String value = "myValue";
+ String result = service.convert(value, String.class);
+ assertSame(value, result);
+ }
+
+ @Test
+ public void testStringToObject() {
+ GenericConversionService service = new DefaultConversionService();
+ String value = "myValue";
+ Object result = service.convert(value, Object.class);
+ assertSame(value, result);
+ }
+
+ @Test
+ public void testIgnoreCopyConstructor() {
+ GenericConversionService service = new DefaultConversionService();
+ WithCopyConstructor value = new WithCopyConstructor();
+ Object result = service.convert(value, WithCopyConstructor.class);
+ assertSame(value, result);
+ }
+
+ @Test
+ public void testConvertUUID() {
+ GenericConversionService service = new DefaultConversionService();
+ UUID uuid = UUID.randomUUID();
+ String convertToString = service.convert(uuid, String.class);
+ UUID convertToUUID = service.convert(convertToString, UUID.class);
+ assertEquals(uuid, convertToUUID);
+ }
+
+ @Test
+ public void testPerformance1() {
+ Assume.group(TestGroup.PERFORMANCE);
+ GenericConversionService conversionService = new DefaultConversionService();
+ StopWatch watch = new StopWatch("integer->string conversionPerformance");
+ watch.start("convert 4,000,000 with conversion service");
+ for (int i = 0; i < 4000000; i++) {
+ conversionService.convert(3, String.class);
+ }
+ watch.stop();
+ watch.start("convert 4,000,000 manually");
+ for (int i = 0; i < 4000000; i++) {
+ new Integer(3).toString();
+ }
+ watch.stop();
+ System.out.println(watch.prettyPrint());
+ }
+
+ @Test
+ public void testPerformance2() throws Exception {
+ Assume.group(TestGroup.PERFORMANCE);
+ GenericConversionService conversionService = new DefaultConversionService();
+ StopWatch watch = new StopWatch("list<string> -> list<integer> conversionPerformance");
+ watch.start("convert 4,000,000 with conversion service");
+ List<String> source = new LinkedList<String>();
+ source.add("1");
+ source.add("2");
+ source.add("3");
+ TypeDescriptor td = new TypeDescriptor(getClass().getField("list"));
+ for (int i = 0; i < 1000000; i++) {
+ conversionService.convert(source, TypeDescriptor.forObject(source), td);
+ }
+ watch.stop();
+ watch.start("convert 4,000,000 manually");
+ for (int i = 0; i < 4000000; i++) {
+ List<Integer> target = new ArrayList<Integer>(source.size());
+ for (String element : source) {
+ target.add(Integer.valueOf(element));
+ }
+ }
+ watch.stop();
+ System.out.println(watch.prettyPrint());
+ }
+
+ public static List<Integer> list;
+
+ @Test
+ public void testPerformance3() throws Exception {
+ Assume.group(TestGroup.PERFORMANCE);
+ GenericConversionService conversionService = new DefaultConversionService();
+ StopWatch watch = new StopWatch("map<string, string> -> map<string, integer> conversionPerformance");
+ watch.start("convert 4,000,000 with conversion service");
+ Map<String, String> source = new HashMap<String, String>();
+ source.put("1", "1");
+ source.put("2", "2");
+ source.put("3", "3");
+ TypeDescriptor td = new TypeDescriptor(getClass().getField("map"));
+ for (int i = 0; i < 1000000; i++) {
+ conversionService.convert(source, TypeDescriptor.forObject(source), td);
+ }
+ watch.stop();
+ watch.start("convert 4,000,000 manually");
+ for (int i = 0; i < 4000000; i++) {
+ Map<String, Integer> target = new HashMap<String, Integer>(source.size());
+ for (Map.Entry<String, String> entry : source.entrySet()) {
+ target.put(entry.getKey(), Integer.valueOf(entry.getValue()));
+ }
+ }
+ watch.stop();
+ System.out.println(watch.prettyPrint());
+ }
+
+ public static Map<String, Integer> map;
+
+ @Test
+ public void emptyListToArray() {
+ conversionService.addConverter(new CollectionToArrayConverter(conversionService));
+ conversionService.addConverterFactory(new StringToNumberConverterFactory());
+ List<String> list = new ArrayList<String>();
+ TypeDescriptor sourceType = TypeDescriptor.forObject(list);
+ TypeDescriptor targetType = TypeDescriptor.valueOf(String[].class);
+ assertTrue(conversionService.canConvert(sourceType, targetType));
+ assertEquals(0, ((String[])conversionService.convert(list, sourceType, targetType)).length);
+ }
+
+ @Test
+ public void emptyListToObject() {
+ conversionService.addConverter(new CollectionToObjectConverter(conversionService));
+ conversionService.addConverterFactory(new StringToNumberConverterFactory());
+ List<String> list = new ArrayList<String>();
+ TypeDescriptor sourceType = TypeDescriptor.forObject(list);
+ TypeDescriptor targetType = TypeDescriptor.valueOf(Integer.class);
+ assertTrue(conversionService.canConvert(sourceType, targetType));
+ assertNull(conversionService.convert(list, sourceType, targetType));
+ }
+
+ private interface MyBaseInterface {
+
+ }
+
+
+ private interface MyInterface extends MyBaseInterface {
+
+ }
+
+
+ private static class MyInterfaceImplementer implements MyInterface {
+
+ }
+
+
+ private static class MyBaseInterfaceConverter implements Converter<MyBaseInterface, String> {
+
+ @Override
+ public String convert(MyBaseInterface source) {
+ return "RESULT";
+ }
+ }
+
+
+ private static class MyStringArrayToResourceArrayConverter implements Converter<String[], Resource[]> {
+
+ @Override
+ public Resource[] convert(String[] source) {
+ Resource[] result = new Resource[source.length];
+ for (int i = 0; i < source.length; i++) {
+ result[i] = new DescriptiveResource(source[i].substring(1));
+ }
+ return result;
+ }
+ }
+
+
+ private static class MyStringArrayToIntegerArrayConverter implements Converter<String[], Integer[]> {
+
+ @Override
+ public Integer[] convert(String[] source) {
+ Integer[] result = new Integer[source.length];
+ for (int i = 0; i < source.length; i++) {
+ result[i] = Integer.parseInt(source[i].substring(1));
+ }
+ return result;
+ }
+ }
+
+
+ private static class MyStringToIntegerArrayConverter implements Converter<String, Integer[]> {
+
+ @Override
+ public Integer[] convert(String source) {
+ String[] srcArray = StringUtils.commaDelimitedListToStringArray(source);
+ Integer[] result = new Integer[srcArray.length];
+ for (int i = 0; i < srcArray.length; i++) {
+ result[i] = Integer.parseInt(srcArray[i].substring(1));
+ }
+ return result;
+ }
+ }
+
+
+ public static class WithCopyConstructor {
+
+ public WithCopyConstructor() {
+ }
+
+ public WithCopyConstructor(WithCopyConstructor value) {
+ }
+ }
+
+
+ public static Map<String, ?> wildcardMap;
+
+ @Test
+ public void stringToArrayCanConvert() {
+ conversionService.addConverter(new StringToArrayConverter(conversionService));
+ assertFalse(conversionService.canConvert(String.class, Integer[].class));
+ conversionService.addConverterFactory(new StringToNumberConverterFactory());
+ assertTrue(conversionService.canConvert(String.class, Integer[].class));
+ }
+
+ @Test
+ public void stringToCollectionCanConvert() throws Exception {
+ conversionService.addConverter(new StringToCollectionConverter(conversionService));
+ assertTrue(conversionService.canConvert(String.class, Collection.class));
+ TypeDescriptor targetType = new TypeDescriptor(getClass().getField("stringToCollection"));
+ assertFalse(conversionService.canConvert(TypeDescriptor.valueOf(String.class), targetType));
+ conversionService.addConverterFactory(new StringToNumberConverterFactory());
+ assertTrue(conversionService.canConvert(TypeDescriptor.valueOf(String.class), targetType));
+ }
+
+ public Collection<Integer> stringToCollection;
+
+ @Test
+ public void testConvertiblePairsInSet() {
+ Set<GenericConverter.ConvertiblePair> set = new HashSet<GenericConverter.ConvertiblePair>();
+ set.add(new GenericConverter.ConvertiblePair(Number.class, String.class));
+ assert set.contains(new GenericConverter.ConvertiblePair(Number.class, String.class));
+ }
+
+ @Test
+ public void testConvertiblePairEqualsAndHash() {
+ GenericConverter.ConvertiblePair pair = new GenericConverter.ConvertiblePair(Number.class, String.class);
+ GenericConverter.ConvertiblePair pairEqual = new GenericConverter.ConvertiblePair(Number.class, String.class);
+ assertEquals(pair, pairEqual);
+ assertEquals(pair.hashCode(), pairEqual.hashCode());
+ }
+
+ @Test
+ public void testConvertiblePairDifferentEqualsAndHash() {
+ GenericConverter.ConvertiblePair pair = new GenericConverter.ConvertiblePair(Number.class, String.class);
+ GenericConverter.ConvertiblePair pairOpposite = new GenericConverter.ConvertiblePair(String.class, Number.class);
+ assertFalse(pair.equals(pairOpposite));
+ assertFalse(pair.hashCode() == pairOpposite.hashCode());
+ }
+
+ @Test
+ public void convertPrimitiveArray() {
+ GenericConversionService conversionService = new DefaultConversionService();
+ byte[] byteArray = new byte[] { 1, 2, 3 };
+ Byte[] converted = conversionService.convert(byteArray, Byte[].class);
+ assertTrue(Arrays.equals(converted, new Byte[] {1, 2, 3}));
+ }
+
+ @Test
+ public void canConvertIllegalArgumentNullTargetTypeFromClass() {
+ try {
+ conversionService.canConvert(String.class, null);
+ fail("Did not thow IllegalArgumentException");
+ }
+ catch (IllegalArgumentException ex) {
+ }
+ }
+
+ @Test
+ public void canConvertIllegalArgumentNullTargetTypeFromTypeDescriptor() {
+ try {
+ conversionService.canConvert(TypeDescriptor.valueOf(String.class), null);
+ fail("Did not thow IllegalArgumentException");
+ }
+ catch(IllegalArgumentException ex) {
+ }
+ }
+
+ @Test
+ @SuppressWarnings({ "rawtypes" })
+ public void convertHashMapValuesToList() {
+ GenericConversionService conversionService = new DefaultConversionService();
+ Map<String, Integer> hashMap = new LinkedHashMap<String, Integer>();
+ hashMap.put("1", 1);
+ hashMap.put("2", 2);
+ List converted = conversionService.convert(hashMap.values(), List.class);
+ assertEquals(Arrays.asList(1, 2), converted);
+ }
+
+ @Test
+ public void removeConvertible() {
+ conversionService.addConverter(new ColorConverter());
+ assertTrue(conversionService.canConvert(String.class, Color.class));
+ conversionService.removeConvertible(String.class, Color.class);
+ assertFalse(conversionService.canConvert(String.class, Color.class));
+ }
+
+ @Test
+ public void conditionalConverter() {
+ GenericConversionService conversionService = new GenericConversionService();
+ MyConditionalConverter converter = new MyConditionalConverter();
+ conversionService.addConverter(new ColorConverter());
+ conversionService.addConverter(converter);
+ assertEquals(Color.BLACK, conversionService.convert("#000000", Color.class));
+ assertTrue(converter.getMatchAttempts() > 0);
+ }
+
+ @Test
+ public void conditionalConverterFactory() {
+ GenericConversionService conversionService = new GenericConversionService();
+ MyConditionalConverterFactory converter = new MyConditionalConverterFactory();
+ conversionService.addConverter(new ColorConverter());
+ conversionService.addConverterFactory(converter);
+ assertEquals(Color.BLACK, conversionService.convert("#000000", Color.class));
+ assertTrue(converter.getMatchAttempts() > 0);
+ assertTrue(converter.getNestedMatchAttempts() > 0);
+ }
+
+ @Test
+ public void shouldNotSupportNullConvertibleTypesFromNonConditionalGenericConverter() {
+ GenericConversionService conversionService = new GenericConversionService();
+ GenericConverter converter = new GenericConverter() {
+ @Override
+ public Set<ConvertiblePair> getConvertibleTypes() {
+ return null;
+ }
+ @Override
+ public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
+ return null;
+ }
+ };
+ try {
+ conversionService.addConverter(converter);
+ fail("Did not throw");
+ }
+ catch (IllegalStateException ex) {
+ assertEquals("Only conditional converters may return null convertible types", ex.getMessage());
+ }
+ }
+
+ @Test
+ public void conditionalConversionForAllTypes() {
+ GenericConversionService conversionService = new GenericConversionService();
+ MyConditionalGenericConverter converter = new MyConditionalGenericConverter();
+ conversionService.addConverter(converter);
+ assertEquals((Integer) 3, conversionService.convert(3, Integer.class));
+ assertThat(converter.getSourceTypes().size(), greaterThan(2));
+ Iterator<TypeDescriptor> iterator = converter.getSourceTypes().iterator();
+ while(iterator.hasNext()) {
+ assertEquals(Integer.class, iterator.next().getType());
+ }
+ }
+
+ @Test
+ public void convertOptimizeArray() {
+ // SPR-9566
+ GenericConversionService conversionService = new DefaultConversionService();
+ byte[] byteArray = new byte[] { 1, 2, 3 };
+ byte[] converted = conversionService.convert(byteArray, byte[].class);
+ assertSame(byteArray, converted);
+ }
+
+ @Test
+ public void convertCannotOptimizeArray() {
+ GenericConversionService conversionService = new GenericConversionService();
+ conversionService.addConverter(new Converter<Byte, Byte>() {
+ @Override
+ public Byte convert(Byte source) {
+ return (byte) (source + 1);
+ }
+ });
+ DefaultConversionService.addDefaultConverters(conversionService);
+ byte[] byteArray = new byte[] { 1, 2, 3 };
+ byte[] converted = conversionService.convert(byteArray, byte[].class);
+ assertNotSame(byteArray, converted);
+ assertTrue(Arrays.equals(new byte[] {2, 3, 4}, converted));
+ }
+
+ @Test
+ public void testEnumToStringConversion() {
+ conversionService.addConverter(new EnumToStringConverter(conversionService));
+ String result = conversionService.convert(MyEnum.A, String.class);
+ assertEquals("A", result);
+ }
+
+ @Test
+ public void testSubclassOfEnumToString() throws Exception {
+ conversionService.addConverter(new EnumToStringConverter(conversionService));
+ String result = conversionService.convert(EnumWithSubclass.FIRST, String.class);
+ assertEquals("FIRST", result);
+ }
+
+ @Test
+ public void testEnumWithInterfaceToStringConversion() {
+ // SPR-9692
+ conversionService.addConverter(new EnumToStringConverter(conversionService));
+ conversionService.addConverter(new MyEnumInterfaceToStringConverter<MyEnum>());
+ String result = conversionService.convert(MyEnum.A, String.class);
+ assertEquals("1", result);
+ }
+
+ @Test
+ public void convertNullAnnotatedStringToString() throws Exception {
+ DefaultConversionService.addDefaultConverters(conversionService);
+ String source = null;
+ TypeDescriptor sourceType = new TypeDescriptor(getClass().getField("annotatedString"));
+ TypeDescriptor targetType = TypeDescriptor.valueOf(String.class);
+ conversionService.convert(source, sourceType, targetType);
+ }
+
+ @Test
+ public void multipleCollectionTypesFromSameSourceType() throws Exception {
+ conversionService.addConverter(new MyStringToRawCollectionConverter());
+ conversionService.addConverter(new MyStringToGenericCollectionConverter());
+ conversionService.addConverter(new MyStringToStringCollectionConverter());
+ conversionService.addConverter(new MyStringToIntegerCollectionConverter());
+
+ assertEquals(Collections.singleton(4), // should be "testX" from MyStringToStringCollectionConverter, ideally
+ conversionService.convert("test", TypeDescriptor.valueOf(String.class), new TypeDescriptor(getClass().getField("stringCollection"))));
+ assertEquals(Collections.singleton(4),
+ conversionService.convert("test", TypeDescriptor.valueOf(String.class), new TypeDescriptor(getClass().getField("integerCollection"))));
+ assertEquals(Collections.singleton(4),
+ conversionService.convert("test", TypeDescriptor.valueOf(String.class), new TypeDescriptor(getClass().getField("rawCollection"))));
+ assertEquals(Collections.singleton(4),
+ conversionService.convert("test", TypeDescriptor.valueOf(String.class), new TypeDescriptor(getClass().getField("genericCollection"))));
+ assertEquals(Collections.singleton(4),
+ conversionService.convert("test", TypeDescriptor.valueOf(String.class), new TypeDescriptor(getClass().getField("rawCollection"))));
+ assertEquals(Collections.singleton(4), // should be "testX" from MyStringToStringCollectionConverter, ideally
+ conversionService.convert("test", TypeDescriptor.valueOf(String.class), new TypeDescriptor(getClass().getField("stringCollection"))));
+ }
+
+ @Test
+ public void adaptedCollectionTypesFromSameSourceType() throws Exception {
+ conversionService.addConverter(new MyStringToStringCollectionConverter());
+
+ assertEquals(Collections.singleton("testX"),
+ conversionService.convert("test", TypeDescriptor.valueOf(String.class), new TypeDescriptor(getClass().getField("stringCollection"))));
+ assertEquals(Collections.singleton("testX"),
+ conversionService.convert("test", TypeDescriptor.valueOf(String.class), new TypeDescriptor(getClass().getField("genericCollection"))));
+ assertEquals(Collections.singleton("testX"),
+ conversionService.convert("test", TypeDescriptor.valueOf(String.class), new TypeDescriptor(getClass().getField("rawCollection"))));
+ assertEquals(Collections.singleton("testX"),
+ conversionService.convert("test", TypeDescriptor.valueOf(String.class), new TypeDescriptor(getClass().getField("genericCollection"))));
+ assertEquals(Collections.singleton("testX"),
+ conversionService.convert("test", TypeDescriptor.valueOf(String.class), new TypeDescriptor(getClass().getField("stringCollection"))));
+ assertEquals(Collections.singleton("testX"),
+ conversionService.convert("test", TypeDescriptor.valueOf(String.class), new TypeDescriptor(getClass().getField("rawCollection"))));
+
+ // The following is unpleasant but simply a consequence of the raw type matching algorithm in Spring 3.x
+ assertEquals(Collections.singleton("testX"),
+ conversionService.convert("test", TypeDescriptor.valueOf(String.class), new TypeDescriptor(getClass().getField("integerCollection"))));
+ }
+
+ @Test
+ public void genericCollectionAsSource() throws Exception {
+ conversionService.addConverter(new MyStringToGenericCollectionConverter());
+
+ assertEquals(Collections.singleton("testX"),
+ conversionService.convert("test", TypeDescriptor.valueOf(String.class), new TypeDescriptor(getClass().getField("stringCollection"))));
+ assertEquals(Collections.singleton("testX"),
+ conversionService.convert("test", TypeDescriptor.valueOf(String.class), new TypeDescriptor(getClass().getField("genericCollection"))));
+ assertEquals(Collections.singleton("testX"),
+ conversionService.convert("test", TypeDescriptor.valueOf(String.class), new TypeDescriptor(getClass().getField("rawCollection"))));
+
+ // The following is unpleasant but a consequence of the generic collection converter above...
+ assertEquals(Collections.singleton("testX"),
+ conversionService.convert("test", TypeDescriptor.valueOf(String.class), new TypeDescriptor(getClass().getField("integerCollection"))));
+ }
+
+ @Test
+ public void rawCollectionAsSource() throws Exception {
+ conversionService.addConverter(new MyStringToRawCollectionConverter());
+
+ assertEquals(Collections.singleton("testX"),
+ conversionService.convert("test", TypeDescriptor.valueOf(String.class), new TypeDescriptor(getClass().getField("stringCollection"))));
+ assertEquals(Collections.singleton("testX"),
+ conversionService.convert("test", TypeDescriptor.valueOf(String.class), new TypeDescriptor(getClass().getField("genericCollection"))));
+ assertEquals(Collections.singleton("testX"),
+ conversionService.convert("test", TypeDescriptor.valueOf(String.class), new TypeDescriptor(getClass().getField("rawCollection"))));
+
+ // The following is unpleasant but a consequence of the raw collection converter above...
+ assertEquals(Collections.singleton("testX"),
+ conversionService.convert("test", TypeDescriptor.valueOf(String.class), new TypeDescriptor(getClass().getField("integerCollection"))));
+ }
+
+
+ @ExampleAnnotation
+ public String annotatedString;
+
+
+ @Retention(RetentionPolicy.RUNTIME)
+ public static @interface ExampleAnnotation {
+ }
+
+
+ private static class MyConditionalConverter implements Converter<String, Color>, ConditionalConverter {
+
+ private int matchAttempts = 0;
+
+ @Override
+ public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
+ matchAttempts++;
+ return false;
+ }
+
+ @Override
+ public Color convert(String source) {
+ throw new IllegalStateException();
+ }
+
+ public int getMatchAttempts() {
+ return matchAttempts;
+ }
+ }
+
+
+ private static class MyConditionalGenericConverter implements GenericConverter, ConditionalConverter {
+
+ private List<TypeDescriptor> sourceTypes = new ArrayList<TypeDescriptor>();
+
+ @Override
+ public Set<ConvertiblePair> getConvertibleTypes() {
+ return null;
+ }
+
+ @Override
+ public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
+ sourceTypes.add(sourceType);
+ return false;
+ }
+
+ @Override
+ public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
+ return null;
+ }
+
+ public List<TypeDescriptor> getSourceTypes() {
+ return sourceTypes;
+ }
+ }
+
+
+ private static class MyConditionalConverterFactory implements ConverterFactory<String, Color>, ConditionalConverter {
+
+ private MyConditionalConverter converter = new MyConditionalConverter();
+
+ private int matchAttempts = 0;
+
+ @Override
+ public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
+ matchAttempts++;
+ return true;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T extends Color> Converter<String, T> getConverter(Class<T> targetType) {
+ return (Converter<String, T>) converter;
+ }
+
+ public int getMatchAttempts() {
+ return matchAttempts;
+ }
+
+ public int getNestedMatchAttempts() {
+ return converter.getMatchAttempts();
+ }
+ }
+
+
+ interface MyEnumInterface {
+
+ String getCode();
+ }
+
+
+ public static enum MyEnum implements MyEnumInterface {
+
+ A {
+ @Override
+ public String getCode() {
+ return "1";
+ }
+ }
+ }
+
+
+ public enum EnumWithSubclass {
+
+ FIRST {
+ @Override
+ public String toString() {
+ return "1st";
+ }
+ }
+ }
+
+
+ public static class MyStringToRawCollectionConverter implements Converter<String, Collection> {
+
+ @Override
+ public Collection convert(String source) {
+ return Collections.singleton(source + "X");
+ }
+ }
+
+
+ public static class MyStringToGenericCollectionConverter implements Converter<String, Collection<?>> {
+
+ @Override
+ public Collection<?> convert(String source) {
+ return Collections.singleton(source + "X");
+ }
+ }
+
+
+ private static class MyEnumInterfaceToStringConverter<T extends MyEnumInterface> implements Converter<T, String> {
+
+ @Override
+ public String convert(T source) {
+ return source.getCode();
+ }
+ }
+
+
+ public static class MyStringToStringCollectionConverter implements Converter<String, Collection<String>> {
+
+ @Override
+ public Collection<String> convert(String source) {
+ return Collections.singleton(source + "X");
+ }
+ }
+
+
+ public static class MyStringToIntegerCollectionConverter implements Converter<String, Collection<Integer>> {
+
+ @Override
+ public Collection<Integer> convert(String source) {
+ return Collections.singleton(source.length());
+ }
+ }
+
+
+ public Collection rawCollection;
+
+ public Collection<?> genericCollection;
+
+ public Collection<String> stringCollection;
+
+ public Collection<Integer> integerCollection;
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/convert/support/MapToMapConverterTests.java b/spring-core/src/test/java/org/springframework/core/convert/support/MapToMapConverterTests.java
new file mode 100644
index 00000000..9f3ca159
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/convert/support/MapToMapConverterTests.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.convert.support;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.springframework.core.convert.ConversionFailedException;
+import org.springframework.core.convert.ConverterNotFoundException;
+import org.springframework.core.convert.TypeDescriptor;
+
+import static org.junit.Assert.*;
+
+public class MapToMapConverterTests {
+
+ private GenericConversionService conversionService = new GenericConversionService();
+
+ @Before
+ public void setUp() {
+ conversionService.addConverter(new MapToMapConverter(conversionService));
+ }
+
+ @Test
+ public void scalarMap() throws Exception {
+ Map<String, String> map = new HashMap<String, String>();
+ map.put("1", "9");
+ map.put("2", "37");
+ TypeDescriptor sourceType = TypeDescriptor.forObject(map);
+ TypeDescriptor targetType = new TypeDescriptor(getClass().getField("scalarMapTarget"));
+ assertTrue(conversionService.canConvert(sourceType, targetType));
+ try {
+ conversionService.convert(map, sourceType, targetType);
+ } catch (ConversionFailedException e) {
+ assertTrue(e.getCause() instanceof ConverterNotFoundException);
+ }
+ conversionService.addConverterFactory(new StringToNumberConverterFactory());
+ assertTrue(conversionService.canConvert(sourceType, targetType));
+ @SuppressWarnings("unchecked")
+ Map<Integer, Integer> result = (Map<Integer, Integer>) conversionService.convert(map, sourceType, targetType);
+ assertFalse(map.equals(result));
+ assertEquals((Integer) 9, result.get(1));
+ assertEquals((Integer) 37, result.get(2));
+ }
+
+ public Map<Integer, Integer> scalarMapTarget;
+
+ @Test
+ public void scalarMapNotGenericTarget() throws Exception {
+ Map<String, String> map = new HashMap<String, String>();
+ map.put("1", "9");
+ map.put("2", "37");
+ assertTrue(conversionService.canConvert(Map.class, Map.class));
+ assertSame(map, conversionService.convert(map, Map.class));
+ }
+
+ @Test
+ public void scalarMapNotGenericSourceField() throws Exception {
+ Map<String, String> map = new HashMap<String, String>();
+ map.put("1", "9");
+ map.put("2", "37");
+ TypeDescriptor sourceType = new TypeDescriptor(getClass().getField("notGenericMapSource"));
+ TypeDescriptor targetType = new TypeDescriptor(getClass().getField("scalarMapTarget"));
+ assertTrue(conversionService.canConvert(sourceType, targetType));
+ try {
+ conversionService.convert(map, sourceType, targetType);
+ } catch (ConversionFailedException e) {
+ assertTrue(e.getCause() instanceof ConverterNotFoundException);
+ }
+ conversionService.addConverterFactory(new StringToNumberConverterFactory());
+ assertTrue(conversionService.canConvert(sourceType, targetType));
+ @SuppressWarnings("unchecked")
+ Map<Integer, Integer> result = (Map<Integer, Integer>) conversionService.convert(map, sourceType, targetType);
+ assertFalse(map.equals(result));
+ assertEquals((Integer) 9, result.get(1));
+ assertEquals((Integer) 37, result.get(2));
+ }
+
+ public Map notGenericMapSource;
+
+ @Test
+ public void collectionMap() throws Exception {
+ Map<String, List<String>> map = new HashMap<String, List<String>>();
+ map.put("1", Arrays.asList("9", "12"));
+ map.put("2", Arrays.asList("37", "23"));
+ TypeDescriptor sourceType = TypeDescriptor.forObject(map);
+ TypeDescriptor targetType = new TypeDescriptor(getClass().getField("collectionMapTarget"));
+ assertTrue(conversionService.canConvert(sourceType, targetType));
+ try {
+ conversionService.convert(map, sourceType, targetType);
+ } catch (ConversionFailedException e) {
+ assertTrue(e.getCause() instanceof ConverterNotFoundException);
+ }
+ conversionService.addConverter(new CollectionToCollectionConverter(conversionService));
+ conversionService.addConverterFactory(new StringToNumberConverterFactory());
+ assertTrue(conversionService.canConvert(sourceType, targetType));
+ @SuppressWarnings("unchecked")
+ Map<Integer, List<Integer>> result = (Map<Integer, List<Integer>>) conversionService.convert(map, sourceType, targetType);
+ assertFalse(map.equals(result));
+ assertEquals(Arrays.asList(9, 12), result.get(1));
+ assertEquals(Arrays.asList(37, 23), result.get(2));
+ }
+
+ public Map<Integer, List<Integer>> collectionMapTarget;
+
+ @Test
+ public void collectionMapSourceTarget() throws Exception {
+ Map<String, List<String>> map = new HashMap<String, List<String>>();
+ map.put("1", Arrays.asList("9", "12"));
+ map.put("2", Arrays.asList("37", "23"));
+ TypeDescriptor sourceType = new TypeDescriptor(getClass().getField("sourceCollectionMapTarget"));
+ TypeDescriptor targetType = new TypeDescriptor(getClass().getField("collectionMapTarget"));
+ assertFalse(conversionService.canConvert(sourceType, targetType));
+ try {
+ conversionService.convert(map, sourceType, targetType);
+ fail("Should have failed");
+ } catch (ConverterNotFoundException e) {
+
+ }
+ conversionService.addConverter(new CollectionToCollectionConverter(conversionService));
+ conversionService.addConverterFactory(new StringToNumberConverterFactory());
+ assertTrue(conversionService.canConvert(sourceType, targetType));
+ @SuppressWarnings("unchecked")
+ Map<Integer, List<Integer>> result = (Map<Integer, List<Integer>>) conversionService.convert(map, sourceType, targetType);
+ assertFalse(map.equals(result));
+ assertEquals(Arrays.asList(9, 12), result.get(1));
+ assertEquals(Arrays.asList(37, 23), result.get(2));
+ }
+
+ public Map<String, List<String>> sourceCollectionMapTarget;
+
+ @Test
+ public void collectionMapNotGenericTarget() throws Exception {
+ Map<String, List<String>> map = new HashMap<String, List<String>>();
+ map.put("1", Arrays.asList("9", "12"));
+ map.put("2", Arrays.asList("37", "23"));
+ assertTrue(conversionService.canConvert(Map.class, Map.class));
+ assertSame(map, conversionService.convert(map, Map.class));
+ }
+
+ @Test
+ public void collectionMapNotGenericTargetCollectionToObjectInteraction() throws Exception {
+ Map<String, List<String>> map = new HashMap<String, List<String>>();
+ map.put("1", Arrays.asList("9", "12"));
+ map.put("2", Arrays.asList("37", "23"));
+ conversionService.addConverter(new CollectionToCollectionConverter(conversionService));
+ conversionService.addConverter(new CollectionToObjectConverter(conversionService));
+ assertTrue(conversionService.canConvert(Map.class, Map.class));
+ assertSame(map, conversionService.convert(map, Map.class));
+ }
+
+ @Test
+ public void emptyMap() throws Exception {
+ Map<String, String> map = new HashMap<String, String>();
+ TypeDescriptor sourceType = TypeDescriptor.forObject(map);
+ TypeDescriptor targetType = new TypeDescriptor(getClass().getField("emptyMapTarget"));
+ assertTrue(conversionService.canConvert(sourceType, targetType));
+ assertSame(map, conversionService.convert(map, sourceType, targetType));
+ }
+
+ public Map<String, String> emptyMapTarget;
+
+ @Test
+ public void emptyMapNoTargetGenericInfo() throws Exception {
+ Map<String, String> map = new HashMap<String, String>();
+ assertTrue(conversionService.canConvert(Map.class, Map.class));
+ assertSame(map, conversionService.convert(map, Map.class));
+ }
+
+ @Test
+ public void emptyMapDifferentTargetImplType() throws Exception {
+ Map<String, String> map = new HashMap<String, String>();
+ TypeDescriptor sourceType = TypeDescriptor.forObject(map);
+ TypeDescriptor targetType = new TypeDescriptor(getClass().getField("emptyMapDifferentTarget"));
+ assertTrue(conversionService.canConvert(sourceType, targetType));
+ @SuppressWarnings("unchecked")
+ LinkedHashMap<String, String> result = (LinkedHashMap<String, String>) conversionService.convert(map, sourceType, targetType);
+ assertEquals(map, result);
+ assertEquals(LinkedHashMap.class, result.getClass());
+ }
+
+ public LinkedHashMap<String, String> emptyMapDifferentTarget;
+
+ @Test
+ public void noDefaultConstructorCopyNotRequired() throws Exception {
+ // SPR-9284
+ NoDefaultConstructorMap<String, Integer> map = new NoDefaultConstructorMap<String,Integer>(
+ Collections.<String, Integer> singletonMap("1", 1));
+ TypeDescriptor sourceType = TypeDescriptor.map(NoDefaultConstructorMap.class,
+ TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(Integer.class));
+ TypeDescriptor targetType = TypeDescriptor.map(NoDefaultConstructorMap.class,
+ TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(Integer.class));
+ assertTrue(conversionService.canConvert(sourceType, targetType));
+ @SuppressWarnings("unchecked")
+ Map<String, Integer> result = (Map<String, Integer>) conversionService.convert(map, sourceType, targetType);
+ assertEquals(map, result);
+ assertEquals(NoDefaultConstructorMap.class, result.getClass());
+ }
+
+ @SuppressWarnings("serial")
+ public static class NoDefaultConstructorMap<K, V> extends HashMap<K, V> {
+ public NoDefaultConstructorMap(Map<? extends K, ? extends V> m) {
+ super(m);
+ }
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/enums/LabeledEnumTests.java b/spring-core/src/test/java/org/springframework/core/enums/LabeledEnumTests.java
new file mode 100644
index 00000000..de0fccf4
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/enums/LabeledEnumTests.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.enums;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Keith Donald
+ * @author Juergen Hoeller
+ * @author Sam Brannen
+ */
+@Deprecated
+public class LabeledEnumTests extends TestCase {
+
+ private byte[] serializeObject(final Object obj) throws IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ oos.writeObject(obj);
+ oos.close();
+ return baos.toByteArray();
+ }
+
+ private Object deserializeObject(final byte[] serializedBytes) throws IOException, ClassNotFoundException {
+ ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(serializedBytes));
+ Object obj = ois.readObject();
+ ois.close();
+ return obj;
+ }
+
+ private Object serializeAndDeserializeObject(Object obj) throws IOException, ClassNotFoundException {
+ return deserializeObject(serializeObject(obj));
+ }
+
+ public void testCodeFound() {
+ Dog golden = (Dog) StaticLabeledEnumResolver.instance().getLabeledEnumByCode(Dog.class, new Short((short) 11));
+ Dog borderCollie = (Dog) StaticLabeledEnumResolver.instance().getLabeledEnumByCode(Dog.class,
+ new Short((short) 13));
+ assertSame(golden, Dog.GOLDEN_RETRIEVER);
+ assertSame(borderCollie, Dog.BORDER_COLLIE);
+ }
+
+ public void testCodeFoundForAbstractEnums() {
+ ValuedEnum one = (ValuedEnum) StaticLabeledEnumResolver.instance().getLabeledEnumByCode(ValuedEnum.class,
+ new Short((short) 1));
+ ValuedEnum two = (ValuedEnum) StaticLabeledEnumResolver.instance().getLabeledEnumByCode(ValuedEnum.class,
+ new Short((short) 2));
+ assertSame(one, ValuedEnum.ONE);
+ assertSame(two, ValuedEnum.TWO);
+ }
+
+ public void testDeserializationOfInnerClassEnums() throws Exception {
+ assertSame(serializeAndDeserializeObject(Other.THING1), Other.THING1);
+ }
+
+ public void testDeserializationOfStandAloneEnums() throws Exception {
+ assertSame(serializeAndDeserializeObject(StandAloneStaticLabeledEnum.ENUM1),
+ StandAloneStaticLabeledEnum.ENUM1);
+ }
+
+ public void testLabelFound() {
+ Dog golden = (Dog) StaticLabeledEnumResolver.instance().getLabeledEnumByLabel(Dog.class, "Golden Retriever");
+ Dog borderCollie = (Dog) StaticLabeledEnumResolver.instance().getLabeledEnumByLabel(Dog.class, "Border Collie");
+ assertSame(golden, Dog.GOLDEN_RETRIEVER);
+ assertSame(borderCollie, Dog.BORDER_COLLIE);
+ }
+
+ public void testLabelFoundForStandAloneEnum() {
+ StandAloneStaticLabeledEnum enum1 = (StandAloneStaticLabeledEnum)
+ StaticLabeledEnumResolver.instance().getLabeledEnumByLabel(StandAloneStaticLabeledEnum.class, "Enum1");
+ StandAloneStaticLabeledEnum enum2 = (StandAloneStaticLabeledEnum)
+ StaticLabeledEnumResolver.instance().getLabeledEnumByLabel(StandAloneStaticLabeledEnum.class, "Enum2");
+ assertSame(enum1, StandAloneStaticLabeledEnum.ENUM1);
+ assertSame(enum2, StandAloneStaticLabeledEnum.ENUM2);
+ }
+
+ public void testLabelFoundForAbstractEnums() {
+ ValuedEnum one = (ValuedEnum)
+ StaticLabeledEnumResolver.instance().getLabeledEnumByLabel(ValuedEnum.class, "one");
+ ValuedEnum two = (ValuedEnum)
+ StaticLabeledEnumResolver.instance().getLabeledEnumByLabel(ValuedEnum.class, "two");
+ assertSame(one, ValuedEnum.ONE);
+ assertSame(two, ValuedEnum.TWO);
+ }
+
+ public void testDoesNotMatchWrongClass() {
+ try {
+ StaticLabeledEnumResolver.instance().getLabeledEnumByCode(Dog.class,
+ new Short((short) 1));
+ fail("Should have failed");
+ }
+ catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ public void testEquals() {
+ assertEquals("Code equality means equals", Dog.GOLDEN_RETRIEVER, new Dog(11, "Golden Retriever"));
+ assertFalse("Code inequality means notEquals", Dog.GOLDEN_RETRIEVER.equals(new Dog(12, "Golden Retriever")));
+ }
+
+
+ @SuppressWarnings({ "serial", "unused" })
+ private static class Other extends StaticLabeledEnum {
+
+ public static final Other THING1 = new Other(1, "Thing1");
+
+ public static final Other THING2 = new Other(2, "Thing2");
+
+
+ private Other(int code, String name) {
+ super(code, name);
+ }
+ }
+
+
+ @SuppressWarnings("serial")
+ private static class Dog extends StaticLabeledEnum {
+
+ public static final Dog GOLDEN_RETRIEVER = new Dog(11, null) {
+
+ @Override
+ public String getLabel() {
+ return "Golden Retriever";
+ }
+
+ // Overriding getType() is no longer necessary as of Spring 2.5;
+ // however, this is left here to provide valid testing for
+ // backwards compatibility.
+ @Override
+ public Class getType() {
+ return Dog.class;
+ }
+ };
+
+ public static final Dog BORDER_COLLIE = new Dog(13, "Border Collie");
+ public static final Dog WHIPPET = new Dog(14, "Whippet");
+
+ // Ignore this
+ public static final Other THING1 = Other.THING1;
+
+
+ private Dog(int code, String name) {
+ super(code, name);
+ }
+ }
+
+
+ @SuppressWarnings("serial")
+ private static abstract class ValuedEnum extends StaticLabeledEnum {
+
+ public static final ValuedEnum ONE = new ValuedEnum(1, "one") {
+ @Override
+ public int getValue() {
+ return 1;
+ }
+ };
+
+ public static final ValuedEnum TWO = new ValuedEnum(2, "two") {
+ @Override
+ public int getValue() {
+ return 2;
+ }
+ };
+
+ private ValuedEnum(int code, String name) {
+ super(code, name);
+ }
+
+ public abstract int getValue();
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/enums/StandAloneStaticLabeledEnum.java b/spring-core/src/test/java/org/springframework/core/enums/StandAloneStaticLabeledEnum.java
new file mode 100644
index 00000000..078f3986
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/enums/StandAloneStaticLabeledEnum.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.enums;
+
+/**
+ * Stand-alone static enum for use in {@link LabeledEnumTests}.
+ *
+ * @author Sam Brannen
+ * @since 2.5
+ */
+public class StandAloneStaticLabeledEnum extends StaticLabeledEnum {
+
+ private static final long serialVersionUID = 1L;
+
+ public static final StandAloneStaticLabeledEnum ENUM1 = new StandAloneStaticLabeledEnum(1, "Enum1");
+ public static final StandAloneStaticLabeledEnum ENUM2 = new StandAloneStaticLabeledEnum(2, "Enum2");
+
+
+ private StandAloneStaticLabeledEnum(int code, String name) {
+ super(code, name);
+ }
+}
diff --git a/spring-core/src/test/java/org/springframework/core/env/CustomEnvironmentTests.java b/spring-core/src/test/java/org/springframework/core/env/CustomEnvironmentTests.java
new file mode 100644
index 00000000..0f8a6c36
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/env/CustomEnvironmentTests.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2002-2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.env;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.junit.Test;
+
+/**
+ * Unit tests covering the extensibility of {@link AbstractEnvironment}.
+ *
+ * @author Chris Beams
+ * @since 3.1
+ */
+public class CustomEnvironmentTests {
+
+ // -- tests relating to customizing reserved default profiles ----------------------
+
+ @Test
+ public void control() {
+ Environment env = new AbstractEnvironment() { };
+ assertThat(env.acceptsProfiles(AbstractEnvironment.RESERVED_DEFAULT_PROFILE_NAME), is(true));
+ }
+
+ @Test
+ public void withNoReservedDefaultProfile() {
+ class CustomEnvironment extends AbstractEnvironment {
+ @Override
+ protected Set<String> getReservedDefaultProfiles() {
+ return Collections.emptySet();
+ }
+ }
+
+ Environment env = new CustomEnvironment();
+ assertThat(env.acceptsProfiles(AbstractEnvironment.RESERVED_DEFAULT_PROFILE_NAME), is(false));
+ }
+
+ @Test
+ public void withSingleCustomReservedDefaultProfile() {
+ class CustomEnvironment extends AbstractEnvironment {
+ @Override
+ protected Set<String> getReservedDefaultProfiles() {
+ return Collections.singleton("rd1");
+ }
+ }
+
+ Environment env = new CustomEnvironment();
+ assertThat(env.acceptsProfiles(AbstractEnvironment.RESERVED_DEFAULT_PROFILE_NAME), is(false));
+ assertThat(env.acceptsProfiles("rd1"), is(true));
+ }
+
+ @Test
+ public void withMultiCustomReservedDefaultProfile() {
+ class CustomEnvironment extends AbstractEnvironment {
+ @Override
+ @SuppressWarnings("serial")
+ protected Set<String> getReservedDefaultProfiles() {
+ return new HashSet<String>() {{ add("rd1"); add("rd2"); }};
+ }
+ }
+
+ ConfigurableEnvironment env = new CustomEnvironment();
+ assertThat(env.acceptsProfiles(AbstractEnvironment.RESERVED_DEFAULT_PROFILE_NAME), is(false));
+ assertThat(env.acceptsProfiles("rd1", "rd2"), is(true));
+
+ // finally, issue additional assertions to cover all combinations of calling these
+ // methods, however unlikely.
+ env.setDefaultProfiles("d1");
+ assertThat(env.acceptsProfiles("rd1", "rd2"), is(false));
+ assertThat(env.acceptsProfiles("d1"), is(true));
+
+ env.setActiveProfiles("a1", "a2");
+ assertThat(env.acceptsProfiles("d1"), is(false));
+ assertThat(env.acceptsProfiles("a1", "a2"), is(true));
+
+ env.setActiveProfiles();
+ assertThat(env.acceptsProfiles("d1"), is(true));
+ assertThat(env.acceptsProfiles("a1", "a2"), is(false));
+
+ env.setDefaultProfiles();
+ assertThat(env.acceptsProfiles(AbstractEnvironment.RESERVED_DEFAULT_PROFILE_NAME), is(false));
+ assertThat(env.acceptsProfiles("rd1", "rd2"), is(false));
+ assertThat(env.acceptsProfiles("d1"), is(false));
+ assertThat(env.acceptsProfiles("a1", "a2"), is(false));
+ }
+
+
+ // -- tests relating to customizing property sources -------------------------------
+}
diff --git a/spring-core/src/test/java/org/springframework/core/env/DummyEnvironment.java b/spring-core/src/test/java/org/springframework/core/env/DummyEnvironment.java
new file mode 100644
index 00000000..88d9347d
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/env/DummyEnvironment.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.env;
+
+public class DummyEnvironment implements Environment {
+
+ public boolean containsProperty(String key) {
+ return false;
+ }
+
+ public String getProperty(String key) {
+ return null;
+ }
+
+ public String getProperty(String key, String defaultValue) {
+ return null;
+ }
+
+ public <T> T getProperty(String key, Class<T> targetType) {
+ return null;
+ }
+
+ public <T> T getProperty(String key, Class<T> targetType, T defaultValue) {
+ return null;
+ }
+
+ public <T> Class<T> getPropertyAsClass(String key, Class<T> targetType) {
+ return null;
+ }
+
+ public String getRequiredProperty(String key) throws IllegalStateException {
+ return null;
+ }
+
+ public <T> T getRequiredProperty(String key, Class<T> targetType)
+ throws IllegalStateException {
+ return null;
+ }
+
+ public String resolvePlaceholders(String text) {
+ return null;
+ }
+
+ public String resolveRequiredPlaceholders(String text)
+ throws IllegalArgumentException {
+ return null;
+ }
+
+ public String[] getActiveProfiles() {
+ return null;
+ }
+
+ public String[] getDefaultProfiles() {
+ return null;
+ }
+
+ public boolean acceptsProfiles(String... profiles) {
+ return false;
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/env/JOptCommandLinePropertySourceTests.java b/spring-core/src/test/java/org/springframework/core/env/JOptCommandLinePropertySourceTests.java
new file mode 100644
index 00000000..6eced35d
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/env/JOptCommandLinePropertySourceTests.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2002-2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.env;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+import java.util.Arrays;
+
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link JOptCommandLinePropertySource}.
+ *
+ * @author Chris Beams
+ * @since 3.1
+ */
+public class JOptCommandLinePropertySourceTests {
+
+ @Test
+ public void withRequiredArg_andArgIsPresent() {
+ OptionParser parser = new OptionParser();
+ parser.accepts("foo").withRequiredArg();
+ OptionSet options = parser.parse("--foo=bar");
+
+ PropertySource<?> ps = new JOptCommandLinePropertySource(options);
+ assertThat((String)ps.getProperty("foo"), equalTo("bar"));
+ }
+
+ @Test
+ public void withOptionalArg_andArgIsMissing() {
+ OptionParser parser = new OptionParser();
+ parser.accepts("foo").withOptionalArg();
+ OptionSet options = parser.parse("--foo");
+
+ PropertySource<?> ps = new JOptCommandLinePropertySource(options);
+ assertThat(ps.containsProperty("foo"), is(true));
+ assertThat((String)ps.getProperty("foo"), equalTo(""));
+ }
+
+ @Test
+ public void withNoArg() {
+ OptionParser parser = new OptionParser();
+ parser.accepts("o1");
+ parser.accepts("o2");
+ OptionSet options = parser.parse("--o1");
+
+ PropertySource<?> ps = new JOptCommandLinePropertySource(options);
+ assertThat(ps.containsProperty("o1"), is(true));
+ assertThat(ps.containsProperty("o2"), is(false));
+ assertThat((String)ps.getProperty("o1"), equalTo(""));
+ assertThat(ps.getProperty("o2"), nullValue());
+ }
+
+ @Test
+ public void withRequiredArg_andMultipleArgsPresent_usingDelimiter() {
+ OptionParser parser = new OptionParser();
+ parser.accepts("foo").withRequiredArg().withValuesSeparatedBy(',');
+ OptionSet options = parser.parse("--foo=bar,baz,biz");
+
+ CommandLinePropertySource<?> ps = new JOptCommandLinePropertySource(options);
+ assertEquals(Arrays.asList("bar","baz","biz"), ps.getOptionValues("foo"));
+ assertThat(ps.getProperty("foo"), equalTo("bar,baz,biz"));
+ }
+
+ @Test
+ public void withRequiredArg_andMultipleArgsPresent_usingRepeatedOption() {
+ OptionParser parser = new OptionParser();
+ parser.accepts("foo").withRequiredArg().withValuesSeparatedBy(',');
+ OptionSet options = parser.parse("--foo=bar", "--foo=baz", "--foo=biz");
+
+ CommandLinePropertySource<?> ps = new JOptCommandLinePropertySource(options);
+ assertEquals(Arrays.asList("bar","baz","biz"), ps.getOptionValues("foo"));
+ assertThat(ps.getProperty("foo"), equalTo("bar,baz,biz"));
+ }
+
+ @Test
+ public void withMissingOption() {
+ OptionParser parser = new OptionParser();
+ parser.accepts("foo").withRequiredArg().withValuesSeparatedBy(',');
+ OptionSet options = parser.parse(); // <-- no options whatsoever
+
+ PropertySource<?> ps = new JOptCommandLinePropertySource(options);
+ assertThat(ps.getProperty("foo"), nullValue());
+ }
+
+ @Test
+ public void withDottedOptionName() {
+ OptionParser parser = new OptionParser();
+ parser.accepts("spring.profiles.active").withRequiredArg();
+ OptionSet options = parser.parse("--spring.profiles.active=p1");
+
+ CommandLinePropertySource<?> ps = new JOptCommandLinePropertySource(options);
+ assertThat(ps.getProperty("spring.profiles.active"), equalTo("p1"));
+ }
+
+ @Test
+ public void withDefaultNonOptionArgsNameAndNoNonOptionArgsPresent() {
+ OptionParser parser = new OptionParser();
+ parser.accepts("o1").withRequiredArg();
+ parser.accepts("o2");
+ OptionSet optionSet = parser.parse("--o1=v1", "--o2");
+ PropertySource<?> ps = new JOptCommandLinePropertySource(optionSet);
+
+ assertThat(ps.containsProperty("nonOptionArgs"), is(false));
+ assertThat(ps.containsProperty("o1"), is(true));
+ assertThat(ps.containsProperty("o2"), is(true));
+
+ assertThat(ps.containsProperty("nonOptionArgs"), is(false));
+ assertThat(ps.getProperty("nonOptionArgs"), nullValue());
+ }
+
+ @Test
+ public void withDefaultNonOptionArgsNameAndNonOptionArgsPresent() {
+ OptionParser parser = new OptionParser();
+ parser.accepts("o1").withRequiredArg();
+ parser.accepts("o2");
+ OptionSet optionSet = parser.parse("--o1=v1", "noa1", "--o2", "noa2");
+ PropertySource<?> ps = new JOptCommandLinePropertySource(optionSet);
+
+ assertThat(ps.containsProperty("nonOptionArgs"), is(true));
+ assertThat(ps.containsProperty("o1"), is(true));
+ assertThat(ps.containsProperty("o2"), is(true));
+
+ String nonOptionArgs = (String)ps.getProperty("nonOptionArgs");
+ assertThat(nonOptionArgs, equalTo("noa1,noa2"));
+ }
+
+ @Test
+ public void withCustomNonOptionArgsNameAndNoNonOptionArgsPresent() {
+ OptionParser parser = new OptionParser();
+ parser.accepts("o1").withRequiredArg();
+ parser.accepts("o2");
+ OptionSet optionSet = parser.parse("--o1=v1", "noa1", "--o2", "noa2");
+ CommandLinePropertySource<?> ps = new JOptCommandLinePropertySource(optionSet);
+ ps.setNonOptionArgsPropertyName("NOA");
+
+ assertThat(ps.containsProperty("nonOptionArgs"), is(false));
+ assertThat(ps.containsProperty("NOA"), is(true));
+ assertThat(ps.containsProperty("o1"), is(true));
+ assertThat(ps.containsProperty("o2"), is(true));
+ String nonOptionArgs = ps.getProperty("NOA");
+ assertThat(nonOptionArgs, equalTo("noa1,noa2"));
+ }
+}
diff --git a/spring-core/src/test/java/org/springframework/core/env/MutablePropertySourcesTests.java b/spring-core/src/test/java/org/springframework/core/env/MutablePropertySourcesTests.java
new file mode 100644
index 00000000..747c30b1
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/env/MutablePropertySourcesTests.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.env;
+
+import org.junit.Test;
+import org.springframework.mock.env.MockPropertySource;
+
+import static java.lang.String.*;
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+import static org.springframework.core.env.MutablePropertySources.*;
+
+/**
+ * Unit tests for {@link MutablePropertySources}
+ *
+ * @author Chris Beams
+ */
+public class MutablePropertySourcesTests {
+
+ @Test
+ public void test() {
+ MutablePropertySources sources = new MutablePropertySources();
+ sources.addLast(new MockPropertySource("b").withProperty("p1", "bValue"));
+ sources.addLast(new MockPropertySource("d").withProperty("p1", "dValue"));
+ sources.addLast(new MockPropertySource("f").withProperty("p1", "fValue"));
+
+ assertThat(sources.size(), equalTo(3));
+ assertThat(sources.contains("a"), is(false));
+ assertThat(sources.contains("b"), is(true));
+ assertThat(sources.contains("c"), is(false));
+ assertThat(sources.contains("d"), is(true));
+ assertThat(sources.contains("e"), is(false));
+ assertThat(sources.contains("f"), is(true));
+ assertThat(sources.contains("g"), is(false));
+
+ assertThat(sources.get("b"), not(nullValue()));
+ assertThat(sources.get("b").getProperty("p1"), equalTo((Object)"bValue"));
+ assertThat(sources.get("d"), not(nullValue()));
+ assertThat(sources.get("d").getProperty("p1"), equalTo((Object)"dValue"));
+
+ sources.addBefore("b", new MockPropertySource("a"));
+ sources.addAfter("b", new MockPropertySource("c"));
+
+ assertThat(sources.size(), equalTo(5));
+ assertThat(sources.precedenceOf(PropertySource.named("a")), is(0));
+ assertThat(sources.precedenceOf(PropertySource.named("b")), is(1));
+ assertThat(sources.precedenceOf(PropertySource.named("c")), is(2));
+ assertThat(sources.precedenceOf(PropertySource.named("d")), is(3));
+ assertThat(sources.precedenceOf(PropertySource.named("f")), is(4));
+
+ sources.addBefore("f", new MockPropertySource("e"));
+ sources.addAfter("f", new MockPropertySource("g"));
+
+ assertThat(sources.size(), equalTo(7));
+ assertThat(sources.precedenceOf(PropertySource.named("a")), is(0));
+ assertThat(sources.precedenceOf(PropertySource.named("b")), is(1));
+ assertThat(sources.precedenceOf(PropertySource.named("c")), is(2));
+ assertThat(sources.precedenceOf(PropertySource.named("d")), is(3));
+ assertThat(sources.precedenceOf(PropertySource.named("e")), is(4));
+ assertThat(sources.precedenceOf(PropertySource.named("f")), is(5));
+ assertThat(sources.precedenceOf(PropertySource.named("g")), is(6));
+
+ sources.addLast(new MockPropertySource("a"));
+ assertThat(sources.size(), equalTo(7));
+ assertThat(sources.precedenceOf(PropertySource.named("b")), is(0));
+ assertThat(sources.precedenceOf(PropertySource.named("c")), is(1));
+ assertThat(sources.precedenceOf(PropertySource.named("d")), is(2));
+ assertThat(sources.precedenceOf(PropertySource.named("e")), is(3));
+ assertThat(sources.precedenceOf(PropertySource.named("f")), is(4));
+ assertThat(sources.precedenceOf(PropertySource.named("g")), is(5));
+ assertThat(sources.precedenceOf(PropertySource.named("a")), is(6));
+
+ sources.addFirst(new MockPropertySource("a"));
+ assertThat(sources.size(), equalTo(7));
+ assertThat(sources.precedenceOf(PropertySource.named("a")), is(0));
+ assertThat(sources.precedenceOf(PropertySource.named("b")), is(1));
+ assertThat(sources.precedenceOf(PropertySource.named("c")), is(2));
+ assertThat(sources.precedenceOf(PropertySource.named("d")), is(3));
+ assertThat(sources.precedenceOf(PropertySource.named("e")), is(4));
+ assertThat(sources.precedenceOf(PropertySource.named("f")), is(5));
+ assertThat(sources.precedenceOf(PropertySource.named("g")), is(6));
+
+ assertEquals(sources.remove("a"), PropertySource.named("a"));
+ assertThat(sources.size(), equalTo(6));
+ assertThat(sources.contains("a"), is(false));
+
+ assertEquals(sources.remove("a"), null);
+ assertThat(sources.size(), equalTo(6));
+
+ String bogusPS = "bogus";
+ try {
+ sources.addAfter(bogusPS, new MockPropertySource("h"));
+ fail("expected non-existent PropertySource exception");
+ } catch (IllegalArgumentException ex) {
+ assertThat(ex.getMessage(),
+ equalTo(format(NON_EXISTENT_PROPERTY_SOURCE_MESSAGE, bogusPS)));
+ }
+
+ sources.addFirst(new MockPropertySource("a"));
+ assertThat(sources.size(), equalTo(7));
+ assertThat(sources.precedenceOf(PropertySource.named("a")), is(0));
+ assertThat(sources.precedenceOf(PropertySource.named("b")), is(1));
+ assertThat(sources.precedenceOf(PropertySource.named("c")), is(2));
+
+ sources.replace("a", new MockPropertySource("a-replaced"));
+ assertThat(sources.size(), equalTo(7));
+ assertThat(sources.precedenceOf(PropertySource.named("a-replaced")), is(0));
+ assertThat(sources.precedenceOf(PropertySource.named("b")), is(1));
+ assertThat(sources.precedenceOf(PropertySource.named("c")), is(2));
+
+ sources.replace("a-replaced", new MockPropertySource("a"));
+
+ try {
+ sources.replace(bogusPS, new MockPropertySource("bogus-replaced"));
+ fail("expected non-existent PropertySource exception");
+ } catch (IllegalArgumentException ex) {
+ assertThat(ex.getMessage(),
+ equalTo(format(NON_EXISTENT_PROPERTY_SOURCE_MESSAGE, bogusPS)));
+ }
+
+ try {
+ sources.addBefore("b", new MockPropertySource("b"));
+ fail("expected exception");
+ } catch (IllegalArgumentException ex) {
+ assertThat(ex.getMessage(),
+ equalTo(format(ILLEGAL_RELATIVE_ADDITION_MESSAGE, "b")));
+ }
+
+ try {
+ sources.addAfter("b", new MockPropertySource("b"));
+ fail("expected exception");
+ } catch (IllegalArgumentException ex) {
+ assertThat(ex.getMessage(),
+ equalTo(format(ILLEGAL_RELATIVE_ADDITION_MESSAGE, "b")));
+ }
+ }
+
+ @Test
+ public void getNonExistentPropertySourceReturnsNull() {
+ MutablePropertySources sources = new MutablePropertySources();
+ assertThat(sources.get("bogus"), nullValue());
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/env/PropertySourceTests.java b/spring-core/src/test/java/org/springframework/core/env/PropertySourceTests.java
new file mode 100644
index 00000000..7bb57701
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/env/PropertySourceTests.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.env;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link AbstractPropertySource} implementations.
+ *
+ * @author Chris Beams
+ * @since 3.1
+ */
+public class PropertySourceTests {
+ @Test @SuppressWarnings("serial")
+ public void equals() {
+ Map<String, Object> map1 = new HashMap<String, Object>() {{ put("a", "b"); }};
+ Map<String, Object> map2 = new HashMap<String, Object>() {{ put("c", "d"); }};
+ Properties props1 = new Properties() {{ setProperty("a", "b"); }};
+ Properties props2 = new Properties() {{ setProperty("c", "d"); }};
+
+ MapPropertySource mps = new MapPropertySource("mps", map1);
+ assertThat(mps, equalTo(mps));
+
+ assertThat(new MapPropertySource("x", map1).equals(new MapPropertySource("x", map1)), is(true));
+ assertThat(new MapPropertySource("x", map1).equals(new MapPropertySource("x", map2)), is(true));
+ assertThat(new MapPropertySource("x", map1).equals(new PropertiesPropertySource("x", props1)), is(true));
+ assertThat(new MapPropertySource("x", map1).equals(new PropertiesPropertySource("x", props2)), is(true));
+
+ assertThat(new MapPropertySource("x", map1).equals(new Object()), is(false));
+ assertThat(new MapPropertySource("x", map1).equals("x"), is(false));
+ assertThat(new MapPropertySource("x", map1).equals(new MapPropertySource("y", map1)), is(false));
+ assertThat(new MapPropertySource("x", map1).equals(new MapPropertySource("y", map2)), is(false));
+ assertThat(new MapPropertySource("x", map1).equals(new PropertiesPropertySource("y", props1)), is(false));
+ assertThat(new MapPropertySource("x", map1).equals(new PropertiesPropertySource("y", props2)), is(false));
+ }
+
+ @Test @SuppressWarnings("serial")
+ public void collectionsOperations() {
+ Map<String, Object> map1 = new HashMap<String, Object>() {{ put("a", "b"); }};
+ Map<String, Object> map2 = new HashMap<String, Object>() {{ put("c", "d"); }};
+
+ PropertySource<?> ps1 = new MapPropertySource("ps1", map1);
+ ps1.getSource();
+ List<PropertySource<?>> propertySources = new ArrayList<PropertySource<?>>();
+ assertThat(propertySources.add(ps1), equalTo(true));
+ assertThat(propertySources.contains(ps1), is(true));
+ assertThat(propertySources.contains(PropertySource.named("ps1")), is(true));
+
+ PropertySource<?> ps1replacement = new MapPropertySource("ps1", map2); // notice - different map
+ assertThat(propertySources.add(ps1replacement), is(true)); // true because linkedlist allows duplicates
+ assertThat(propertySources.size(), is(2));
+ assertThat(propertySources.remove(PropertySource.named("ps1")), is(true));
+ assertThat(propertySources.size(), is(1));
+ assertThat(propertySources.remove(PropertySource.named("ps1")), is(true));
+ assertThat(propertySources.size(), is(0));
+
+ PropertySource<?> ps2 = new MapPropertySource("ps2", map2);
+ propertySources.add(ps1);
+ propertySources.add(ps2);
+ assertThat(propertySources.indexOf(PropertySource.named("ps1")), is(0));
+ assertThat(propertySources.indexOf(PropertySource.named("ps2")), is(1));
+ propertySources.clear();
+ }
+
+ @Test @SuppressWarnings("serial")
+ public void toString_verbosityVariesOnLogLevel() {
+ String name = "props";
+ Map<String, Object> map = new HashMap<String, Object>() {{ put("k1", "v1"); }};
+ MapPropertySource ps = new MapPropertySource(name, map);
+ Logger logger = Logger.getLogger(ps.getClass());
+ Level original = logger.getLevel();
+
+ try {
+ logger.setLevel(Level.DEBUG);
+ assertThat("PropertySource.toString() should render verbose output for log levels <= DEBUG",
+ ps.toString(),
+ equalTo(String.format("%s@%s [name='%s', properties=%s]",
+ ps.getClass().getSimpleName(),
+ System.identityHashCode(ps),
+ name,
+ map)));
+
+ logger.setLevel(Level.INFO);
+ assertThat("PropertySource.toString() should render concise output for log levels >= INFO",
+ ps.toString(),
+ equalTo(String.format("%s [name='%s']",
+ ps.getClass().getSimpleName(),
+ name,
+ map.size())));
+ } finally {
+ logger.setLevel(original);
+ }
+ }
+}
diff --git a/spring-core/src/test/java/org/springframework/core/env/PropertySourcesPropertyResolverTests.java b/spring-core/src/test/java/org/springframework/core/env/PropertySourcesPropertyResolverTests.java
new file mode 100644
index 00000000..84f6fce0
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/env/PropertySourcesPropertyResolverTests.java
@@ -0,0 +1,441 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.env;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.springframework.core.convert.ConversionException;
+import org.springframework.mock.env.MockPropertySource;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author Chris Beams
+ * @since 3.1
+ */
+public class PropertySourcesPropertyResolverTests {
+
+ private Properties testProperties;
+
+ private MutablePropertySources propertySources;
+
+ private ConfigurablePropertyResolver propertyResolver;
+
+
+ @Before
+ public void setUp() {
+ propertySources = new MutablePropertySources();
+ propertyResolver = new PropertySourcesPropertyResolver(propertySources);
+ testProperties = new Properties();
+ propertySources.addFirst(new PropertiesPropertySource("testProperties", testProperties));
+ }
+
+
+ @Test
+ public void containsProperty() {
+ assertThat(propertyResolver.containsProperty("foo"), is(false));
+ testProperties.put("foo", "bar");
+ assertThat(propertyResolver.containsProperty("foo"), is(true));
+ }
+
+ @Test
+ public void getProperty() {
+ assertThat(propertyResolver.getProperty("foo"), nullValue());
+ testProperties.put("foo", "bar");
+ assertThat(propertyResolver.getProperty("foo"), is("bar"));
+ }
+
+ @Test
+ public void getProperty_withDefaultValue() {
+ assertThat(propertyResolver.getProperty("foo", "myDefault"), is("myDefault"));
+ testProperties.put("foo", "bar");
+ assertThat(propertyResolver.getProperty("foo"), is("bar"));
+ }
+
+ @Test
+ public void getProperty_propertySourceSearchOrderIsFIFO() {
+ MutablePropertySources sources = new MutablePropertySources();
+ PropertyResolver resolver = new PropertySourcesPropertyResolver(sources);
+ sources.addFirst(new MockPropertySource("ps1").withProperty("pName", "ps1Value"));
+ assertThat(resolver.getProperty("pName"), equalTo("ps1Value"));
+ sources.addFirst(new MockPropertySource("ps2").withProperty("pName", "ps2Value"));
+ assertThat(resolver.getProperty("pName"), equalTo("ps2Value"));
+ sources.addFirst(new MockPropertySource("ps3").withProperty("pName", "ps3Value"));
+ assertThat(resolver.getProperty("pName"), equalTo("ps3Value"));
+ }
+
+ @Test
+ public void getProperty_withExplicitNullValue() {
+ // java.util.Properties does not allow null values (because Hashtable does not)
+ Map<String, Object> nullableProperties = new HashMap<String, Object>();
+ propertySources.addLast(new MapPropertySource("nullableProperties", nullableProperties));
+ nullableProperties.put("foo", null);
+ assertThat(propertyResolver.getProperty("foo"), nullValue());
+ }
+
+ @Test
+ public void getProperty_withTargetType_andDefaultValue() {
+ assertThat(propertyResolver.getProperty("foo", Integer.class, 42), equalTo(42));
+ testProperties.put("foo", 13);
+ assertThat(propertyResolver.getProperty("foo", Integer.class, 42), equalTo(13));
+ }
+
+ @Test
+ public void getProperty_withStringArrayConversion() {
+ testProperties.put("foo", "bar,baz");
+ assertThat(propertyResolver.getProperty("foo", String[].class), equalTo(new String[] { "bar", "baz" }));
+ }
+
+ @Test
+ public void getProperty_withNonConvertibleTargetType() {
+ testProperties.put("foo", "bar");
+
+ class TestType { }
+
+ try {
+ propertyResolver.getProperty("foo", TestType.class);
+ fail("Expected IllegalArgumentException due to non-convertible types");
+ }
+ catch (IllegalArgumentException ex) {
+ // expected
+ }
+ }
+
+ @Test
+ public void getProperty_doesNotCache_replaceExistingKeyPostConstruction() {
+ String key = "foo";
+ String value1 = "bar";
+ String value2 = "biz";
+
+ HashMap<String, Object> map = new HashMap<String, Object>();
+ map.put(key, value1); // before construction
+ MutablePropertySources propertySources = new MutablePropertySources();
+ propertySources.addFirst(new MapPropertySource("testProperties", map));
+ PropertyResolver propertyResolver = new PropertySourcesPropertyResolver(propertySources);
+ assertThat(propertyResolver.getProperty(key), equalTo(value1));
+ map.put(key, value2); // after construction and first resolution
+ assertThat(propertyResolver.getProperty(key), equalTo(value2));
+ }
+
+ @Test
+ public void getProperty_doesNotCache_addNewKeyPostConstruction() {
+ HashMap<String, Object> map = new HashMap<String, Object>();
+ MutablePropertySources propertySources = new MutablePropertySources();
+ propertySources.addFirst(new MapPropertySource("testProperties", map));
+ PropertyResolver propertyResolver = new PropertySourcesPropertyResolver(propertySources);
+ assertThat(propertyResolver.getProperty("foo"), equalTo(null));
+ map.put("foo", "42");
+ assertThat(propertyResolver.getProperty("foo"), equalTo("42"));
+ }
+
+ @Test
+ public void getPropertySources_replacePropertySource() {
+ propertySources = new MutablePropertySources();
+ propertyResolver = new PropertySourcesPropertyResolver(propertySources);
+ propertySources.addLast(new MockPropertySource("local").withProperty("foo", "localValue"));
+ propertySources.addLast(new MockPropertySource("system").withProperty("foo", "systemValue"));
+
+ // 'local' was added first so has precedence
+ assertThat(propertyResolver.getProperty("foo"), equalTo("localValue"));
+
+ // replace 'local' with new property source
+ propertySources.replace("local", new MockPropertySource("new").withProperty("foo", "newValue"));
+
+ // 'system' now has precedence
+ assertThat(propertyResolver.getProperty("foo"), equalTo("newValue"));
+
+ assertThat(propertySources.size(), is(2));
+ }
+
+ @Test
+ public void getRequiredProperty() {
+ testProperties.put("exists", "xyz");
+ assertThat(propertyResolver.getRequiredProperty("exists"), is("xyz"));
+
+ try {
+ propertyResolver.getRequiredProperty("bogus");
+ fail("expected IllegalStateException");
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ }
+ }
+
+ @Test
+ public void getRequiredProperty_withStringArrayConversion() {
+ testProperties.put("exists", "abc,123");
+ assertThat(propertyResolver.getRequiredProperty("exists", String[].class), equalTo(new String[] { "abc", "123" }));
+
+ try {
+ propertyResolver.getRequiredProperty("bogus", String[].class);
+ fail("expected IllegalStateException");
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ }
+ }
+
+ @Test
+ public void resolvePlaceholders() {
+ MutablePropertySources propertySources = new MutablePropertySources();
+ propertySources.addFirst(new MockPropertySource().withProperty("key", "value"));
+ PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
+ assertThat(resolver.resolvePlaceholders("Replace this ${key}"), equalTo("Replace this value"));
+ }
+
+ @Test
+ public void resolvePlaceholders_withUnresolvable() {
+ MutablePropertySources propertySources = new MutablePropertySources();
+ propertySources.addFirst(new MockPropertySource().withProperty("key", "value"));
+ PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
+ assertThat(resolver.resolvePlaceholders("Replace this ${key} plus ${unknown}"),
+ equalTo("Replace this value plus ${unknown}"));
+ }
+
+ @Test
+ public void resolvePlaceholders_withDefaultValue() {
+ MutablePropertySources propertySources = new MutablePropertySources();
+ propertySources.addFirst(new MockPropertySource().withProperty("key", "value"));
+ PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
+ assertThat(resolver.resolvePlaceholders("Replace this ${key} plus ${unknown:defaultValue}"),
+ equalTo("Replace this value plus defaultValue"));
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void resolvePlaceholders_withNullInput() {
+ new PropertySourcesPropertyResolver(new MutablePropertySources()).resolvePlaceholders(null);
+ }
+
+ @Test
+ public void resolveRequiredPlaceholders() {
+ MutablePropertySources propertySources = new MutablePropertySources();
+ propertySources.addFirst(new MockPropertySource().withProperty("key", "value"));
+ PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
+ assertThat(resolver.resolveRequiredPlaceholders("Replace this ${key}"), equalTo("Replace this value"));
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void resolveRequiredPlaceholders_withUnresolvable() {
+ MutablePropertySources propertySources = new MutablePropertySources();
+ propertySources.addFirst(new MockPropertySource().withProperty("key", "value"));
+ PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
+ resolver.resolveRequiredPlaceholders("Replace this ${key} plus ${unknown}");
+ }
+
+ @Test
+ public void resolveRequiredPlaceholders_withDefaultValue() {
+ MutablePropertySources propertySources = new MutablePropertySources();
+ propertySources.addFirst(new MockPropertySource().withProperty("key", "value"));
+ PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
+ assertThat(resolver.resolveRequiredPlaceholders("Replace this ${key} plus ${unknown:defaultValue}"),
+ equalTo("Replace this value plus defaultValue"));
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void resolveRequiredPlaceholders_withNullInput() {
+ new PropertySourcesPropertyResolver(new MutablePropertySources()).resolveRequiredPlaceholders(null);
+ }
+
+ @Test
+ public void getPropertyAsClass() throws ClassNotFoundException, LinkageError {
+ MutablePropertySources propertySources = new MutablePropertySources();
+ propertySources.addFirst(new MockPropertySource().withProperty("some.class", SpecificType.class.getName()));
+ PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
+ assertTrue(resolver.getPropertyAsClass("some.class", SomeType.class).equals(SpecificType.class));
+ }
+
+ @Test
+ public void getPropertyAsClass_withInterfaceAsTarget() throws ClassNotFoundException, LinkageError {
+ MutablePropertySources propertySources = new MutablePropertySources();
+ propertySources.addFirst(new MockPropertySource().withProperty("some.class", SomeType.class.getName()));
+ PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
+ assertTrue(resolver.getPropertyAsClass("some.class", SomeType.class).equals(SomeType.class));
+ }
+
+ @Test(expected=ConversionException.class)
+ public void getPropertyAsClass_withMismatchedTypeForValue() {
+ MutablePropertySources propertySources = new MutablePropertySources();
+ propertySources.addFirst(new MockPropertySource().withProperty("some.class", "java.lang.String"));
+ PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
+ resolver.getPropertyAsClass("some.class", SomeType.class);
+ }
+
+ @Test(expected=ConversionException.class)
+ public void getPropertyAsClass_withNonExistentClassForValue() {
+ MutablePropertySources propertySources = new MutablePropertySources();
+ propertySources.addFirst(new MockPropertySource().withProperty("some.class", "some.bogus.Class"));
+ PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
+ resolver.getPropertyAsClass("some.class", SomeType.class);
+ }
+
+ @Test
+ public void getPropertyAsClass_withObjectForValue() {
+ MutablePropertySources propertySources = new MutablePropertySources();
+ propertySources.addFirst(new MockPropertySource().withProperty("some.class", new SpecificType()));
+ PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
+ assertTrue(resolver.getPropertyAsClass("some.class", SomeType.class).equals(SpecificType.class));
+ }
+
+ @Test(expected=ConversionException.class)
+ public void getPropertyAsClass_withMismatchedObjectForValue() {
+ MutablePropertySources propertySources = new MutablePropertySources();
+ propertySources.addFirst(new MockPropertySource().withProperty("some.class", new Integer(42)));
+ PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
+ resolver.getPropertyAsClass("some.class", SomeType.class);
+ }
+
+ @Test
+ public void getPropertyAsClass_withRealClassForValue() {
+ MutablePropertySources propertySources = new MutablePropertySources();
+ propertySources.addFirst(new MockPropertySource().withProperty("some.class", SpecificType.class));
+ PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
+ assertTrue(resolver.getPropertyAsClass("some.class", SomeType.class).equals(SpecificType.class));
+ }
+
+ @Test(expected=ConversionException.class)
+ public void getPropertyAsClass_withMismatchedRealClassForValue() {
+ MutablePropertySources propertySources = new MutablePropertySources();
+ propertySources.addFirst(new MockPropertySource().withProperty("some.class", Integer.class));
+ PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
+ resolver.getPropertyAsClass("some.class", SomeType.class);
+ }
+
+ @Test
+ public void setRequiredProperties_andValidateRequiredProperties() {
+ // no properties have been marked as required -> validation should pass
+ propertyResolver.validateRequiredProperties();
+
+ // mark which properties are required
+ propertyResolver.setRequiredProperties("foo", "bar");
+
+ // neither foo nor bar properties are present -> validating should throw
+ try {
+ propertyResolver.validateRequiredProperties();
+ fail("expected validation exception");
+ }
+ catch (MissingRequiredPropertiesException ex) {
+ assertThat(ex.getMessage(), equalTo(
+ "The following properties were declared as required " +
+ "but could not be resolved: [foo, bar]"));
+ }
+
+ // add foo property -> validation should fail only on missing 'bar' property
+ testProperties.put("foo", "fooValue");
+ try {
+ propertyResolver.validateRequiredProperties();
+ fail("expected validation exception");
+ }
+ catch (MissingRequiredPropertiesException ex) {
+ assertThat(ex.getMessage(), equalTo(
+ "The following properties were declared as required " +
+ "but could not be resolved: [bar]"));
+ }
+
+ // add bar property -> validation should pass, even with an empty string value
+ testProperties.put("bar", "");
+ propertyResolver.validateRequiredProperties();
+ }
+
+ @Test
+ public void resolveNestedPropertyPlaceholders() {
+ MutablePropertySources ps = new MutablePropertySources();
+ ps.addFirst(new MockPropertySource()
+ .withProperty("p1", "v1")
+ .withProperty("p2", "v2")
+ .withProperty("p3", "${p1}:${p2}") // nested placeholders
+ .withProperty("p4", "${p3}") // deeply nested placeholders
+ .withProperty("p5", "${p1}:${p2}:${bogus}") // unresolvable placeholder
+ .withProperty("p6", "${p1}:${p2}:${bogus:def}") // unresolvable w/ default
+ .withProperty("pL", "${pR}") // cyclic reference left
+ .withProperty("pR", "${pL}") // cyclic reference right
+ );
+ ConfigurablePropertyResolver pr = new PropertySourcesPropertyResolver(ps);
+ assertThat(pr.getProperty("p1"), equalTo("v1"));
+ assertThat(pr.getProperty("p2"), equalTo("v2"));
+ assertThat(pr.getProperty("p3"), equalTo("v1:v2"));
+ assertThat(pr.getProperty("p4"), equalTo("v1:v2"));
+ try {
+ pr.getProperty("p5");
+ }
+ catch (IllegalArgumentException ex) {
+ assertThat(ex.getMessage(), containsString(
+ "Could not resolve placeholder 'bogus' in string value \"${p1}:${p2}:${bogus}\""));
+ }
+ assertThat(pr.getProperty("p6"), equalTo("v1:v2:def"));
+ try {
+ pr.getProperty("pL");
+ }
+ catch (IllegalArgumentException ex) {
+ assertTrue(ex.getMessage().toLowerCase().contains("circular"));
+ }
+ }
+
+ @Test
+ public void ignoreUnresolvableNestedPlaceholdersIsConfigurable() {
+ MutablePropertySources ps = new MutablePropertySources();
+ ps.addFirst(new MockPropertySource()
+ .withProperty("p1", "v1")
+ .withProperty("p2", "v2")
+ .withProperty("p3", "${p1}:${p2}:${bogus:def}") // unresolvable w/ default
+ .withProperty("p4", "${p1}:${p2}:${bogus}") // unresolvable placeholder
+ );
+ ConfigurablePropertyResolver pr = new PropertySourcesPropertyResolver(ps);
+ assertThat(pr.getProperty("p1"), equalTo("v1"));
+ assertThat(pr.getProperty("p2"), equalTo("v2"));
+ assertThat(pr.getProperty("p3"), equalTo("v1:v2:def"));
+
+ // placeholders nested within the value of "p4" are unresolvable and cause an
+ // exception by default
+ try {
+ pr.getProperty("p4");
+ }
+ catch (IllegalArgumentException ex) {
+ assertThat(ex.getMessage(), containsString(
+ "Could not resolve placeholder 'bogus' in string value \"${p1}:${p2}:${bogus}\""));
+ }
+
+ // relax the treatment of unresolvable nested placeholders
+ pr.setIgnoreUnresolvableNestedPlaceholders(true);
+ // and observe they now pass through unresolved
+ assertThat(pr.getProperty("p4"), equalTo("v1:v2:${bogus}"));
+
+ // resolve[Nested]Placeholders methods behave as usual regardless the value of
+ // ignoreUnresolvableNestedPlaceholders
+ assertThat(pr.resolvePlaceholders("${p1}:${p2}:${bogus}"), equalTo("v1:v2:${bogus}"));
+ try {
+ pr.resolveRequiredPlaceholders("${p1}:${p2}:${bogus}");
+ }
+ catch (IllegalArgumentException ex) {
+ assertThat(ex.getMessage(), containsString(
+ "Could not resolve placeholder 'bogus' in string value \"${p1}:${p2}:${bogus}\""));
+ }
+ }
+
+
+ interface SomeType {
+ }
+
+ static class SpecificType implements SomeType {
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/env/SimpleCommandLineParserTests.java b/spring-core/src/test/java/org/springframework/core/env/SimpleCommandLineParserTests.java
new file mode 100644
index 00000000..08111c70
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/env/SimpleCommandLineParserTests.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2002-2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.env;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.Test;
+
+public class SimpleCommandLineParserTests {
+
+ @Test
+ public void withNoOptions() {
+ SimpleCommandLineArgsParser parser = new SimpleCommandLineArgsParser();
+ assertThat(parser.parse().getOptionValues("foo"), nullValue());
+ }
+
+ @Test
+ public void withSingleOptionAndNoValue() {
+ SimpleCommandLineArgsParser parser = new SimpleCommandLineArgsParser();
+ CommandLineArgs args = parser.parse("--o1");
+ assertThat(args.containsOption("o1"), is(true));
+ assertThat(args.getOptionValues("o1"), equalTo(Collections.EMPTY_LIST));
+ }
+
+ @Test
+ public void withSingleOptionAndValue() {
+ SimpleCommandLineArgsParser parser = new SimpleCommandLineArgsParser();
+ CommandLineArgs args = parser.parse("--o1=v1");
+ assertThat(args.containsOption("o1"), is(true));
+ assertThat(args.getOptionValues("o1").get(0), equalTo("v1"));
+ }
+
+ @Test
+ public void withMixOfOptionsHavingValueAndOptionsHavingNoValue() {
+ SimpleCommandLineArgsParser parser = new SimpleCommandLineArgsParser();
+ CommandLineArgs args = parser.parse("--o1=v1", "--o2");
+ assertThat(args.containsOption("o1"), is(true));
+ assertThat(args.containsOption("o2"), is(true));
+ assertThat(args.containsOption("o3"), is(false));
+ assertThat(args.getOptionValues("o1").get(0), equalTo("v1"));
+ assertThat(args.getOptionValues("o2"), equalTo(Collections.EMPTY_LIST));
+ assertThat(args.getOptionValues("o3"), nullValue());
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void withEmptyOptionText() {
+ SimpleCommandLineArgsParser parser = new SimpleCommandLineArgsParser();
+ parser.parse("--");
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void withEmptyOptionName() {
+ SimpleCommandLineArgsParser parser = new SimpleCommandLineArgsParser();
+ parser.parse("--=v1");
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void withEmptyOptionValue() {
+ SimpleCommandLineArgsParser parser = new SimpleCommandLineArgsParser();
+ parser.parse("--o1=");
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void withEmptyOptionNameAndEmptyOptionValue() {
+ SimpleCommandLineArgsParser parser = new SimpleCommandLineArgsParser();
+ parser.parse("--=");
+ }
+
+ @Test
+ public void withNonOptionArguments() {
+ SimpleCommandLineArgsParser parser = new SimpleCommandLineArgsParser();
+ CommandLineArgs args = parser.parse("--o1=v1", "noa1", "--o2=v2", "noa2");
+ assertThat(args.getOptionValues("o1").get(0), equalTo("v1"));
+ assertThat(args.getOptionValues("o2").get(0), equalTo("v2"));
+
+ List<String> nonOptions = args.getNonOptionArgs();
+ assertThat(nonOptions.get(0), equalTo("noa1"));
+ assertThat(nonOptions.get(1), equalTo("noa2"));
+ assertThat(nonOptions.size(), equalTo(2));
+ }
+
+ @Test(expected=UnsupportedOperationException.class)
+ public void assertOptionNamesIsUnmodifiable() {
+ CommandLineArgs args = new SimpleCommandLineArgsParser().parse();
+ args.getOptionNames().add("bogus");
+ }
+
+ @Test(expected=UnsupportedOperationException.class)
+ public void assertNonOptionArgsIsUnmodifiable() {
+ CommandLineArgs args = new SimpleCommandLineArgsParser().parse();
+ args.getNonOptionArgs().add("foo");
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/env/SimpleCommandLinePropertySourceTests.java b/spring-core/src/test/java/org/springframework/core/env/SimpleCommandLinePropertySourceTests.java
new file mode 100644
index 00000000..2f7c0fcc
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/env/SimpleCommandLinePropertySourceTests.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2002-2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.env;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+import java.util.List;
+
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link SimpleCommandLinePropertySource}.
+ *
+ * @author Chris Beams
+ * @since 3.1
+ */
+public class SimpleCommandLinePropertySourceTests {
+
+ @Test
+ public void withDefaultName() {
+ PropertySource<?> ps = new SimpleCommandLinePropertySource();
+ assertThat(ps.getName(),
+ equalTo(CommandLinePropertySource.COMMAND_LINE_PROPERTY_SOURCE_NAME));
+ }
+
+ @Test
+ public void withCustomName() {
+ PropertySource<?> ps = new SimpleCommandLinePropertySource("ps1", new String[0]);
+ assertThat(ps.getName(), equalTo("ps1"));
+ }
+
+ @Test
+ public void withNoArgs() {
+ PropertySource<?> ps = new SimpleCommandLinePropertySource();
+ assertThat(ps.containsProperty("foo"), is(false));
+ assertThat(ps.getProperty("foo"), nullValue());
+ }
+
+ @Test
+ public void withOptionArgsOnly() {
+ CommandLinePropertySource<?> ps =
+ new SimpleCommandLinePropertySource("--o1=v1", "--o2");
+ assertThat(ps.containsProperty("o1"), is(true));
+ assertThat(ps.containsProperty("o2"), is(true));
+ assertThat(ps.containsProperty("o3"), is(false));
+ assertThat(ps.getProperty("o1"), equalTo("v1"));
+ assertThat(ps.getProperty("o2"), equalTo(""));
+ assertThat(ps.getProperty("o3"), nullValue());
+ }
+
+ @Test
+ public void withDefaultNonOptionArgsNameAndNoNonOptionArgsPresent() {
+ PropertySource<?> ps = new SimpleCommandLinePropertySource("--o1=v1", "--o2");
+
+ assertThat(ps.containsProperty("nonOptionArgs"), is(false));
+ assertThat(ps.containsProperty("o1"), is(true));
+ assertThat(ps.containsProperty("o2"), is(true));
+
+ assertThat(ps.containsProperty("nonOptionArgs"), is(false));
+ assertThat(ps.getProperty("nonOptionArgs"), nullValue());
+ }
+
+ @Test
+ public void withDefaultNonOptionArgsNameAndNonOptionArgsPresent() {
+ CommandLinePropertySource<?> ps =
+ new SimpleCommandLinePropertySource("--o1=v1", "noa1", "--o2", "noa2");
+
+ assertThat(ps.containsProperty("nonOptionArgs"), is(true));
+ assertThat(ps.containsProperty("o1"), is(true));
+ assertThat(ps.containsProperty("o2"), is(true));
+
+ String nonOptionArgs = ps.getProperty("nonOptionArgs");
+ assertThat(nonOptionArgs, equalTo("noa1,noa2"));
+ }
+
+ @Test
+ public void withCustomNonOptionArgsNameAndNoNonOptionArgsPresent() {
+ CommandLinePropertySource<?> ps =
+ new SimpleCommandLinePropertySource("--o1=v1", "noa1", "--o2", "noa2");
+ ps.setNonOptionArgsPropertyName("NOA");
+
+ assertThat(ps.containsProperty("nonOptionArgs"), is(false));
+ assertThat(ps.containsProperty("NOA"), is(true));
+ assertThat(ps.containsProperty("o1"), is(true));
+ assertThat(ps.containsProperty("o2"), is(true));
+ String nonOptionArgs = ps.getProperty("NOA");
+ assertThat(nonOptionArgs, equalTo("noa1,noa2"));
+ }
+
+ @Test
+ public void covertNonOptionArgsToStringArrayAndList() {
+ CommandLinePropertySource<?> ps =
+ new SimpleCommandLinePropertySource("--o1=v1", "noa1", "--o2", "noa2");
+ StandardEnvironment env = new StandardEnvironment();
+ env.getPropertySources().addFirst(ps);
+
+ String nonOptionArgs = env.getProperty("nonOptionArgs");
+ assertThat(nonOptionArgs, equalTo("noa1,noa2"));
+
+ String[] nonOptionArgsArray = env.getProperty("nonOptionArgs", String[].class);
+ assertThat(nonOptionArgsArray[0], equalTo("noa1"));
+ assertThat(nonOptionArgsArray[1], equalTo("noa2"));
+
+ @SuppressWarnings("unchecked")
+ List<String> nonOptionArgsList = env.getProperty("nonOptionArgs", List.class);
+ assertThat(nonOptionArgsList.get(0), equalTo("noa1"));
+ assertThat(nonOptionArgsList.get(1), equalTo("noa2"));
+ }
+}
diff --git a/spring-core/src/test/java/org/springframework/core/env/StandardEnvironmentTests.java b/spring-core/src/test/java/org/springframework/core/env/StandardEnvironmentTests.java
new file mode 100644
index 00000000..e094e342
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/env/StandardEnvironmentTests.java
@@ -0,0 +1,550 @@
+/*
+ * Copyright 2002-2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.env;
+
+import java.lang.reflect.Field;
+import java.security.AccessControlException;
+import java.security.Permission;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Map;
+
+import org.junit.Test;
+
+import org.springframework.core.SpringProperties;
+import org.springframework.mock.env.MockPropertySource;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+import static org.springframework.core.env.AbstractEnvironment.*;
+
+/**
+ * Unit tests for {@link StandardEnvironment}.
+ *
+ * @author Chris Beams
+ * @author Juergen Hoeller
+ */
+public class StandardEnvironmentTests {
+
+ private static final String ALLOWED_PROPERTY_NAME = "theanswer";
+ private static final String ALLOWED_PROPERTY_VALUE = "42";
+
+ private static final String DISALLOWED_PROPERTY_NAME = "verboten";
+ private static final String DISALLOWED_PROPERTY_VALUE = "secret";
+
+ private static final String STRING_PROPERTY_NAME = "stringPropName";
+ private static final String STRING_PROPERTY_VALUE = "stringPropValue";
+ private static final Object NON_STRING_PROPERTY_NAME = new Object();
+ private static final Object NON_STRING_PROPERTY_VALUE = new Object();
+
+ private ConfigurableEnvironment environment = new StandardEnvironment();
+
+ @Test
+ public void merge() {
+ ConfigurableEnvironment child = new StandardEnvironment();
+ child.setActiveProfiles("c1", "c2");
+ child.getPropertySources().addLast(
+ new MockPropertySource("childMock")
+ .withProperty("childKey", "childVal")
+ .withProperty("bothKey", "childBothVal"));
+
+ ConfigurableEnvironment parent = new StandardEnvironment();
+ parent.setActiveProfiles("p1", "p2");
+ parent.getPropertySources().addLast(
+ new MockPropertySource("parentMock")
+ .withProperty("parentKey", "parentVal")
+ .withProperty("bothKey", "parentBothVal"));
+
+ assertThat(child.getProperty("childKey"), is("childVal"));
+ assertThat(child.getProperty("parentKey"), nullValue());
+ assertThat(child.getProperty("bothKey"), is("childBothVal"));
+
+ assertThat(parent.getProperty("childKey"), nullValue());
+ assertThat(parent.getProperty("parentKey"), is("parentVal"));
+ assertThat(parent.getProperty("bothKey"), is("parentBothVal"));
+
+ assertThat(child.getActiveProfiles(), equalTo(new String[]{"c1","c2"}));
+ assertThat(parent.getActiveProfiles(), equalTo(new String[]{"p1","p2"}));
+
+ child.merge(parent);
+
+ assertThat(child.getProperty("childKey"), is("childVal"));
+ assertThat(child.getProperty("parentKey"), is("parentVal"));
+ assertThat(child.getProperty("bothKey"), is("childBothVal"));
+
+ assertThat(parent.getProperty("childKey"), nullValue());
+ assertThat(parent.getProperty("parentKey"), is("parentVal"));
+ assertThat(parent.getProperty("bothKey"), is("parentBothVal"));
+
+ assertThat(child.getActiveProfiles(), equalTo(new String[]{"c1","c2","p1","p2"}));
+ assertThat(parent.getActiveProfiles(), equalTo(new String[]{"p1","p2"}));
+ }
+
+ @Test
+ public void propertySourceOrder() {
+ ConfigurableEnvironment env = new StandardEnvironment();
+ MutablePropertySources sources = env.getPropertySources();
+ assertThat(sources.precedenceOf(PropertySource.named(StandardEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME)), equalTo(0));
+ assertThat(sources.precedenceOf(PropertySource.named(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME)), equalTo(1));
+ assertThat(sources.size(), is(2));
+ }
+
+ @Test
+ public void propertySourceTypes() {
+ ConfigurableEnvironment env = new StandardEnvironment();
+ MutablePropertySources sources = env.getPropertySources();
+ assertThat(sources.get(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME), instanceOf(SystemEnvironmentPropertySource.class));
+ }
+
+ @Test
+ public void activeProfilesIsEmptyByDefault() {
+ assertThat(environment.getActiveProfiles().length, is(0));
+ }
+
+ @Test
+ public void defaultProfilesContainsDefaultProfileByDefault() {
+ assertThat(environment.getDefaultProfiles().length, is(1));
+ assertThat(environment.getDefaultProfiles()[0], equalTo("default"));
+ }
+
+ @Test
+ public void setActiveProfiles() {
+ environment.setActiveProfiles("local", "embedded");
+ String[] activeProfiles = environment.getActiveProfiles();
+ assertThat(Arrays.asList(activeProfiles), hasItems("local", "embedded"));
+ assertThat(activeProfiles.length, is(2));
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void setActiveProfiles_withNullProfileArray() {
+ environment.setActiveProfiles((String[])null);
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void setActiveProfiles_withNullProfile() {
+ environment.setActiveProfiles((String)null);
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void setActiveProfiles_withEmptyProfile() {
+ environment.setActiveProfiles("");
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void setActiveProfiles_withNotOperator() {
+ environment.setActiveProfiles("p1", "!p2");
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void setDefaultProfiles_withNullProfileArray() {
+ environment.setDefaultProfiles((String[])null);
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void setDefaultProfiles_withNullProfile() {
+ environment.setDefaultProfiles((String)null);
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void setDefaultProfiles_withEmptyProfile() {
+ environment.setDefaultProfiles("");
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void setDefaultProfiles_withNotOperator() {
+ environment.setDefaultProfiles("d1", "!d2");
+ }
+
+ @Test
+ public void addActiveProfile() {
+ assertThat(environment.getActiveProfiles().length, is(0));
+ environment.setActiveProfiles("local", "embedded");
+ assertThat(Arrays.asList(environment.getActiveProfiles()), hasItems("local", "embedded"));
+ assertThat(environment.getActiveProfiles().length, is(2));
+ environment.addActiveProfile("p1");
+ assertThat(Arrays.asList(environment.getActiveProfiles()), hasItems("p1"));
+ assertThat(environment.getActiveProfiles().length, is(3));
+ environment.addActiveProfile("p2");
+ environment.addActiveProfile("p3");
+ assertThat(Arrays.asList(environment.getActiveProfiles()), hasItems("p2", "p3"));
+ assertThat(environment.getActiveProfiles().length, is(5));
+ }
+
+ @Test
+ public void addActiveProfile_whenActiveProfilesPropertyIsAlreadySet() {
+ ConfigurableEnvironment env = new StandardEnvironment();
+ assertThat(env.getProperty(ACTIVE_PROFILES_PROPERTY_NAME), nullValue());
+ env.getPropertySources().addFirst(new MockPropertySource().withProperty(ACTIVE_PROFILES_PROPERTY_NAME, "p1"));
+ assertThat(env.getProperty(ACTIVE_PROFILES_PROPERTY_NAME), equalTo("p1"));
+ env.addActiveProfile("p2");
+ assertThat(env.getActiveProfiles(), arrayContaining("p1", "p2"));
+ }
+
+ @Test
+ public void reservedDefaultProfile() {
+ assertThat(environment.getDefaultProfiles(), equalTo(new String[]{RESERVED_DEFAULT_PROFILE_NAME}));
+ System.setProperty(DEFAULT_PROFILES_PROPERTY_NAME, "d0");
+ assertThat(environment.getDefaultProfiles(), equalTo(new String[]{"d0"}));
+ environment.setDefaultProfiles("d1", "d2");
+ assertThat(environment.getDefaultProfiles(), equalTo(new String[]{"d1","d2"}));
+ System.getProperties().remove(DEFAULT_PROFILES_PROPERTY_NAME);
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void defaultProfileWithCircularPlaceholder() {
+ System.setProperty(DEFAULT_PROFILES_PROPERTY_NAME, "${spring.profiles.default}");
+ try {
+ environment.getDefaultProfiles();
+ }
+ finally {
+ System.getProperties().remove(DEFAULT_PROFILES_PROPERTY_NAME);
+ }
+ }
+
+ @Test
+ public void getActiveProfiles_systemPropertiesEmpty() {
+ assertThat(environment.getActiveProfiles().length, is(0));
+ System.setProperty(ACTIVE_PROFILES_PROPERTY_NAME, "");
+ assertThat(environment.getActiveProfiles().length, is(0));
+ System.getProperties().remove(ACTIVE_PROFILES_PROPERTY_NAME);
+ }
+
+ @Test
+ public void getActiveProfiles_fromSystemProperties() {
+ System.setProperty(ACTIVE_PROFILES_PROPERTY_NAME, "foo");
+ assertThat(Arrays.asList(environment.getActiveProfiles()), hasItem("foo"));
+ System.getProperties().remove(ACTIVE_PROFILES_PROPERTY_NAME);
+ }
+
+ @Test
+ public void getActiveProfiles_fromSystemProperties_withMultipleProfiles() {
+ System.setProperty(ACTIVE_PROFILES_PROPERTY_NAME, "foo,bar");
+ assertThat(Arrays.asList(environment.getActiveProfiles()), hasItems("foo", "bar"));
+ System.getProperties().remove(ACTIVE_PROFILES_PROPERTY_NAME);
+ }
+
+ @Test
+ public void getActiveProfiles_fromSystemProperties_withMulitpleProfiles_withWhitespace() {
+ System.setProperty(ACTIVE_PROFILES_PROPERTY_NAME, " bar , baz "); // notice whitespace
+ assertThat(Arrays.asList(environment.getActiveProfiles()), hasItems("bar", "baz"));
+ System.getProperties().remove(ACTIVE_PROFILES_PROPERTY_NAME);
+ }
+
+ @Test
+ public void getDefaultProfiles() {
+ assertThat(environment.getDefaultProfiles(), equalTo(new String[] {RESERVED_DEFAULT_PROFILE_NAME}));
+ environment.getPropertySources().addFirst(new MockPropertySource().withProperty(DEFAULT_PROFILES_PROPERTY_NAME, "pd1"));
+ assertThat(environment.getDefaultProfiles().length, is(1));
+ assertThat(Arrays.asList(environment.getDefaultProfiles()), hasItem("pd1"));
+ }
+
+ @Test
+ public void setDefaultProfiles() {
+ environment.setDefaultProfiles();
+ assertThat(environment.getDefaultProfiles().length, is(0));
+ environment.setDefaultProfiles("pd1");
+ assertThat(Arrays.asList(environment.getDefaultProfiles()), hasItem("pd1"));
+ environment.setDefaultProfiles("pd2", "pd3");
+ assertThat(Arrays.asList(environment.getDefaultProfiles()), not(hasItem("pd1")));
+ assertThat(Arrays.asList(environment.getDefaultProfiles()), hasItems("pd2", "pd3"));
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void acceptsProfiles_withEmptyArgumentList() {
+ environment.acceptsProfiles();
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void acceptsProfiles_withNullArgumentList() {
+ environment.acceptsProfiles((String[])null);
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void acceptsProfiles_withNullArgument() {
+ environment.acceptsProfiles((String)null);
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void acceptsProfiles_withEmptyArgument() {
+ environment.acceptsProfiles("");
+ }
+
+
+ @Test
+ public void acceptsProfiles_activeProfileSetProgrammatically() {
+ assertThat(environment.acceptsProfiles("p1", "p2"), is(false));
+ environment.setActiveProfiles("p1");
+ assertThat(environment.acceptsProfiles("p1", "p2"), is(true));
+ environment.setActiveProfiles("p2");
+ assertThat(environment.acceptsProfiles("p1", "p2"), is(true));
+ environment.setActiveProfiles("p1", "p2");
+ assertThat(environment.acceptsProfiles("p1", "p2"), is(true));
+ }
+
+ @Test
+ public void acceptsProfiles_activeProfileSetViaProperty() {
+ assertThat(environment.acceptsProfiles("p1"), is(false));
+ environment.getPropertySources().addFirst(new MockPropertySource().withProperty(ACTIVE_PROFILES_PROPERTY_NAME, "p1"));
+ assertThat(environment.acceptsProfiles("p1"), is(true));
+ }
+
+ @Test
+ public void acceptsProfiles_defaultProfile() {
+ assertThat(environment.acceptsProfiles("pd"), is(false));
+ environment.setDefaultProfiles("pd");
+ assertThat(environment.acceptsProfiles("pd"), is(true));
+ environment.setActiveProfiles("p1");
+ assertThat(environment.acceptsProfiles("pd"), is(false));
+ assertThat(environment.acceptsProfiles("p1"), is(true));
+ }
+
+ @Test
+ public void acceptsProfiles_withNotOperator() {
+ assertThat(environment.acceptsProfiles("p1"), is(false));
+ assertThat(environment.acceptsProfiles("!p1"), is(true));
+ environment.addActiveProfile("p1");
+ assertThat(environment.acceptsProfiles("p1"), is(true));
+ assertThat(environment.acceptsProfiles("!p1"), is(false));
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void acceptsProfiles_withInvalidNotOperator() {
+ environment.acceptsProfiles("p1", "!");
+ }
+
+ @Test
+ public void environmentSubclass_withCustomProfileValidation() {
+ ConfigurableEnvironment env = new AbstractEnvironment() {
+ @Override
+ protected void validateProfile(String profile) {
+ super.validateProfile(profile);
+ if (profile.contains("-")) {
+ throw new IllegalArgumentException(
+ "Invalid profile [" + profile + "]: must not contain dash character");
+ }
+ }
+ };
+
+ env.addActiveProfile("validProfile"); // succeeds
+
+ try {
+ env.addActiveProfile("invalid-profile");
+ fail("expected validation exception");
+ }
+ catch (IllegalArgumentException ex) {
+ assertThat(ex.getMessage(),
+ equalTo("Invalid profile [invalid-profile]: must not contain dash character"));
+ }
+ }
+
+ @Test
+ public void suppressGetenvAccessThroughSystemProperty() {
+ System.setProperty("spring.getenv.ignore", "true");
+ assertTrue(environment.getSystemEnvironment().isEmpty());
+ System.clearProperty("spring.getenv.ignore");
+ }
+
+ @Test
+ public void suppressGetenvAccessThroughSpringProperty() {
+ SpringProperties.setProperty("spring.getenv.ignore", "true");
+ assertTrue(environment.getSystemEnvironment().isEmpty());
+ SpringProperties.setProperty("spring.getenv.ignore", null);
+ }
+
+ @Test
+ public void suppressGetenvAccessThroughSpringFlag() {
+ SpringProperties.setFlag("spring.getenv.ignore");
+ assertTrue(environment.getSystemEnvironment().isEmpty());
+ SpringProperties.setProperty("spring.getenv.ignore", null);
+ }
+
+ @Test
+ public void getSystemProperties_withAndWithoutSecurityManager() {
+ System.setProperty(ALLOWED_PROPERTY_NAME, ALLOWED_PROPERTY_VALUE);
+ System.setProperty(DISALLOWED_PROPERTY_NAME, DISALLOWED_PROPERTY_VALUE);
+ System.getProperties().put(STRING_PROPERTY_NAME, NON_STRING_PROPERTY_VALUE);
+ System.getProperties().put(NON_STRING_PROPERTY_NAME, STRING_PROPERTY_VALUE);
+
+ {
+ Map<?, ?> systemProperties = environment.getSystemProperties();
+ assertThat(systemProperties, notNullValue());
+ assertSame(systemProperties, System.getProperties());
+ assertThat(systemProperties.get(ALLOWED_PROPERTY_NAME), equalTo((Object)ALLOWED_PROPERTY_VALUE));
+ assertThat(systemProperties.get(DISALLOWED_PROPERTY_NAME), equalTo((Object)DISALLOWED_PROPERTY_VALUE));
+
+ // non-string keys and values work fine... until the security manager is introduced below
+ assertThat(systemProperties.get(STRING_PROPERTY_NAME), equalTo(NON_STRING_PROPERTY_VALUE));
+ assertThat(systemProperties.get(NON_STRING_PROPERTY_NAME), equalTo((Object)STRING_PROPERTY_VALUE));
+ }
+
+ SecurityManager oldSecurityManager = System.getSecurityManager();
+ SecurityManager securityManager = new SecurityManager() {
+ @Override
+ public void checkPropertiesAccess() {
+ // see http://download.oracle.com/javase/1.5.0/docs/api/java/lang/System.html#getProperties()
+ throw new AccessControlException("Accessing the system properties is disallowed");
+ }
+ @Override
+ public void checkPropertyAccess(String key) {
+ // see http://download.oracle.com/javase/1.5.0/docs/api/java/lang/System.html#getProperty(java.lang.String)
+ if (DISALLOWED_PROPERTY_NAME.equals(key)) {
+ throw new AccessControlException(
+ String.format("Accessing the system property [%s] is disallowed", DISALLOWED_PROPERTY_NAME));
+ }
+ }
+ @Override
+ public void checkPermission(Permission perm) {
+ // allow everything else
+ }
+ };
+ System.setSecurityManager(securityManager);
+
+ {
+ Map<?, ?> systemProperties = environment.getSystemProperties();
+ assertThat(systemProperties, notNullValue());
+ assertThat(systemProperties, instanceOf(ReadOnlySystemAttributesMap.class));
+ assertThat((String)systemProperties.get(ALLOWED_PROPERTY_NAME), equalTo(ALLOWED_PROPERTY_VALUE));
+ assertThat(systemProperties.get(DISALLOWED_PROPERTY_NAME), equalTo(null));
+
+ // nothing we can do here in terms of warning the user that there was
+ // actually a (non-string) value available. By this point, we only
+ // have access to calling System.getProperty(), which itself returns null
+ // if the value is non-string. So we're stuck with returning a potentially
+ // misleading null.
+ assertThat(systemProperties.get(STRING_PROPERTY_NAME), nullValue());
+
+ // in the case of a non-string *key*, however, we can do better. Alert
+ // the user that under these very special conditions (non-object key +
+ // SecurityManager that disallows access to system properties), they
+ // cannot do what they're attempting.
+ try {
+ systemProperties.get(NON_STRING_PROPERTY_NAME);
+ fail("Expected IllegalArgumentException when searching with non-string key against ReadOnlySystemAttributesMap");
+ }
+ catch (IllegalArgumentException ex) {
+ // expected
+ }
+ }
+
+ System.setSecurityManager(oldSecurityManager);
+ System.clearProperty(ALLOWED_PROPERTY_NAME);
+ System.clearProperty(DISALLOWED_PROPERTY_NAME);
+ System.getProperties().remove(STRING_PROPERTY_NAME);
+ System.getProperties().remove(NON_STRING_PROPERTY_NAME);
+ }
+
+ @Test
+ public void getSystemEnvironment_withAndWithoutSecurityManager() {
+ getModifiableSystemEnvironment().put(ALLOWED_PROPERTY_NAME, ALLOWED_PROPERTY_VALUE);
+ getModifiableSystemEnvironment().put(DISALLOWED_PROPERTY_NAME, DISALLOWED_PROPERTY_VALUE);
+
+ {
+ Map<String, Object> systemEnvironment = environment.getSystemEnvironment();
+ assertThat(systemEnvironment, notNullValue());
+ assertSame(systemEnvironment, System.getenv());
+ }
+
+ SecurityManager oldSecurityManager = System.getSecurityManager();
+ SecurityManager securityManager = new SecurityManager() {
+ @Override
+ public void checkPermission(Permission perm) {
+ //see http://download.oracle.com/javase/1.5.0/docs/api/java/lang/System.html#getenv()
+ if ("getenv.*".equals(perm.getName())) {
+ throw new AccessControlException("Accessing the system environment is disallowed");
+ }
+ //see http://download.oracle.com/javase/1.5.0/docs/api/java/lang/System.html#getenv(java.lang.String)
+ if (("getenv."+DISALLOWED_PROPERTY_NAME).equals(perm.getName())) {
+ throw new AccessControlException(
+ String.format("Accessing the system environment variable [%s] is disallowed", DISALLOWED_PROPERTY_NAME));
+ }
+ }
+ };
+ System.setSecurityManager(securityManager);
+
+ {
+ Map<String, Object> systemEnvironment = environment.getSystemEnvironment();
+ assertThat(systemEnvironment, notNullValue());
+ assertThat(systemEnvironment, instanceOf(ReadOnlySystemAttributesMap.class));
+ assertThat(systemEnvironment.get(ALLOWED_PROPERTY_NAME), equalTo((Object)ALLOWED_PROPERTY_VALUE));
+ assertThat(systemEnvironment.get(DISALLOWED_PROPERTY_NAME), nullValue());
+ }
+
+ System.setSecurityManager(oldSecurityManager);
+ getModifiableSystemEnvironment().remove(ALLOWED_PROPERTY_NAME);
+ getModifiableSystemEnvironment().remove(DISALLOWED_PROPERTY_NAME);
+ }
+
+ @SuppressWarnings("unchecked")
+ public static Map<String, String> getModifiableSystemEnvironment() {
+ // for os x / linux
+ Class<?>[] classes = Collections.class.getDeclaredClasses();
+ Map<String, String> env = System.getenv();
+ for (Class<?> cl : classes) {
+ if ("java.util.Collections$UnmodifiableMap".equals(cl.getName())) {
+ try {
+ Field field = cl.getDeclaredField("m");
+ field.setAccessible(true);
+ Object obj = field.get(env);
+ if (obj != null && obj.getClass().getName().equals("java.lang.ProcessEnvironment$StringEnvironment")) {
+ return (Map<String, String>) obj;
+ }
+ }
+ catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ }
+
+ // for windows
+ Class<?> processEnvironmentClass;
+ try {
+ processEnvironmentClass = Class.forName("java.lang.ProcessEnvironment");
+ }
+ catch (Exception ex) {
+ throw new IllegalStateException(ex);
+ }
+
+ try {
+ Field theCaseInsensitiveEnvironmentField = processEnvironmentClass.getDeclaredField("theCaseInsensitiveEnvironment");
+ theCaseInsensitiveEnvironmentField.setAccessible(true);
+ Object obj = theCaseInsensitiveEnvironmentField.get(null);
+ return (Map<String, String>) obj;
+ }
+ catch (NoSuchFieldException ex) {
+ // do nothing
+ }
+ catch (Exception ex) {
+ throw new IllegalStateException(ex);
+ }
+
+ try {
+ Field theEnvironmentField = processEnvironmentClass.getDeclaredField("theEnvironment");
+ theEnvironmentField.setAccessible(true);
+ Object obj = theEnvironmentField.get(null);
+ return (Map<String, String>) obj;
+ }
+ catch (NoSuchFieldException ex) {
+ // do nothing
+ }
+ catch (Exception ex) {
+ throw new IllegalStateException(ex);
+ }
+
+ throw new IllegalStateException();
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/env/SystemEnvironmentPropertySourceTests.java b/spring-core/src/test/java/org/springframework/core/env/SystemEnvironmentPropertySourceTests.java
new file mode 100644
index 00000000..880868ee
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/env/SystemEnvironmentPropertySourceTests.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2002-2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.env;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link SystemEnvironmentPropertySource}.
+ *
+ * @author Chris Beams
+ * @since 3.1
+ */
+public class SystemEnvironmentPropertySourceTests {
+
+ private Map<String, Object> envMap;
+ private PropertySource<?> ps;
+
+ @Before
+ public void setUp() {
+ envMap = new HashMap<String, Object>();
+ ps = new SystemEnvironmentPropertySource("sysEnv", envMap);
+ }
+
+ @Test
+ public void none() {
+ //envMap.put("a.key", "a_value");
+
+ assertThat(ps.containsProperty("a.key"), equalTo(false));
+ assertThat(ps.getProperty("a.key"), equalTo(null));
+ }
+
+ @Test
+ public void normalWithoutPeriod() {
+ envMap.put("akey", "avalue");
+
+ assertThat(ps.containsProperty("akey"), equalTo(true));
+ assertThat(ps.getProperty("akey"), equalTo((Object)"avalue"));
+ }
+
+ @Test
+ public void normalWithPeriod() {
+ envMap.put("a.key", "a.value");
+
+ assertThat(ps.containsProperty("a.key"), equalTo(true));
+ assertThat(ps.getProperty("a.key"), equalTo((Object)"a.value"));
+ }
+
+ @Test
+ public void withUnderscore() {
+ envMap.put("a_key", "a_value");
+
+ assertThat(ps.containsProperty("a_key"), equalTo(true));
+ assertThat(ps.containsProperty("a.key"), equalTo(true));
+
+ assertThat(ps.getProperty("a_key"), equalTo((Object)"a_value"));
+ assertThat( ps.getProperty("a.key"), equalTo((Object)"a_value"));
+ }
+
+ @Test
+ public void withBothPeriodAndUnderscore() {
+ envMap.put("a_key", "a_value");
+ envMap.put("a.key", "a.value");
+
+ assertThat(ps.getProperty("a_key"), equalTo((Object)"a_value"));
+ assertThat( ps.getProperty("a.key"), equalTo((Object)"a.value"));
+ }
+
+ @Test
+ public void withUppercase() {
+ envMap.put("A_KEY", "a_value");
+
+ assertThat(ps.containsProperty("A_KEY"), equalTo(true));
+ assertThat(ps.containsProperty("A.KEY"), equalTo(true));
+ assertThat(ps.containsProperty("a_key"), equalTo(true));
+ assertThat(ps.containsProperty("a.key"), equalTo(true));
+
+ assertThat(ps.getProperty("A_KEY"), equalTo((Object)"a_value"));
+ assertThat(ps.getProperty("A.KEY"), equalTo((Object)"a_value"));
+ assertThat(ps.getProperty("a_key"), equalTo((Object)"a_value"));
+ assertThat(ps.getProperty("a.key"), equalTo((Object)"a_value"));
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/io/ClassPathResourceTests.java b/spring-core/src/test/java/org/springframework/core/io/ClassPathResourceTests.java
new file mode 100644
index 00000000..bae6fb98
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/io/ClassPathResourceTests.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.io;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.junit.Test;
+
+import static org.hamcrest.Matchers.*;
+
+/**
+ * Unit tests that serve as regression tests for the bugs described in SPR-6888
+ * and SPR-9413.
+ *
+ * @author Chris Beams
+ * @author Sam Brannen
+ */
+public class ClassPathResourceTests {
+
+ private static final String PACKAGE_PATH = "org/springframework/core/io";
+ private static final String NONEXISTENT_RESOURCE_NAME = "nonexistent.xml";
+ private static final String FQ_RESOURCE_PATH = PACKAGE_PATH + '/' + NONEXISTENT_RESOURCE_NAME;
+
+ /**
+ * Absolute path version of {@link #FQ_RESOURCE_PATH}.
+ */
+ private static final String FQ_RESOURCE_PATH_WITH_LEADING_SLASH = '/' + FQ_RESOURCE_PATH;
+
+ private static final Pattern DESCRIPTION_PATTERN = Pattern.compile("^class path resource \\[(.+?)\\]$");
+
+
+ private void assertDescriptionContainsExpectedPath(ClassPathResource resource, String expectedPath) {
+ Matcher matcher = DESCRIPTION_PATTERN.matcher(resource.getDescription());
+ assertTrue(matcher.matches());
+ assertEquals(1, matcher.groupCount());
+ String match = matcher.group(1);
+
+ assertEquals(expectedPath, match);
+ }
+
+ private void assertExceptionContainsFullyQualifiedPath(ClassPathResource resource) {
+ try {
+ resource.getInputStream();
+ fail("FileNotFoundException expected for resource: " + resource);
+ }
+ catch (IOException ex) {
+ assertThat(ex, instanceOf(FileNotFoundException.class));
+ assertThat(ex.getMessage(), containsString(FQ_RESOURCE_PATH));
+ }
+ }
+
+ @Test
+ public void stringConstructorRaisesExceptionWithFullyQualifiedPath() {
+ assertExceptionContainsFullyQualifiedPath(new ClassPathResource(FQ_RESOURCE_PATH));
+ }
+
+ @Test
+ public void classLiteralConstructorRaisesExceptionWithFullyQualifiedPath() {
+ assertExceptionContainsFullyQualifiedPath(new ClassPathResource(NONEXISTENT_RESOURCE_NAME, this.getClass()));
+ }
+
+ @Test
+ public void classLoaderConstructorRaisesExceptionWithFullyQualifiedPath() {
+ assertExceptionContainsFullyQualifiedPath(new ClassPathResource(FQ_RESOURCE_PATH,
+ this.getClass().getClassLoader()));
+ }
+
+ @Test
+ public void getDescriptionWithStringConstructor() {
+ assertDescriptionContainsExpectedPath(new ClassPathResource(FQ_RESOURCE_PATH), FQ_RESOURCE_PATH);
+ }
+
+ @Test
+ public void getDescriptionWithStringConstructorAndLeadingSlash() {
+ assertDescriptionContainsExpectedPath(new ClassPathResource(FQ_RESOURCE_PATH_WITH_LEADING_SLASH),
+ FQ_RESOURCE_PATH);
+ }
+
+ @Test
+ public void getDescriptionWithClassLiteralConstructor() {
+ assertDescriptionContainsExpectedPath(new ClassPathResource(NONEXISTENT_RESOURCE_NAME, this.getClass()),
+ FQ_RESOURCE_PATH);
+ }
+
+ @Test
+ public void getDescriptionWithClassLiteralConstructorAndLeadingSlash() {
+ assertDescriptionContainsExpectedPath(
+ new ClassPathResource(FQ_RESOURCE_PATH_WITH_LEADING_SLASH, this.getClass()), FQ_RESOURCE_PATH);
+ }
+
+ @Test
+ public void getDescriptionWithClassLoaderConstructor() {
+ assertDescriptionContainsExpectedPath(
+ new ClassPathResource(FQ_RESOURCE_PATH, this.getClass().getClassLoader()), FQ_RESOURCE_PATH);
+ }
+
+ @Test
+ public void getDescriptionWithClassLoaderConstructorAndLeadingSlash() {
+ assertDescriptionContainsExpectedPath(new ClassPathResource(FQ_RESOURCE_PATH_WITH_LEADING_SLASH,
+ this.getClass().getClassLoader()), FQ_RESOURCE_PATH);
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/io/ResourceEditorTests.java b/spring-core/src/test/java/org/springframework/core/io/ResourceEditorTests.java
new file mode 100644
index 00000000..ff6a1fc6
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/io/ResourceEditorTests.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2002-2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.io;
+
+import java.beans.PropertyEditor;
+
+import static org.junit.Assert.*;
+import org.junit.Test;
+import org.springframework.core.env.StandardEnvironment;
+
+/**
+ * Unit tests for the {@link ResourceEditor} class.
+ *
+ * @author Rick Evans
+ * @author Arjen Poutsma
+ * @author Dave Syer
+ */
+public final class ResourceEditorTests {
+
+ @Test
+ public void sunnyDay() throws Exception {
+ PropertyEditor editor = new ResourceEditor();
+ editor.setAsText("classpath:org/springframework/core/io/ResourceEditorTests.class");
+ Resource resource = (Resource) editor.getValue();
+ assertNotNull(resource);
+ assertTrue(resource.exists());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void ctorWithNullCtorArgs() throws Exception {
+ new ResourceEditor(null, null);
+ }
+
+ @Test
+ public void setAndGetAsTextWithNull() throws Exception {
+ PropertyEditor editor = new ResourceEditor();
+ editor.setAsText(null);
+ assertEquals("", editor.getAsText());
+ }
+
+ @Test
+ public void setAndGetAsTextWithWhitespaceResource() throws Exception {
+ PropertyEditor editor = new ResourceEditor();
+ editor.setAsText(" ");
+ assertEquals("", editor.getAsText());
+ }
+
+ @Test
+ public void testSystemPropertyReplacement() {
+ PropertyEditor editor = new ResourceEditor();
+ System.setProperty("test.prop", "foo");
+ try {
+ editor.setAsText("${test.prop}-${bar}");
+ Resource resolved = (Resource) editor.getValue();
+ assertEquals("foo-${bar}", resolved.getFilename());
+ }
+ finally {
+ System.getProperties().remove("test.prop");
+ }
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void testStrictSystemPropertyReplacement() {
+ PropertyEditor editor = new ResourceEditor(new DefaultResourceLoader(), new StandardEnvironment(), false);
+ System.setProperty("test.prop", "foo");
+ try {
+ editor.setAsText("${test.prop}-${bar}");
+ Resource resolved = (Resource) editor.getValue();
+ assertEquals("foo-${bar}", resolved.getFilename());
+ }
+ finally {
+ System.getProperties().remove("test.prop");
+ }
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/io/ResourceTests.java b/spring-core/src/test/java/org/springframework/core/io/ResourceTests.java
new file mode 100644
index 00000000..2da1da51
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/io/ResourceTests.java
@@ -0,0 +1,254 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.io;
+
+import java.io.ByteArrayInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.HashSet;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.springframework.util.FileCopyUtils;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author Juergen Hoeller
+ * @author Chris Beams
+ * @since 09.09.2004
+ */
+public class ResourceTests {
+
+ @Test
+ public void testByteArrayResource() throws IOException {
+ Resource resource = new ByteArrayResource("testString".getBytes());
+ assertTrue(resource.exists());
+ assertFalse(resource.isOpen());
+ String content = FileCopyUtils.copyToString(new InputStreamReader(resource.getInputStream()));
+ assertEquals("testString", content);
+ assertEquals(resource, new ByteArrayResource("testString".getBytes()));
+ }
+
+ @Test
+ public void testByteArrayResourceWithDescription() throws IOException {
+ Resource resource = new ByteArrayResource("testString".getBytes(), "my description");
+ assertTrue(resource.exists());
+ assertFalse(resource.isOpen());
+ String content = FileCopyUtils.copyToString(new InputStreamReader(resource.getInputStream()));
+ assertEquals("testString", content);
+ assertEquals("my description", resource.getDescription());
+ assertEquals(resource, new ByteArrayResource("testString".getBytes()));
+ }
+
+ @Test
+ public void testInputStreamResource() throws IOException {
+ InputStream is = new ByteArrayInputStream("testString".getBytes());
+ Resource resource = new InputStreamResource(is);
+ assertTrue(resource.exists());
+ assertTrue(resource.isOpen());
+ String content = FileCopyUtils.copyToString(new InputStreamReader(resource.getInputStream()));
+ assertEquals("testString", content);
+ assertEquals(resource, new InputStreamResource(is));
+ }
+
+ @Test
+ public void testInputStreamResourceWithDescription() throws IOException {
+ InputStream is = new ByteArrayInputStream("testString".getBytes());
+ Resource resource = new InputStreamResource(is, "my description");
+ assertTrue(resource.exists());
+ assertTrue(resource.isOpen());
+ String content = FileCopyUtils.copyToString(new InputStreamReader(resource.getInputStream()));
+ assertEquals("testString", content);
+ assertEquals("my description", resource.getDescription());
+ assertEquals(resource, new InputStreamResource(is));
+ }
+
+ @Test
+ public void testClassPathResource() throws IOException {
+ Resource resource = new ClassPathResource("org/springframework/core/io/Resource.class");
+ doTestResource(resource);
+ Resource resource2 = new ClassPathResource("org/springframework/core/../core/io/./Resource.class");
+ assertEquals(resource, resource2);
+ Resource resource3 = new ClassPathResource("org/springframework/core/").createRelative("../core/io/./Resource.class");
+ assertEquals(resource, resource3);
+
+ // Check whether equal/hashCode works in a HashSet.
+ HashSet<Resource> resources = new HashSet<Resource>();
+ resources.add(resource);
+ resources.add(resource2);
+ assertEquals(1, resources.size());
+ }
+
+ @Test
+ public void testClassPathResourceWithClassLoader() throws IOException {
+ Resource resource =
+ new ClassPathResource("org/springframework/core/io/Resource.class", getClass().getClassLoader());
+ doTestResource(resource);
+ assertEquals(resource,
+ new ClassPathResource("org/springframework/core/../core/io/./Resource.class", getClass().getClassLoader()));
+ }
+
+ @Test
+ public void testClassPathResourceWithClass() throws IOException {
+ Resource resource = new ClassPathResource("Resource.class", getClass());
+ doTestResource(resource);
+ assertEquals(resource, new ClassPathResource("Resource.class", getClass()));
+ }
+
+ @Ignore // passes under eclipse, fails under ant
+ @Test
+ public void testFileSystemResource() throws IOException {
+ Resource resource = new FileSystemResource(getClass().getResource("Resource.class").getFile());
+ doTestResource(resource);
+ assertEquals(new FileSystemResource(getClass().getResource("Resource.class").getFile()), resource);
+ Resource resource2 = new FileSystemResource("core/io/Resource.class");
+ assertEquals(resource2, new FileSystemResource("core/../core/io/./Resource.class"));
+ }
+
+ @Test
+ public void testUrlResource() throws IOException {
+ Resource resource = new UrlResource(getClass().getResource("Resource.class"));
+ doTestResource(resource);
+ assertEquals(new UrlResource(getClass().getResource("Resource.class")), resource);
+ Resource resource2 = new UrlResource("file:core/io/Resource.class");
+ assertEquals(resource2, new UrlResource("file:core/../core/io/./Resource.class"));
+ }
+
+ private void doTestResource(Resource resource) throws IOException {
+ assertEquals("Resource.class", resource.getFilename());
+ assertTrue(resource.getURL().getFile().endsWith("Resource.class"));
+
+ Resource relative1 = resource.createRelative("ClassPathResource.class");
+ assertEquals("ClassPathResource.class", relative1.getFilename());
+ assertTrue(relative1.getURL().getFile().endsWith("ClassPathResource.class"));
+ assertTrue(relative1.exists());
+
+ Resource relative2 = resource.createRelative("support/ResourcePatternResolver.class");
+ assertEquals("ResourcePatternResolver.class", relative2.getFilename());
+ assertTrue(relative2.getURL().getFile().endsWith("ResourcePatternResolver.class"));
+ assertTrue(relative2.exists());
+
+ /*
+ Resource relative3 = resource.createRelative("../SpringVersion.class");
+ assertEquals("SpringVersion.class", relative3.getFilename());
+ assertTrue(relative3.getURL().getFile().endsWith("SpringVersion.class"));
+ assertTrue(relative3.exists());
+ */
+ }
+
+ @Test
+ public void testClassPathResourceWithRelativePath() throws IOException {
+ Resource resource = new ClassPathResource("dir/");
+ Resource relative = resource.createRelative("subdir");
+ assertEquals(new ClassPathResource("dir/subdir"), relative);
+ }
+
+ @Test
+ public void testFileSystemResourceWithRelativePath() throws IOException {
+ Resource resource = new FileSystemResource("dir/");
+ Resource relative = resource.createRelative("subdir");
+ assertEquals(new FileSystemResource("dir/subdir"), relative);
+ }
+
+ @Test
+ public void testUrlResourceWithRelativePath() throws IOException {
+ Resource resource = new UrlResource("file:dir/");
+ Resource relative = resource.createRelative("subdir");
+ assertEquals(new UrlResource("file:dir/subdir"), relative);
+ }
+
+ @Ignore @Test // this test is quite slow. TODO: re-enable with JUnit categories
+ public void testNonFileResourceExists() throws Exception {
+ Resource resource = new UrlResource("http://www.springframework.org");
+ assertTrue(resource.exists());
+ }
+
+ @Test
+ public void testAbstractResourceExceptions() throws Exception {
+ final String name = "test-resource";
+
+ Resource resource = new AbstractResource() {
+ @Override
+ public String getDescription() {
+ return name;
+ }
+ @Override
+ public InputStream getInputStream() {
+ return null;
+ }
+ };
+
+ try {
+ resource.getURL();
+ fail("FileNotFoundException should have been thrown");
+ }
+ catch (FileNotFoundException ex) {
+ assertTrue(ex.getMessage().indexOf(name) != -1);
+ }
+ try {
+ resource.getFile();
+ fail("FileNotFoundException should have been thrown");
+ }
+ catch (FileNotFoundException ex) {
+ assertTrue(ex.getMessage().indexOf(name) != -1);
+ }
+ try {
+ resource.createRelative("/testing");
+ fail("FileNotFoundException should have been thrown");
+ }
+ catch (FileNotFoundException ex) {
+ assertTrue(ex.getMessage().indexOf(name) != -1);
+ }
+
+ assertThat(resource.getFilename(), nullValue());
+ }
+
+ @Test
+ public void testContentLength() throws IOException {
+ AbstractResource resource = new AbstractResource() {
+ @Override
+ public InputStream getInputStream() throws IOException {
+ return new ByteArrayInputStream(new byte[] { 'a', 'b', 'c' });
+ }
+ @Override
+ public String getDescription() {
+ return null;
+ }
+ };
+ assertThat(resource.contentLength(), is(3L));
+ }
+
+ @Test(expected=IllegalStateException.class)
+ public void testContentLength_withNullInputStream() throws IOException {
+ AbstractResource resource = new AbstractResource() {
+ @Override
+ public InputStream getInputStream() throws IOException {
+ return null;
+ }
+ @Override
+ public String getDescription() {
+ return null;
+ }
+ };
+ resource.contentLength();
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/io/example.properties b/spring-core/src/test/java/org/springframework/core/io/example.properties
new file mode 100644
index 00000000..74d0a43f
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/io/example.properties
@@ -0,0 +1 @@
+foo=bar
diff --git a/spring-core/src/test/java/org/springframework/core/io/example.xml b/spring-core/src/test/java/org/springframework/core/io/example.xml
new file mode 100644
index 00000000..1d638537
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/io/example.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+<properties version="1.0">
+ <entry key="foo">bar</entry>
+</properties>
+
diff --git a/spring-core/src/test/java/org/springframework/core/io/support/DummyFactory.java b/spring-core/src/test/java/org/springframework/core/io/support/DummyFactory.java
new file mode 100644
index 00000000..12d98292
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/io/support/DummyFactory.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.io.support;
+
+/**
+ * Used by {@link SpringFactoriesLoaderTests}
+ *
+ * @author Arjen Poutsma
+ */
+public interface DummyFactory {
+
+ String getString();
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/io/support/MyDummyFactory1.java b/spring-core/src/test/java/org/springframework/core/io/support/MyDummyFactory1.java
new file mode 100644
index 00000000..11dd7ebf
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/io/support/MyDummyFactory1.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.io.support;
+
+import org.springframework.core.annotation.Order;
+
+/**
+ * Used by {@link SpringFactoriesLoaderTests}
+ *
+ * @author Arjen Poutsma
+ */
+@Order(1)
+public class MyDummyFactory1 implements DummyFactory {
+
+ @Override
+ public String getString() {
+ return "Foo";
+ }
+}
diff --git a/spring-core/src/test/java/org/springframework/core/io/support/MyDummyFactory2.java b/spring-core/src/test/java/org/springframework/core/io/support/MyDummyFactory2.java
new file mode 100644
index 00000000..5105c6b4
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/io/support/MyDummyFactory2.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.io.support;
+
+import org.springframework.core.annotation.Order;
+
+/**
+ * Used by {@link SpringFactoriesLoaderTests}
+ *
+ * @author Arjen Poutsma
+ */
+@Order(2)
+public class MyDummyFactory2 implements DummyFactory {
+
+ @Override
+ public String getString() {
+ return "Bar";
+ }
+}
diff --git a/spring-core/src/test/java/org/springframework/core/io/support/PathMatchingResourcePatternResolverTests.java b/spring-core/src/test/java/org/springframework/core/io/support/PathMatchingResourcePatternResolverTests.java
new file mode 100644
index 00000000..b494c708
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/io/support/PathMatchingResourcePatternResolverTests.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.io.support;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.springframework.core.io.Resource;
+
+/**
+ * If this test case fails, uncomment diagnostics in
+ * {@code assertProtocolAndFilenames} method.
+ *
+ * @author Oliver Hutchison
+ * @author Juergen Hoeller
+ * @author Chris Beams
+ * @since 17.11.2004
+ */
+public class PathMatchingResourcePatternResolverTests {
+
+ private static final String[] CLASSES_IN_CORE_IO_SUPPORT =
+ new String[] {"EncodedResource.class", "LocalizedResourceHelper.class",
+ "PathMatchingResourcePatternResolver.class",
+ "PropertiesLoaderSupport.class", "PropertiesLoaderUtils.class",
+ "ResourceArrayPropertyEditor.class",
+ "ResourcePatternResolver.class", "ResourcePatternUtils.class"};
+
+ private static final String[] TEST_CLASSES_IN_CORE_IO_SUPPORT =
+ new String[] {"PathMatchingResourcePatternResolverTests.class"};
+
+ private static final String[] CLASSES_IN_COMMONSLOGGING =
+ new String[] {"Log.class", "LogConfigurationException.class", "LogFactory.class",
+ "LogFactory$1.class", "LogFactory$2.class", "LogFactory$3.class",
+ "LogFactory$4.class", "LogFactory$5.class", "LogFactory$6.class",
+ "LogSource.class"};
+
+ private PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
+
+
+ @Test
+ public void testInvalidPrefixWithPatternElementInIt() throws IOException {
+ try {
+ resolver.getResources("xx**:**/*.xy");
+ fail("Should have thrown FileNotFoundException");
+ }
+ catch (FileNotFoundException ex) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testSingleResourceOnFileSystem() throws IOException {
+ Resource[] resources =
+ resolver.getResources("org/springframework/core/io/support/PathMatchingResourcePatternResolverTests.class");
+ assertEquals(1, resources.length);
+ assertProtocolAndFilename(resources[0], "file", "PathMatchingResourcePatternResolverTests.class");
+ }
+
+ @Test
+ public void testSingleResourceInJar() throws IOException {
+ Resource[] resources = resolver.getResources("java/net/URL.class");
+ assertEquals(1, resources.length);
+ assertProtocolAndFilename(resources[0], "jar", "URL.class");
+ }
+
+ @Ignore // passes under eclipse, fails under ant
+ @Test
+ public void testClasspathStarWithPatternOnFileSystem() throws IOException {
+ Resource[] resources = resolver.getResources("classpath*:org/springframework/core/io/sup*/*.class");
+ // Have to exclude Clover-generated class files here,
+ // as we might be running as part of a Clover test run.
+ List noCloverResources = new ArrayList();
+ for (int i = 0; i < resources.length; i++) {
+ if (resources[i].getFilename().indexOf("$__CLOVER_") == -1) {
+ noCloverResources.add(resources[i]);
+ }
+ }
+ resources = (Resource[]) noCloverResources.toArray(new Resource[noCloverResources.size()]);
+ assertProtocolAndFilenames(resources, "file", CLASSES_IN_CORE_IO_SUPPORT, TEST_CLASSES_IN_CORE_IO_SUPPORT);
+ }
+
+ @Test
+ public void testClasspathWithPatternInJar() throws IOException {
+ Resource[] resources = resolver.getResources("classpath:org/apache/commons/logging/*.class");
+ assertProtocolAndFilenames(resources, "jar", CLASSES_IN_COMMONSLOGGING);
+ }
+
+ @Test
+ public void testClasspathStartWithPatternInJar() throws IOException {
+ Resource[] resources = resolver.getResources("classpath*:org/apache/commons/logging/*.class");
+ assertProtocolAndFilenames(resources, "jar", CLASSES_IN_COMMONSLOGGING);
+ }
+
+ private void assertProtocolAndFilename(Resource resource, String urlProtocol, String fileName) throws IOException {
+ assertProtocolAndFilenames(new Resource[] {resource}, urlProtocol, new String[] {fileName});
+ }
+
+ private void assertProtocolAndFilenames(
+ Resource[] resources, String urlProtocol, String[] fileNames1, String[] fileNames2) throws IOException {
+ List fileNames = new ArrayList(Arrays.asList(fileNames1));
+ fileNames.addAll(Arrays.asList(fileNames2));
+ assertProtocolAndFilenames(resources, urlProtocol, (String[]) fileNames.toArray(new String[fileNames.size()]));
+ }
+
+ private void assertProtocolAndFilenames(Resource[] resources, String urlProtocol, String[] fileNames)
+ throws IOException {
+
+ // Uncomment the following if you encounter problems with matching against the file system
+ // It shows file locations.
+// String[] actualNames = new String[resources.length];
+// for (int i = 0; i < resources.length; i++) {
+// actualNames[i] = resources[i].getFilename();
+// }
+// List sortedActualNames = new LinkedList(Arrays.asList(actualNames));
+// List expectedNames = new LinkedList(Arrays.asList(fileNames));
+// Collections.sort(sortedActualNames);
+// Collections.sort(expectedNames);
+//
+// System.out.println("-----------");
+// System.out.println("Expected: " + StringUtils.collectionToCommaDelimitedString(expectedNames));
+// System.out.println("Actual: " + StringUtils.collectionToCommaDelimitedString(sortedActualNames));
+// for (int i = 0; i < resources.length; i++) {
+// System.out.println(resources[i]);
+// }
+
+ assertEquals("Correct number of files found", fileNames.length, resources.length);
+ for (int i = 0; i < resources.length; i++) {
+ Resource resource = resources[i];
+ assertEquals(urlProtocol, resource.getURL().getProtocol());
+ assertFilenameIn(resource, fileNames);
+ }
+ }
+
+ private void assertFilenameIn(Resource resource, String[] fileNames) {
+ for (int i = 0; i < fileNames.length; i++) {
+ if (resource.getFilename().endsWith(fileNames[i])) {
+ return;
+ }
+ }
+ fail("resource [" + resource + "] does not have a filename that matches and of the names in 'fileNames'");
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/io/support/ResourceArrayPropertyEditorTests.java b/spring-core/src/test/java/org/springframework/core/io/support/ResourceArrayPropertyEditorTests.java
new file mode 100644
index 00000000..a12d2c09
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/io/support/ResourceArrayPropertyEditorTests.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.io.support;
+
+import java.beans.PropertyEditor;
+
+import static org.junit.Assert.*;
+import org.junit.Test;
+
+import org.springframework.core.env.StandardEnvironment;
+import org.springframework.core.io.Resource;
+
+/**
+ * @author Dave Syer
+ * @author Juergen Hoeller
+ */
+public class ResourceArrayPropertyEditorTests {
+
+ @Test
+ public void testVanillaResource() throws Exception {
+ PropertyEditor editor = new ResourceArrayPropertyEditor();
+ editor.setAsText("classpath:org/springframework/core/io/support/ResourceArrayPropertyEditor.class");
+ Resource[] resources = (Resource[]) editor.getValue();
+ assertNotNull(resources);
+ assertTrue(resources[0].exists());
+ }
+
+ @Test
+ public void testPatternResource() throws Exception {
+ // N.B. this will sometimes fail if you use classpath: instead of classpath*:.
+ // The result depends on the classpath - if test-classes are segregated from classes
+ // and they come first on the classpath (like in Maven) then it breaks, if classes
+ // comes first (like in Spring Build) then it is OK.
+ PropertyEditor editor = new ResourceArrayPropertyEditor();
+ editor.setAsText("classpath*:org/springframework/core/io/support/Resource*Editor.class");
+ Resource[] resources = (Resource[]) editor.getValue();
+ assertNotNull(resources);
+ assertTrue(resources[0].exists());
+ }
+
+ @Test
+ public void testSystemPropertyReplacement() {
+ PropertyEditor editor = new ResourceArrayPropertyEditor();
+ System.setProperty("test.prop", "foo");
+ try {
+ editor.setAsText("${test.prop}-${bar}");
+ Resource[] resources = (Resource[]) editor.getValue();
+ assertEquals("foo-${bar}", resources[0].getFilename());
+ }
+ finally {
+ System.getProperties().remove("test.prop");
+ }
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void testStrictSystemPropertyReplacement() {
+ PropertyEditor editor = new ResourceArrayPropertyEditor(
+ new PathMatchingResourcePatternResolver(), new StandardEnvironment(),
+ false);
+ System.setProperty("test.prop", "foo");
+ try {
+ editor.setAsText("${test.prop}-${bar}");
+ Resource[] resources = (Resource[]) editor.getValue();
+ assertEquals("foo-${bar}", resources[0].getFilename());
+ }
+ finally {
+ System.getProperties().remove("test.prop");
+ }
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/io/support/ResourcePropertySourceTests.java b/spring-core/src/test/java/org/springframework/core/io/support/ResourcePropertySourceTests.java
new file mode 100644
index 00000000..1bbc3cb2
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/io/support/ResourcePropertySourceTests.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.io.support;
+
+import java.io.IOException;
+
+import org.junit.Test;
+
+import org.springframework.core.env.PropertySource;
+import org.springframework.core.io.ByteArrayResource;
+import org.springframework.core.io.ClassPathResource;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+/**
+ * Unit tests for {@link ResourcePropertySource}.
+ *
+ * @author Chris Beams
+ * @since 3.1
+ */
+public class ResourcePropertySourceTests {
+
+ private static final String PROPERTIES_PATH = "org/springframework/core/io/example.properties";
+ private static final String PROPERTIES_LOCATION = "classpath:" + PROPERTIES_PATH;
+ private static final String PROPERTIES_RESOURCE_DESCRIPTION = "class path resource [" + PROPERTIES_PATH + "]";
+
+ private static final String XML_PROPERTIES_PATH = "org/springframework/core/io/example.xml";
+ private static final String XML_PROPERTIES_LOCATION = "classpath:" + XML_PROPERTIES_PATH;
+ private static final String XML_PROPERTIES_RESOURCE_DESCRIPTION = "class path resource [" + XML_PROPERTIES_PATH + "]";
+
+ @Test
+ public void withLocationAndGeneratedName() throws IOException {
+ PropertySource<?> ps = new ResourcePropertySource(PROPERTIES_LOCATION);
+ assertEquals(ps.getProperty("foo"), "bar");
+ assertThat(ps.getName(), is(PROPERTIES_RESOURCE_DESCRIPTION));
+ }
+
+ @Test
+ public void xmlWithLocationAndGeneratedName() throws IOException {
+ PropertySource<?> ps = new ResourcePropertySource(XML_PROPERTIES_LOCATION);
+ assertEquals(ps.getProperty("foo"), "bar");
+ assertThat(ps.getName(), is(XML_PROPERTIES_RESOURCE_DESCRIPTION));
+ }
+
+ @Test
+ public void withLocationAndExplicitName() throws IOException {
+ PropertySource<?> ps = new ResourcePropertySource("ps1", PROPERTIES_LOCATION);
+ assertEquals(ps.getProperty("foo"), "bar");
+ assertThat(ps.getName(), is("ps1"));
+ }
+
+ @Test
+ public void withLocationAndExplicitNameAndExplicitClassLoader() throws IOException {
+ PropertySource<?> ps = new ResourcePropertySource("ps1", PROPERTIES_LOCATION, getClass().getClassLoader());
+ assertEquals(ps.getProperty("foo"), "bar");
+ assertThat(ps.getName(), is("ps1"));
+ }
+
+ @Test
+ public void withLocationAndGeneratedNameAndExplicitClassLoader() throws IOException {
+ PropertySource<?> ps = new ResourcePropertySource(PROPERTIES_LOCATION, getClass().getClassLoader());
+ assertEquals(ps.getProperty("foo"), "bar");
+ assertThat(ps.getName(), is(PROPERTIES_RESOURCE_DESCRIPTION));
+ }
+
+ @Test
+ public void withResourceAndGeneratedName() throws IOException {
+ PropertySource<?> ps = new ResourcePropertySource(new ClassPathResource(PROPERTIES_PATH));
+ assertEquals(ps.getProperty("foo"), "bar");
+ assertThat(ps.getName(), is(PROPERTIES_RESOURCE_DESCRIPTION));
+ }
+
+ @Test
+ public void withResourceAndExplicitName() throws IOException {
+ PropertySource<?> ps = new ResourcePropertySource("ps1", new ClassPathResource(PROPERTIES_PATH));
+ assertEquals(ps.getProperty("foo"), "bar");
+ assertThat(ps.getName(), is("ps1"));
+ }
+
+ @Test
+ public void withResourceHavingNoDescriptionAndGeneratedName() throws IOException {
+ PropertySource<?> ps = new ResourcePropertySource(new ByteArrayResource("foo=bar".getBytes(), ""));
+ assertEquals(ps.getProperty("foo"), "bar");
+ assertTrue(ps.getName().startsWith("ByteArrayResource@"));
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/serializer/SerializationConverterTests.java b/spring-core/src/test/java/org/springframework/core/serializer/SerializationConverterTests.java
new file mode 100644
index 00000000..42c724ec
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/serializer/SerializationConverterTests.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2002-2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.serializer;
+
+import java.io.NotSerializableException;
+import java.io.Serializable;
+
+import static org.junit.Assert.*;
+import org.junit.Test;
+
+import org.springframework.core.serializer.support.DeserializingConverter;
+import org.springframework.core.serializer.support.SerializationFailedException;
+import org.springframework.core.serializer.support.SerializingConverter;
+
+/**
+ * @author Gary Russell
+ * @author Mark Fisher
+ * @since 3.0.5
+ */
+public class SerializationConverterTests {
+
+ @Test
+ public void serializeAndDeserializeString() {
+ SerializingConverter toBytes = new SerializingConverter();
+ byte[] bytes = toBytes.convert("Testing");
+ DeserializingConverter fromBytes = new DeserializingConverter();
+ assertEquals("Testing", fromBytes.convert(bytes));
+ }
+
+ @Test
+ public void nonSerializableObject() {
+ SerializingConverter toBytes = new SerializingConverter();
+ try {
+ toBytes.convert(new Object());
+ fail("Expected IllegalArgumentException");
+ }
+ catch (SerializationFailedException e) {
+ assertNotNull(e.getCause());
+ assertTrue(e.getCause() instanceof IllegalArgumentException);
+ }
+ }
+
+ @Test
+ public void nonSerializableField() {
+ SerializingConverter toBytes = new SerializingConverter();
+ try {
+ toBytes.convert(new UnSerializable());
+ fail("Expected SerializationFailureException");
+ }
+ catch (SerializationFailedException e) {
+ assertNotNull(e.getCause());
+ assertTrue(e.getCause() instanceof NotSerializableException);
+ }
+ }
+
+ @Test(expected = SerializationFailedException.class)
+ public void deserializationFailure() {
+ DeserializingConverter fromBytes = new DeserializingConverter();
+ fromBytes.convert("Junk".getBytes());
+ }
+
+
+ class UnSerializable implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @SuppressWarnings("unused")
+ private Object object;
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/style/ToStringCreatorTests.java b/spring-core/src/test/java/org/springframework/core/style/ToStringCreatorTests.java
new file mode 100644
index 00000000..f353d34f
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/style/ToStringCreatorTests.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.style;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+import org.springframework.util.ObjectUtils;
+
+/**
+ * @author Keith Donald
+ */
+public class ToStringCreatorTests extends TestCase {
+
+ private SomeObject s1, s2, s3;
+
+ @Override
+ protected void setUp() throws Exception {
+ s1 = new SomeObject() {
+ public String toString() {
+ return "A";
+ }
+ };
+ s2 = new SomeObject() {
+ public String toString() {
+ return "B";
+ }
+ };
+ s3 = new SomeObject() {
+ public String toString() {
+ return "C";
+ }
+ };
+ }
+
+ public void testDefaultStyleMap() {
+ final Map map = getMap();
+ Object stringy = new Object() {
+ public String toString() {
+ return new ToStringCreator(this).append("familyFavoriteSport", map).toString();
+ }
+ };
+ assertEquals("[ToStringCreatorTests.4@" + ObjectUtils.getIdentityHexString(stringy)
+ + " familyFavoriteSport = map['Keri' -> 'Softball', 'Scot' -> 'Fishing', 'Keith' -> 'Flag Football']]",
+ stringy.toString());
+ }
+
+ private Map getMap() {
+ Map map = new LinkedHashMap(3);
+ map.put("Keri", "Softball");
+ map.put("Scot", "Fishing");
+ map.put("Keith", "Flag Football");
+ return map;
+ }
+
+ public void testDefaultStyleArray() {
+ SomeObject[] array = new SomeObject[] { s1, s2, s3 };
+ String str = new ToStringCreator(array).toString();
+ assertEquals("[@" + ObjectUtils.getIdentityHexString(array)
+ + " array<ToStringCreatorTests.SomeObject>[A, B, C]]", str);
+ }
+
+ public void testPrimitiveArrays() {
+ int[] integers = new int[] { 0, 1, 2, 3, 4 };
+ String str = new ToStringCreator(integers).toString();
+ assertEquals("[@" + ObjectUtils.getIdentityHexString(integers) + " array<Integer>[0, 1, 2, 3, 4]]", str);
+ }
+
+ public void testList() {
+ List list = new ArrayList();
+ list.add(s1);
+ list.add(s2);
+ list.add(s3);
+ String str = new ToStringCreator(this).append("myLetters", list).toString();
+ assertEquals("[ToStringCreatorTests@" + ObjectUtils.getIdentityHexString(this) + " myLetters = list[A, B, C]]",
+ str);
+ }
+
+ public void testSet() {
+ Set set = new LinkedHashSet<>(3);
+ set.add(s1);
+ set.add(s2);
+ set.add(s3);
+ String str = new ToStringCreator(this).append("myLetters", set).toString();
+ assertEquals("[ToStringCreatorTests@" + ObjectUtils.getIdentityHexString(this) + " myLetters = set[A, B, C]]",
+ str);
+ }
+
+ public void testClass() {
+ String str = new ToStringCreator(this).append("myClass", this.getClass()).toString();
+ assertEquals("[ToStringCreatorTests@" + ObjectUtils.getIdentityHexString(this)
+ + " myClass = ToStringCreatorTests]", str);
+ }
+
+ public void testMethod() throws Exception {
+ String str = new ToStringCreator(this).append("myMethod", this.getClass().getMethod("testMethod"))
+ .toString();
+ assertEquals("[ToStringCreatorTests@" + ObjectUtils.getIdentityHexString(this)
+ + " myMethod = testMethod@ToStringCreatorTests]", str);
+ }
+
+
+ public static class SomeObject {
+
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/task/SimpleAsyncTaskExecutorTests.java b/spring-core/src/test/java/org/springframework/core/task/SimpleAsyncTaskExecutorTests.java
new file mode 100644
index 00000000..57560a25
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/task/SimpleAsyncTaskExecutorTests.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.task;
+
+import java.util.concurrent.ThreadFactory;
+
+import junit.framework.TestCase;
+
+import org.springframework.util.ConcurrencyThrottleSupport;
+
+/**
+ * @author Rick Evans
+ * @author Juergen Hoeller
+ */
+public final class SimpleAsyncTaskExecutorTests extends TestCase {
+
+ public void testCannotExecuteWhenConcurrencyIsSwitchedOff() throws Exception {
+ SimpleAsyncTaskExecutor executor = new SimpleAsyncTaskExecutor();
+ executor.setConcurrencyLimit(ConcurrencyThrottleSupport.NO_CONCURRENCY);
+ assertFalse(executor.isThrottleActive());
+ try {
+ executor.execute(new NoOpRunnable());
+ }
+ catch (IllegalStateException expected) {
+ }
+ }
+
+ public void testThrottleIsNotActiveByDefault() throws Exception {
+ SimpleAsyncTaskExecutor executor = new SimpleAsyncTaskExecutor();
+ assertFalse("Concurrency throttle must not default to being active (on)", executor.isThrottleActive());
+ }
+
+ public void testThreadNameGetsSetCorrectly() throws Exception {
+ final String customPrefix = "chankPop#";
+ final Object monitor = new Object();
+ SimpleAsyncTaskExecutor executor = new SimpleAsyncTaskExecutor(customPrefix);
+ ThreadNameHarvester task = new ThreadNameHarvester(monitor);
+ executeAndWait(executor, task, monitor);
+ assertTrue(task.getThreadName().startsWith(customPrefix));
+ }
+
+ public void testThreadFactoryOverridesDefaults() throws Exception {
+ final Object monitor = new Object();
+ SimpleAsyncTaskExecutor executor = new SimpleAsyncTaskExecutor(new ThreadFactory() {
+ @Override
+ public Thread newThread(Runnable r) {
+ return new Thread(r, "test");
+ }
+ });
+ ThreadNameHarvester task = new ThreadNameHarvester(monitor);
+ executeAndWait(executor, task, monitor);
+ assertTrue(task.getThreadName().equals("test"));
+ }
+
+ public void testThrowsExceptionWhenSuppliedWithNullRunnable() throws Exception {
+ try {
+ new SimpleAsyncTaskExecutor().execute(null);
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ private void executeAndWait(SimpleAsyncTaskExecutor executor, Runnable task, Object monitor) {
+ synchronized (monitor) {
+ executor.execute(task);
+ try {
+ monitor.wait();
+ }
+ catch (InterruptedException ignored) {
+ }
+ }
+ }
+
+
+ private static final class NoOpRunnable implements Runnable {
+
+ @Override
+ public void run() {
+ // no-op
+ }
+ }
+
+
+ private static abstract class AbstractNotifyingRunnable implements Runnable {
+
+ private final Object monitor;
+
+ protected AbstractNotifyingRunnable(Object monitor) {
+ this.monitor = monitor;
+ }
+
+ @Override
+ public final void run() {
+ synchronized (this.monitor) {
+ try {
+ doRun();
+ }
+ finally {
+ this.monitor.notifyAll();
+ }
+ }
+ }
+
+ protected abstract void doRun();
+ }
+
+
+ private static final class ThreadNameHarvester extends AbstractNotifyingRunnable {
+
+ private String threadName;
+
+ protected ThreadNameHarvester(Object monitor) {
+ super(monitor);
+ }
+
+ public String getThreadName() {
+ return this.threadName;
+ }
+
+ @Override
+ protected void doRun() {
+ this.threadName = Thread.currentThread().getName();
+ }
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/type/AbstractClassMetadataMemberClassTests.java b/spring-core/src/test/java/org/springframework/core/type/AbstractClassMetadataMemberClassTests.java
new file mode 100644
index 00000000..64802bbe
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/type/AbstractClassMetadataMemberClassTests.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2002-2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.type;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+import org.junit.Test;
+
+/**
+ * Abstract base class for testing implementations of
+ * {@link ClassMetadata#getMemberClassNames()}.
+ *
+ * @author Chris Beams
+ * @since 3.1
+ */
+public abstract class AbstractClassMetadataMemberClassTests {
+
+ public abstract ClassMetadata getClassMetadataFor(Class<?> clazz);
+
+ @Test
+ public void withNoMemberClasses() {
+ ClassMetadata metadata = getClassMetadataFor(L0_a.class);
+ String[] nestedClasses = metadata.getMemberClassNames();
+ assertThat(nestedClasses, equalTo(new String[]{}));
+ }
+
+ public static class L0_a {
+ }
+
+
+ @Test
+ public void withPublicMemberClasses() {
+ ClassMetadata metadata = getClassMetadataFor(L0_b.class);
+ String[] nestedClasses = metadata.getMemberClassNames();
+ assertThat(nestedClasses, equalTo(new String[]{L0_b.L1.class.getName()}));
+ }
+
+ public static class L0_b {
+ public static class L1 { }
+ }
+
+
+ @Test
+ public void withNonPublicMemberClasses() {
+ ClassMetadata metadata = getClassMetadataFor(L0_c.class);
+ String[] nestedClasses = metadata.getMemberClassNames();
+ assertThat(nestedClasses, equalTo(new String[]{L0_c.L1.class.getName()}));
+ }
+
+ public static class L0_c {
+ private static class L1 { }
+ }
+
+
+ @Test
+ public void againstMemberClass() {
+ ClassMetadata metadata = getClassMetadataFor(L0_b.L1.class);
+ String[] nestedClasses = metadata.getMemberClassNames();
+ assertThat(nestedClasses, equalTo(new String[]{}));
+ }
+}
diff --git a/spring-core/src/test/java/org/springframework/core/type/AnnotationMetadataTests.java b/spring-core/src/test/java/org/springframework/core/type/AnnotationMetadataTests.java
new file mode 100644
index 00000000..cb680811
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/type/AnnotationMetadataTests.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.type;
+
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.Set;
+
+import org.junit.Test;
+
+import org.springframework.core.annotation.AnnotationAttributes;
+import org.springframework.core.type.classreading.MetadataReader;
+import org.springframework.core.type.classreading.MetadataReaderFactory;
+import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
+import org.springframework.stereotype.Component;
+
+/**
+ * Unit tests demonstrating that the reflection-based {@link StandardAnnotationMetadata}
+ * and ASM-based {@code AnnotationMetadataReadingVisitor} produce identical output.
+ *
+ * @author Juergen Hoeller
+ * @author Chris Beams
+ */
+public class AnnotationMetadataTests {
+
+ @Test
+ public void testStandardAnnotationMetadata() throws IOException {
+ AnnotationMetadata metadata = new StandardAnnotationMetadata(AnnotatedComponent.class, true);
+ doTestAnnotationInfo(metadata);
+ doTestMethodAnnotationInfo(metadata);
+ }
+
+ @Test
+ public void testAsmAnnotationMetadata() throws IOException {
+ MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
+ MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(AnnotatedComponent.class.getName());
+ AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
+ doTestAnnotationInfo(metadata);
+ doTestMethodAnnotationInfo(metadata);
+ }
+
+ /**
+ * In order to preserve backward-compatibility, {@link StandardAnnotationMetadata}
+ * defaults to return nested annotations and annotation arrays as actual
+ * Annotation instances. It is recommended for compatibility with ASM-based
+ * AnnotationMetadata implementations to set the 'nestedAnnotationsAsMap' flag to
+ * 'true' as is done in the main test above.
+ */
+ @Test
+ public void testStandardAnnotationMetadata_nestedAnnotationsAsMap_false() throws IOException {
+ AnnotationMetadata metadata = new StandardAnnotationMetadata(AnnotatedComponent.class);
+
+ AnnotationAttributes specialAttrs = (AnnotationAttributes) metadata.getAnnotationAttributes(SpecialAttr.class.getName());
+ Annotation[] nestedAnnoArray = (Annotation[])specialAttrs.get("nestedAnnoArray");
+ assertThat(nestedAnnoArray[0], instanceOf(NestedAnno.class));
+ }
+
+ private void doTestAnnotationInfo(AnnotationMetadata metadata) {
+ assertThat(metadata.getClassName(), is(AnnotatedComponent.class.getName()));
+ assertThat(metadata.isInterface(), is(false));
+ assertThat(metadata.isAbstract(), is(false));
+ assertThat(metadata.isConcrete(), is(true));
+ assertThat(metadata.hasSuperClass(), is(true));
+ assertThat(metadata.getSuperClassName(), is(Object.class.getName()));
+ assertThat(metadata.getInterfaceNames().length, is(1));
+ assertThat(metadata.getInterfaceNames()[0], is(Serializable.class.getName()));
+
+ assertThat(metadata.hasAnnotation(Component.class.getName()), is(true));
+ assertThat(metadata.hasAnnotation(Scope.class.getName()), is(true));
+ assertThat(metadata.hasAnnotation(SpecialAttr.class.getName()), is(true));
+ assertThat(metadata.getAnnotationTypes().size(), is(3));
+ assertThat(metadata.getAnnotationTypes().contains(Component.class.getName()), is(true));
+ assertThat(metadata.getAnnotationTypes().contains(Scope.class.getName()), is(true));
+ assertThat(metadata.getAnnotationTypes().contains(SpecialAttr.class.getName()), is(true));
+
+ AnnotationAttributes compAttrs = (AnnotationAttributes) metadata.getAnnotationAttributes(Component.class.getName());
+ assertThat(compAttrs.size(), is(1));
+ assertThat(compAttrs.getString("value"), is("myName"));
+ AnnotationAttributes scopeAttrs = (AnnotationAttributes) metadata.getAnnotationAttributes(Scope.class.getName());
+ assertThat(scopeAttrs.size(), is(1));
+ assertThat(scopeAttrs.getString("value"), is("myScope"));
+ { // perform tests with classValuesAsString = false (the default)
+ AnnotationAttributes specialAttrs = (AnnotationAttributes) metadata.getAnnotationAttributes(SpecialAttr.class.getName());
+ assertThat(specialAttrs.size(), is(6));
+ assertTrue(String.class.isAssignableFrom(specialAttrs.getClass("clazz")));
+ assertTrue(specialAttrs.getEnum("state").equals(Thread.State.NEW));
+
+ AnnotationAttributes nestedAnno = specialAttrs.getAnnotation("nestedAnno");
+ assertThat("na", is(nestedAnno.getString("value")));
+ assertTrue(nestedAnno.getEnum("anEnum").equals(SomeEnum.LABEL1));
+ assertArrayEquals(new Class[]{String.class}, (Class[])nestedAnno.get("classArray"));
+
+ AnnotationAttributes[] nestedAnnoArray = specialAttrs.getAnnotationArray("nestedAnnoArray");
+ assertThat(nestedAnnoArray.length, is(2));
+ assertThat(nestedAnnoArray[0].getString("value"), is("default"));
+ assertTrue(nestedAnnoArray[0].getEnum("anEnum").equals(SomeEnum.DEFAULT));
+ assertArrayEquals(new Class[]{Void.class}, (Class[])nestedAnnoArray[0].get("classArray"));
+ assertThat(nestedAnnoArray[1].getString("value"), is("na1"));
+ assertTrue(nestedAnnoArray[1].getEnum("anEnum").equals(SomeEnum.LABEL2));
+ assertArrayEquals(new Class[]{Number.class}, (Class[])nestedAnnoArray[1].get("classArray"));
+ assertArrayEquals(new Class[]{Number.class}, nestedAnnoArray[1].getClassArray("classArray"));
+
+ AnnotationAttributes optional = specialAttrs.getAnnotation("optional");
+ assertThat(optional.getString("value"), is("optional"));
+ assertTrue(optional.getEnum("anEnum").equals(SomeEnum.DEFAULT));
+ assertArrayEquals(new Class[]{Void.class}, (Class[])optional.get("classArray"));
+ assertArrayEquals(new Class[]{Void.class}, optional.getClassArray("classArray"));
+
+ AnnotationAttributes[] optionalArray = specialAttrs.getAnnotationArray("optionalArray");
+ assertThat(optionalArray.length, is(1));
+ assertThat(optionalArray[0].getString("value"), is("optional"));
+ assertTrue(optionalArray[0].getEnum("anEnum").equals(SomeEnum.DEFAULT));
+ assertArrayEquals(new Class[]{Void.class}, (Class[])optionalArray[0].get("classArray"));
+ assertArrayEquals(new Class[]{Void.class}, optionalArray[0].getClassArray("classArray"));
+ }
+ { // perform tests with classValuesAsString = true
+ AnnotationAttributes specialAttrs = (AnnotationAttributes) metadata.getAnnotationAttributes(SpecialAttr.class.getName(), true);
+ assertThat(specialAttrs.size(), is(6));
+ assertThat(specialAttrs.get("clazz"), is((Object)String.class.getName()));
+ assertThat(specialAttrs.getString("clazz"), is(String.class.getName()));
+
+ AnnotationAttributes nestedAnno = specialAttrs.getAnnotation("nestedAnno");
+ assertArrayEquals(new String[]{String.class.getName()}, nestedAnno.getStringArray("classArray"));
+ assertArrayEquals(new String[]{String.class.getName()}, nestedAnno.getStringArray("classArray"));
+
+ AnnotationAttributes[] nestedAnnoArray = specialAttrs.getAnnotationArray("nestedAnnoArray");
+ assertArrayEquals(new String[]{Void.class.getName()}, (String[])nestedAnnoArray[0].get("classArray"));
+ assertArrayEquals(new String[]{Void.class.getName()}, nestedAnnoArray[0].getStringArray("classArray"));
+ assertArrayEquals(new String[]{Number.class.getName()}, (String[])nestedAnnoArray[1].get("classArray"));
+ assertArrayEquals(new String[]{Number.class.getName()}, nestedAnnoArray[1].getStringArray("classArray"));
+
+ AnnotationAttributes optional = specialAttrs.getAnnotation("optional");
+ assertArrayEquals(new String[]{Void.class.getName()}, (String[])optional.get("classArray"));
+ assertArrayEquals(new String[]{Void.class.getName()}, optional.getStringArray("classArray"));
+
+ AnnotationAttributes[] optionalArray = specialAttrs.getAnnotationArray("optionalArray");
+ assertArrayEquals(new String[]{Void.class.getName()}, (String[])optionalArray[0].get("classArray"));
+ assertArrayEquals(new String[]{Void.class.getName()}, optionalArray[0].getStringArray("classArray"));
+ }
+ }
+
+ private void doTestMethodAnnotationInfo(AnnotationMetadata classMetadata) {
+ Set<MethodMetadata> methods = classMetadata.getAnnotatedMethods(TestAutowired.class.getName());
+ assertThat(methods.size(), is(1));
+ for (MethodMetadata methodMetadata : methods) {
+ assertThat(methodMetadata.isAnnotated(TestAutowired.class.getName()), is(true));
+ }
+ }
+
+ public static enum SomeEnum {
+ LABEL1, LABEL2, DEFAULT;
+ }
+
+ @Target({})
+ @Retention(RetentionPolicy.RUNTIME)
+ public @interface NestedAnno {
+ String value() default "default";
+ SomeEnum anEnum() default SomeEnum.DEFAULT;
+ Class<?>[] classArray() default Void.class;
+ }
+
+ @Target(ElementType.TYPE)
+ @Retention(RetentionPolicy.RUNTIME)
+ public @interface SpecialAttr {
+
+ Class<?> clazz();
+
+ Thread.State state();
+
+ NestedAnno nestedAnno();
+
+ NestedAnno[] nestedAnnoArray();
+
+ NestedAnno optional() default @NestedAnno(value="optional", anEnum=SomeEnum.DEFAULT, classArray=Void.class);
+
+ NestedAnno[] optionalArray() default {@NestedAnno(value="optional", anEnum=SomeEnum.DEFAULT, classArray=Void.class)};
+ }
+
+
+ @Component("myName")
+ @Scope("myScope")
+ @SpecialAttr(clazz = String.class, state = Thread.State.NEW,
+ nestedAnno = @NestedAnno(value = "na", anEnum = SomeEnum.LABEL1, classArray = {String.class}),
+ nestedAnnoArray = {
+ @NestedAnno,
+ @NestedAnno(value = "na1", anEnum = SomeEnum.LABEL2, classArray = {Number.class})
+ })
+ @SuppressWarnings({"serial", "unused"})
+ private static class AnnotatedComponent implements Serializable {
+
+ @TestAutowired
+ public void doWork(@TestQualifier("myColor") java.awt.Color color) {
+ }
+
+ public void doSleep() {
+ }
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/type/AnnotationTypeFilterTests.java b/spring-core/src/test/java/org/springframework/core/type/AnnotationTypeFilterTests.java
new file mode 100644
index 00000000..b316d174
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/type/AnnotationTypeFilterTests.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.type;
+
+import static org.junit.Assert.*;
+
+import java.lang.annotation.Inherited;
+
+import org.junit.Test;
+import org.springframework.core.type.classreading.MetadataReader;
+import org.springframework.core.type.classreading.MetadataReaderFactory;
+import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
+import org.springframework.core.type.filter.AnnotationTypeFilter;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author Ramnivas Laddad
+ * @author Juergen Hoeller
+ * @author Oliver Gierke
+ */
+public class AnnotationTypeFilterTests {
+
+ @Test
+ public void testDirectAnnotationMatch() throws Exception {
+ MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
+ String classUnderTest = "org.springframework.core.type.AnnotationTypeFilterTests$SomeComponent";
+ MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(classUnderTest);
+
+ AnnotationTypeFilter filter = new AnnotationTypeFilter(InheritedAnnotation.class);
+ assertTrue(filter.match(metadataReader, metadataReaderFactory));
+ ClassloadingAssertions.assertClassNotLoaded(classUnderTest);
+ }
+
+ @Test
+ public void testInheritedAnnotationFromInterfaceDoesNotMatch() throws Exception {
+ MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
+ String classUnderTest = "org.springframework.core.type.AnnotationTypeFilterTests$SomeSubClassOfSomeComponentInterface";
+ MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(classUnderTest);
+
+ AnnotationTypeFilter filter = new AnnotationTypeFilter(InheritedAnnotation.class);
+ // Must fail as annotation on interfaces should not be considered a match
+ assertFalse(filter.match(metadataReader, metadataReaderFactory));
+ ClassloadingAssertions.assertClassNotLoaded(classUnderTest);
+ }
+
+ @Test
+ public void testInheritedAnnotationFromBaseClassDoesMatch() throws Exception {
+ MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
+ String classUnderTest = "org.springframework.core.type.AnnotationTypeFilterTests$SomeSubClassOfSomeComponent";
+ MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(classUnderTest);
+
+ AnnotationTypeFilter filter = new AnnotationTypeFilter(InheritedAnnotation.class);
+ assertTrue(filter.match(metadataReader, metadataReaderFactory));
+ ClassloadingAssertions.assertClassNotLoaded(classUnderTest);
+ }
+
+ @Test
+ public void testNonInheritedAnnotationDoesNotMatch() throws Exception {
+ MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
+ String classUnderTest = "org.springframework.core.type.AnnotationTypeFilterTests$SomeSubclassOfSomeClassMarkedWithNonInheritedAnnotation";
+ MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(classUnderTest);
+
+ AnnotationTypeFilter filter = new AnnotationTypeFilter(NonInheritedAnnotation.class);
+ // Must fail as annotation isn't inherited
+ assertFalse(filter.match(metadataReader, metadataReaderFactory));
+ ClassloadingAssertions.assertClassNotLoaded(classUnderTest);
+ }
+
+ @Test
+ public void testNonAnnotatedClassDoesntMatch() throws Exception {
+ MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
+ String classUnderTest = "org.springframework.core.type.AnnotationTypeFilterTests$SomeNonCandidateClass";
+ MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(classUnderTest);
+
+ AnnotationTypeFilter filter = new AnnotationTypeFilter(Component.class);
+ assertFalse(filter.match(metadataReader, metadataReaderFactory));
+ ClassloadingAssertions.assertClassNotLoaded(classUnderTest);
+ }
+
+ @Test
+ public void testMatchesInterfacesIfConfigured() throws Exception {
+
+ MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
+ String classUnderTest = "org.springframework.core.type.AnnotationTypeFilterTests$SomeComponentInterface";
+ MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(classUnderTest);
+
+ AnnotationTypeFilter filter = new AnnotationTypeFilter(InheritedAnnotation.class, false, true);
+
+ assertTrue(filter.match(metadataReader, metadataReaderFactory));
+ ClassloadingAssertions.assertClassNotLoaded(classUnderTest);
+ }
+
+ // We must use a standalone set of types to ensure that no one else is loading them
+ // and interfering with ClassloadingAssertions.assertClassNotLoaded()
+
+ @Inherited
+ private static @interface InheritedAnnotation {
+ }
+
+
+ @InheritedAnnotation
+ private static class SomeComponent {
+ }
+
+
+ @InheritedAnnotation
+ private static interface SomeComponentInterface {
+ }
+
+
+ @SuppressWarnings("unused")
+ private static class SomeSubClassOfSomeComponentInterface implements SomeComponentInterface {
+ }
+
+
+ @SuppressWarnings("unused")
+ private static class SomeSubClassOfSomeComponent extends SomeComponent {
+ }
+
+
+ private static @interface NonInheritedAnnotation {
+ }
+
+
+ @NonInheritedAnnotation
+ private static class SomeClassMarkedWithNonInheritedAnnotation {
+ }
+
+
+ @SuppressWarnings("unused")
+ private static class SomeSubclassOfSomeClassMarkedWithNonInheritedAnnotation extends SomeClassMarkedWithNonInheritedAnnotation {
+ }
+
+
+ @SuppressWarnings("unused")
+ private static class SomeNonCandidateClass {
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/type/AspectJTypeFilterTests.java b/spring-core/src/test/java/org/springframework/core/type/AspectJTypeFilterTests.java
new file mode 100644
index 00000000..45abc29c
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/type/AspectJTypeFilterTests.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2002-2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.type;
+
+import junit.framework.TestCase;
+
+import org.springframework.core.type.classreading.MetadataReaderFactory;
+import org.springframework.core.type.classreading.MetadataReader;
+import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
+import org.springframework.core.type.filter.AspectJTypeFilter;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author Ramnivas Laddad
+ */
+public class AspectJTypeFilterTests extends TestCase {
+
+ public void testNamePatternMatches() throws Exception {
+ assertMatch("org.springframework.core.type.AspectJTypeFilterTests$SomeClass",
+ "org.springframework.core.type.AspectJTypeFilterTests.SomeClass");
+ assertMatch("org.springframework.core.type.AspectJTypeFilterTests$SomeClass",
+ "*");
+ assertMatch("org.springframework.core.type.AspectJTypeFilterTests$SomeClass",
+ "*..SomeClass");
+ assertMatch("org.springframework.core.type.AspectJTypeFilterTests$SomeClass",
+ "org..SomeClass");
+ }
+
+ public void testNamePatternNoMatches() throws Exception {
+ assertNoMatch("org.springframework.core.type.AspectJTypeFilterTests$SomeClass",
+ "org.springframework.core.type.AspectJTypeFilterTests.SomeClassX");
+ }
+
+ public void testSubclassPatternMatches() throws Exception {
+ assertMatch("org.springframework.core.type.AspectJTypeFilterTests$SomeClassExtendingSomeClass",
+ "org.springframework.core.type.AspectJTypeFilterTests.SomeClass+");
+ assertMatch("org.springframework.core.type.AspectJTypeFilterTests$SomeClassExtendingSomeClass",
+ "*+");
+ assertMatch("org.springframework.core.type.AspectJTypeFilterTests$SomeClassExtendingSomeClass",
+ "java.lang.Object+");
+
+ assertMatch("org.springframework.core.type.AspectJTypeFilterTests$SomeClassImplementingSomeInterface",
+ "org.springframework.core.type.AspectJTypeFilterTests.SomeInterface+");
+ assertMatch("org.springframework.core.type.AspectJTypeFilterTests$SomeClassImplementingSomeInterface",
+ "*+");
+ assertMatch("org.springframework.core.type.AspectJTypeFilterTests$SomeClassImplementingSomeInterface",
+ "java.lang.Object+");
+
+ assertMatch("org.springframework.core.type.AspectJTypeFilterTests$SomeClassExtendingSomeClassExtendingSomeClassAndImplemnentingSomeInterface",
+ "org.springframework.core.type.AspectJTypeFilterTests.SomeInterface+");
+ assertMatch("org.springframework.core.type.AspectJTypeFilterTests$SomeClassExtendingSomeClassExtendingSomeClassAndImplemnentingSomeInterface",
+ "org.springframework.core.type.AspectJTypeFilterTests.SomeClassExtendingSomeClass+");
+ assertMatch("org.springframework.core.type.AspectJTypeFilterTests$SomeClassExtendingSomeClassExtendingSomeClassAndImplemnentingSomeInterface",
+ "org.springframework.core.type.AspectJTypeFilterTests.SomeClass+");
+ assertMatch("org.springframework.core.type.AspectJTypeFilterTests$SomeClassExtendingSomeClassExtendingSomeClassAndImplemnentingSomeInterface",
+ "*+");
+ assertMatch("org.springframework.core.type.AspectJTypeFilterTests$SomeClassExtendingSomeClassExtendingSomeClassAndImplemnentingSomeInterface",
+ "java.lang.Object+");
+ }
+
+ public void testSubclassPatternNoMatches() throws Exception {
+ assertNoMatch("org.springframework.core.type.AspectJTypeFilterTests$SomeClassExtendingSomeClass",
+ "java.lang.String+");
+ }
+
+ public void testAnnotationPatternMatches() throws Exception {
+ assertMatch("org.springframework.core.type.AspectJTypeFilterTests$SomeClassAnnotatedWithComponent",
+ "@org.springframework.stereotype.Component *..*");
+ assertMatch("org.springframework.core.type.AspectJTypeFilterTests$SomeClassAnnotatedWithComponent",
+ "@* *..*");
+ assertMatch("org.springframework.core.type.AspectJTypeFilterTests$SomeClassAnnotatedWithComponent",
+ "@*..* *..*");
+ assertMatch("org.springframework.core.type.AspectJTypeFilterTests$SomeClassAnnotatedWithComponent",
+ "@*..*Component *..*");
+ assertMatch("org.springframework.core.type.AspectJTypeFilterTests$SomeClassAnnotatedWithComponent",
+ "@org.springframework.stereotype.Component *..*Component");
+ assertMatch("org.springframework.core.type.AspectJTypeFilterTests$SomeClassAnnotatedWithComponent",
+ "@org.springframework.stereotype.Component *");
+ }
+
+ public void testAnnotationPatternNoMathces() throws Exception {
+ assertNoMatch("org.springframework.core.type.AspectJTypeFilterTests$SomeClassAnnotatedWithComponent",
+ "@org.springframework.stereotype.Repository *..*");
+ }
+
+ public void testCompositionPatternMatches() throws Exception {
+ assertMatch("org.springframework.core.type.AspectJTypeFilterTests$SomeClass",
+ "!*..SomeOtherClass");
+ assertMatch("org.springframework.core.type.AspectJTypeFilterTests$SomeClassExtendingSomeClassExtendingSomeClassAndImplemnentingSomeInterface",
+ "org.springframework.core.type.AspectJTypeFilterTests.SomeInterface+ " +
+ "&& org.springframework.core.type.AspectJTypeFilterTests.SomeClass+ " +
+ "&& org.springframework.core.type.AspectJTypeFilterTests.SomeClassExtendingSomeClass+");
+ assertMatch("org.springframework.core.type.AspectJTypeFilterTests$SomeClassExtendingSomeClassExtendingSomeClassAndImplemnentingSomeInterface",
+ "org.springframework.core.type.AspectJTypeFilterTests.SomeInterface+ " +
+ "|| org.springframework.core.type.AspectJTypeFilterTests.SomeClass+ " +
+ "|| org.springframework.core.type.AspectJTypeFilterTests.SomeClassExtendingSomeClass+");
+ }
+
+ public void testCompositionPatternNoMatches() throws Exception {
+ assertNoMatch("org.springframework.core.type.AspectJTypeFilterTests$SomeClass",
+ "*..Bogus && org.springframework.core.type.AspectJTypeFilterTests.SomeClass");
+ }
+
+ private void assertMatch(String type, String typePattern) throws Exception {
+ MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
+ MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(type);
+
+ AspectJTypeFilter filter = new AspectJTypeFilter(typePattern, getClass().getClassLoader());
+ assertTrue(filter.match(metadataReader, metadataReaderFactory));
+ ClassloadingAssertions.assertClassNotLoaded(type);
+ }
+
+ private void assertNoMatch(String type, String typePattern) throws Exception {
+ MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
+ MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(type);
+
+ AspectJTypeFilter filter = new AspectJTypeFilter(typePattern, getClass().getClassLoader());
+ assertFalse(filter.match(metadataReader, metadataReaderFactory));
+ ClassloadingAssertions.assertClassNotLoaded(type);
+ }
+
+
+ // We must use a standalone set of types to ensure that no one else is loading them
+ // and interfering with ClassloadingAssertions.assertClassNotLoaded()
+ static interface SomeInterface {
+ }
+
+
+ static class SomeClass {
+ }
+
+
+ static class SomeClassExtendingSomeClass extends SomeClass {
+ }
+
+
+ static class SomeClassImplementingSomeInterface implements SomeInterface {
+ }
+
+
+ static class SomeClassExtendingSomeClassExtendingSomeClassAndImplemnentingSomeInterface
+ extends SomeClassExtendingSomeClass implements SomeInterface {
+ }
+
+
+ @Component
+ static class SomeClassAnnotatedWithComponent {
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/type/AssignableTypeFilterTests.java b/spring-core/src/test/java/org/springframework/core/type/AssignableTypeFilterTests.java
new file mode 100644
index 00000000..cc624af1
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/type/AssignableTypeFilterTests.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.type;
+
+import junit.framework.TestCase;
+
+import org.springframework.core.type.classreading.MetadataReaderFactory;
+import org.springframework.core.type.classreading.MetadataReader;
+import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
+import org.springframework.core.type.filter.AssignableTypeFilter;
+
+/**
+ * @author Ramnivas Laddad
+ * @author Juergen Hoeller
+ */
+public class AssignableTypeFilterTests extends TestCase {
+
+ public void testDirectMatch() throws Exception {
+ MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
+ String classUnderTest = "org.springframework.core.type.AssignableTypeFilterTests$TestNonInheritingClass";
+ MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(classUnderTest);
+
+ AssignableTypeFilter matchingFilter = new AssignableTypeFilter(TestNonInheritingClass.class);
+ AssignableTypeFilter notMatchingFilter = new AssignableTypeFilter(TestInterface.class);
+ assertFalse(notMatchingFilter.match(metadataReader, metadataReaderFactory));
+ assertTrue(matchingFilter.match(metadataReader, metadataReaderFactory));
+ }
+
+ public void testInterfaceMatch() throws Exception {
+ MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
+ String classUnderTest = "org.springframework.core.type.AssignableTypeFilterTests$TestInterfaceImpl";
+ MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(classUnderTest);
+
+ AssignableTypeFilter filter = new AssignableTypeFilter(TestInterface.class);
+ assertTrue(filter.match(metadataReader, metadataReaderFactory));
+ ClassloadingAssertions.assertClassNotLoaded(classUnderTest);
+ }
+
+ public void testSuperClassMatch() throws Exception {
+ MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
+ String classUnderTest = "org.springframework.core.type.AssignableTypeFilterTests$SomeDaoLikeImpl";
+ MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(classUnderTest);
+
+ AssignableTypeFilter filter = new AssignableTypeFilter(SimpleJdbcDaoSupport.class);
+ assertTrue(filter.match(metadataReader, metadataReaderFactory));
+ ClassloadingAssertions.assertClassNotLoaded(classUnderTest);
+ }
+
+ public void testInterfaceThroughSuperClassMatch() throws Exception {
+ MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
+ String classUnderTest = "org.springframework.core.type.AssignableTypeFilterTests$SomeDaoLikeImpl";
+ MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(classUnderTest);
+
+ AssignableTypeFilter filter = new AssignableTypeFilter(JdbcDaoSupport.class);
+ assertTrue(filter.match(metadataReader, metadataReaderFactory));
+ ClassloadingAssertions.assertClassNotLoaded(classUnderTest);
+ }
+
+
+ // We must use a standalone set of types to ensure that no one else is loading them
+ // and interfere with ClassloadingAssertions.assertClassNotLoaded()
+ private static class TestNonInheritingClass {
+ }
+
+
+ private static interface TestInterface {
+ }
+
+
+ @SuppressWarnings("unused")
+ private static class TestInterfaceImpl implements TestInterface {
+ }
+
+
+ private static interface SomeDaoLikeInterface {
+ }
+
+
+ @SuppressWarnings("unused")
+ private static class SomeDaoLikeImpl extends SimpleJdbcDaoSupport implements SomeDaoLikeInterface {
+ }
+
+ private static interface JdbcDaoSupport {
+
+ }
+
+ private static class SimpleJdbcDaoSupport implements JdbcDaoSupport {
+
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/type/CachingMetadataReaderLeakTest.java b/spring-core/src/test/java/org/springframework/core/type/CachingMetadataReaderLeakTest.java
new file mode 100644
index 00000000..1d138b76
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/type/CachingMetadataReaderLeakTest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.core.type;
+
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+
+import java.net.URL;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.UrlResource;
+import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
+import org.springframework.core.type.classreading.MetadataReader;
+import org.springframework.core.type.classreading.MetadataReaderFactory;
+import org.springframework.tests.Assume;
+import org.springframework.tests.TestGroup;
+
+/**
+ * Unit test checking the behaviour of {@link CachingMetadataReaderFactory} under load.
+ * If the cache is not controller, this test should fail with an out of memory exception around entry
+ * 5k.
+ *
+ * @author Costin Leau
+ */
+public class CachingMetadataReaderLeakTest {
+
+ private static int ITEMS_LOAD = 9999;
+ private MetadataReaderFactory mrf;
+
+ @Before
+ public void before() {
+ mrf = new CachingMetadataReaderFactory();
+ }
+
+ @Test
+ public void testSignificantLoad() throws Exception {
+ Assume.group(TestGroup.LONG_RUNNING);
+
+ // the biggest public class in the JDK (>60k)
+ URL url = getClass().getResource("/java/awt/Component.class");
+ assertThat(url, notNullValue());
+
+ // look at a LOT of items
+ for (int i = 0; i < ITEMS_LOAD; i++) {
+ Resource resource = new UrlResource(url) {
+ private int counter = 0;
+
+ @Override
+ public boolean equals(Object obj) {
+ return (obj == this);
+
+ }
+
+ @Override
+ public int hashCode() {
+ return System.identityHashCode(this);
+ }
+ };
+
+ MetadataReader reader = mrf.getMetadataReader(resource);
+ assertThat(reader, notNullValue());
+ }
+
+ // useful for profiling to take snapshots
+ //System.in.read();
+ }
+}
diff --git a/spring-core/src/test/java/org/springframework/core/type/ClassloadingAssertions.java b/spring-core/src/test/java/org/springframework/core/type/ClassloadingAssertions.java
new file mode 100644
index 00000000..a9996e33
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/type/ClassloadingAssertions.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.core.type;
+
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+
+import org.springframework.util.ClassUtils;
+import org.springframework.util.ReflectionUtils;
+
+/**
+ *
+ * @author Ramnivas Laddad
+ *
+ */
+public class ClassloadingAssertions {
+ public static boolean isClassLoaded(String className) {
+ ClassLoader cl = ClassUtils.getDefaultClassLoader();
+ Method findLoadeClassMethod = ReflectionUtils.findMethod(cl.getClass(), "findLoadedClass", new Class[]{String.class});
+ findLoadeClassMethod.setAccessible(true);
+ Class loadedClass = (Class)ReflectionUtils.invokeMethod(findLoadeClassMethod, cl, new Object[]{className});
+ return loadedClass != null;
+ }
+
+ public static void assertClassLoaded(String className) {
+ }
+
+ public static void assertClassNotLoaded(String className) {
+ TestCase.assertFalse("Class shouldn't have been loaded", isClassLoaded(className));
+ }
+} \ No newline at end of file
diff --git a/spring-core/src/test/java/org/springframework/core/type/Scope.java b/spring-core/src/test/java/org/springframework/core/type/Scope.java
new file mode 100644
index 00000000..a365f2a8
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/type/Scope.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2002-2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.type;
+
+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;
+
+@Target({ElementType.TYPE, ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface Scope {
+
+ /**
+ * Specifies the scope to use for instances of the annotated class.
+ * @return the desired scope
+ */
+ String value() default "singleton";
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/type/StandardClassMetadataMemberClassTests.java b/spring-core/src/test/java/org/springframework/core/type/StandardClassMetadataMemberClassTests.java
new file mode 100644
index 00000000..716c03c4
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/type/StandardClassMetadataMemberClassTests.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2002-2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.type;
+
+/**
+ * @author Chris Beams
+ * @since 3.1
+ * @see AbstractClassMetadataMemberClassTests
+ */
+public class StandardClassMetadataMemberClassTests
+ extends AbstractClassMetadataMemberClassTests {
+
+ @Override
+ public ClassMetadata getClassMetadataFor(Class<?> clazz) {
+ return new StandardClassMetadata(clazz);
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/type/TestAutowired.java b/spring-core/src/test/java/org/springframework/core/type/TestAutowired.java
new file mode 100644
index 00000000..c1a1b1d2
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/type/TestAutowired.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.type;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD})
+public @interface TestAutowired {
+
+ /**
+ * Declares whether the annotated dependency is required.
+ * <p>Defaults to {@code true}.
+ */
+ boolean required() default true;
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/type/TestQualifier.java b/spring-core/src/test/java/org/springframework/core/type/TestQualifier.java
new file mode 100644
index 00000000..9698ec71
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/type/TestQualifier.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.type;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
+@Inherited
+@Documented
+public @interface TestQualifier {
+
+ String value() default "";
+
+}
diff --git a/spring-core/src/test/java/org/springframework/core/type/classreading/ClassMetadataReadingVisitorMemberClassTests.java b/spring-core/src/test/java/org/springframework/core/type/classreading/ClassMetadataReadingVisitorMemberClassTests.java
new file mode 100644
index 00000000..cc4ca072
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/type/classreading/ClassMetadataReadingVisitorMemberClassTests.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2002-2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.type.classreading;
+
+import java.io.IOException;
+
+import org.springframework.core.type.AbstractClassMetadataMemberClassTests;
+import org.springframework.core.type.ClassMetadata;
+
+/**
+ * @author Chris Beams
+ * @since 3.1
+ * @see AbstractClassMetadataMemberClassTests
+ */
+public class ClassMetadataReadingVisitorMemberClassTests
+ extends AbstractClassMetadataMemberClassTests {
+
+ @Override
+ public ClassMetadata getClassMetadataFor(Class<?> clazz) {
+ try {
+ MetadataReader reader =
+ new SimpleMetadataReaderFactory().getMetadataReader(clazz.getName());
+ return reader.getAnnotationMetadata();
+ } catch (IOException ex) {
+ throw new IllegalStateException(ex);
+ }
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/mock/env/MockPropertySource.java b/spring-core/src/test/java/org/springframework/mock/env/MockPropertySource.java
new file mode 100644
index 00000000..2783f244
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/mock/env/MockPropertySource.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.mock.env;
+
+import java.util.Properties;
+
+import org.springframework.core.env.PropertiesPropertySource;
+import org.springframework.core.env.PropertySource;
+
+/**
+ * Simple {@link PropertySource} implementation for use in testing. Accepts
+ * a user-provided {@link Properties} object, or if omitted during construction,
+ * the implementation will initialize its own.
+ *
+ * The {@link #setProperty} and {@link #withProperty} methods are exposed for
+ * convenience, for example:
+ * <pre>
+ * {@code
+ * PropertySource<?> source = new MockPropertySource().withProperty("foo", "bar");
+ * }
+ * </pre>
+ *
+ * @author Chris Beams
+ * @since 3.1
+ * @see org.springframework.mock.env.MockEnvironment
+ */
+public class MockPropertySource extends PropertiesPropertySource {
+
+ /**
+ * {@value} is the default name for {@link MockPropertySource} instances not
+ * otherwise given an explicit name.
+ * @see #MockPropertySource()
+ * @see #MockPropertySource(String)
+ */
+ public static final String MOCK_PROPERTIES_PROPERTY_SOURCE_NAME = "mockProperties";
+
+ /**
+ * Create a new {@code MockPropertySource} named {@value #MOCK_PROPERTIES_PROPERTY_SOURCE_NAME}
+ * that will maintain its own internal {@link Properties} instance.
+ */
+ public MockPropertySource() {
+ this(new Properties());
+ }
+
+ /**
+ * Create a new {@code MockPropertySource} with the given name that will
+ * maintain its own internal {@link Properties} instance.
+ * @param name the {@linkplain #getName() name} of the property source
+ */
+ public MockPropertySource(String name) {
+ this(name, new Properties());
+ }
+
+ /**
+ * Create a new {@code MockPropertySource} named {@value #MOCK_PROPERTIES_PROPERTY_SOURCE_NAME}
+ * and backed by the given {@link Properties} object.
+ * @param properties the properties to use
+ */
+ public MockPropertySource(Properties properties) {
+ this(MOCK_PROPERTIES_PROPERTY_SOURCE_NAME, properties);
+ }
+
+ /**
+ * Create a new {@code MockPropertySource} with the given name and backed by the given
+ * {@link Properties} object
+ * @param name the {@linkplain #getName() name} of the property source
+ * @param properties the properties to use
+ */
+ public MockPropertySource(String name, Properties properties) {
+ super(name, properties);
+ }
+
+ /**
+ * Set the given property on the underlying {@link Properties} object.
+ */
+ public void setProperty(String name, Object value) {
+ this.source.put(name, value);
+ }
+
+ /**
+ * Convenient synonym for {@link #setProperty} that returns the current instance.
+ * Useful for method chaining and fluent-style use.
+ * @return this {@link MockPropertySource} instance
+ */
+ public MockPropertySource withProperty(String name, Object value) {
+ this.setProperty(name, value);
+ return this;
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/stereotype/Component.java b/spring-core/src/test/java/org/springframework/stereotype/Component.java
new file mode 100644
index 00000000..e0b637f8
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/stereotype/Component.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.stereotype;
+
+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;
+
+/**
+ * Indicates that an annotated class is a "component".
+ * Such classes are considered as candidates for auto-detection
+ * when using annotation-based configuration and classpath scanning.
+ *
+ * <p>Other class-level annotations may be considered as identifying
+ * a component as well, typically a special kind of component:
+ * e.g. the {@link Repository @Repository} annotation or AspectJ's
+ * {@link org.aspectj.lang.annotation.Aspect @Aspect} annotation.
+ *
+ * @author Mark Fisher
+ * @since 2.5
+ * @see Repository
+ * @see Service
+ * @see Controller
+ * @see org.springframework.context.annotation.ClassPathBeanDefinitionScanner
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface Component {
+
+ /**
+ * The value may indicate a suggestion for a logical component name,
+ * to be turned into a Spring bean in case of an autodetected component.
+ * @return the suggested component name, if any
+ */
+ public abstract String value() default "";
+
+} \ No newline at end of file
diff --git a/spring-core/src/test/java/org/springframework/tests/Assume.java b/spring-core/src/test/java/org/springframework/tests/Assume.java
new file mode 100644
index 00000000..801cd93a
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/tests/Assume.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.tests;
+
+import static org.junit.Assume.assumeFalse;
+
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.junit.internal.AssumptionViolatedException;
+
+/**
+ * Provides utility methods that allow JUnit tests to {@link org.junit.Assume} certain
+ * conditions hold {@code true}. If the assumption fails, it means the test should be
+ * skipped.
+ *
+ * <p>For example, if a set of tests require at least JDK 1.7 it can use
+ * {@code Assume#atLeast(JdkVersion.JAVA_17)} as shown below:
+ *
+ * <pre class="code">
+ * public void MyTests {
+ *
+ * &#064;BeforeClass
+ * public static assumptions() {
+ * Assume.atLeast(JdkVersion.JAVA_17);
+ * }
+ *
+ * // ... all the test methods that require at least JDK 1.7
+ * }
+ * </pre>
+ *
+ * If only a single test requires at least JDK 1.7 it can use the
+ * {@code Assume#atLeast(JdkVersion.JAVA_17)} as shown below:
+ *
+ * <pre class="code">
+ * public void MyTests {
+ *
+ * &#064;Test
+ * public void requiresJdk17 {
+ * Assume.atLeast(JdkVersion.JAVA_17);
+ * // ... perform the actual test
+ * }
+ * }
+ * </pre>
+ *
+ * In addition to assumptions based on the JDK version, tests can be categorized into
+ * {@link TestGroup}s. Active groups are enabled using the 'testGroups' system property,
+ * usually activated from the gradle command line:
+ * <pre>
+ * gradle test -PtestGroups="performance"
+ * </pre>
+ *
+ * Groups can be specified as a comma separated list of values, or using the pseudo group
+ * 'all'. See {@link TestGroup} for a list of valid groups.
+ *
+ * @author Rob Winch
+ * @author Phillip Webb
+ * @since 3.2
+ * @see #atLeast(JavaVersion)
+ * @see #group(TestGroup)
+ */
+public abstract class Assume {
+
+
+ private static final Set<TestGroup> GROUPS = TestGroup.parse(System.getProperty("testGroups"));
+
+
+ /**
+ * Assume a minimum {@link JavaVersion} is running.
+ * @param version the minimum version for the test to run
+ */
+ public static void atLeast(JavaVersion version) {
+ if (!JavaVersion.runningVersion().isAtLeast(version)) {
+ throw new AssumptionViolatedException("Requires JDK " + version + " but running "
+ + JavaVersion.runningVersion());
+ }
+ }
+
+ /**
+ * Assume that a particular {@link TestGroup} has been specified.
+ * @param group the group that must be specified.
+ */
+ public static void group(TestGroup group) {
+ if (!GROUPS.contains(group)) {
+ throw new AssumptionViolatedException("Requires unspecified group " + group
+ + " from " + GROUPS);
+ }
+ }
+
+ /**
+ * Assume that the specified log is not set to Trace or Debug.
+ * @param log the log to test
+ */
+ public static void notLogging(Log log) {
+ assumeFalse(log.isTraceEnabled());
+ assumeFalse(log.isDebugEnabled());
+ }
+}
diff --git a/spring-core/src/test/java/org/springframework/tests/BuildTests.java b/spring-core/src/test/java/org/springframework/tests/BuildTests.java
new file mode 100644
index 00000000..92008dfb
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/tests/BuildTests.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.tests;
+
+import org.junit.Test;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+/**
+ * General build related tests. Part of spring-core to ensure that they run early in the
+ * build process.
+ */
+public class BuildTests {
+
+ @Test
+ public void javaVersion() throws Exception {
+ Assume.group(TestGroup.CI);
+ assertThat("Java Version", JavaVersion.runningVersion(), equalTo(JavaVersion.JAVA_17));
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/tests/JavaVersion.java b/spring-core/src/test/java/org/springframework/tests/JavaVersion.java
new file mode 100644
index 00000000..b36319b2
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/tests/JavaVersion.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.tests;
+
+/**
+ * Enumeration of known JDK versions.
+ *
+ * @author Phillip Webb
+ * @see #runningVersion()
+ */
+public enum JavaVersion {
+
+
+ /**
+ * Java 1.5
+ */
+ JAVA_15("1.5", 15),
+
+ /**
+ * Java 1.6
+ */
+ JAVA_16("1.6", 16),
+
+ /**
+ * Java 1.7
+ */
+ JAVA_17("1.7", 17),
+
+ /**
+ * Java 1.8
+ */
+ JAVA_18("1.8", 18);
+
+
+ private static final JavaVersion runningVersion = findRunningVersion();
+
+ private static JavaVersion findRunningVersion() {
+ String version = System.getProperty("java.version");
+ for (JavaVersion candidate : values()) {
+ if (version.startsWith(candidate.version)) {
+ return candidate;
+ }
+ }
+ return JavaVersion.JAVA_15;
+ }
+
+
+ private String version;
+
+ private int value;
+
+
+ private JavaVersion(String version, int value) {
+ this.version = version;
+ this.value = value;
+ }
+
+
+ @Override
+ public String toString() {
+ return version;
+ }
+
+ /**
+ * Determines if the specified version is the same as or greater than this version.
+ * @param version the version to check
+ * @return {@code true} if the specified version is at least this version
+ */
+ public boolean isAtLeast(JavaVersion version) {
+ return this.value >= version.value;
+ }
+
+
+ /**
+ * Returns the current running JDK version. If the current version cannot be
+ * determined {@link #JAVA_15} will be returned.
+ * @return the JDK version
+ */
+ public static JavaVersion runningVersion() {
+ return runningVersion;
+ }
+}
diff --git a/spring-core/src/test/java/org/springframework/tests/JavaVersionTests.java b/spring-core/src/test/java/org/springframework/tests/JavaVersionTests.java
new file mode 100644
index 00000000..82b51e00
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/tests/JavaVersionTests.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.tests;
+
+import static org.hamcrest.Matchers.startsWith;
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+/**
+ * Tests for {@link JavaVersion}.
+ *
+ * @author Phillip Webb
+ */
+public class JavaVersionTests {
+
+ @Test
+ public void runningVersion() {
+ assertNotNull(JavaVersion.runningVersion());
+ assertThat(System.getProperty("java.version"), startsWith(JavaVersion.runningVersion().toString()));
+ }
+
+ @Test
+ public void isAtLeast() throws Exception {
+ assertTrue(JavaVersion.JAVA_16.isAtLeast(JavaVersion.JAVA_15));
+ assertTrue(JavaVersion.JAVA_16.isAtLeast(JavaVersion.JAVA_16));
+ assertFalse(JavaVersion.JAVA_16.isAtLeast(JavaVersion.JAVA_17));
+ }
+}
diff --git a/spring-core/src/test/java/org/springframework/tests/Matchers.java b/spring-core/src/test/java/org/springframework/tests/Matchers.java
new file mode 100644
index 00000000..826bd1c7
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/tests/Matchers.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.tests;
+
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.junit.Rule;
+import org.junit.rules.ExpectedException;
+
+/**
+ * Additional hamcrest matchers.
+ *
+ * @author Phillip Webb
+ */
+public class Matchers {
+
+ /**
+ * Create a matcher that wrapps the specified matcher and tests against the
+ * {@link Throwable#getCause() cause} of an exception. If the item tested
+ * is {@code null} not a {@link Throwable} the wrapped matcher will be called
+ * with a {@code null} item.
+ *
+ * <p>Often useful when working with JUnit {@link ExpectedException}
+ * {@link Rule @Rule}s, for example:
+ * <pre>
+ * thrown.expect(DataAccessException.class);
+ * thrown.except(exceptionCause(isA(SQLException.class)));
+ * </pre>
+ *
+ * @param matcher the matcher to wrap (must not be null)
+ * @return a matcher that tests using the exception cause
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> Matcher<T> exceptionCause(final Matcher<T> matcher) {
+ return (Matcher<T>) new BaseMatcher<Object>() {
+ @Override
+ public boolean matches(Object item) {
+ Throwable cause = null;
+ if(item != null && item instanceof Throwable) {
+ cause = ((Throwable)item).getCause();
+ }
+ return matcher.matches(cause);
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("exception cause ").appendDescriptionOf(matcher);
+ }
+ };
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/tests/MockitoUtils.java b/spring-core/src/test/java/org/springframework/tests/MockitoUtils.java
new file mode 100644
index 00000000..0fb20f30
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/tests/MockitoUtils.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.tests;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.util.List;
+
+import org.mockito.Mockito;
+import org.mockito.internal.util.MockUtil;
+import org.mockito.invocation.Invocation;
+
+/**
+ * General test utilities for use with {@link Mockito}.
+ *
+ * @author Phillip Webb
+ */
+public class MockitoUtils {
+
+ private static MockUtil mockUtil = new MockUtil();
+
+ /**
+ * Verify the same invocations have been applied to two mocks. This is generally not
+ * the preferred way test with mockito and should be avoided if possible.
+ * @param expected the mock containing expected invocations
+ * @param actual the mock containing actual invocations
+ * @param argumentAdapters adapters that can be used to change argument values before
+ * they are compared
+ */
+ public static <T> void verifySameInvocations(T expected, T actual, InvocationArgumentsAdapter... argumentAdapters) {
+ List<Invocation> expectedInvocations = mockUtil.getMockHandler(expected).getInvocationContainer().getInvocations();
+ List<Invocation> actualInvocations = mockUtil.getMockHandler(actual).getInvocationContainer().getInvocations();
+ verifySameInvocations(expectedInvocations, actualInvocations, argumentAdapters);
+ }
+
+ private static void verifySameInvocations(List<Invocation> expectedInvocations, List<Invocation> actualInvocations, InvocationArgumentsAdapter... argumentAdapters) {
+ assertThat(expectedInvocations.size(), is(equalTo(actualInvocations.size())));
+ for (int i = 0; i < expectedInvocations.size(); i++) {
+ verifySameInvocation(expectedInvocations.get(i), actualInvocations.get(i), argumentAdapters);
+ }
+ }
+
+ private static void verifySameInvocation(Invocation expectedInvocation, Invocation actualInvocation, InvocationArgumentsAdapter... argumentAdapters) {
+ System.out.println(expectedInvocation);
+ System.out.println(actualInvocation);
+ assertThat(expectedInvocation.getMethod(), is(equalTo(actualInvocation.getMethod())));
+ Object[] expectedArguments = getInvocationArguments(expectedInvocation, argumentAdapters);
+ Object[] actualArguments = getInvocationArguments(actualInvocation, argumentAdapters);
+ assertThat(expectedArguments, is(equalTo(actualArguments)));
+ }
+
+ private static Object[] getInvocationArguments(Invocation invocation, InvocationArgumentsAdapter... argumentAdapters) {
+ Object[] arguments = invocation.getArguments();
+ for (InvocationArgumentsAdapter adapter : argumentAdapters) {
+ arguments = adapter.adaptArguments(arguments);
+ }
+ return arguments;
+ }
+
+ /**
+ * Adapter strategy that can be used to change invocation arguments.
+ */
+ public static interface InvocationArgumentsAdapter {
+
+ /**
+ * Change the arguments if required
+ * @param arguments the source arguments
+ * @return updated or original arguments (never {@code null})
+ */
+ Object[] adaptArguments(Object[] arguments);
+ }
+}
diff --git a/spring-core/src/test/java/org/springframework/tests/TestGroup.java b/spring-core/src/test/java/org/springframework/tests/TestGroup.java
new file mode 100644
index 00000000..c135e8e6
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/tests/TestGroup.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.tests;
+
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.springframework.util.StringUtils;
+
+import static java.lang.String.*;
+
+/**
+ * A test group used to limit when certain tests are run.
+ *
+ * @see Assume#group(TestGroup)
+ * @author Phillip Webb
+ * @author Chris Beams
+ */
+public enum TestGroup {
+
+
+ /**
+ * Tests that take a considerable amount of time to run. Any test lasting longer than
+ * 500ms should be considered a candidate in order to avoid making the overall test
+ * suite too slow to run during the normal development cycle.
+ */
+ LONG_RUNNING,
+
+ /**
+ * Performance-related tests that may fail unpredictably based on CPU profile and load.
+ * Any test using {@link Thread#sleep}, {@link Object#wait}, Spring's
+ * {@code StopWatch}, etc. should be considered a candidate as their successful
+ * execution is likely to be based on events occurring within a given time window.
+ */
+ PERFORMANCE,
+
+ /**
+ * Tests requiring the presence of jmxremote_optional.jar in jre/lib/ext in order to
+ * avoid "Unsupported protocol: jmxmp" errors.
+ */
+ JMXMP,
+
+ /**
+ * Tests that should only be run on the continuous integration server.
+ */
+ CI,
+
+ /**
+ * Tests that require custom compilation beyond that of the standard JDK. This helps to
+ * allow running tests that will otherwise fail when using JDK > 1.8 b88. See
+ * <a href="https://jira.springsource.org/browse/SPR-10558">SPR-10558</a>
+ */
+ CUSTOM_COMPILATION;
+
+ /**
+ * Parse the specified comma separates string of groups.
+ * @param value the comma separated string of groups
+ * @return a set of groups
+ */
+ public static Set<TestGroup> parse(String value) {
+ if (value == null || "".equals(value)) {
+ return Collections.emptySet();
+ }
+ if("ALL".equalsIgnoreCase(value)) {
+ return EnumSet.allOf(TestGroup.class);
+ }
+ Set<TestGroup> groups = new HashSet<TestGroup>();
+ for (String group : value.split(",")) {
+ try {
+ groups.add(valueOf(group.trim().toUpperCase()));
+ } catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException(format(
+ "Unable to find test group '%s' when parsing testGroups value: '%s'. " +
+ "Available groups include: [%s]", group.trim(), value,
+ StringUtils.arrayToCommaDelimitedString(TestGroup.values())));
+ }
+ }
+ return groups;
+ }
+}
diff --git a/spring-core/src/test/java/org/springframework/tests/TestGroupTests.java b/spring-core/src/test/java/org/springframework/tests/TestGroupTests.java
new file mode 100644
index 00000000..2d519345
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/tests/TestGroupTests.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.tests;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Set;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+/**
+ * Tests for {@link TestGroup}.
+ *
+ * @author Phillip Webb
+ */
+public class TestGroupTests {
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void parseNull() throws Exception {
+ assertThat(TestGroup.parse(null), is(Collections.<TestGroup> emptySet()));
+ }
+
+ @Test
+ public void parseEmptyString() throws Exception {
+ assertThat(TestGroup.parse(""), is(Collections.<TestGroup> emptySet()));
+ }
+
+ @Test
+ public void parseWithSpaces() throws Exception {
+ assertThat(TestGroup.parse("PERFORMANCE, PERFORMANCE"),
+ is((Set<TestGroup>) EnumSet.of(TestGroup.PERFORMANCE)));
+ }
+
+ @Test
+ public void parseInMixedCase() throws Exception {
+ assertThat(TestGroup.parse("performance, PERFormaNCE"),
+ is((Set<TestGroup>) EnumSet.of(TestGroup.PERFORMANCE)));
+ }
+
+ @Test
+ public void parseMissing() throws Exception {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("Unable to find test group 'missing' when parsing " +
+ "testGroups value: 'performance, missing'. Available groups include: " +
+ "[LONG_RUNNING,PERFORMANCE,JMXMP,CI,CUSTOM_COMPILATION]");
+ TestGroup.parse("performance, missing");
+ }
+
+ @Test
+ public void parseAll() throws Exception {
+ assertThat(TestGroup.parse("all"), is((Set<TestGroup>)EnumSet.allOf(TestGroup.class)));
+ }
+}
diff --git a/spring-core/src/test/java/org/springframework/tests/TestResourceUtils.java b/spring-core/src/test/java/org/springframework/tests/TestResourceUtils.java
new file mode 100644
index 00000000..93aab194
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/tests/TestResourceUtils.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.tests;
+
+import static java.lang.String.format;
+
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * Convenience utilities for common operations with test resources.
+ *
+ * @author Chris Beams
+ */
+public class TestResourceUtils {
+
+ /**
+ * Loads a {@link ClassPathResource} qualified by the simple name of clazz,
+ * and relative to the package for clazz.
+ *
+ * <p>Example: given a clazz 'com.foo.BarTests' and a resourceSuffix of 'context.xml',
+ * this method will return a ClassPathResource representing com/foo/BarTests-context.xml
+ *
+ * <p>Intended for use loading context configuration XML files within JUnit tests.
+ *
+ * @param clazz
+ * @param resourceSuffix
+ */
+ public static ClassPathResource qualifiedResource(Class<?> clazz, String resourceSuffix) {
+ return new ClassPathResource(format("%s-%s", clazz.getSimpleName(), resourceSuffix), clazz);
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/tests/TimeStamped.java b/spring-core/src/test/java/org/springframework/tests/TimeStamped.java
new file mode 100644
index 00000000..ad653a50
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/tests/TimeStamped.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.tests;
+
+/**
+ * This interface can be implemented by cacheable objects or cache entries,
+ * to enable the freshness of objects to be checked.
+ *
+ * @author Rod Johnson
+ */
+public interface TimeStamped {
+
+ /**
+ * Return the timestamp for this object.
+ * @return long the timestamp for this object,
+ * as returned by System.currentTimeMillis()
+ */
+ long getTimeStamp();
+
+}
diff --git a/spring-core/src/test/java/org/springframework/tests/package-info.java b/spring-core/src/test/java/org/springframework/tests/package-info.java
new file mode 100644
index 00000000..545c413c
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/tests/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Shared utilities that are used internally throughout the test suite but are not
+ * published. This package should not be confused with {@code org.springframework.test}
+ * which contains published code from the 'spring-test' module.
+ */
+package org.springframework.tests;
diff --git a/spring-core/src/test/java/org/springframework/tests/sample/objects/DerivedTestObject.java b/spring-core/src/test/java/org/springframework/tests/sample/objects/DerivedTestObject.java
new file mode 100644
index 00000000..45ab490a
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/tests/sample/objects/DerivedTestObject.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.tests.sample.objects;
+
+import java.io.Serializable;
+
+@SuppressWarnings("serial")
+public class DerivedTestObject extends TestObject implements Serializable {
+
+}
diff --git a/spring-core/src/test/java/org/springframework/tests/sample/objects/GenericObject.java b/spring-core/src/test/java/org/springframework/tests/sample/objects/GenericObject.java
new file mode 100644
index 00000000..efd0455f
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/tests/sample/objects/GenericObject.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.tests.sample.objects;
+
+import java.util.List;
+
+import org.springframework.core.io.Resource;
+
+
+public class GenericObject<T> {
+
+ private List<Resource> resourceList;
+
+ public List<Resource> getResourceList() {
+ return this.resourceList;
+ }
+
+ public void setResourceList(List<Resource> resourceList) {
+ this.resourceList = resourceList;
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/tests/sample/objects/ITestInterface.java b/spring-core/src/test/java/org/springframework/tests/sample/objects/ITestInterface.java
new file mode 100644
index 00000000..4aca1f25
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/tests/sample/objects/ITestInterface.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.tests.sample.objects;
+
+
+public interface ITestInterface {
+
+ void absquatulate();
+
+}
diff --git a/spring-core/src/test/java/org/springframework/tests/sample/objects/ITestObject.java b/spring-core/src/test/java/org/springframework/tests/sample/objects/ITestObject.java
new file mode 100644
index 00000000..ca795cb0
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/tests/sample/objects/ITestObject.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.tests.sample.objects;
+
+public interface ITestObject {
+
+ String getName();
+
+ void setName(String name);
+
+ int getAge();
+
+ void setAge(int age);
+
+ TestObject getSpouse();
+
+ void setSpouse(TestObject spouse);
+
+}
diff --git a/spring-core/src/test/java/org/springframework/tests/sample/objects/TestObject.java b/spring-core/src/test/java/org/springframework/tests/sample/objects/TestObject.java
new file mode 100644
index 00000000..68ce8c64
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/tests/sample/objects/TestObject.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.tests.sample.objects;
+
+public class TestObject implements ITestObject, ITestInterface, Comparable<Object> {
+
+ private String name;
+
+ private int age;
+
+ private TestObject spouse;
+
+ public TestObject() {
+ }
+
+ public TestObject(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 this.age;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+
+ public TestObject getSpouse() {
+ return this.spouse;
+ }
+
+ public void setSpouse(TestObject spouse) {
+ this.spouse = spouse;
+ }
+
+ @Override
+ public void absquatulate() {
+ }
+
+ @Override
+ public int compareTo(Object o) {
+ if (this.name != null && o instanceof TestObject) {
+ return this.name.compareTo(((TestObject) o).getName());
+ }
+ else {
+ return 1;
+ }
+ }
+}
diff --git a/spring-core/src/test/java/org/springframework/tests/sample/objects/package-info.java b/spring-core/src/test/java/org/springframework/tests/sample/objects/package-info.java
new file mode 100644
index 00000000..98c15ca6
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/tests/sample/objects/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * General purpose sample objects that can be used with tests.
+ */
+package org.springframework.tests.sample.objects;
diff --git a/spring-core/src/test/java/org/springframework/util/AntPathMatcherTests.java b/spring-core/src/test/java/org/springframework/util/AntPathMatcherTests.java
new file mode 100644
index 00000000..05a98f40
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/AntPathMatcherTests.java
@@ -0,0 +1,556 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.*;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Alef Arendsen
+ * @author Seth Ladd
+ * @author Juergen Hoeller
+ * @author Arjen Poutsma
+ * @author Rossen Stoyanchev
+ */
+public class AntPathMatcherTests {
+
+ private AntPathMatcher pathMatcher;
+
+ @Before
+ public void createMatcher() {
+ pathMatcher = new AntPathMatcher();
+ }
+
+ @Test
+ public void match() {
+ // test exact matching
+ assertTrue(pathMatcher.match("test", "test"));
+ assertTrue(pathMatcher.match("/test", "/test"));
+ assertFalse(pathMatcher.match("/test.jpg", "test.jpg"));
+ assertFalse(pathMatcher.match("test", "/test"));
+ assertFalse(pathMatcher.match("/test", "test"));
+
+ // test matching with ?'s
+ assertTrue(pathMatcher.match("t?st", "test"));
+ assertTrue(pathMatcher.match("??st", "test"));
+ assertTrue(pathMatcher.match("tes?", "test"));
+ assertTrue(pathMatcher.match("te??", "test"));
+ assertTrue(pathMatcher.match("?es?", "test"));
+ assertFalse(pathMatcher.match("tes?", "tes"));
+ assertFalse(pathMatcher.match("tes?", "testt"));
+ assertFalse(pathMatcher.match("tes?", "tsst"));
+
+ // test matchin with *'s
+ assertTrue(pathMatcher.match("*", "test"));
+ assertTrue(pathMatcher.match("test*", "test"));
+ assertTrue(pathMatcher.match("test*", "testTest"));
+ assertTrue(pathMatcher.match("test/*", "test/Test"));
+ assertTrue(pathMatcher.match("test/*", "test/t"));
+ assertTrue(pathMatcher.match("test/*", "test/"));
+ assertTrue(pathMatcher.match("*test*", "AnothertestTest"));
+ assertTrue(pathMatcher.match("*test", "Anothertest"));
+ assertTrue(pathMatcher.match("*.*", "test."));
+ assertTrue(pathMatcher.match("*.*", "test.test"));
+ assertTrue(pathMatcher.match("*.*", "test.test.test"));
+ assertTrue(pathMatcher.match("test*aaa", "testblaaaa"));
+ assertFalse(pathMatcher.match("test*", "tst"));
+ assertFalse(pathMatcher.match("test*", "tsttest"));
+ assertFalse(pathMatcher.match("test*", "test/"));
+ assertFalse(pathMatcher.match("test*", "test/t"));
+ assertFalse(pathMatcher.match("test/*", "test"));
+ assertFalse(pathMatcher.match("*test*", "tsttst"));
+ assertFalse(pathMatcher.match("*test", "tsttst"));
+ assertFalse(pathMatcher.match("*.*", "tsttst"));
+ assertFalse(pathMatcher.match("test*aaa", "test"));
+ assertFalse(pathMatcher.match("test*aaa", "testblaaab"));
+
+ // test matching with ?'s and /'s
+ assertTrue(pathMatcher.match("/?", "/a"));
+ assertTrue(pathMatcher.match("/?/a", "/a/a"));
+ assertTrue(pathMatcher.match("/a/?", "/a/b"));
+ assertTrue(pathMatcher.match("/??/a", "/aa/a"));
+ assertTrue(pathMatcher.match("/a/??", "/a/bb"));
+ assertTrue(pathMatcher.match("/?", "/a"));
+
+ // test matching with **'s
+ assertTrue(pathMatcher.match("/**", "/testing/testing"));
+ assertTrue(pathMatcher.match("/*/**", "/testing/testing"));
+ assertTrue(pathMatcher.match("/**/*", "/testing/testing"));
+ assertTrue(pathMatcher.match("/bla/**/bla", "/bla/testing/testing/bla"));
+ assertTrue(pathMatcher.match("/bla/**/bla", "/bla/testing/testing/bla/bla"));
+ assertTrue(pathMatcher.match("/**/test", "/bla/bla/test"));
+ assertTrue(pathMatcher.match("/bla/**/**/bla", "/bla/bla/bla/bla/bla/bla"));
+ assertTrue(pathMatcher.match("/bla*bla/test", "/blaXXXbla/test"));
+ assertTrue(pathMatcher.match("/*bla/test", "/XXXbla/test"));
+ assertFalse(pathMatcher.match("/bla*bla/test", "/blaXXXbl/test"));
+ assertFalse(pathMatcher.match("/*bla/test", "XXXblab/test"));
+ assertFalse(pathMatcher.match("/*bla/test", "XXXbl/test"));
+
+ assertFalse(pathMatcher.match("/????", "/bala/bla"));
+ assertFalse(pathMatcher.match("/**/*bla", "/bla/bla/bla/bbb"));
+
+ assertTrue(pathMatcher.match("/*bla*/**/bla/**", "/XXXblaXXXX/testing/testing/bla/testing/testing/"));
+ assertTrue(pathMatcher.match("/*bla*/**/bla/*", "/XXXblaXXXX/testing/testing/bla/testing"));
+ assertTrue(pathMatcher.match("/*bla*/**/bla/**", "/XXXblaXXXX/testing/testing/bla/testing/testing"));
+ assertTrue(pathMatcher.match("/*bla*/**/bla/**", "/XXXblaXXXX/testing/testing/bla/testing/testing.jpg"));
+
+ assertTrue(pathMatcher.match("*bla*/**/bla/**", "XXXblaXXXX/testing/testing/bla/testing/testing/"));
+ assertTrue(pathMatcher.match("*bla*/**/bla/*", "XXXblaXXXX/testing/testing/bla/testing"));
+ assertTrue(pathMatcher.match("*bla*/**/bla/**", "XXXblaXXXX/testing/testing/bla/testing/testing"));
+ assertFalse(pathMatcher.match("*bla*/**/bla/*", "XXXblaXXXX/testing/testing/bla/testing/testing"));
+
+ assertFalse(pathMatcher.match("/x/x/**/bla", "/x/x/x/"));
+
+ assertTrue(pathMatcher.match("", ""));
+
+ assertTrue(pathMatcher.match("/{bla}.*", "/testing.html"));
+ }
+
+ @Test
+ public void withMatchStart() {
+ // test exact matching
+ assertTrue(pathMatcher.matchStart("test", "test"));
+ assertTrue(pathMatcher.matchStart("/test", "/test"));
+ assertFalse(pathMatcher.matchStart("/test.jpg", "test.jpg"));
+ assertFalse(pathMatcher.matchStart("test", "/test"));
+ assertFalse(pathMatcher.matchStart("/test", "test"));
+
+ // test matching with ?'s
+ assertTrue(pathMatcher.matchStart("t?st", "test"));
+ assertTrue(pathMatcher.matchStart("??st", "test"));
+ assertTrue(pathMatcher.matchStart("tes?", "test"));
+ assertTrue(pathMatcher.matchStart("te??", "test"));
+ assertTrue(pathMatcher.matchStart("?es?", "test"));
+ assertFalse(pathMatcher.matchStart("tes?", "tes"));
+ assertFalse(pathMatcher.matchStart("tes?", "testt"));
+ assertFalse(pathMatcher.matchStart("tes?", "tsst"));
+
+ // test matchin with *'s
+ assertTrue(pathMatcher.matchStart("*", "test"));
+ assertTrue(pathMatcher.matchStart("test*", "test"));
+ assertTrue(pathMatcher.matchStart("test*", "testTest"));
+ assertTrue(pathMatcher.matchStart("test/*", "test/Test"));
+ assertTrue(pathMatcher.matchStart("test/*", "test/t"));
+ assertTrue(pathMatcher.matchStart("test/*", "test/"));
+ assertTrue(pathMatcher.matchStart("*test*", "AnothertestTest"));
+ assertTrue(pathMatcher.matchStart("*test", "Anothertest"));
+ assertTrue(pathMatcher.matchStart("*.*", "test."));
+ assertTrue(pathMatcher.matchStart("*.*", "test.test"));
+ assertTrue(pathMatcher.matchStart("*.*", "test.test.test"));
+ assertTrue(pathMatcher.matchStart("test*aaa", "testblaaaa"));
+ assertFalse(pathMatcher.matchStart("test*", "tst"));
+ assertFalse(pathMatcher.matchStart("test*", "test/"));
+ assertFalse(pathMatcher.matchStart("test*", "tsttest"));
+ assertFalse(pathMatcher.matchStart("test*", "test/"));
+ assertFalse(pathMatcher.matchStart("test*", "test/t"));
+ assertTrue(pathMatcher.matchStart("test/*", "test"));
+ assertTrue(pathMatcher.matchStart("test/t*.txt", "test"));
+ assertFalse(pathMatcher.matchStart("*test*", "tsttst"));
+ assertFalse(pathMatcher.matchStart("*test", "tsttst"));
+ assertFalse(pathMatcher.matchStart("*.*", "tsttst"));
+ assertFalse(pathMatcher.matchStart("test*aaa", "test"));
+ assertFalse(pathMatcher.matchStart("test*aaa", "testblaaab"));
+
+ // test matching with ?'s and /'s
+ assertTrue(pathMatcher.matchStart("/?", "/a"));
+ assertTrue(pathMatcher.matchStart("/?/a", "/a/a"));
+ assertTrue(pathMatcher.matchStart("/a/?", "/a/b"));
+ assertTrue(pathMatcher.matchStart("/??/a", "/aa/a"));
+ assertTrue(pathMatcher.matchStart("/a/??", "/a/bb"));
+ assertTrue(pathMatcher.matchStart("/?", "/a"));
+
+ // test matching with **'s
+ assertTrue(pathMatcher.matchStart("/**", "/testing/testing"));
+ assertTrue(pathMatcher.matchStart("/*/**", "/testing/testing"));
+ assertTrue(pathMatcher.matchStart("/**/*", "/testing/testing"));
+ assertTrue(pathMatcher.matchStart("test*/**", "test/"));
+ assertTrue(pathMatcher.matchStart("test*/**", "test/t"));
+ assertTrue(pathMatcher.matchStart("/bla/**/bla", "/bla/testing/testing/bla"));
+ assertTrue(pathMatcher.matchStart("/bla/**/bla", "/bla/testing/testing/bla/bla"));
+ assertTrue(pathMatcher.matchStart("/**/test", "/bla/bla/test"));
+ assertTrue(pathMatcher.matchStart("/bla/**/**/bla", "/bla/bla/bla/bla/bla/bla"));
+ assertTrue(pathMatcher.matchStart("/bla*bla/test", "/blaXXXbla/test"));
+ assertTrue(pathMatcher.matchStart("/*bla/test", "/XXXbla/test"));
+ assertFalse(pathMatcher.matchStart("/bla*bla/test", "/blaXXXbl/test"));
+ assertFalse(pathMatcher.matchStart("/*bla/test", "XXXblab/test"));
+ assertFalse(pathMatcher.matchStart("/*bla/test", "XXXbl/test"));
+
+ assertFalse(pathMatcher.matchStart("/????", "/bala/bla"));
+ assertTrue(pathMatcher.matchStart("/**/*bla", "/bla/bla/bla/bbb"));
+
+ assertTrue(pathMatcher.matchStart("/*bla*/**/bla/**", "/XXXblaXXXX/testing/testing/bla/testing/testing/"));
+ assertTrue(pathMatcher.matchStart("/*bla*/**/bla/*", "/XXXblaXXXX/testing/testing/bla/testing"));
+ assertTrue(pathMatcher.matchStart("/*bla*/**/bla/**", "/XXXblaXXXX/testing/testing/bla/testing/testing"));
+ assertTrue(pathMatcher.matchStart("/*bla*/**/bla/**", "/XXXblaXXXX/testing/testing/bla/testing/testing.jpg"));
+
+ assertTrue(pathMatcher.matchStart("*bla*/**/bla/**", "XXXblaXXXX/testing/testing/bla/testing/testing/"));
+ assertTrue(pathMatcher.matchStart("*bla*/**/bla/*", "XXXblaXXXX/testing/testing/bla/testing"));
+ assertTrue(pathMatcher.matchStart("*bla*/**/bla/**", "XXXblaXXXX/testing/testing/bla/testing/testing"));
+ assertTrue(pathMatcher.matchStart("*bla*/**/bla/*", "XXXblaXXXX/testing/testing/bla/testing/testing"));
+
+ assertTrue(pathMatcher.matchStart("/x/x/**/bla", "/x/x/x/"));
+
+ assertTrue(pathMatcher.matchStart("", ""));
+ }
+
+ @Test
+ public void uniqueDeliminator() {
+ pathMatcher.setPathSeparator(".");
+
+ // test exact matching
+ assertTrue(pathMatcher.match("test", "test"));
+ assertTrue(pathMatcher.match(".test", ".test"));
+ assertFalse(pathMatcher.match(".test/jpg", "test/jpg"));
+ assertFalse(pathMatcher.match("test", ".test"));
+ assertFalse(pathMatcher.match(".test", "test"));
+
+ // test matching with ?'s
+ assertTrue(pathMatcher.match("t?st", "test"));
+ assertTrue(pathMatcher.match("??st", "test"));
+ assertTrue(pathMatcher.match("tes?", "test"));
+ assertTrue(pathMatcher.match("te??", "test"));
+ assertTrue(pathMatcher.match("?es?", "test"));
+ assertFalse(pathMatcher.match("tes?", "tes"));
+ assertFalse(pathMatcher.match("tes?", "testt"));
+ assertFalse(pathMatcher.match("tes?", "tsst"));
+
+ // test matchin with *'s
+ assertTrue(pathMatcher.match("*", "test"));
+ assertTrue(pathMatcher.match("test*", "test"));
+ assertTrue(pathMatcher.match("test*", "testTest"));
+ assertTrue(pathMatcher.match("*test*", "AnothertestTest"));
+ assertTrue(pathMatcher.match("*test", "Anothertest"));
+ assertTrue(pathMatcher.match("*/*", "test/"));
+ assertTrue(pathMatcher.match("*/*", "test/test"));
+ assertTrue(pathMatcher.match("*/*", "test/test/test"));
+ assertTrue(pathMatcher.match("test*aaa", "testblaaaa"));
+ assertFalse(pathMatcher.match("test*", "tst"));
+ assertFalse(pathMatcher.match("test*", "tsttest"));
+ assertFalse(pathMatcher.match("*test*", "tsttst"));
+ assertFalse(pathMatcher.match("*test", "tsttst"));
+ assertFalse(pathMatcher.match("*/*", "tsttst"));
+ assertFalse(pathMatcher.match("test*aaa", "test"));
+ assertFalse(pathMatcher.match("test*aaa", "testblaaab"));
+
+ // test matching with ?'s and .'s
+ assertTrue(pathMatcher.match(".?", ".a"));
+ assertTrue(pathMatcher.match(".?.a", ".a.a"));
+ assertTrue(pathMatcher.match(".a.?", ".a.b"));
+ assertTrue(pathMatcher.match(".??.a", ".aa.a"));
+ assertTrue(pathMatcher.match(".a.??", ".a.bb"));
+ assertTrue(pathMatcher.match(".?", ".a"));
+
+ // test matching with **'s
+ assertTrue(pathMatcher.match(".**", ".testing.testing"));
+ assertTrue(pathMatcher.match(".*.**", ".testing.testing"));
+ assertTrue(pathMatcher.match(".**.*", ".testing.testing"));
+ assertTrue(pathMatcher.match(".bla.**.bla", ".bla.testing.testing.bla"));
+ assertTrue(pathMatcher.match(".bla.**.bla", ".bla.testing.testing.bla.bla"));
+ assertTrue(pathMatcher.match(".**.test", ".bla.bla.test"));
+ assertTrue(pathMatcher.match(".bla.**.**.bla", ".bla.bla.bla.bla.bla.bla"));
+ assertTrue(pathMatcher.match(".bla*bla.test", ".blaXXXbla.test"));
+ assertTrue(pathMatcher.match(".*bla.test", ".XXXbla.test"));
+ assertFalse(pathMatcher.match(".bla*bla.test", ".blaXXXbl.test"));
+ assertFalse(pathMatcher.match(".*bla.test", "XXXblab.test"));
+ assertFalse(pathMatcher.match(".*bla.test", "XXXbl.test"));
+ }
+
+ @Test
+ public void extractPathWithinPattern() throws Exception {
+ assertEquals("", pathMatcher.extractPathWithinPattern("/docs/commit.html", "/docs/commit.html"));
+
+ assertEquals("cvs/commit", pathMatcher.extractPathWithinPattern("/docs/*", "/docs/cvs/commit"));
+ assertEquals("commit.html", pathMatcher.extractPathWithinPattern("/docs/cvs/*.html", "/docs/cvs/commit.html"));
+ assertEquals("cvs/commit", pathMatcher.extractPathWithinPattern("/docs/**", "/docs/cvs/commit"));
+ assertEquals("cvs/commit.html",
+ pathMatcher.extractPathWithinPattern("/docs/**/*.html", "/docs/cvs/commit.html"));
+ assertEquals("commit.html", pathMatcher.extractPathWithinPattern("/docs/**/*.html", "/docs/commit.html"));
+ assertEquals("commit.html", pathMatcher.extractPathWithinPattern("/*.html", "/commit.html"));
+ assertEquals("docs/commit.html", pathMatcher.extractPathWithinPattern("/*.html", "/docs/commit.html"));
+ assertEquals("/commit.html", pathMatcher.extractPathWithinPattern("*.html", "/commit.html"));
+ assertEquals("/docs/commit.html", pathMatcher.extractPathWithinPattern("*.html", "/docs/commit.html"));
+ assertEquals("/docs/commit.html", pathMatcher.extractPathWithinPattern("**/*.*", "/docs/commit.html"));
+ assertEquals("/docs/commit.html", pathMatcher.extractPathWithinPattern("*", "/docs/commit.html"));
+
+ assertEquals("docs/cvs/commit", pathMatcher.extractPathWithinPattern("/d?cs/*", "/docs/cvs/commit"));
+ assertEquals("cvs/commit.html",
+ pathMatcher.extractPathWithinPattern("/docs/c?s/*.html", "/docs/cvs/commit.html"));
+ assertEquals("docs/cvs/commit", pathMatcher.extractPathWithinPattern("/d?cs/**", "/docs/cvs/commit"));
+ assertEquals("docs/cvs/commit.html",
+ pathMatcher.extractPathWithinPattern("/d?cs/**/*.html", "/docs/cvs/commit.html"));
+ }
+
+ @Test
+ public void extractUriTemplateVariables() throws Exception {
+ Map<String, String> result = pathMatcher.extractUriTemplateVariables("/hotels/{hotel}", "/hotels/1");
+ assertEquals(Collections.singletonMap("hotel", "1"), result);
+
+ result = pathMatcher.extractUriTemplateVariables("/h?tels/{hotel}", "/hotels/1");
+ assertEquals(Collections.singletonMap("hotel", "1"), result);
+
+ result = pathMatcher.extractUriTemplateVariables("/hotels/{hotel}/bookings/{booking}", "/hotels/1/bookings/2");
+ Map<String, String> expected = new LinkedHashMap<String, String>();
+ expected.put("hotel", "1");
+ expected.put("booking", "2");
+ assertEquals(expected, result);
+
+ result = pathMatcher.extractUriTemplateVariables("/**/hotels/**/{hotel}", "/foo/hotels/bar/1");
+ assertEquals(Collections.singletonMap("hotel", "1"), result);
+
+ result = pathMatcher.extractUriTemplateVariables("/{page}.html", "/42.html");
+ assertEquals(Collections.singletonMap("page", "42"), result);
+
+ result = pathMatcher.extractUriTemplateVariables("/{page}.*", "/42.html");
+ assertEquals(Collections.singletonMap("page", "42"), result);
+
+ result = pathMatcher.extractUriTemplateVariables("/A-{B}-C", "/A-b-C");
+ assertEquals(Collections.singletonMap("B", "b"), result);
+
+ result = pathMatcher.extractUriTemplateVariables("/{name}.{extension}", "/test.html");
+ expected = new LinkedHashMap<String, String>();
+ expected.put("name", "test");
+ expected.put("extension", "html");
+ assertEquals(expected, result);
+ }
+
+ @Test
+ public void extractUriTemplateVariablesRegex() {
+ Map<String, String> result = pathMatcher
+ .extractUriTemplateVariables("{symbolicName:[\\w\\.]+}-{version:[\\w\\.]+}.jar",
+ "com.example-1.0.0.jar");
+ assertEquals("com.example", result.get("symbolicName"));
+ assertEquals("1.0.0", result.get("version"));
+
+ result = pathMatcher.extractUriTemplateVariables("{symbolicName:[\\w\\.]+}-sources-{version:[\\w\\.]+}.jar",
+ "com.example-sources-1.0.0.jar");
+ assertEquals("com.example", result.get("symbolicName"));
+ assertEquals("1.0.0", result.get("version"));
+ }
+
+ // SPR-7787
+
+ @Test
+ public void extractUriTemplateVarsRegexQualifiers() {
+ Map<String, String> result = pathMatcher.extractUriTemplateVariables(
+ "{symbolicName:[\\p{L}\\.]+}-sources-{version:[\\p{N}\\.]+}.jar",
+ "com.example-sources-1.0.0.jar");
+ assertEquals("com.example", result.get("symbolicName"));
+ assertEquals("1.0.0", result.get("version"));
+
+ result = pathMatcher.extractUriTemplateVariables(
+ "{symbolicName:[\\w\\.]+}-sources-{version:[\\d\\.]+}-{year:\\d{4}}{month:\\d{2}}{day:\\d{2}}.jar",
+ "com.example-sources-1.0.0-20100220.jar");
+ assertEquals("com.example", result.get("symbolicName"));
+ assertEquals("1.0.0", result.get("version"));
+ assertEquals("2010", result.get("year"));
+ assertEquals("02", result.get("month"));
+ assertEquals("20", result.get("day"));
+
+ result = pathMatcher.extractUriTemplateVariables(
+ "{symbolicName:[\\p{L}\\.]+}-sources-{version:[\\p{N}\\.\\{\\}]+}.jar",
+ "com.example-sources-1.0.0.{12}.jar");
+ assertEquals("com.example", result.get("symbolicName"));
+ assertEquals("1.0.0.{12}", result.get("version"));
+ }
+
+ // SPR-8455
+
+ @Test
+ public void extractUriTemplateVarsRegexCapturingGroups() {
+ try {
+ pathMatcher.extractUriTemplateVariables("/web/{id:foo(bar)?}", "/web/foobar");
+ fail("Expected exception");
+ } catch (IllegalArgumentException e) {
+ assertTrue("Expected helpful message on the use of capturing groups",
+ e.getMessage().contains("The number of capturing groups in the pattern"));
+ }
+ }
+
+ @Test
+ public void combine() {
+ assertEquals("", pathMatcher.combine(null, null));
+ assertEquals("/hotels", pathMatcher.combine("/hotels", null));
+ assertEquals("/hotels", pathMatcher.combine(null, "/hotels"));
+ assertEquals("/hotels/booking", pathMatcher.combine("/hotels/*", "booking"));
+ assertEquals("/hotels/booking", pathMatcher.combine("/hotels/*", "/booking"));
+ assertEquals("/hotels/**/booking", pathMatcher.combine("/hotels/**", "booking"));
+ assertEquals("/hotels/**/booking", pathMatcher.combine("/hotels/**", "/booking"));
+ assertEquals("/hotels/booking", pathMatcher.combine("/hotels", "/booking"));
+ assertEquals("/hotels/booking", pathMatcher.combine("/hotels", "booking"));
+ assertEquals("/hotels/{hotel}", pathMatcher.combine("/hotels/*", "{hotel}"));
+ assertEquals("/hotels/**/{hotel}", pathMatcher.combine("/hotels/**", "{hotel}"));
+ assertEquals("/hotels/{hotel}", pathMatcher.combine("/hotels", "{hotel}"));
+ assertEquals("/hotels/{hotel}.*", pathMatcher.combine("/hotels", "{hotel}.*"));
+ assertEquals("/hotels/*/booking/{booking}", pathMatcher.combine("/hotels/*/booking", "{booking}"));
+ assertEquals("/hotel.html", pathMatcher.combine("/*.html", "/hotel.html"));
+ assertEquals("/hotel.html", pathMatcher.combine("/*.html", "/hotel"));
+ assertEquals("/hotel.html", pathMatcher.combine("/*.html", "/hotel.*"));
+ assertEquals("/*.html", pathMatcher.combine("/**", "/*.html"));
+ assertEquals("/*.html", pathMatcher.combine("/*", "/*.html"));
+ assertEquals("/*.html", pathMatcher.combine("/*.*", "/*.html"));
+ assertEquals("/{foo}/bar", pathMatcher.combine("/{foo}", "/bar")); // SPR-8858
+ assertEquals("/user/user", pathMatcher.combine("/user", "/user")); // SPR-7970
+ assertEquals("/{foo:.*[^0-9].*}/edit/", pathMatcher.combine("/{foo:.*[^0-9].*}", "/edit/")); // SPR-10062
+ }
+
+ @Test
+ public void patternComparator() {
+ Comparator<String> comparator = pathMatcher.getPatternComparator("/hotels/new");
+
+ assertEquals(0, comparator.compare(null, null));
+ assertEquals(1, comparator.compare(null, "/hotels/new"));
+ assertEquals(-1, comparator.compare("/hotels/new", null));
+
+ assertEquals(0, comparator.compare("/hotels/new", "/hotels/new"));
+
+ assertEquals(-1, comparator.compare("/hotels/new", "/hotels/*"));
+ assertEquals(1, comparator.compare("/hotels/*", "/hotels/new"));
+ assertEquals(0, comparator.compare("/hotels/*", "/hotels/*"));
+
+ assertEquals(-1, comparator.compare("/hotels/new", "/hotels/{hotel}"));
+ assertEquals(1, comparator.compare("/hotels/{hotel}", "/hotels/new"));
+ assertEquals(0, comparator.compare("/hotels/{hotel}", "/hotels/{hotel}"));
+ assertEquals(-1, comparator.compare("/hotels/{hotel}/booking", "/hotels/{hotel}/bookings/{booking}"));
+ assertEquals(1, comparator.compare("/hotels/{hotel}/bookings/{booking}", "/hotels/{hotel}/booking"));
+
+ assertEquals(-1, comparator.compare("/hotels/{hotel}", "/hotels/*"));
+ assertEquals(1, comparator.compare("/hotels/*", "/hotels/{hotel}"));
+
+ assertEquals(-2, comparator.compare("/hotels/*", "/hotels/*/**"));
+ assertEquals(2, comparator.compare("/hotels/*/**", "/hotels/*"));
+
+ assertEquals(-1, comparator.compare("/hotels/new", "/hotels/new.*"));
+
+ // longer is better
+ assertEquals(1, comparator.compare("/hotels", "/hotels2"));
+ }
+
+ @Test
+ public void patternComparatorSort() {
+ Comparator<String> comparator = pathMatcher.getPatternComparator("/hotels/new");
+ List<String> paths = new ArrayList<String>(3);
+
+ paths.add(null);
+ paths.add("/hotels/new");
+ Collections.sort(paths, comparator);
+ assertEquals("/hotels/new", paths.get(0));
+ assertNull(paths.get(1));
+ paths.clear();
+
+ paths.add("/hotels/new");
+ paths.add(null);
+ Collections.sort(paths, comparator);
+ assertEquals("/hotels/new", paths.get(0));
+ assertNull(paths.get(1));
+ paths.clear();
+
+ paths.add("/hotels/*");
+ paths.add("/hotels/new");
+ Collections.sort(paths, comparator);
+ assertEquals("/hotels/new", paths.get(0));
+ assertEquals("/hotels/*", paths.get(1));
+ paths.clear();
+
+ paths.add("/hotels/new");
+ paths.add("/hotels/*");
+ Collections.sort(paths, comparator);
+ assertEquals("/hotels/new", paths.get(0));
+ assertEquals("/hotels/*", paths.get(1));
+ paths.clear();
+
+ paths.add("/hotels/**");
+ paths.add("/hotels/*");
+ Collections.sort(paths, comparator);
+ assertEquals("/hotels/*", paths.get(0));
+ assertEquals("/hotels/**", paths.get(1));
+ paths.clear();
+
+ paths.add("/hotels/*");
+ paths.add("/hotels/**");
+ Collections.sort(paths, comparator);
+ assertEquals("/hotels/*", paths.get(0));
+ assertEquals("/hotels/**", paths.get(1));
+ paths.clear();
+
+ paths.add("/hotels/{hotel}");
+ paths.add("/hotels/new");
+ Collections.sort(paths, comparator);
+ assertEquals("/hotels/new", paths.get(0));
+ assertEquals("/hotels/{hotel}", paths.get(1));
+ paths.clear();
+
+ paths.add("/hotels/new");
+ paths.add("/hotels/{hotel}");
+ Collections.sort(paths, comparator);
+ assertEquals("/hotels/new", paths.get(0));
+ assertEquals("/hotels/{hotel}", paths.get(1));
+ paths.clear();
+
+ paths.add("/hotels/*");
+ paths.add("/hotels/{hotel}");
+ paths.add("/hotels/new");
+ Collections.sort(paths, comparator);
+ assertEquals("/hotels/new", paths.get(0));
+ assertEquals("/hotels/{hotel}", paths.get(1));
+ assertEquals("/hotels/*", paths.get(2));
+ paths.clear();
+
+ paths.add("/hotels/ne*");
+ paths.add("/hotels/n*");
+ Collections.shuffle(paths);
+ Collections.sort(paths, comparator);
+ assertEquals("/hotels/ne*", paths.get(0));
+ assertEquals("/hotels/n*", paths.get(1));
+ paths.clear();
+
+ comparator = pathMatcher.getPatternComparator("/hotels/new.html");
+ paths.add("/hotels/new.*");
+ paths.add("/hotels/{hotel}");
+ Collections.shuffle(paths);
+ Collections.sort(paths, comparator);
+ assertEquals("/hotels/new.*", paths.get(0));
+ assertEquals("/hotels/{hotel}", paths.get(1));
+ paths.clear();
+
+ comparator = pathMatcher.getPatternComparator("/web/endUser/action/login.html");
+ paths.add("/**/login.*");
+ paths.add("/**/endUser/action/login.*");
+ Collections.sort(paths, comparator);
+ assertEquals("/**/endUser/action/login.*", paths.get(0));
+ assertEquals("/**/login.*", paths.get(1));
+ paths.clear();
+ }
+
+ // SPR-8687
+
+ @Test
+ public void trimTokensOff() {
+ pathMatcher.setTrimTokens(false);
+
+ assertTrue(pathMatcher.match("/group/{groupName}/members", "/group/sales/members"));
+ assertTrue(pathMatcher.match("/group/{groupName}/members", "/group/ sales/members"));
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/AssertTests.java b/spring-core/src/test/java/org/springframework/util/AssertTests.java
new file mode 100644
index 00000000..0dfe86f1
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/AssertTests.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+/**
+ * Unit tests for the {@link Assert} class.
+ *
+ * @author Keith Donald
+ * @author Erwin Vervaet
+ * @author Rick Evans
+ * @author Arjen Poutsma
+ */
+public class AssertTests {
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Test(expected = IllegalArgumentException.class)
+ public void instanceOf() {
+ final Set<?> set = new HashSet<Object>();
+ Assert.isInstanceOf(HashSet.class, set);
+ Assert.isInstanceOf(HashMap.class, set);
+ }
+
+ @Test
+ public void instanceOfNoMessage() throws Exception {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("Object of class [java.lang.Object] must be an instance " +
+ "of interface java.util.Set");
+ Assert.isInstanceOf(Set.class, new Object(), null);
+ }
+
+ @Test
+ public void instanceOfMessage() throws Exception {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("Custom message. Object of class [java.lang.Object] must " +
+ "be an instance of interface java.util.Set");
+ Assert.isInstanceOf(Set.class, new Object(), "Custom message.");
+ }
+
+ @Test
+ public void isNullDoesNotThrowExceptionIfArgumentIsNullWithMessage() {
+ Assert.isNull(null, "Bla");
+ }
+
+ @Test
+ public void isNullDoesNotThrowExceptionIfArgumentIsNull() {
+ Assert.isNull(null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void isNullThrowsExceptionIfArgumentIsNotNull() {
+ Assert.isNull(new Object());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void isTrueWithFalseExpressionThrowsException() throws Exception {
+ Assert.isTrue(false);
+ }
+
+ @Test
+ public void isTrueWithTrueExpressionSunnyDay() throws Exception {
+ Assert.isTrue(true);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testHasLengthWithNullStringThrowsException() throws Exception {
+ Assert.hasLength(null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void hasLengthWithEmptyStringThrowsException() throws Exception {
+ Assert.hasLength("");
+ }
+
+ @Test
+ public void hasLengthWithWhitespaceOnlyStringDoesNotThrowException() throws Exception {
+ Assert.hasLength("\t ");
+ }
+
+ @Test
+ public void hasLengthSunnyDay() throws Exception {
+ Assert.hasLength("I Heart ...");
+ }
+
+ @Test
+ public void doesNotContainWithNullSearchStringDoesNotThrowException() throws Exception {
+ Assert.doesNotContain(null, "rod");
+ }
+
+ @Test
+ public void doesNotContainWithNullSubstringDoesNotThrowException() throws Exception {
+ Assert.doesNotContain("A cool chick's name is Brod. ", null);
+ }
+
+ @Test
+ public void doesNotContainWithEmptySubstringDoesNotThrowException() throws Exception {
+ Assert.doesNotContain("A cool chick's name is Brod. ", "");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void assertNotEmptyWithNullCollectionThrowsException() throws Exception {
+ Assert.notEmpty((Collection<?>) null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void assertNotEmptyWithEmptyCollectionThrowsException() throws Exception {
+ Assert.notEmpty(new ArrayList<Object>());
+ }
+
+ @Test
+ public void assertNotEmptyWithCollectionSunnyDay() throws Exception {
+ List<String> collection = new ArrayList<String>();
+ collection.add("");
+ Assert.notEmpty(collection);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void assertNotEmptyWithNullMapThrowsException() throws Exception {
+ Assert.notEmpty((Map<?, ?>) null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void assertNotEmptyWithEmptyMapThrowsException() throws Exception {
+ Assert.notEmpty(new HashMap<Object, Object>());
+ }
+
+ @Test
+ public void assertNotEmptyWithMapSunnyDay() throws Exception {
+ Map<String, String> map = new HashMap<String, String>();
+ map.put("", "");
+ Assert.notEmpty(map);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void isInstanceofClassWithNullInstanceThrowsException() throws Exception {
+ Assert.isInstanceOf(String.class, null);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void stateWithFalseExpressionThrowsException() throws Exception {
+ Assert.state(false);
+ }
+
+ @Test
+ public void stateWithTrueExpressionSunnyDay() throws Exception {
+ Assert.state(true);
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/AutoPopulatingListTests.java b/spring-core/src/test/java/org/springframework/util/AutoPopulatingListTests.java
new file mode 100644
index 00000000..550b826f
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/AutoPopulatingListTests.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util;
+
+import java.util.LinkedList;
+
+import junit.framework.*;
+
+import org.springframework.tests.sample.objects.TestObject;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ */
+public class AutoPopulatingListTests extends TestCase {
+
+ public void testWithClass() throws Exception {
+ doTestWithClass(new AutoPopulatingList<Object>(TestObject.class));
+ }
+
+ public void testWithClassAndUserSuppliedBackingList() throws Exception {
+ doTestWithClass(new AutoPopulatingList<Object>(new LinkedList<Object>(), TestObject.class));
+ }
+
+ public void testWithElementFactory() throws Exception {
+ doTestWithElementFactory(new AutoPopulatingList<Object>(new MockElementFactory()));
+ }
+
+ public void testWithElementFactoryAndUserSuppliedBackingList() throws Exception {
+ doTestWithElementFactory(new AutoPopulatingList<Object>(new LinkedList<Object>(), new MockElementFactory()));
+ }
+
+ private void doTestWithClass(AutoPopulatingList<Object> list) {
+ Object lastElement = null;
+ for (int x = 0; x < 10; x++) {
+ Object element = list.get(x);
+ assertNotNull("Element is null", list.get(x));
+ assertTrue("Element is incorrect type", element instanceof TestObject);
+ assertNotSame(lastElement, element);
+ lastElement = element;
+ }
+
+ String helloWorld = "Hello World!";
+ list.add(10, null);
+ list.add(11, helloWorld);
+ assertEquals(helloWorld, list.get(11));
+
+ assertTrue(list.get(10) instanceof TestObject);
+ assertTrue(list.get(12) instanceof TestObject);
+ assertTrue(list.get(13) instanceof TestObject);
+ assertTrue(list.get(20) instanceof TestObject);
+ }
+
+ private void doTestWithElementFactory(AutoPopulatingList<Object> list) {
+ doTestWithClass(list);
+
+ for(int x = 0; x < list.size(); x++) {
+ Object element = list.get(x);
+ if(element instanceof TestObject) {
+ assertEquals(x, ((TestObject) element).getAge());
+ }
+ }
+ }
+
+ public void testSerialization() throws Exception {
+ AutoPopulatingList<?> list = new AutoPopulatingList<Object>(TestObject.class);
+ assertEquals(list, SerializationTestUtils.serializeAndDeserialize(list));
+ }
+
+
+ private static class MockElementFactory implements AutoPopulatingList.ElementFactory {
+
+ @Override
+ public Object createElement(int index) {
+ TestObject bean = new TestObject();
+ bean.setAge(index);
+ return bean;
+ }
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/CachingMapDecoratorTests.java b/spring-core/src/test/java/org/springframework/util/CachingMapDecoratorTests.java
new file mode 100644
index 00000000..8e6dcc56
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/CachingMapDecoratorTests.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Keith Donald
+ * @author Juergen Hoeller
+ */
+@Deprecated
+public class CachingMapDecoratorTests extends TestCase {
+
+ public void testValidCache() {
+ MyCachingMap cache = new MyCachingMap();
+
+ assertFalse(cache.containsKey("value key"));
+ assertFalse(cache.containsValue("expensive value to cache"));
+ Object value = cache.get("value key");
+ assertTrue(cache.createCalled());
+ assertEquals(value, "expensive value to cache");
+ assertTrue(cache.containsKey("value key"));
+ assertTrue(cache.containsValue("expensive value to cache"));
+
+ assertFalse(cache.containsKey("value key 2"));
+ value = cache.get("value key 2");
+ assertTrue(cache.createCalled());
+ assertEquals(value, "expensive value to cache");
+ assertTrue(cache.containsKey("value key 2"));
+
+ value = cache.get("value key");
+ assertFalse(cache.createCalled());
+ assertEquals(value, "expensive value to cache");
+
+ cache.get("value key 2");
+ assertFalse(cache.createCalled());
+ assertEquals(value, "expensive value to cache");
+
+ assertFalse(cache.containsKey(null));
+ assertFalse(cache.containsValue(null));
+ value = cache.get(null);
+ assertTrue(cache.createCalled());
+ assertNull(value);
+ assertTrue(cache.containsKey(null));
+ assertTrue(cache.containsValue(null));
+
+ value = cache.get(null);
+ assertFalse(cache.createCalled());
+ assertNull(value);
+
+ Set<String> keySet = cache.keySet();
+ assertEquals(3, keySet.size());
+ assertTrue(keySet.contains("value key"));
+ assertTrue(keySet.contains("value key 2"));
+ assertTrue(keySet.contains(null));
+
+ Collection<String> values = cache.values();
+ assertEquals(3, values.size());
+ assertTrue(values.contains("expensive value to cache"));
+ assertTrue(values.contains(null));
+
+ Set<Map.Entry<String, String>> entrySet = cache.entrySet();
+ assertEquals(3, entrySet.size());
+ keySet = new HashSet<String>();
+ values = new HashSet<String>();
+ for (Map.Entry<String, String> entry : entrySet) {
+ keySet.add(entry.getKey());
+ values.add(entry.getValue());
+ }
+ assertTrue(keySet.contains("value key"));
+ assertTrue(keySet.contains("value key 2"));
+ assertTrue(keySet.contains(null));
+ assertEquals(2, values.size());
+ assertTrue(values.contains("expensive value to cache"));
+ assertTrue(values.contains(null));
+ }
+
+
+ @SuppressWarnings("serial")
+ private static class MyCachingMap extends CachingMapDecorator<String, String> {
+
+ private boolean createCalled;
+
+ @Override
+ protected String create(String key) {
+ createCalled = true;
+ return (key != null ? "expensive value to cache" : null);
+ }
+
+ public boolean createCalled() {
+ boolean c = createCalled;
+ this.createCalled = false;
+ return c;
+ }
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/ClassUtilsTests.java b/spring-core/src/test/java/org/springframework/util/ClassUtilsTests.java
new file mode 100644
index 00000000..f29b8b61
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/ClassUtilsTests.java
@@ -0,0 +1,401 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util;
+
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import org.springframework.tests.sample.objects.DerivedTestObject;
+import org.springframework.tests.sample.objects.ITestInterface;
+import org.springframework.tests.sample.objects.ITestObject;
+import org.springframework.tests.sample.objects.TestObject;
+
+import static org.junit.Assert.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Colin Sampaleanu
+ * @author Juergen Hoeller
+ * @author Rob Harrop
+ * @author Rick Evans
+ */
+public class ClassUtilsTests {
+
+ private ClassLoader classLoader = getClass().getClassLoader();
+
+ @Before
+ public void setUp() {
+ InnerClass.noArgCalled = false;
+ InnerClass.argCalled = false;
+ InnerClass.overloadedCalled = false;
+ }
+
+ @Test
+ public void testIsPresent() throws Exception {
+ assertTrue(ClassUtils.isPresent("java.lang.String", classLoader));
+ assertFalse(ClassUtils.isPresent("java.lang.MySpecialString", classLoader));
+ }
+
+ @Test
+ public void testForName() throws ClassNotFoundException {
+ assertEquals(String.class, ClassUtils.forName("java.lang.String", classLoader));
+ assertEquals(String[].class, ClassUtils.forName("java.lang.String[]", classLoader));
+ assertEquals(String[].class, ClassUtils.forName(String[].class.getName(), classLoader));
+ assertEquals(String[][].class, ClassUtils.forName(String[][].class.getName(), classLoader));
+ assertEquals(String[][][].class, ClassUtils.forName(String[][][].class.getName(), classLoader));
+ assertEquals(TestObject.class, ClassUtils.forName("org.springframework.tests.sample.objects.TestObject", classLoader));
+ assertEquals(TestObject[].class, ClassUtils.forName("org.springframework.tests.sample.objects.TestObject[]", classLoader));
+ assertEquals(TestObject[].class, ClassUtils.forName(TestObject[].class.getName(), classLoader));
+ assertEquals(TestObject[][].class, ClassUtils.forName("org.springframework.tests.sample.objects.TestObject[][]", classLoader));
+ assertEquals(TestObject[][].class, ClassUtils.forName(TestObject[][].class.getName(), classLoader));
+ assertEquals(short[][][].class, ClassUtils.forName("[[[S", classLoader));
+ }
+
+ @Test
+ public void testForNameWithPrimitiveClasses() throws ClassNotFoundException {
+ assertEquals(boolean.class, ClassUtils.forName("boolean", classLoader));
+ assertEquals(byte.class, ClassUtils.forName("byte", classLoader));
+ assertEquals(char.class, ClassUtils.forName("char", classLoader));
+ assertEquals(short.class, ClassUtils.forName("short", classLoader));
+ assertEquals(int.class, ClassUtils.forName("int", classLoader));
+ assertEquals(long.class, ClassUtils.forName("long", classLoader));
+ assertEquals(float.class, ClassUtils.forName("float", classLoader));
+ assertEquals(double.class, ClassUtils.forName("double", classLoader));
+ assertEquals(void.class, ClassUtils.forName("void", classLoader));
+ }
+
+ @Test
+ public void testForNameWithPrimitiveArrays() throws ClassNotFoundException {
+ assertEquals(boolean[].class, ClassUtils.forName("boolean[]", classLoader));
+ assertEquals(byte[].class, ClassUtils.forName("byte[]", classLoader));
+ assertEquals(char[].class, ClassUtils.forName("char[]", classLoader));
+ assertEquals(short[].class, ClassUtils.forName("short[]", classLoader));
+ assertEquals(int[].class, ClassUtils.forName("int[]", classLoader));
+ assertEquals(long[].class, ClassUtils.forName("long[]", classLoader));
+ assertEquals(float[].class, ClassUtils.forName("float[]", classLoader));
+ assertEquals(double[].class, ClassUtils.forName("double[]", classLoader));
+ }
+
+ @Test
+ public void testForNameWithPrimitiveArraysInternalName() throws ClassNotFoundException {
+ assertEquals(boolean[].class, ClassUtils.forName(boolean[].class.getName(), classLoader));
+ assertEquals(byte[].class, ClassUtils.forName(byte[].class.getName(), classLoader));
+ assertEquals(char[].class, ClassUtils.forName(char[].class.getName(), classLoader));
+ assertEquals(short[].class, ClassUtils.forName(short[].class.getName(), classLoader));
+ assertEquals(int[].class, ClassUtils.forName(int[].class.getName(), classLoader));
+ assertEquals(long[].class, ClassUtils.forName(long[].class.getName(), classLoader));
+ assertEquals(float[].class, ClassUtils.forName(float[].class.getName(), classLoader));
+ assertEquals(double[].class, ClassUtils.forName(double[].class.getName(), classLoader));
+ }
+
+ @Test
+ public void testGetShortName() {
+ String className = ClassUtils.getShortName(getClass());
+ assertEquals("Class name did not match", "ClassUtilsTests", className);
+ }
+
+ @Test
+ public void testGetShortNameForObjectArrayClass() {
+ String className = ClassUtils.getShortName(Object[].class);
+ assertEquals("Class name did not match", "Object[]", className);
+ }
+
+ @Test
+ public void testGetShortNameForMultiDimensionalObjectArrayClass() {
+ String className = ClassUtils.getShortName(Object[][].class);
+ assertEquals("Class name did not match", "Object[][]", className);
+ }
+
+ @Test
+ public void testGetShortNameForPrimitiveArrayClass() {
+ String className = ClassUtils.getShortName(byte[].class);
+ assertEquals("Class name did not match", "byte[]", className);
+ }
+
+ @Test
+ public void testGetShortNameForMultiDimensionalPrimitiveArrayClass() {
+ String className = ClassUtils.getShortName(byte[][][].class);
+ assertEquals("Class name did not match", "byte[][][]", className);
+ }
+
+ @Test
+ public void testGetShortNameForInnerClass() {
+ String className = ClassUtils.getShortName(InnerClass.class);
+ assertEquals("Class name did not match", "ClassUtilsTests.InnerClass", className);
+ }
+
+ @Test
+ public void testGetShortNameAsProperty() {
+ String shortName = ClassUtils.getShortNameAsProperty(this.getClass());
+ assertEquals("Class name did not match", "classUtilsTests", shortName);
+ }
+
+ @Test
+ public void testGetClassFileName() {
+ assertEquals("String.class", ClassUtils.getClassFileName(String.class));
+ assertEquals("ClassUtilsTests.class", ClassUtils.getClassFileName(getClass()));
+ }
+
+ @Test
+ public void testGetPackageName() {
+ assertEquals("java.lang", ClassUtils.getPackageName(String.class));
+ assertEquals(getClass().getPackage().getName(), ClassUtils.getPackageName(getClass()));
+ }
+
+ @Test
+ public void testGetQualifiedName() {
+ String className = ClassUtils.getQualifiedName(getClass());
+ assertEquals("Class name did not match", "org.springframework.util.ClassUtilsTests", className);
+ }
+
+ @Test
+ public void testGetQualifiedNameForObjectArrayClass() {
+ String className = ClassUtils.getQualifiedName(Object[].class);
+ assertEquals("Class name did not match", "java.lang.Object[]", className);
+ }
+
+ @Test
+ public void testGetQualifiedNameForMultiDimensionalObjectArrayClass() {
+ String className = ClassUtils.getQualifiedName(Object[][].class);
+ assertEquals("Class name did not match", "java.lang.Object[][]", className);
+ }
+
+ @Test
+ public void testGetQualifiedNameForPrimitiveArrayClass() {
+ String className = ClassUtils.getQualifiedName(byte[].class);
+ assertEquals("Class name did not match", "byte[]", className);
+ }
+
+ @Test
+ public void testGetQualifiedNameForMultiDimensionalPrimitiveArrayClass() {
+ String className = ClassUtils.getQualifiedName(byte[][].class);
+ assertEquals("Class name did not match", "byte[][]", className);
+ }
+
+ @Test
+ public void testHasMethod() throws Exception {
+ assertTrue(ClassUtils.hasMethod(Collection.class, "size"));
+ assertTrue(ClassUtils.hasMethod(Collection.class, "remove", Object.class));
+ assertFalse(ClassUtils.hasMethod(Collection.class, "remove"));
+ assertFalse(ClassUtils.hasMethod(Collection.class, "someOtherMethod"));
+ }
+
+ @Test
+ public void testGetMethodIfAvailable() throws Exception {
+ Method method = ClassUtils.getMethodIfAvailable(Collection.class, "size");
+ assertNotNull(method);
+ assertEquals("size", method.getName());
+
+ method = ClassUtils.getMethodIfAvailable(Collection.class, "remove", new Class[] {Object.class});
+ assertNotNull(method);
+ assertEquals("remove", method.getName());
+
+ assertNull(ClassUtils.getMethodIfAvailable(Collection.class, "remove"));
+ assertNull(ClassUtils.getMethodIfAvailable(Collection.class, "someOtherMethod"));
+ }
+
+ @Test
+ public void testGetMethodCountForName() {
+ assertEquals("Verifying number of overloaded 'print' methods for OverloadedMethodsClass.", 2,
+ ClassUtils.getMethodCountForName(OverloadedMethodsClass.class, "print"));
+ assertEquals("Verifying number of overloaded 'print' methods for SubOverloadedMethodsClass.", 4,
+ ClassUtils.getMethodCountForName(SubOverloadedMethodsClass.class, "print"));
+ }
+
+ @Test
+ public void testCountOverloadedMethods() {
+ assertFalse(ClassUtils.hasAtLeastOneMethodWithName(TestObject.class, "foobar"));
+ // no args
+ assertTrue(ClassUtils.hasAtLeastOneMethodWithName(TestObject.class, "hashCode"));
+ // matches although it takes an arg
+ assertTrue(ClassUtils.hasAtLeastOneMethodWithName(TestObject.class, "setAge"));
+ }
+
+ @Test
+ public void testNoArgsStaticMethod() throws IllegalAccessException, InvocationTargetException {
+ Method method = ClassUtils.getStaticMethod(InnerClass.class, "staticMethod", (Class[]) null);
+ method.invoke(null, (Object[]) null);
+ assertTrue("no argument method was not invoked.",
+ InnerClass.noArgCalled);
+ }
+
+ @Test
+ public void testArgsStaticMethod() throws IllegalAccessException, InvocationTargetException {
+ Method method = ClassUtils.getStaticMethod(InnerClass.class, "argStaticMethod",
+ new Class[] {String.class});
+ method.invoke(null, new Object[] {"test"});
+ assertTrue("argument method was not invoked.", InnerClass.argCalled);
+ }
+
+ @Test
+ public void testOverloadedStaticMethod() throws IllegalAccessException, InvocationTargetException {
+ Method method = ClassUtils.getStaticMethod(InnerClass.class, "staticMethod",
+ new Class[] {String.class});
+ method.invoke(null, new Object[] {"test"});
+ assertTrue("argument method was not invoked.",
+ InnerClass.overloadedCalled);
+ }
+
+ @Test
+ public void testIsAssignable() {
+ assertTrue(ClassUtils.isAssignable(Object.class, Object.class));
+ assertTrue(ClassUtils.isAssignable(String.class, String.class));
+ assertTrue(ClassUtils.isAssignable(Object.class, String.class));
+ assertTrue(ClassUtils.isAssignable(Object.class, Integer.class));
+ assertTrue(ClassUtils.isAssignable(Number.class, Integer.class));
+ assertTrue(ClassUtils.isAssignable(Number.class, int.class));
+ assertTrue(ClassUtils.isAssignable(Integer.class, int.class));
+ assertTrue(ClassUtils.isAssignable(int.class, Integer.class));
+ assertFalse(ClassUtils.isAssignable(String.class, Object.class));
+ assertFalse(ClassUtils.isAssignable(Integer.class, Number.class));
+ assertFalse(ClassUtils.isAssignable(Integer.class, double.class));
+ assertFalse(ClassUtils.isAssignable(double.class, Integer.class));
+ }
+
+ @Test
+ public void testClassPackageAsResourcePath() {
+ String result = ClassUtils.classPackageAsResourcePath(Proxy.class);
+ assertTrue(result.equals("java/lang/reflect"));
+ }
+
+ @Test
+ public void testAddResourcePathToPackagePath() {
+ String result = "java/lang/reflect/xyzabc.xml";
+ assertEquals(result, ClassUtils.addResourcePathToPackagePath(Proxy.class, "xyzabc.xml"));
+ assertEquals(result, ClassUtils.addResourcePathToPackagePath(Proxy.class, "/xyzabc.xml"));
+
+ assertEquals("java/lang/reflect/a/b/c/d.xml",
+ ClassUtils.addResourcePathToPackagePath(Proxy.class, "a/b/c/d.xml"));
+ }
+
+ @Test
+ public void testGetAllInterfaces() {
+ DerivedTestObject testBean = new DerivedTestObject();
+ List ifcs = Arrays.asList(ClassUtils.getAllInterfaces(testBean));
+ assertEquals("Correct number of interfaces", 4, ifcs.size());
+ assertTrue("Contains Serializable", ifcs.contains(Serializable.class));
+ assertTrue("Contains ITestBean", ifcs.contains(ITestObject.class));
+ assertTrue("Contains IOther", ifcs.contains(ITestInterface.class));
+ }
+
+ @Test
+ public void testClassNamesToString() {
+ List ifcs = new LinkedList();
+ ifcs.add(Serializable.class);
+ ifcs.add(Runnable.class);
+ assertEquals("[interface java.io.Serializable, interface java.lang.Runnable]", ifcs.toString());
+ assertEquals("[java.io.Serializable, java.lang.Runnable]", ClassUtils.classNamesToString(ifcs));
+
+ List classes = new LinkedList();
+ classes.add(LinkedList.class);
+ classes.add(Integer.class);
+ assertEquals("[class java.util.LinkedList, class java.lang.Integer]", classes.toString());
+ assertEquals("[java.util.LinkedList, java.lang.Integer]", ClassUtils.classNamesToString(classes));
+
+ assertEquals("[interface java.util.List]", Collections.singletonList(List.class).toString());
+ assertEquals("[java.util.List]", ClassUtils.classNamesToString(List.class));
+
+ assertEquals("[]", Collections.EMPTY_LIST.toString());
+ assertEquals("[]", ClassUtils.classNamesToString(Collections.EMPTY_LIST));
+ }
+
+ @Test
+ public void testDetermineCommonAncestor() {
+ assertEquals(Number.class, ClassUtils.determineCommonAncestor(Integer.class, Number.class));
+ assertEquals(Number.class, ClassUtils.determineCommonAncestor(Number.class, Integer.class));
+ assertEquals(Number.class, ClassUtils.determineCommonAncestor(Number.class, null));
+ assertEquals(Integer.class, ClassUtils.determineCommonAncestor(null, Integer.class));
+ assertEquals(Integer.class, ClassUtils.determineCommonAncestor(Integer.class, Integer.class));
+
+ assertEquals(Number.class, ClassUtils.determineCommonAncestor(Integer.class, Float.class));
+ assertEquals(Number.class, ClassUtils.determineCommonAncestor(Float.class, Integer.class));
+ assertNull(ClassUtils.determineCommonAncestor(Integer.class, String.class));
+ assertNull(ClassUtils.determineCommonAncestor(String.class, Integer.class));
+
+ assertEquals(Collection.class, ClassUtils.determineCommonAncestor(List.class, Collection.class));
+ assertEquals(Collection.class, ClassUtils.determineCommonAncestor(Collection.class, List.class));
+ assertEquals(Collection.class, ClassUtils.determineCommonAncestor(Collection.class, null));
+ assertEquals(List.class, ClassUtils.determineCommonAncestor(null, List.class));
+ assertEquals(List.class, ClassUtils.determineCommonAncestor(List.class, List.class));
+
+ assertNull(ClassUtils.determineCommonAncestor(List.class, Set.class));
+ assertNull(ClassUtils.determineCommonAncestor(Set.class, List.class));
+ assertNull(ClassUtils.determineCommonAncestor(List.class, Runnable.class));
+ assertNull(ClassUtils.determineCommonAncestor(Runnable.class, List.class));
+
+ assertEquals(List.class, ClassUtils.determineCommonAncestor(List.class, ArrayList.class));
+ assertEquals(List.class, ClassUtils.determineCommonAncestor(ArrayList.class, List.class));
+ assertNull(ClassUtils.determineCommonAncestor(List.class, String.class));
+ assertNull(ClassUtils.determineCommonAncestor(String.class, List.class));
+ }
+
+
+ public static class InnerClass {
+
+ static boolean noArgCalled;
+ static boolean argCalled;
+ static boolean overloadedCalled;
+
+ public static void staticMethod() {
+ noArgCalled = true;
+ }
+
+ public static void staticMethod(String anArg) {
+ overloadedCalled = true;
+ }
+
+ public static void argStaticMethod(String anArg) {
+ argCalled = true;
+ }
+ }
+
+ @SuppressWarnings("unused")
+ private static class OverloadedMethodsClass {
+
+ public void print(String messages) {
+ /* no-op */
+ }
+
+ public void print(String[] messages) {
+ /* no-op */
+ }
+ }
+
+ @SuppressWarnings("unused")
+ private static class SubOverloadedMethodsClass extends OverloadedMethodsClass {
+
+ public void print(String header, String[] messages) {
+ /* no-op */
+ }
+
+ void print(String header, String[] messages, String footer) {
+ /* no-op */
+ }
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/CollectionUtilsTests.java b/spring-core/src/test/java/org/springframework/util/CollectionUtilsTests.java
new file mode 100644
index 00000000..42ac9309
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/CollectionUtilsTests.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import static org.junit.Assert.*;
+import org.junit.Test;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ * @author Rick Evans
+ */
+public class CollectionUtilsTests {
+
+ @Test
+ public void testIsEmpty() {
+ assertTrue(CollectionUtils.isEmpty((Set<Object>) null));
+ assertTrue(CollectionUtils.isEmpty((Map<String, String>) null));
+ assertTrue(CollectionUtils.isEmpty(new HashMap<String, String>()));
+ assertTrue(CollectionUtils.isEmpty(new HashSet<Object>()));
+
+ List<Object> list = new LinkedList<Object>();
+ list.add(new Object());
+ assertFalse(CollectionUtils.isEmpty(list));
+
+ Map<String, String> map = new HashMap<String, String>();
+ map.put("foo", "bar");
+ assertFalse(CollectionUtils.isEmpty(map));
+ }
+
+ @Test
+ public void testMergeArrayIntoCollection() {
+ Object[] arr = new Object[] {"value1", "value2"};
+ List<Comparable<?>> list = new LinkedList<Comparable<?>>();
+ list.add("value3");
+
+ CollectionUtils.mergeArrayIntoCollection(arr, list);
+ assertEquals("value3", list.get(0));
+ assertEquals("value1", list.get(1));
+ assertEquals("value2", list.get(2));
+ }
+
+ @Test
+ public void testMergePrimitiveArrayIntoCollection() {
+ int[] arr = new int[] {1, 2};
+ List<Comparable<?>> list = new LinkedList<Comparable<?>>();
+ list.add(new Integer(3));
+
+ CollectionUtils.mergeArrayIntoCollection(arr, list);
+ assertEquals(new Integer(3), list.get(0));
+ assertEquals(new Integer(1), list.get(1));
+ assertEquals(new Integer(2), list.get(2));
+ }
+
+ @Test
+ public void testMergePropertiesIntoMap() {
+ Properties defaults = new Properties();
+ defaults.setProperty("prop1", "value1");
+ Properties props = new Properties(defaults);
+ props.setProperty("prop2", "value2");
+ props.put("prop3", new Integer(3));
+
+ Map<String, String> map = new HashMap<String, String>();
+ map.put("prop4", "value4");
+
+ CollectionUtils.mergePropertiesIntoMap(props, map);
+ assertEquals("value1", map.get("prop1"));
+ assertEquals("value2", map.get("prop2"));
+ assertEquals(new Integer(3), map.get("prop3"));
+ assertEquals("value4", map.get("prop4"));
+ }
+
+ @Test
+ public void testContains() {
+ assertFalse(CollectionUtils.contains((Iterator<String>) null, "myElement"));
+ assertFalse(CollectionUtils.contains((Enumeration<String>) null, "myElement"));
+ assertFalse(CollectionUtils.contains(new LinkedList<String>().iterator(), "myElement"));
+ assertFalse(CollectionUtils.contains(new Hashtable<String, Object>().keys(), "myElement"));
+
+ List<String> list = new LinkedList<String>();
+ list.add("myElement");
+ assertTrue(CollectionUtils.contains(list.iterator(), "myElement"));
+
+ Hashtable<String, String> ht = new Hashtable<String, String>();
+ ht.put("myElement", "myValue");
+ assertTrue(CollectionUtils.contains(ht.keys(), "myElement"));
+ }
+
+ @Test
+ public void testContainsAny() throws Exception {
+ List<String> source = new ArrayList<String>();
+ source.add("abc");
+ source.add("def");
+ source.add("ghi");
+
+ List<String> candidates = new ArrayList<String>();
+ candidates.add("xyz");
+ candidates.add("def");
+ candidates.add("abc");
+
+ assertTrue(CollectionUtils.containsAny(source, candidates));
+ candidates.remove("def");
+ assertTrue(CollectionUtils.containsAny(source, candidates));
+ candidates.remove("abc");
+ assertFalse(CollectionUtils.containsAny(source, candidates));
+ }
+
+ @Test
+ public void testContainsInstanceWithNullCollection() throws Exception {
+ assertFalse("Must return false if supplied Collection argument is null",
+ CollectionUtils.containsInstance(null, this));
+ }
+
+ @Test
+ public void testContainsInstanceWithInstancesThatAreEqualButDistinct() throws Exception {
+ List<Instance> list = new ArrayList<Instance>();
+ list.add(new Instance("fiona"));
+ assertFalse("Must return false if instance is not in the supplied Collection argument",
+ CollectionUtils.containsInstance(list, new Instance("fiona")));
+ }
+
+ @Test
+ public void testContainsInstanceWithSameInstance() throws Exception {
+ List<Instance> list = new ArrayList<Instance>();
+ list.add(new Instance("apple"));
+ Instance instance = new Instance("fiona");
+ list.add(instance);
+ assertTrue("Must return true if instance is in the supplied Collection argument",
+ CollectionUtils.containsInstance(list, instance));
+ }
+
+ @Test
+ public void testContainsInstanceWithNullInstance() throws Exception {
+ List<Instance> list = new ArrayList<Instance>();
+ list.add(new Instance("apple"));
+ list.add(new Instance("fiona"));
+ assertFalse("Must return false if null instance is supplied",
+ CollectionUtils.containsInstance(list, null));
+ }
+
+ @Test
+ public void testFindFirstMatch() throws Exception {
+ List<String> source = new ArrayList<String>();
+ source.add("abc");
+ source.add("def");
+ source.add("ghi");
+
+ List<String> candidates = new ArrayList<String>();
+ candidates.add("xyz");
+ candidates.add("def");
+ candidates.add("abc");
+
+ assertEquals("def", CollectionUtils.findFirstMatch(source, candidates));
+ }
+
+ @Test
+ public void testHasUniqueObject() {
+ List<String> list = new LinkedList<String>();
+ list.add("myElement");
+ list.add("myOtherElement");
+ assertFalse(CollectionUtils.hasUniqueObject(list));
+
+ list = new LinkedList<String>();
+ list.add("myElement");
+ assertTrue(CollectionUtils.hasUniqueObject(list));
+
+ list = new LinkedList<String>();
+ list.add("myElement");
+ list.add(null);
+ assertFalse(CollectionUtils.hasUniqueObject(list));
+
+ list = new LinkedList<String>();
+ list.add(null);
+ list.add("myElement");
+ assertFalse(CollectionUtils.hasUniqueObject(list));
+
+ list = new LinkedList<String>();
+ list.add(null);
+ list.add(null);
+ assertTrue(CollectionUtils.hasUniqueObject(list));
+
+ list = new LinkedList<String>();
+ list.add(null);
+ assertTrue(CollectionUtils.hasUniqueObject(list));
+
+ list = new LinkedList<String>();
+ assertFalse(CollectionUtils.hasUniqueObject(list));
+ }
+
+
+ private static final class Instance {
+
+ private final String name;
+
+ public Instance(String name) {
+ this.name = name;
+ }
+
+ public boolean equals(Object rhs) {
+ if (this == rhs) {
+ return true;
+ }
+ if (rhs == null || this.getClass() != rhs.getClass()) {
+ return false;
+ }
+ Instance instance = (Instance) rhs;
+ return this.name.equals(instance.name);
+ }
+
+ public int hashCode() {
+ return this.name.hashCode();
+ }
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/CompositeIteratorTests.java b/spring-core/src/test/java/org/springframework/util/CompositeIteratorTests.java
new file mode 100644
index 00000000..124bc04a
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/CompositeIteratorTests.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2002-2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util;
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+
+/**
+ * Test case for {@link CompositeIterator}.
+ *
+ * @author Erwin Vervaet
+ * @author Juergen Hoeller
+ */
+public class CompositeIteratorTests {
+
+ @Test
+ public void testNoIterators() {
+ CompositeIterator<String> it = new CompositeIterator<String>();
+ assertFalse(it.hasNext());
+ try {
+ it.next();
+ fail();
+ }
+ catch (NoSuchElementException ex) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testSingleIterator() {
+ CompositeIterator<String> it = new CompositeIterator<String>();
+ it.add(Arrays.asList("0", "1").iterator());
+ for (int i = 0; i < 2; i++) {
+ assertTrue(it.hasNext());
+ assertEquals(String.valueOf(i), it.next());
+ }
+ assertFalse(it.hasNext());
+ try {
+ it.next();
+ fail();
+ }
+ catch (NoSuchElementException ex) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testMultipleIterators() {
+ CompositeIterator<String> it = new CompositeIterator<String>();
+ it.add(Arrays.asList("0", "1").iterator());
+ it.add(Arrays.asList("2").iterator());
+ it.add(Arrays.asList("3", "4").iterator());
+ for (int i = 0; i < 5; i++) {
+ assertTrue(it.hasNext());
+ assertEquals(String.valueOf(i), it.next());
+ }
+ assertFalse(it.hasNext());
+ try {
+ it.next();
+ fail();
+ }
+ catch (NoSuchElementException ex) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testInUse() {
+ List<String> list = Arrays.asList("0", "1");
+ CompositeIterator<String> it = new CompositeIterator<String>();
+ it.add(list.iterator());
+ it.hasNext();
+ try {
+ it.add(list.iterator());
+ fail();
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ }
+ it = new CompositeIterator<String>();
+ it.add(list.iterator());
+ it.next();
+ try {
+ it.add(list.iterator());
+ fail();
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testDuplicateIterators() {
+ List<String> list = Arrays.asList("0", "1");
+ Iterator<String> iterator = list.iterator();
+ CompositeIterator<String> it = new CompositeIterator<String>();
+ it.add(iterator);
+ it.add(list.iterator());
+ try {
+ it.add(iterator);
+ fail();
+ }
+ catch (IllegalArgumentException ex) {
+ // expected
+ }
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/ConcurrentReferenceHashMapTests.java b/spring-core/src/test/java/org/springframework/util/ConcurrentReferenceHashMapTests.java
new file mode 100644
index 00000000..d585d0ae
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/ConcurrentReferenceHashMapTests.java
@@ -0,0 +1,674 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.WeakHashMap;
+
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import org.springframework.util.ConcurrentReferenceHashMap.Entry;
+import org.springframework.util.ConcurrentReferenceHashMap.Reference;
+import org.springframework.util.ConcurrentReferenceHashMap.Restructure;
+import org.springframework.util.comparator.ComparableComparator;
+import org.springframework.util.comparator.NullSafeComparator;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+/**
+ * Tests for {@link ConcurrentReferenceHashMap}.
+ *
+ * @author Phillip Webb
+ */
+public class ConcurrentReferenceHashMapTests {
+
+ private static final Comparator<? super String> NULL_SAFE_STRING_SORT = new NullSafeComparator<String>(
+ new ComparableComparator<String>(), true);
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ private TestWeakConcurrentCache<Integer, String> map = new TestWeakConcurrentCache<Integer, String>();
+
+
+ @Test
+ public void shouldCreateWithDefaults() throws Exception {
+ ConcurrentReferenceHashMap<Integer, String> map = new ConcurrentReferenceHashMap<Integer, String>();
+ assertThat(map.getSegmentsSize(), is(16));
+ assertThat(map.getSegment(0).getSize(), is(1));
+ assertThat(map.getLoadFactor(), is(0.75f));
+ }
+
+ @Test
+ public void shouldCreateWithInitialCapacity() throws Exception {
+ ConcurrentReferenceHashMap<Integer, String> map = new ConcurrentReferenceHashMap<Integer, String>(32);
+ assertThat(map.getSegmentsSize(), is(16));
+ assertThat(map.getSegment(0).getSize(), is(2));
+ assertThat(map.getLoadFactor(), is(0.75f));
+ }
+
+ @Test
+ public void shouldCreateWithInitialCapacityAndLoadFactor() throws Exception {
+ ConcurrentReferenceHashMap<Integer, String> map = new ConcurrentReferenceHashMap<Integer, String>(32, 0.5f);
+ assertThat(map.getSegmentsSize(), is(16));
+ assertThat(map.getSegment(0).getSize(), is(2));
+ assertThat(map.getLoadFactor(), is(0.5f));
+ }
+
+ @Test
+ public void shouldCreateWithInitialCapacityAndConcurrenyLevel() throws Exception {
+ ConcurrentReferenceHashMap<Integer, String> map = new ConcurrentReferenceHashMap<Integer, String>(16, 2);
+ assertThat(map.getSegmentsSize(), is(2));
+ assertThat(map.getSegment(0).getSize(), is(8));
+ assertThat(map.getLoadFactor(), is(0.75f));
+ }
+
+ @Test
+ public void shouldCreateFullyCustom() throws Exception {
+ ConcurrentReferenceHashMap<Integer, String> map = new ConcurrentReferenceHashMap<Integer, String>(5, 0.5f, 3);
+ // concurrencyLevel of 3 ends up as 4 (nearest power of 2)
+ assertThat(map.getSegmentsSize(), is(4));
+ // initialCapacity is 5/4 (rounded up, to nearest power of 2)
+ assertThat(map.getSegment(0).getSize(), is(2));
+ assertThat(map.getLoadFactor(), is(0.5f));
+ }
+
+ @Test
+ public void shouldNeedNonNegativeInitialCapacity() throws Exception {
+ new ConcurrentReferenceHashMap<Integer, String>(0, 1);
+ this.thrown.expect(IllegalArgumentException.class);
+ this.thrown.expectMessage("Initial capacity must not be negative");
+ new TestWeakConcurrentCache<Integer, String>(-1, 1);
+ }
+
+ @Test
+ public void shouldNeedPositiveLoadFactor() throws Exception {
+ new ConcurrentReferenceHashMap<Integer, String>(0, 0.1f, 1);
+ this.thrown.expect(IllegalArgumentException.class);
+ this.thrown.expectMessage("Load factor must be positive");
+ new TestWeakConcurrentCache<Integer, String>(0, 0.0f, 1);
+ }
+
+ @Test
+ public void shouldNeedPositiveConcurrencyLevel() throws Exception {
+ new ConcurrentReferenceHashMap<Integer, String>(1, 1);
+ this.thrown.expect(IllegalArgumentException.class);
+ this.thrown.expectMessage("Concurrency level must be positive");
+ new TestWeakConcurrentCache<Integer, String>(1, 0);
+ }
+
+ @Test
+ public void shouldPutAndGet() throws Exception {
+ // NOTE we are using mock references so we don't need to worry about GC
+ assertThat(this.map.size(), is(0));
+ this.map.put(123, "123");
+ assertThat(this.map.get(123), is("123"));
+ assertThat(this.map.size(), is(1));
+ this.map.put(123, "123b");
+ assertThat(this.map.size(), is(1));
+ this.map.put(123, null);
+ assertThat(this.map.size(), is(1));
+ }
+
+ @Test
+ public void shouldReplaceOnDoublePut() throws Exception {
+ this.map.put(123, "321");
+ this.map.put(123, "123");
+ assertThat(this.map.get(123), is("123"));
+ }
+
+ @Test
+ public void shouldPutNullKey() throws Exception {
+ this.map.put(null, "123");
+ assertThat(this.map.get(null), is("123"));
+ }
+
+ @Test
+ public void shouldPutNullValue() throws Exception {
+ this.map.put(123, "321");
+ this.map.put(123, null);
+ assertThat(this.map.get(123), is(nullValue()));
+ }
+
+ @Test
+ public void shouldGetWithNoItems() throws Exception {
+ assertThat(this.map.get(123), is(nullValue()));
+ }
+
+ @Test
+ public void shouldApplySupplimentalHash() throws Exception {
+ Integer key = 123;
+ this.map.put(key, "123");
+ assertThat(this.map.getSupplimentalHash(), is(not(key.hashCode())));
+ assertThat(this.map.getSupplimentalHash() >> 30 & 0xFF, is(not(0)));
+ }
+
+ @Test
+ public void shouldGetFollowingNexts() throws Exception {
+ // Use loadFactor to disable resize
+ this.map = new TestWeakConcurrentCache<Integer, String>(1, 10.0f, 1);
+ this.map.put(1, "1");
+ this.map.put(2, "2");
+ this.map.put(3, "3");
+ assertThat(this.map.getSegment(0).getSize(), is(1));
+ assertThat(this.map.get(1), is("1"));
+ assertThat(this.map.get(2), is("2"));
+ assertThat(this.map.get(3), is("3"));
+ assertThat(this.map.get(4), is(nullValue()));
+ }
+
+ @Test
+ public void shouldResize() throws Exception {
+ this.map = new TestWeakConcurrentCache<Integer, String>(1, 0.75f, 1);
+ this.map.put(1, "1");
+ assertThat(this.map.getSegment(0).getSize(), is(1));
+ assertThat(this.map.get(1), is("1"));
+
+ this.map.put(2, "2");
+ assertThat(this.map.getSegment(0).getSize(), is(2));
+ assertThat(this.map.get(1), is("1"));
+ assertThat(this.map.get(2), is("2"));
+
+ this.map.put(3, "3");
+ assertThat(this.map.getSegment(0).getSize(), is(4));
+ assertThat(this.map.get(1), is("1"));
+ assertThat(this.map.get(2), is("2"));
+ assertThat(this.map.get(3), is("3"));
+
+ this.map.put(4, "4");
+ assertThat(this.map.getSegment(0).getSize(), is(8));
+ assertThat(this.map.get(4), is("4"));
+
+ // Putting again should not increase the count
+ for (int i = 1; i <= 5; i++) {
+ this.map.put(i, String.valueOf(i));
+ }
+ assertThat(this.map.getSegment(0).getSize(), is(8));
+ assertThat(this.map.get(5), is("5"));
+ }
+
+ @Test
+ public void shouldPurgeOnGet() throws Exception {
+ this.map = new TestWeakConcurrentCache<Integer, String>(1, 0.75f, 1);
+ for (int i = 1; i <= 5; i++) {
+ this.map.put(i, String.valueOf(i));
+ }
+ this.map.getMockReference(1, Restructure.NEVER).queueForPurge();
+ this.map.getMockReference(3, Restructure.NEVER).queueForPurge();
+ assertThat(this.map.getReference(1, Restructure.WHEN_NECESSARY), is(nullValue()));
+ assertThat(this.map.get(2), is("2"));
+ assertThat(this.map.getReference(3, Restructure.WHEN_NECESSARY), is(nullValue()));
+ assertThat(this.map.get(4), is("4"));
+ assertThat(this.map.get(5), is("5"));
+ }
+
+ @Test
+ public void shouldPergeOnPut() throws Exception {
+ this.map = new TestWeakConcurrentCache<Integer, String>(1, 0.75f, 1);
+ for (int i = 1; i <= 5; i++) {
+ this.map.put(i, String.valueOf(i));
+ }
+ this.map.getMockReference(1, Restructure.NEVER).queueForPurge();
+ this.map.getMockReference(3, Restructure.NEVER).queueForPurge();
+ this.map.put(1, "1");
+ assertThat(this.map.get(1), is("1"));
+ assertThat(this.map.get(2), is("2"));
+ assertThat(this.map.getReference(3, Restructure.WHEN_NECESSARY), is(nullValue()));
+ assertThat(this.map.get(4), is("4"));
+ assertThat(this.map.get(5), is("5"));
+ }
+
+ @Test
+ public void shouldPutIfAbsent() throws Exception {
+ assertThat(this.map.putIfAbsent(123, "123"), is(nullValue()));
+ assertThat(this.map.putIfAbsent(123, "123b"), is("123"));
+ assertThat(this.map.get(123), is("123"));
+ }
+
+ @Test
+ public void shouldPutIfAbsentWithNullValue() throws Exception {
+ assertThat(this.map.putIfAbsent(123, null), is(nullValue()));
+ assertThat(this.map.putIfAbsent(123, "123"), is(nullValue()));
+ assertThat(this.map.get(123), is(nullValue()));
+ }
+
+ @Test
+ public void shouldPutIfAbsentWithNullKey() throws Exception {
+ assertThat(this.map.putIfAbsent(null, "123"), is(nullValue()));
+ assertThat(this.map.putIfAbsent(null, "123b"), is("123"));
+ assertThat(this.map.get(null), is("123"));
+ }
+
+ @Test
+ public void shouldRemoveKeyAndValue() throws Exception {
+ this.map.put(123, "123");
+ assertThat(this.map.remove(123, "456"), is(false));
+ assertThat(this.map.get(123), is("123"));
+ assertThat(this.map.remove(123, "123"), is(true));
+ assertFalse(this.map.containsKey(123));
+ assertThat(this.map.isEmpty(), is(true));
+ }
+
+ @Test
+ public void shouldRemoveKeyAndValueWithExistingNull() throws Exception {
+ this.map.put(123, null);
+ assertThat(this.map.remove(123, "456"), is(false));
+ assertThat(this.map.get(123), is(nullValue()));
+ assertThat(this.map.remove(123, null), is(true));
+ assertFalse(this.map.containsKey(123));
+ assertThat(this.map.isEmpty(), is(true));
+ }
+
+ @Test
+ public void shouldReplaceOldValueWithNewValue() throws Exception {
+ this.map.put(123, "123");
+ assertThat(this.map.replace(123, "456", "789"), is(false));
+ assertThat(this.map.get(123), is("123"));
+ assertThat(this.map.replace(123, "123", "789"), is(true));
+ assertThat(this.map.get(123), is("789"));
+ }
+
+ @Test
+ public void shouldReplaceOldNullValueWithNewValue() throws Exception {
+ this.map.put(123, null);
+ assertThat(this.map.replace(123, "456", "789"), is(false));
+ assertThat(this.map.get(123), is(nullValue()));
+ assertThat(this.map.replace(123, null, "789"), is(true));
+ assertThat(this.map.get(123), is("789"));
+ }
+
+ @Test
+ public void shouldReplaceValue() throws Exception {
+ this.map.put(123, "123");
+ assertThat(this.map.replace(123, "456"), is("123"));
+ assertThat(this.map.get(123), is("456"));
+ }
+
+ @Test
+ public void shouldReplaceNullValue() throws Exception {
+ this.map.put(123, null);
+ assertThat(this.map.replace(123, "456"), is(nullValue()));
+ assertThat(this.map.get(123), is("456"));
+ }
+
+ @Test
+ public void shouldGetSize() throws Exception {
+ assertThat(this.map.size(), is(0));
+ this.map.put(123, "123");
+ this.map.put(123, null);
+ this.map.put(456, "456");
+ assertThat(this.map.size(), is(2));
+ }
+
+ @Test
+ public void shouldSupportIsEmpty() throws Exception {
+ assertThat(this.map.isEmpty(), is(true));
+ this.map.put(123, "123");
+ this.map.put(123, null);
+ this.map.put(456, "456");
+ assertThat(this.map.isEmpty(), is(false));
+ }
+
+ @Test
+ public void shouldContainKey() throws Exception {
+ assertThat(this.map.containsKey(123), is(false));
+ assertThat(this.map.containsKey(456), is(false));
+ this.map.put(123, "123");
+ this.map.put(456, null);
+ assertThat(this.map.containsKey(123), is(true));
+ assertThat(this.map.containsKey(456), is(true));
+ }
+
+ @Test
+ public void shouldContainValue() throws Exception {
+ assertThat(this.map.containsValue("123"), is(false));
+ assertThat(this.map.containsValue(null), is(false));
+ this.map.put(123, "123");
+ this.map.put(456, null);
+ assertThat(this.map.containsValue("123"), is(true));
+ assertThat(this.map.containsValue(null), is(true));
+ }
+
+ @Test
+ public void shouldRemoveWhenKeyIsInMap() throws Exception {
+ this.map.put(123, null);
+ this.map.put(456, "456");
+ this.map.put(null, "789");
+ assertThat(this.map.remove(123), is(nullValue()));
+ assertThat(this.map.remove(456), is("456"));
+ assertThat(this.map.remove(null), is("789"));
+ assertThat(this.map.isEmpty(), is(true));
+ }
+
+ @Test
+ public void shouldRemoveWhenKeyIsNotInMap() throws Exception {
+ assertThat(this.map.remove(123), is(nullValue()));
+ assertThat(this.map.remove(null), is(nullValue()));
+ assertThat(this.map.isEmpty(), is(true));
+ }
+
+ @Test
+ public void shouldPutAll() throws Exception {
+ Map<Integer, String> m = new HashMap<Integer, String>();
+ m.put(123, "123");
+ m.put(456, null);
+ m.put(null, "789");
+ this.map.putAll(m);
+ assertThat(this.map.size(), is(3));
+ assertThat(this.map.get(123), is("123"));
+ assertThat(this.map.get(456), is(nullValue()));
+ assertThat(this.map.get(null), is("789"));
+ }
+
+ @Test
+ public void shouldClear() throws Exception {
+ this.map.put(123, "123");
+ this.map.put(456, null);
+ this.map.put(null, "789");
+ this.map.clear();
+ assertThat(this.map.size(), is(0));
+ assertThat(this.map.containsKey(123), is(false));
+ assertThat(this.map.containsKey(456), is(false));
+ assertThat(this.map.containsKey(null), is(false));
+ }
+
+ @Test
+ public void shouldGetKeySet() throws Exception {
+ this.map.put(123, "123");
+ this.map.put(456, null);
+ this.map.put(null, "789");
+ Set<Integer> expected = new HashSet<Integer>();
+ expected.add(123);
+ expected.add(456);
+ expected.add(null);
+ assertThat(this.map.keySet(), is(expected));
+ }
+
+ @Test
+ public void shouldGetValues() throws Exception {
+ this.map.put(123, "123");
+ this.map.put(456, null);
+ this.map.put(null, "789");
+ List<String> actual = new ArrayList<String>(this.map.values());
+ List<String> expected = new ArrayList<String>();
+ expected.add("123");
+ expected.add(null);
+ expected.add("789");
+ Collections.sort(actual, NULL_SAFE_STRING_SORT);
+ Collections.sort(expected, NULL_SAFE_STRING_SORT);
+ assertThat(actual, is(expected));
+ }
+
+ @Test
+ public void shouldGetEntrySet() throws Exception {
+ this.map.put(123, "123");
+ this.map.put(456, null);
+ this.map.put(null, "789");
+ HashMap<Integer, String> expected = new HashMap<Integer, String>();
+ expected.put(123, "123");
+ expected.put(456, null);
+ expected.put(null, "789");
+ assertThat(this.map.entrySet(), is(expected.entrySet()));
+ }
+
+ @Test
+ public void shouldGetEntrySetFollowingNext() throws Exception {
+ // Use loadFactor to disable resize
+ this.map = new TestWeakConcurrentCache<Integer, String>(1, 10.0f, 1);
+ this.map.put(1, "1");
+ this.map.put(2, "2");
+ this.map.put(3, "3");
+ HashMap<Integer, String> expected = new HashMap<Integer, String>();
+ expected.put(1, "1");
+ expected.put(2, "2");
+ expected.put(3, "3");
+ assertThat(this.map.entrySet(), is(expected.entrySet()));
+ }
+
+ @Test
+ public void shouldRemoveViaEntrySet() throws Exception {
+ this.map.put(1, "1");
+ this.map.put(2, "2");
+ this.map.put(3, "3");
+ Iterator<Map.Entry<Integer, String>> iterator = this.map.entrySet().iterator();
+ iterator.next();
+ iterator.next();
+ iterator.remove();
+ iterator.next();
+ assertThat(iterator.hasNext(), is(false));
+ assertThat(this.map.size(), is(2));
+ assertThat(this.map.containsKey(2), is(false));
+ }
+
+ @Test
+ public void shouldSetViaEntrySet() throws Exception {
+ this.map.put(1, "1");
+ this.map.put(2, "2");
+ this.map.put(3, "3");
+ Iterator<Map.Entry<Integer, String>> iterator = this.map.entrySet().iterator();
+ iterator.next();
+ iterator.next().setValue("2b");
+ iterator.next();
+ assertThat(iterator.hasNext(), is(false));
+ assertThat(this.map.size(), is(3));
+ assertThat(this.map.get(2), is("2b"));
+ }
+
+ @Test
+ @Ignore("Intended for use during development only")
+ public void shouldBeFasterThanSynchronizedMap() throws Exception {
+ Map<Integer, WeakReference<String>> synchronizedMap = Collections.synchronizedMap(new WeakHashMap<Integer, WeakReference<String>>());
+ StopWatch mapTime = timeMultiThreaded("SynchronizedMap", synchronizedMap,
+ new ValueFactory<WeakReference<String>>() {
+
+ @Override
+ public WeakReference<String> newValue(int v) {
+ return new WeakReference<String>(String.valueOf(v));
+ }
+ });
+ System.out.println(mapTime.prettyPrint());
+
+ this.map.setDisableTestHooks(true);
+ StopWatch cacheTime = timeMultiThreaded("WeakConcurrentCache", this.map,
+ new ValueFactory<String>() {
+
+ @Override
+ public String newValue(int v) {
+ return String.valueOf(v);
+ }
+ });
+ System.out.println(cacheTime.prettyPrint());
+
+ // We should be at least 4 time faster
+ assertThat(cacheTime.getTotalTimeSeconds(),
+ is(lessThan(mapTime.getTotalTimeSeconds() / 4.0)));
+ }
+
+ @Test
+ public void shouldSupportNullReference() throws Exception {
+ // GC could happen during restructure so we must be able to create a reference for a null entry
+ map.createReferenceManager().createReference(null, 1234, null);
+ }
+
+ /**
+ * Time a multi-threaded access to a cache.
+ * @return the timing stopwatch
+ */
+ private <V> StopWatch timeMultiThreaded(String id, final Map<Integer, V> map,
+ ValueFactory<V> factory) throws InterruptedException {
+
+ StopWatch stopWatch = new StopWatch(id);
+ for (int i = 0; i < 500; i++) {
+ map.put(i, factory.newValue(i));
+ }
+ Thread[] threads = new Thread[30];
+ stopWatch.start("Running threads");
+ for (int threadIndex = 0; threadIndex < threads.length; threadIndex++) {
+ threads[threadIndex] = new Thread("Cache access thread " + threadIndex) {
+ @Override
+ public void run() {
+ for (int j = 0; j < 1000; j++) {
+ for (int i = 0; i < 1000; i++) {
+ map.get(i);
+ }
+ }
+ }
+ };
+ }
+ for (Thread thread : threads) {
+ thread.start();
+ }
+
+ for (Thread thread : threads) {
+ if (thread.isAlive()) {
+ thread.join(2000);
+ }
+ }
+ stopWatch.stop();
+ return stopWatch;
+ }
+
+
+ private static interface ValueFactory<V> {
+
+ V newValue(int k);
+ }
+
+
+ private static class TestWeakConcurrentCache<K, V> extends ConcurrentReferenceHashMap<K, V> {
+
+ private int supplimentalHash;
+
+ private final LinkedList<MockReference<K, V>> queue = new LinkedList<MockReference<K, V>>();
+
+ private boolean disableTestHooks;
+
+ public TestWeakConcurrentCache() {
+ super();
+ }
+
+ public void setDisableTestHooks(boolean disableTestHooks) {
+ this.disableTestHooks = disableTestHooks;
+ }
+
+ public TestWeakConcurrentCache(int initialCapacity, float loadFactor, int concurrencyLevel) {
+ super(initialCapacity, loadFactor, concurrencyLevel);
+ }
+
+ public TestWeakConcurrentCache(int initialCapacity, int concurrencyLevel) {
+ super(initialCapacity, concurrencyLevel);
+ }
+
+ @Override
+ protected int getHash(Object o) {
+ if (this.disableTestHooks) {
+ return super.getHash(o);
+ }
+ // For testing we want more control of the hash
+ this.supplimentalHash = super.getHash(o);
+ return o == null ? 0 : o.hashCode();
+ }
+
+ public int getSupplimentalHash() {
+ return this.supplimentalHash;
+ }
+
+ @Override
+ protected ReferenceManager createReferenceManager() {
+ return new ReferenceManager() {
+ @Override
+ public Reference<K, V> createReference(Entry<K, V> entry, int hash,
+ Reference<K, V> next) {
+ if (TestWeakConcurrentCache.this.disableTestHooks) {
+ return super.createReference(entry, hash, next);
+ }
+ return new MockReference<K, V>(entry, hash, next, TestWeakConcurrentCache.this.queue);
+ }
+ @Override
+ public Reference<K, V> pollForPurge() {
+ if (TestWeakConcurrentCache.this.disableTestHooks) {
+ return super.pollForPurge();
+ }
+ return TestWeakConcurrentCache.this.queue.isEmpty() ? null : TestWeakConcurrentCache.this.queue.removeFirst();
+ }
+ };
+ }
+
+ public MockReference<K, V> getMockReference(K key, Restructure restructure) {
+ return (MockReference<K, V>) super.getReference(key, restructure);
+ }
+ }
+
+
+ private static class MockReference<K, V> implements Reference<K, V> {
+
+ private final int hash;
+
+ private Entry<K, V> entry;
+
+ private final Reference<K, V> next;
+
+ private final LinkedList<MockReference<K, V>> queue;
+
+ public MockReference(Entry<K, V> entry, int hash, Reference<K, V> next, LinkedList<MockReference<K, V>> queue) {
+ this.hash = hash;
+ this.entry = entry;
+ this.next = next;
+ this.queue = queue;
+ }
+
+ @Override
+ public Entry<K, V> get() {
+ return this.entry;
+ }
+
+ @Override
+ public int getHash() {
+ return this.hash;
+ }
+
+ @Override
+ public Reference<K, V> getNext() {
+ return this.next;
+ }
+
+ @Override
+ public void release() {
+ this.queue.add(this);
+ this.entry = null;
+ }
+
+ public void queueForPurge() {
+ this.queue.add(this);
+ }
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/DigestUtilsTests.java b/spring-core/src/test/java/org/springframework/util/DigestUtilsTests.java
new file mode 100644
index 00000000..7233ad38
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/DigestUtilsTests.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2002-2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util;
+
+import java.io.UnsupportedEncodingException;
+
+import static org.junit.Assert.*;
+import org.junit.Before;
+import org.junit.Test;
+
+public class DigestUtilsTests {
+
+ private byte[] bytes;
+
+ @Before
+ public void createBytes() throws UnsupportedEncodingException {
+ bytes = "Hello World".getBytes("UTF-8");
+ }
+
+ @Test
+ public void md5() {
+ byte[] result = DigestUtils.md5Digest(bytes);
+ byte[] expected = new byte[]{-0x4f, 0xa, -0x73, -0x4f, 0x64, -0x20, 0x75, 0x41, 0x5, -0x49, -0x57, -0x65, -0x19,
+ 0x2e, 0x3f, -0x1b};
+ assertArrayEquals("Invalid hash", expected, result);
+ }
+
+ @Test
+ public void md5Hex() throws UnsupportedEncodingException {
+ String hash = DigestUtils.md5DigestAsHex(bytes);
+ assertEquals("Invalid hash", "b10a8db164e0754105b7a99be72e3fe5", hash);
+ }
+
+ @Test
+ public void md5StringBuilder() throws UnsupportedEncodingException {
+ StringBuilder builder = new StringBuilder();
+ DigestUtils.appendMd5DigestAsHex(bytes, builder);
+ assertEquals("Invalid hash", "b10a8db164e0754105b7a99be72e3fe5", builder.toString());
+ }
+
+
+} \ No newline at end of file
diff --git a/spring-core/src/test/java/org/springframework/util/FileCopyUtilsTests.java b/spring-core/src/test/java/org/springframework/util/FileCopyUtilsTests.java
new file mode 100644
index 00000000..6848c4d1
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/FileCopyUtilsTests.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for the FileCopyUtils class.
+ *
+ * @author Juergen Hoeller
+ * @since 12.03.2005
+ */
+public class FileCopyUtilsTests extends TestCase {
+
+ public void testCopyFromInputStream() throws IOException {
+ byte[] content = "content".getBytes();
+ ByteArrayInputStream in = new ByteArrayInputStream(content);
+ ByteArrayOutputStream out = new ByteArrayOutputStream(content.length);
+ int count = FileCopyUtils.copy(in, out);
+ assertEquals(content.length, count);
+ assertTrue(Arrays.equals(content, out.toByteArray()));
+ }
+
+ public void testCopyFromByteArray() throws IOException {
+ byte[] content = "content".getBytes();
+ ByteArrayOutputStream out = new ByteArrayOutputStream(content.length);
+ FileCopyUtils.copy(content, out);
+ assertTrue(Arrays.equals(content, out.toByteArray()));
+ }
+
+ public void testCopyToByteArray() throws IOException {
+ byte[] content = "content".getBytes();
+ ByteArrayInputStream in = new ByteArrayInputStream(content);
+ byte[] result = FileCopyUtils.copyToByteArray(in);
+ assertTrue(Arrays.equals(content, result));
+ }
+
+ public void testCopyFromReader() throws IOException {
+ String content = "content";
+ StringReader in = new StringReader(content);
+ StringWriter out = new StringWriter();
+ int count = FileCopyUtils.copy(in, out);
+ assertEquals(content.length(), count);
+ assertEquals(content, out.toString());
+ }
+
+ public void testCopyFromString() throws IOException {
+ String content = "content";
+ StringWriter out = new StringWriter();
+ FileCopyUtils.copy(content, out);
+ assertEquals(content, out.toString());
+ }
+
+ public void testCopyToString() throws IOException {
+ String content = "content";
+ StringReader in = new StringReader(content);
+ String result = FileCopyUtils.copyToString(in);
+ assertEquals(content, result);
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/FileSystemUtilsTests.java b/spring-core/src/test/java/org/springframework/util/FileSystemUtilsTests.java
new file mode 100644
index 00000000..d87212c1
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/FileSystemUtilsTests.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util;
+
+import java.io.File;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Rob Harrop
+ */
+public class FileSystemUtilsTests extends TestCase {
+
+ public void testDeleteRecursively() throws Exception {
+ File root = new File("./tmp/root");
+ File child = new File(root, "child");
+ File grandchild = new File(child, "grandchild");
+
+ grandchild.mkdirs();
+
+ File bar = new File(child, "bar.txt");
+ bar.createNewFile();
+
+ assertTrue(root.exists());
+ assertTrue(child.exists());
+ assertTrue(grandchild.exists());
+ assertTrue(bar.exists());
+
+ FileSystemUtils.deleteRecursively(root);
+
+ assertFalse(root.exists());
+ assertFalse(child.exists());
+ assertFalse(grandchild.exists());
+ assertFalse(bar.exists());
+ }
+
+ public void testCopyRecursively() throws Exception {
+ File src = new File("./tmp/src");
+ File child = new File(src, "child");
+ File grandchild = new File(child, "grandchild");
+
+ grandchild.mkdirs();
+
+ File bar = new File(child, "bar.txt");
+ bar.createNewFile();
+
+ assertTrue(src.exists());
+ assertTrue(child.exists());
+ assertTrue(grandchild.exists());
+ assertTrue(bar.exists());
+
+ File dest = new File("./dest");
+ FileSystemUtils.copyRecursively(src, dest);
+
+ assertTrue(dest.exists());
+ assertTrue(new File(dest, child.getName()).exists());
+
+ FileSystemUtils.deleteRecursively(src);
+ assertTrue(!src.exists());
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ File tmp = new File("./tmp");
+ if (tmp.exists()) {
+ FileSystemUtils.deleteRecursively(tmp);
+ }
+ File dest = new File("./dest");
+ if (dest.exists()) {
+ FileSystemUtils.deleteRecursively(dest);
+ }
+ super.tearDown();
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/LinkedCaseInsensitiveMapTests.java b/spring-core/src/test/java/org/springframework/util/LinkedCaseInsensitiveMapTests.java
new file mode 100644
index 00000000..7d3b171b
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/LinkedCaseInsensitiveMapTests.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class LinkedCaseInsensitiveMapTests {
+
+ private LinkedCaseInsensitiveMap<String> map;
+
+ @Before
+ public void setUp() {
+ map = new LinkedCaseInsensitiveMap<String>();
+ }
+
+ @Test
+ public void putAndGet() {
+ map.put("key", "value1");
+ map.put("key", "value2");
+ map.put("key", "value3");
+ assertEquals(1, map.size());
+ assertEquals("value3", map.get("key"));
+ assertEquals("value3", map.get("KEY"));
+ assertEquals("value3", map.get("Key"));
+ }
+
+ @Test
+ public void putWithOverlappingKeys() {
+ map.put("key", "value1");
+ map.put("KEY", "value2");
+ map.put("Key", "value3");
+ assertEquals(1, map.size());
+ assertEquals("value3", map.get("key"));
+ assertEquals("value3", map.get("KEY"));
+ assertEquals("value3", map.get("Key"));
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/LinkedMultiValueMapTests.java b/spring-core/src/test/java/org/springframework/util/LinkedMultiValueMapTests.java
new file mode 100644
index 00000000..7e274557
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/LinkedMultiValueMapTests.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2002-2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.*;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Arjen Poutsma
+ */
+public class LinkedMultiValueMapTests {
+
+ private LinkedMultiValueMap<String, String> map;
+
+ @Before
+ public void setUp() {
+ map = new LinkedMultiValueMap<String, String>();
+ }
+
+ @Test
+ public void add() {
+ map.add("key", "value1");
+ map.add("key", "value2");
+ assertEquals(1, map.size());
+ List<String> expected = new ArrayList<String>(2);
+ expected.add("value1");
+ expected.add("value2");
+ assertEquals(expected, map.get("key"));
+ }
+
+ @Test
+ public void getFirst() {
+ List<String> values = new ArrayList<String>(2);
+ values.add("value1");
+ values.add("value2");
+ map.put("key", values);
+ assertEquals("value1", map.getFirst("key"));
+ assertNull(map.getFirst("other"));
+ }
+
+ @Test
+ public void set() {
+ map.set("key", "value1");
+ map.set("key", "value2");
+ assertEquals(1, map.size());
+ assertEquals(Collections.singletonList("value2"), map.get("key"));
+ }
+
+ @Test
+ public void equals() {
+ map.set("key1", "value1");
+ assertEquals(map, map);
+ MultiValueMap<String, String> o1 = new LinkedMultiValueMap<String, String>();
+ o1.set("key1", "value1");
+ assertEquals(map, o1);
+ assertEquals(o1, map);
+ Map<String, List<String>> o2 = new HashMap<String, List<String>>();
+ o2.put("key1", Collections.singletonList("value1"));
+ assertEquals(map, o2);
+ assertEquals(o2, map);
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/Log4jConfigurerTests.java b/spring-core/src/test/java/org/springframework/util/Log4jConfigurerTests.java
new file mode 100644
index 00000000..90d40d7b
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/Log4jConfigurerTests.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util;
+
+import java.io.FileNotFoundException;
+import java.net.URL;
+
+import junit.framework.TestCase;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * @author Alef Arendsen
+ * @author Juergen Hoeller
+ */
+public class Log4jConfigurerTests extends TestCase {
+
+ public void testInitLoggingWithClasspath() throws FileNotFoundException {
+ doTestInitLogging("classpath:org/springframework/util/testlog4j.properties", false);
+ }
+
+ public void testInitLoggingWithRelativeFilePath() throws FileNotFoundException {
+ doTestInitLogging("src/test/resources/org/springframework/util/testlog4j.properties", false);
+ }
+
+ public void testInitLoggingWithAbsoluteFilePath() throws FileNotFoundException {
+ URL url = getClass().getResource("testlog4j.properties");
+ doTestInitLogging(url.toString(), false);
+ }
+
+ public void testInitLoggingWithClasspathAndRefreshInterval() throws FileNotFoundException {
+ doTestInitLogging("classpath:org/springframework/util/testlog4j.properties", true);
+ }
+
+ public void testInitLoggingWithRelativeFilePathAndRefreshInterval() throws FileNotFoundException {
+ doTestInitLogging("src/test/resources/org/springframework/util/testlog4j.properties", true);
+ }
+
+ /* only works on Windows
+ public void testInitLoggingWithAbsoluteFilePathAndRefreshInterval() throws FileNotFoundException {
+ URL url = getClass().getResource("testlog4j.properties");
+ doTestInitLogging(url.getFile(), true);
+ }
+ */
+
+ public void testInitLoggingWithFileUrlAndRefreshInterval() throws FileNotFoundException {
+ URL url = getClass().getResource("testlog4j.properties");
+ doTestInitLogging(url.toString(), true);
+ }
+
+ private void doTestInitLogging(String location, boolean refreshInterval) throws FileNotFoundException {
+ if (refreshInterval) {
+ Log4jConfigurer.initLogging(location, 10);
+ }
+ else {
+ Log4jConfigurer.initLogging(location);
+ }
+
+ Log log = LogFactory.getLog(this.getClass());
+ log.debug("debug");
+ log.info("info");
+ log.warn("warn");
+ log.error("error");
+ log.fatal("fatal");
+
+ assertTrue(MockLog4jAppender.loggingStrings.contains("debug"));
+ assertTrue(MockLog4jAppender.loggingStrings.contains("info"));
+ assertTrue(MockLog4jAppender.loggingStrings.contains("warn"));
+ assertTrue(MockLog4jAppender.loggingStrings.contains("error"));
+ assertTrue(MockLog4jAppender.loggingStrings.contains("fatal"));
+
+ Log4jConfigurer.shutdownLogging();
+ assertTrue(MockLog4jAppender.closeCalled);
+ }
+
+ public void testInitLoggingWithRefreshIntervalAndFileNotFound() throws FileNotFoundException {
+ try {
+ Log4jConfigurer.initLogging("test/org/springframework/util/bla.properties", 10);
+ fail("Exception should have been thrown, file does not exist!");
+ }
+ catch (FileNotFoundException ex) {
+ // OK
+ }
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/MethodInvokerTests.java b/spring-core/src/test/java/org/springframework/util/MethodInvokerTests.java
new file mode 100644
index 00000000..679ab956
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/MethodInvokerTests.java
@@ -0,0 +1,292 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Colin Sampaleanu
+ * @author Juergen Hoeller
+ * @since 21.11.2003
+ */
+public class MethodInvokerTests extends TestCase {
+
+ public void testPlainMethodInvoker() throws Exception {
+ // sanity check: singleton, non-static should work
+ TestClass1 tc1 = new TestClass1();
+ MethodInvoker mi = new MethodInvoker();
+ mi.setTargetObject(tc1);
+ mi.setTargetMethod("method1");
+ mi.prepare();
+ Integer i = (Integer) mi.invoke();
+ assertEquals(1, i.intValue());
+
+ // sanity check: check that argument count matching works
+ mi = new MethodInvoker();
+ mi.setTargetClass(TestClass1.class);
+ mi.setTargetMethod("supertypes");
+ mi.setArguments(new Object[] {new ArrayList<>(), new ArrayList<>(), "hello"});
+ mi.prepare();
+ assertEquals("hello", mi.invoke());
+
+ mi = new MethodInvoker();
+ mi.setTargetClass(TestClass1.class);
+ mi.setTargetMethod("supertypes2");
+ mi.setArguments(new Object[] {new ArrayList<>(), new ArrayList<>(), "hello", "bogus"});
+ mi.prepare();
+ assertEquals("hello", mi.invoke());
+
+ // Sanity check: check that argument conversion doesn't work with plain MethodInvoker
+ mi = new MethodInvoker();
+ mi.setTargetClass(TestClass1.class);
+ mi.setTargetMethod("supertypes2");
+ mi.setArguments(new Object[] {new ArrayList<>(), new ArrayList<>(), "hello", Boolean.TRUE});
+ try {
+ mi.prepare();
+ fail("Shouldn't have matched without argument conversion");
+ }
+ catch (NoSuchMethodException ex) {
+ // expected
+ }
+ }
+
+ public void testStringWithMethodInvoker() throws Exception {
+ try {
+ MethodInvoker methodInvoker = new MethodInvoker();
+ methodInvoker.setTargetObject(new Greeter());
+ methodInvoker.setTargetMethod("greet");
+ methodInvoker.setArguments(new Object[] {new String("no match")});
+ methodInvoker.prepare();
+ fail("Should have thrown a NoSuchMethodException");
+ }
+ catch (NoSuchMethodException e) {
+ // expected
+ }
+ }
+
+ public void testPurchaserWithMethodInvoker() throws Exception {
+ MethodInvoker methodInvoker = new MethodInvoker();
+ methodInvoker.setTargetObject(new Greeter());
+ methodInvoker.setTargetMethod("greet");
+ methodInvoker.setArguments(new Object[] {new Purchaser()});
+ methodInvoker.prepare();
+ String greeting = (String) methodInvoker.invoke();
+ assertEquals("purchaser: hello", greeting);
+ }
+
+ public void testShopperWithMethodInvoker() throws Exception {
+ MethodInvoker methodInvoker = new MethodInvoker();
+ methodInvoker.setTargetObject(new Greeter());
+ methodInvoker.setTargetMethod("greet");
+ methodInvoker.setArguments(new Object[] {new Shopper()});
+ methodInvoker.prepare();
+ String greeting = (String) methodInvoker.invoke();
+ assertEquals("purchaser: may I help you?", greeting);
+ }
+
+ public void testSalesmanWithMethodInvoker() throws Exception {
+ MethodInvoker methodInvoker = new MethodInvoker();
+ methodInvoker.setTargetObject(new Greeter());
+ methodInvoker.setTargetMethod("greet");
+ methodInvoker.setArguments(new Object[] {new Salesman()});
+ methodInvoker.prepare();
+ String greeting = (String) methodInvoker.invoke();
+ assertEquals("greetable: how are sales?", greeting);
+ }
+
+ public void testCustomerWithMethodInvoker() throws Exception {
+ MethodInvoker methodInvoker = new MethodInvoker();
+ methodInvoker.setTargetObject(new Greeter());
+ methodInvoker.setTargetMethod("greet");
+ methodInvoker.setArguments(new Object[] {new Customer()});
+ methodInvoker.prepare();
+ String greeting = (String) methodInvoker.invoke();
+ assertEquals("customer: good day", greeting);
+ }
+
+ public void testRegularWithMethodInvoker() throws Exception {
+ MethodInvoker methodInvoker = new MethodInvoker();
+ methodInvoker.setTargetObject(new Greeter());
+ methodInvoker.setTargetMethod("greet");
+ methodInvoker.setArguments(new Object[] {new Regular("Kotter")});
+ methodInvoker.prepare();
+ String greeting = (String) methodInvoker.invoke();
+ assertEquals("regular: welcome back Kotter", greeting);
+ }
+
+ public void testVIPWithMethodInvoker() throws Exception {
+ MethodInvoker methodInvoker = new MethodInvoker();
+ methodInvoker.setTargetObject(new Greeter());
+ methodInvoker.setTargetMethod("greet");
+ methodInvoker.setArguments(new Object[] {new VIP("Fonzie")});
+ methodInvoker.prepare();
+ String greeting = (String) methodInvoker.invoke();
+ assertEquals("regular: whassup dude?", greeting);
+ }
+
+
+ public static class TestClass1 {
+
+ public static int _staticField1;
+
+ public int _field1 = 0;
+
+ public int method1() {
+ return ++_field1;
+ }
+
+ public static int staticMethod1() {
+ return ++TestClass1._staticField1;
+ }
+
+ public static void voidRetvalMethod() {
+ }
+
+ public static void nullArgument(Object arg) {
+ }
+
+ public static void intArgument(int arg) {
+ }
+
+ public static void intArguments(int[] arg) {
+ }
+
+ public static String supertypes(Collection<?> c, Integer i) {
+ return i.toString();
+ }
+
+ public static String supertypes(Collection<?> c, List<?> l, String s) {
+ return s;
+ }
+
+ public static String supertypes2(Collection<?> c, List<?> l, Integer i) {
+ return i.toString();
+ }
+
+ public static String supertypes2(Collection<?> c, List<?> l, String s, Integer i) {
+ return s;
+ }
+
+ public static String supertypes2(Collection<?> c, List<?> l, String s, String s2) {
+ return s;
+ }
+ }
+
+
+ @SuppressWarnings("unused")
+ public static class Greeter {
+
+ // should handle Salesman (only interface)
+ public String greet(Greetable greetable) {
+ return "greetable: " + greetable.getGreeting();
+ }
+
+ // should handle Shopper (beats Greetable since it is a class)
+ protected String greet(Purchaser purchaser) {
+ return "purchaser: " + purchaser.getGreeting();
+ }
+
+ // should handle Customer (exact match)
+ String greet(Customer customer) {
+ return "customer: " + customer.getGreeting();
+ }
+
+ // should handle Regular (exact) and VIP (closest match)
+ private String greet(Regular regular) {
+ return "regular: " + regular.getGreeting();
+ }
+ }
+
+
+ private static interface Greetable {
+
+ String getGreeting();
+ }
+
+
+ private static interface Person extends Greetable {
+ }
+
+
+ private static class Purchaser implements Greetable {
+
+ @Override
+ public String getGreeting() {
+ return "hello";
+ }
+ }
+
+
+ private static class Shopper extends Purchaser implements Person {
+
+ @Override
+ public String getGreeting() {
+ return "may I help you?";
+ }
+ }
+
+
+ private static class Salesman implements Person {
+
+ @Override
+ public String getGreeting() {
+ return "how are sales?";
+ }
+ }
+
+
+ private static class Customer extends Shopper {
+
+ @Override
+ public String getGreeting() {
+ return "good day";
+ }
+ }
+
+
+ private static class Regular extends Customer {
+
+ private String name;
+
+ public Regular(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String getGreeting() {
+ return "welcome back " + name ;
+ }
+ }
+
+
+ private static class VIP extends Regular {
+
+ public VIP(String name) {
+ super(name);
+ }
+
+ @Override
+ public String getGreeting() {
+ return "whassup dude?";
+ }
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/MockLog4jAppender.java b/spring-core/src/test/java/org/springframework/util/MockLog4jAppender.java
new file mode 100644
index 00000000..e145195b
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/MockLog4jAppender.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.AppenderSkeleton;
+import org.apache.log4j.spi.LoggingEvent;
+
+/**
+ * @author Alef Arendsen
+ */
+public class MockLog4jAppender extends AppenderSkeleton {
+
+ public static final List loggingStrings = new ArrayList();
+
+ public static boolean closeCalled = false;
+
+ /* (non-Javadoc)
+ * @see org.apache.log4j.AppenderSkeleton#append(org.apache.log4j.spi.LoggingEvent)
+ */
+ @Override
+ protected void append(LoggingEvent evt) {
+ //System.out.println("Adding " + evt.getMessage());
+ loggingStrings.add(evt.getMessage());
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.log4j.Appender#close()
+ */
+ @Override
+ public void close() {
+ closeCalled = true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.log4j.Appender#requiresLayout()
+ */
+ @Override
+ public boolean requiresLayout() {
+ return false;
+ }
+
+
+
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/NumberUtilsTests.java b/spring-core/src/test/java/org/springframework/util/NumberUtilsTests.java
new file mode 100644
index 00000000..aae2b8a7
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/NumberUtilsTests.java
@@ -0,0 +1,348 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.text.NumberFormat;
+import java.util.Locale;
+
+import junit.framework.TestCase;
+
+import org.springframework.core.JdkVersion;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ */
+public class NumberUtilsTests extends TestCase {
+
+ public void testParseNumber() {
+ String aByte = "" + Byte.MAX_VALUE;
+ String aShort = "" + Short.MAX_VALUE;
+ String anInteger = "" + Integer.MAX_VALUE;
+ String aLong = "" + Long.MAX_VALUE;
+ String aFloat = "" + Float.MAX_VALUE;
+ String aDouble = "" + Double.MAX_VALUE;
+
+ assertEquals("Byte did not parse", new Byte(Byte.MAX_VALUE), NumberUtils.parseNumber(aByte, Byte.class));
+ assertEquals("Short did not parse", new Short(Short.MAX_VALUE), NumberUtils.parseNumber(aShort, Short.class));
+ assertEquals("Integer did not parse", new Integer(Integer.MAX_VALUE), NumberUtils.parseNumber(anInteger, Integer.class));
+ assertEquals("Long did not parse", new Long(Long.MAX_VALUE), NumberUtils.parseNumber(aLong, Long.class));
+ assertEquals("Float did not parse", new Float(Float.MAX_VALUE), NumberUtils.parseNumber(aFloat, Float.class));
+ assertEquals("Double did not parse", new Double(Double.MAX_VALUE), NumberUtils.parseNumber(aDouble, Double.class));
+ }
+
+ public void testParseNumberUsingNumberFormat() {
+ NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
+ String aByte = "" + Byte.MAX_VALUE;
+ String aShort = "" + Short.MAX_VALUE;
+ String anInteger = "" + Integer.MAX_VALUE;
+ String aLong = "" + Long.MAX_VALUE;
+ String aFloat = "" + Float.MAX_VALUE;
+ String aDouble = "" + Double.MAX_VALUE;
+
+ assertEquals("Byte did not parse", new Byte(Byte.MAX_VALUE), NumberUtils.parseNumber(aByte, Byte.class, nf));
+ assertEquals("Short did not parse", new Short(Short.MAX_VALUE), NumberUtils.parseNumber(aShort, Short.class, nf));
+ assertEquals("Integer did not parse", new Integer(Integer.MAX_VALUE), NumberUtils.parseNumber(anInteger, Integer.class, nf));
+ assertEquals("Long did not parse", new Long(Long.MAX_VALUE), NumberUtils.parseNumber(aLong, Long.class, nf));
+ assertEquals("Float did not parse", new Float(Float.MAX_VALUE), NumberUtils.parseNumber(aFloat, Float.class, nf));
+ assertEquals("Double did not parse", new Double(Double.MAX_VALUE), NumberUtils.parseNumber(aDouble, Double.class, nf));
+ }
+
+ public void testParseWithTrim() {
+ String aByte = " " + Byte.MAX_VALUE + " ";
+ String aShort = " " + Short.MAX_VALUE + " ";
+ String anInteger = " " + Integer.MAX_VALUE + " ";
+ String aLong = " " + Long.MAX_VALUE + " ";
+ String aFloat = " " + Float.MAX_VALUE + " ";
+ String aDouble = " " + Double.MAX_VALUE + " ";
+
+ assertEquals("Byte did not parse", new Byte(Byte.MAX_VALUE), NumberUtils.parseNumber(aByte, Byte.class));
+ assertEquals("Short did not parse", new Short(Short.MAX_VALUE), NumberUtils.parseNumber(aShort, Short.class));
+ assertEquals("Integer did not parse", new Integer(Integer.MAX_VALUE), NumberUtils.parseNumber(anInteger, Integer.class));
+ assertEquals("Long did not parse", new Long(Long.MAX_VALUE), NumberUtils.parseNumber(aLong, Long.class));
+ assertEquals("Float did not parse", new Float(Float.MAX_VALUE), NumberUtils.parseNumber(aFloat, Float.class));
+ assertEquals("Double did not parse", new Double(Double.MAX_VALUE), NumberUtils.parseNumber(aDouble, Double.class));
+ }
+
+ public void testParseWithTrimUsingNumberFormat() {
+ NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
+ String aByte = " " + Byte.MAX_VALUE + " ";
+ String aShort = " " + Short.MAX_VALUE + " ";
+ String anInteger = " " + Integer.MAX_VALUE + " ";
+ String aLong = " " + Long.MAX_VALUE + " ";
+ String aFloat = " " + Float.MAX_VALUE + " ";
+ String aDouble = " " + Double.MAX_VALUE + " ";
+
+ assertEquals("Byte did not parse", new Byte(Byte.MAX_VALUE), NumberUtils.parseNumber(aByte, Byte.class, nf));
+ assertEquals("Short did not parse", new Short(Short.MAX_VALUE), NumberUtils.parseNumber(aShort, Short.class, nf));
+ assertEquals("Integer did not parse", new Integer(Integer.MAX_VALUE), NumberUtils.parseNumber(anInteger, Integer.class, nf));
+ assertEquals("Long did not parse", new Long(Long.MAX_VALUE), NumberUtils.parseNumber(aLong, Long.class, nf));
+ assertEquals("Float did not parse", new Float(Float.MAX_VALUE), NumberUtils.parseNumber(aFloat, Float.class, nf));
+ assertEquals("Double did not parse", new Double(Double.MAX_VALUE), NumberUtils.parseNumber(aDouble, Double.class, nf));
+ }
+
+ public void testParseAsHex() {
+ String aByte = "0x" + Integer.toHexString(new Byte(Byte.MAX_VALUE).intValue());
+ String aShort = "0x" + Integer.toHexString(new Short(Short.MAX_VALUE).intValue());
+ String anInteger = "0x" + Integer.toHexString(Integer.MAX_VALUE);
+ String aLong = "0x" + Long.toHexString(Long.MAX_VALUE);
+ String aReallyBigInt = "FEBD4E677898DFEBFFEE44";
+
+ assertByteEquals(aByte);
+ assertShortEquals(aShort);
+ assertIntegerEquals(anInteger);
+ assertLongEquals(aLong);
+ assertEquals("BigInteger did not parse",
+ new BigInteger(aReallyBigInt, 16), NumberUtils.parseNumber("0x" + aReallyBigInt, BigInteger.class));
+ }
+
+ public void testParseNegativeHex() {
+ String aByte = "-0x80";
+ String aShort = "-0x8000";
+ String anInteger = "-0x80000000";
+ String aLong = "-0x8000000000000000";
+ String aReallyBigInt = "FEBD4E677898DFEBFFEE44";
+
+ assertNegativeByteEquals(aByte);
+ assertNegativeShortEquals(aShort);
+ assertNegativeIntegerEquals(anInteger);
+ assertNegativeLongEquals(aLong);
+ assertEquals("BigInteger did not parse",
+ new BigInteger(aReallyBigInt, 16).negate(), NumberUtils.parseNumber("-0x" + aReallyBigInt, BigInteger.class));
+ }
+
+ public void testDoubleToBigInteger() {
+ Double decimal = new Double(3.14d);
+ assertEquals(new BigInteger("3"), NumberUtils.convertNumberToTargetClass(decimal, BigInteger.class));
+ }
+
+ public void testBigDecimalToBigInteger() {
+ String number = "987459837583750387355346";
+ BigDecimal decimal = new BigDecimal(number);
+ assertEquals(new BigInteger(number), NumberUtils.convertNumberToTargetClass(decimal, BigInteger.class));
+ }
+
+ public void testNonExactBigDecimalToBigInteger() {
+ BigDecimal decimal = new BigDecimal("987459837583750387355346.14");
+ assertEquals(new BigInteger("987459837583750387355346"), NumberUtils.convertNumberToTargetClass(decimal, BigInteger.class));
+ }
+
+ public void testParseBigDecimalNumber1() {
+ String bigDecimalAsString = "0.10";
+ Number bigDecimal = NumberUtils.parseNumber(bigDecimalAsString, BigDecimal.class);
+ assertEquals(new BigDecimal(bigDecimalAsString), bigDecimal);
+ }
+
+ public void testParseBigDecimalNumber2() {
+ String bigDecimalAsString = "0.001";
+ Number bigDecimal = NumberUtils.parseNumber(bigDecimalAsString, BigDecimal.class);
+ assertEquals(new BigDecimal(bigDecimalAsString), bigDecimal);
+ }
+
+ public void testParseBigDecimalNumber3() {
+ String bigDecimalAsString = "3.14159265358979323846";
+ Number bigDecimal = NumberUtils.parseNumber(bigDecimalAsString, BigDecimal.class);
+ assertEquals(new BigDecimal(bigDecimalAsString), bigDecimal);
+ }
+
+ public void testParseLocalizedBigDecimalNumber1() {
+ if (JdkVersion.getMajorJavaVersion() < JdkVersion.JAVA_15) {
+ return;
+ }
+ String bigDecimalAsString = "0.10";
+ NumberFormat numberFormat = NumberFormat.getInstance(Locale.ENGLISH);
+ Number bigDecimal = NumberUtils.parseNumber(bigDecimalAsString, BigDecimal.class, numberFormat);
+ assertEquals(new BigDecimal(bigDecimalAsString), bigDecimal);
+ }
+
+ public void testParseLocalizedBigDecimalNumber2() {
+ if (JdkVersion.getMajorJavaVersion() < JdkVersion.JAVA_15) {
+ return;
+ }
+ String bigDecimalAsString = "0.001";
+ NumberFormat numberFormat = NumberFormat.getInstance(Locale.ENGLISH);
+ Number bigDecimal = NumberUtils.parseNumber(bigDecimalAsString, BigDecimal.class, numberFormat);
+ assertEquals(new BigDecimal(bigDecimalAsString), bigDecimal);
+ }
+
+ public void testParseLocalizedBigDecimalNumber3() {
+ if (JdkVersion.getMajorJavaVersion() < JdkVersion.JAVA_15) {
+ return;
+ }
+ String bigDecimalAsString = "3.14159265358979323846";
+ NumberFormat numberFormat = NumberFormat.getInstance(Locale.ENGLISH);
+ Number bigDecimal = NumberUtils.parseNumber(bigDecimalAsString, BigDecimal.class, numberFormat);
+ assertEquals(new BigDecimal(bigDecimalAsString), bigDecimal);
+ }
+
+ public void testParseOverflow() {
+ String aLong = "" + Long.MAX_VALUE;
+ String aDouble = "" + Double.MAX_VALUE;
+
+ try {
+ NumberUtils.parseNumber(aLong, Byte.class);
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+
+ try {
+ NumberUtils.parseNumber(aLong, Short.class);
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+
+ try {
+ NumberUtils.parseNumber(aLong, Integer.class);
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+
+ assertEquals(new Long(Long.MAX_VALUE), NumberUtils.parseNumber(aLong, Long.class));
+
+ assertEquals(new Double(Double.MAX_VALUE), NumberUtils.parseNumber(aDouble, Double.class));
+ }
+
+ public void testParseNegativeOverflow() {
+ String aLong = "" + Long.MIN_VALUE;
+ String aDouble = "" + Double.MIN_VALUE;
+
+ try {
+ NumberUtils.parseNumber(aLong, Byte.class);
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+
+ try {
+ NumberUtils.parseNumber(aLong, Short.class);
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+
+ try {
+ NumberUtils.parseNumber(aLong, Integer.class);
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+
+ assertEquals(new Long(Long.MIN_VALUE), NumberUtils.parseNumber(aLong, Long.class));
+
+ assertEquals(new Double(Double.MIN_VALUE), NumberUtils.parseNumber(aDouble, Double.class));
+ }
+
+ public void testParseOverflowUsingNumberFormat() {
+ NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
+ String aLong = "" + Long.MAX_VALUE;
+ String aDouble = "" + Double.MAX_VALUE;
+
+ try {
+ NumberUtils.parseNumber(aLong, Byte.class, nf);
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+
+ try {
+ NumberUtils.parseNumber(aLong, Short.class, nf);
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+
+ try {
+ NumberUtils.parseNumber(aLong, Integer.class, nf);
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+
+ assertEquals(new Long(Long.MAX_VALUE), NumberUtils.parseNumber(aLong, Long.class, nf));
+
+ assertEquals(new Double(Double.MAX_VALUE), NumberUtils.parseNumber(aDouble, Double.class, nf));
+ }
+
+ public void testParseNegativeOverflowUsingNumberFormat() {
+ NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
+ String aLong = "" + Long.MIN_VALUE;
+ String aDouble = "" + Double.MIN_VALUE;
+
+ try {
+ NumberUtils.parseNumber(aLong, Byte.class, nf);
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+
+ try {
+ NumberUtils.parseNumber(aLong, Short.class, nf);
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+
+ try {
+ NumberUtils.parseNumber(aLong, Integer.class, nf);
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+
+ assertEquals(new Long(Long.MIN_VALUE), NumberUtils.parseNumber(aLong, Long.class, nf));
+
+ assertEquals(new Double(Double.MIN_VALUE), NumberUtils.parseNumber(aDouble, Double.class, nf));
+ }
+
+ private void assertLongEquals(String aLong) {
+ assertEquals("Long did not parse", Long.MAX_VALUE, NumberUtils.parseNumber(aLong, Long.class).longValue());
+ }
+
+ private void assertIntegerEquals(String anInteger) {
+ assertEquals("Integer did not parse", Integer.MAX_VALUE, NumberUtils.parseNumber(anInteger, Integer.class).intValue());
+ }
+
+ private void assertShortEquals(String aShort) {
+ assertEquals("Short did not parse", Short.MAX_VALUE, NumberUtils.parseNumber(aShort, Short.class).shortValue());
+ }
+
+ private void assertByteEquals(String aByte) {
+ assertEquals("Byte did not parse", Byte.MAX_VALUE, NumberUtils.parseNumber(aByte, Byte.class).byteValue());
+ }
+
+ private void assertNegativeLongEquals(String aLong) {
+ assertEquals("Long did not parse", Long.MIN_VALUE, NumberUtils.parseNumber(aLong, Long.class).longValue());
+ }
+
+ private void assertNegativeIntegerEquals(String anInteger) {
+ assertEquals("Integer did not parse", Integer.MIN_VALUE, NumberUtils.parseNumber(anInteger, Integer.class).intValue());
+ }
+
+ private void assertNegativeShortEquals(String aShort) {
+ assertEquals("Short did not parse", Short.MIN_VALUE, NumberUtils.parseNumber(aShort, Short.class).shortValue());
+ }
+
+ private void assertNegativeByteEquals(String aByte) {
+ assertEquals("Byte did not parse", Byte.MIN_VALUE, NumberUtils.parseNumber(aByte, Byte.class).byteValue());
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/ObjectUtilsTests.java b/spring-core/src/test/java/org/springframework/util/ObjectUtilsTests.java
new file mode 100644
index 00000000..8f4c1e28
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/ObjectUtilsTests.java
@@ -0,0 +1,763 @@
+/*
+ * Copyright 2002-2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util;
+
+import java.io.IOException;
+import java.sql.SQLException;
+
+import org.junit.Test;
+
+import org.springframework.core.task.TaskRejectedException;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ * @author Rick Evans
+ */
+public class ObjectUtilsTests {
+
+ @Test
+ public void testIsCheckedException() {
+ assertTrue(ObjectUtils.isCheckedException(new Exception()));
+ assertTrue(ObjectUtils.isCheckedException(new SQLException()));
+
+ assertFalse(ObjectUtils.isCheckedException(new RuntimeException()));
+ assertFalse(ObjectUtils.isCheckedException(new TaskRejectedException("")));
+
+ // Any Throwable other than RuntimeException and Error
+ // has to be considered checked according to the JLS.
+ assertTrue(ObjectUtils.isCheckedException(new Throwable()));
+ }
+
+ @Test
+ public void testIsCompatibleWithThrowsClause() {
+ Class<?>[] empty = new Class[0];
+ Class<?>[] exception = new Class[] {Exception.class};
+ Class<?>[] sqlAndIO = new Class[] {SQLException.class, IOException.class};
+ Class<?>[] throwable = new Class[] {Throwable.class};
+
+ assertTrue(ObjectUtils.isCompatibleWithThrowsClause(new RuntimeException()));
+ assertTrue(ObjectUtils.isCompatibleWithThrowsClause(new RuntimeException(), empty));
+ assertTrue(ObjectUtils.isCompatibleWithThrowsClause(new RuntimeException(), exception));
+ assertTrue(ObjectUtils.isCompatibleWithThrowsClause(new RuntimeException(), sqlAndIO));
+ assertTrue(ObjectUtils.isCompatibleWithThrowsClause(new RuntimeException(), throwable));
+
+ assertFalse(ObjectUtils.isCompatibleWithThrowsClause(new Exception()));
+ assertFalse(ObjectUtils.isCompatibleWithThrowsClause(new Exception(), empty));
+ assertTrue(ObjectUtils.isCompatibleWithThrowsClause(new Exception(), exception));
+ assertFalse(ObjectUtils.isCompatibleWithThrowsClause(new Exception(), sqlAndIO));
+ assertTrue(ObjectUtils.isCompatibleWithThrowsClause(new Exception(), throwable));
+
+ assertFalse(ObjectUtils.isCompatibleWithThrowsClause(new SQLException()));
+ assertFalse(ObjectUtils.isCompatibleWithThrowsClause(new SQLException(), empty));
+ assertTrue(ObjectUtils.isCompatibleWithThrowsClause(new SQLException(), exception));
+ assertTrue(ObjectUtils.isCompatibleWithThrowsClause(new SQLException(), sqlAndIO));
+ assertTrue(ObjectUtils.isCompatibleWithThrowsClause(new SQLException(), throwable));
+
+ assertFalse(ObjectUtils.isCompatibleWithThrowsClause(new Throwable()));
+ assertFalse(ObjectUtils.isCompatibleWithThrowsClause(new Throwable(), empty));
+ assertFalse(ObjectUtils.isCompatibleWithThrowsClause(new Throwable(), exception));
+ assertFalse(ObjectUtils.isCompatibleWithThrowsClause(new Throwable(), sqlAndIO));
+ assertTrue(ObjectUtils.isCompatibleWithThrowsClause(new Throwable(), throwable));
+ }
+
+ @Test
+ public void testToObjectArray() {
+ int[] a = new int[] {1, 2, 3, 4, 5};
+ Integer[] wrapper = (Integer[]) ObjectUtils.toObjectArray(a);
+ assertTrue(wrapper.length == 5);
+ for (int i = 0; i < wrapper.length; i++) {
+ assertEquals(a[i], wrapper[i].intValue());
+ }
+ }
+
+ @Test
+ public void testToObjectArrayWithNull() {
+ Object[] objects = ObjectUtils.toObjectArray(null);
+ assertNotNull(objects);
+ assertEquals(0, objects.length);
+ }
+
+ @Test
+ public void testToObjectArrayWithEmptyPrimitiveArray() {
+ Object[] objects = ObjectUtils.toObjectArray(new byte[] {});
+ assertNotNull(objects);
+ assertEquals(0, objects.length);
+ }
+
+ @Test
+ public void testToObjectArrayWithNonArrayType() {
+ try {
+ ObjectUtils.toObjectArray("Not an []");
+ fail("Must have thrown an IllegalArgumentException by this point.");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ @Test
+ public void testToObjectArrayWithNonPrimitiveArray() {
+ String[] source = new String[] {"Bingo"};
+ assertArrayEquals(source, ObjectUtils.toObjectArray(source));
+ }
+
+ @Test
+ public void testAddObjectToArraySunnyDay() {
+ String[] array = new String[] {"foo", "bar"};
+ String newElement = "baz";
+ Object[] newArray = ObjectUtils.addObjectToArray(array, newElement);
+ assertEquals(3, newArray.length);
+ assertEquals(newElement, newArray[2]);
+ }
+
+ @Test
+ public void testAddObjectToArrayWhenEmpty() {
+ String[] array = new String[0];
+ String newElement = "foo";
+ String[] newArray = ObjectUtils.addObjectToArray(array, newElement);
+ assertEquals(1, newArray.length);
+ assertEquals(newElement, newArray[0]);
+ }
+
+ @Test
+ public void testAddObjectToSingleNonNullElementArray() {
+ String existingElement = "foo";
+ String[] array = new String[] {existingElement};
+ String newElement = "bar";
+ String[] newArray = ObjectUtils.addObjectToArray(array, newElement);
+ assertEquals(2, newArray.length);
+ assertEquals(existingElement, newArray[0]);
+ assertEquals(newElement, newArray[1]);
+ }
+
+ @Test
+ public void testAddObjectToSingleNullElementArray() {
+ String[] array = new String[] {null};
+ String newElement = "bar";
+ String[] newArray = ObjectUtils.addObjectToArray(array, newElement);
+ assertEquals(2, newArray.length);
+ assertEquals(null, newArray[0]);
+ assertEquals(newElement, newArray[1]);
+ }
+
+ @Test
+ public void testAddObjectToNullArray() throws Exception {
+ String newElement = "foo";
+ String[] newArray = ObjectUtils.addObjectToArray(null, newElement);
+ assertEquals(1, newArray.length);
+ assertEquals(newElement, newArray[0]);
+ }
+
+ @Test
+ public void testAddNullObjectToNullArray() throws Exception {
+ Object[] newArray = ObjectUtils.addObjectToArray(null, null);
+ assertEquals(1, newArray.length);
+ assertEquals(null, newArray[0]);
+ }
+
+ @Test
+ public void testNullSafeEqualsWithArrays() throws Exception {
+ assertTrue(ObjectUtils.nullSafeEquals(new String[] {"a", "b", "c"}, new String[] {"a", "b", "c"}));
+ assertTrue(ObjectUtils.nullSafeEquals(new int[] {1, 2, 3}, new int[] {1, 2, 3}));
+ }
+
+ @Test
+ public void testHashCodeWithBooleanFalse() {
+ int expected = Boolean.FALSE.hashCode();
+ assertEquals(expected, ObjectUtils.hashCode(false));
+ }
+
+ @Test
+ public void testHashCodeWithBooleanTrue() {
+ int expected = Boolean.TRUE.hashCode();
+ assertEquals(expected, ObjectUtils.hashCode(true));
+ }
+
+ @Test
+ public void testHashCodeWithDouble() {
+ double dbl = 9830.43;
+ int expected = (new Double(dbl)).hashCode();
+ assertEquals(expected, ObjectUtils.hashCode(dbl));
+ }
+
+ @Test
+ public void testHashCodeWithFloat() {
+ float flt = 34.8f;
+ int expected = (new Float(flt)).hashCode();
+ assertEquals(expected, ObjectUtils.hashCode(flt));
+ }
+
+ @Test
+ public void testHashCodeWithLong() {
+ long lng = 883l;
+ int expected = (new Long(lng)).hashCode();
+ assertEquals(expected, ObjectUtils.hashCode(lng));
+ }
+
+ @Test
+ public void testIdentityToString() {
+ Object obj = new Object();
+ String expected = obj.getClass().getName() + "@" + ObjectUtils.getIdentityHexString(obj);
+ String actual = ObjectUtils.identityToString(obj);
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testIdentityToStringWithNullObject() {
+ assertEquals("", ObjectUtils.identityToString(null));
+ }
+
+ @Test
+ public void testIsArrayOfPrimitivesWithBooleanArray() {
+ assertTrue(ClassUtils.isPrimitiveArray(boolean[].class));
+ }
+
+ @Test
+ public void testIsArrayOfPrimitivesWithObjectArray() {
+ assertFalse(ClassUtils.isPrimitiveArray(Object[].class));
+ }
+
+ @Test
+ public void testIsArrayOfPrimitivesWithNonArray() {
+ assertFalse(ClassUtils.isPrimitiveArray(String.class));
+ }
+
+ @Test
+ public void testIsPrimitiveOrWrapperWithBooleanPrimitiveClass() {
+ assertTrue(ClassUtils.isPrimitiveOrWrapper(boolean.class));
+ }
+
+ @Test
+ public void testIsPrimitiveOrWrapperWithBooleanWrapperClass() {
+ assertTrue(ClassUtils.isPrimitiveOrWrapper(Boolean.class));
+ }
+
+ @Test
+ public void testIsPrimitiveOrWrapperWithBytePrimitiveClass() {
+ assertTrue(ClassUtils.isPrimitiveOrWrapper(byte.class));
+ }
+
+ @Test
+ public void testIsPrimitiveOrWrapperWithByteWrapperClass() {
+ assertTrue(ClassUtils.isPrimitiveOrWrapper(Byte.class));
+ }
+
+ @Test
+ public void testIsPrimitiveOrWrapperWithCharacterClass() {
+ assertTrue(ClassUtils.isPrimitiveOrWrapper(Character.class));
+ }
+
+ @Test
+ public void testIsPrimitiveOrWrapperWithCharClass() {
+ assertTrue(ClassUtils.isPrimitiveOrWrapper(char.class));
+ }
+
+ @Test
+ public void testIsPrimitiveOrWrapperWithDoublePrimitiveClass() {
+ assertTrue(ClassUtils.isPrimitiveOrWrapper(double.class));
+ }
+
+ @Test
+ public void testIsPrimitiveOrWrapperWithDoubleWrapperClass() {
+ assertTrue(ClassUtils.isPrimitiveOrWrapper(Double.class));
+ }
+
+ @Test
+ public void testIsPrimitiveOrWrapperWithFloatPrimitiveClass() {
+ assertTrue(ClassUtils.isPrimitiveOrWrapper(float.class));
+ }
+
+ @Test
+ public void testIsPrimitiveOrWrapperWithFloatWrapperClass() {
+ assertTrue(ClassUtils.isPrimitiveOrWrapper(Float.class));
+ }
+
+ @Test
+ public void testIsPrimitiveOrWrapperWithIntClass() {
+ assertTrue(ClassUtils.isPrimitiveOrWrapper(int.class));
+ }
+
+ @Test
+ public void testIsPrimitiveOrWrapperWithIntegerClass() {
+ assertTrue(ClassUtils.isPrimitiveOrWrapper(Integer.class));
+ }
+
+ @Test
+ public void testIsPrimitiveOrWrapperWithLongPrimitiveClass() {
+ assertTrue(ClassUtils.isPrimitiveOrWrapper(long.class));
+ }
+
+ @Test
+ public void testIsPrimitiveOrWrapperWithLongWrapperClass() {
+ assertTrue(ClassUtils.isPrimitiveOrWrapper(Long.class));
+ }
+
+ @Test
+ public void testIsPrimitiveOrWrapperWithNonPrimitiveOrWrapperClass() {
+ assertFalse(ClassUtils.isPrimitiveOrWrapper(Object.class));
+ }
+
+ @Test
+ public void testIsPrimitiveOrWrapperWithShortPrimitiveClass() {
+ assertTrue(ClassUtils.isPrimitiveOrWrapper(short.class));
+ }
+
+ @Test
+ public void testIsPrimitiveOrWrapperWithShortWrapperClass() {
+ assertTrue(ClassUtils.isPrimitiveOrWrapper(Short.class));
+ }
+
+ @Test
+ public void testNullSafeHashCodeWithBooleanArray() {
+ int expected = 31 * 7 + Boolean.TRUE.hashCode();
+ expected = 31 * expected + Boolean.FALSE.hashCode();
+
+ boolean[] array = {true, false};
+ int actual = ObjectUtils.nullSafeHashCode(array);
+
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testNullSafeHashCodeWithBooleanArrayEqualToNull() {
+ assertEquals(0, ObjectUtils.nullSafeHashCode((boolean[]) null));
+ }
+
+ @Test
+ public void testNullSafeHashCodeWithByteArray() {
+ int expected = 31 * 7 + 8;
+ expected = 31 * expected + 10;
+
+ byte[] array = {8, 10};
+ int actual = ObjectUtils.nullSafeHashCode(array);
+
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testNullSafeHashCodeWithByteArrayEqualToNull() {
+ assertEquals(0, ObjectUtils.nullSafeHashCode((byte[]) null));
+ }
+
+ @Test
+ public void testNullSafeHashCodeWithCharArray() {
+ int expected = 31 * 7 + 'a';
+ expected = 31 * expected + 'E';
+
+ char[] array = {'a', 'E'};
+ int actual = ObjectUtils.nullSafeHashCode(array);
+
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testNullSafeHashCodeWithCharArrayEqualToNull() {
+ assertEquals(0, ObjectUtils.nullSafeHashCode((char[]) null));
+ }
+
+ @Test
+ public void testNullSafeHashCodeWithDoubleArray() {
+ long bits = Double.doubleToLongBits(8449.65);
+ int expected = 31 * 7 + (int) (bits ^ (bits >>> 32));
+ bits = Double.doubleToLongBits(9944.923);
+ expected = 31 * expected + (int) (bits ^ (bits >>> 32));
+
+ double[] array = {8449.65, 9944.923};
+ int actual = ObjectUtils.nullSafeHashCode(array);
+
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testNullSafeHashCodeWithDoubleArrayEqualToNull() {
+ assertEquals(0, ObjectUtils.nullSafeHashCode((double[]) null));
+ }
+
+ @Test
+ public void testNullSafeHashCodeWithFloatArray() {
+ int expected = 31 * 7 + Float.floatToIntBits(9.6f);
+ expected = 31 * expected + Float.floatToIntBits(7.4f);
+
+ float[] array = {9.6f, 7.4f};
+ int actual = ObjectUtils.nullSafeHashCode(array);
+
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testNullSafeHashCodeWithFloatArrayEqualToNull() {
+ assertEquals(0, ObjectUtils.nullSafeHashCode((float[]) null));
+ }
+
+ @Test
+ public void testNullSafeHashCodeWithIntArray() {
+ int expected = 31 * 7 + 884;
+ expected = 31 * expected + 340;
+
+ int[] array = {884, 340};
+ int actual = ObjectUtils.nullSafeHashCode(array);
+
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testNullSafeHashCodeWithIntArrayEqualToNull() {
+ assertEquals(0, ObjectUtils.nullSafeHashCode((int[]) null));
+ }
+
+ @Test
+ public void testNullSafeHashCodeWithLongArray() {
+ long lng = 7993l;
+ int expected = 31 * 7 + (int) (lng ^ (lng >>> 32));
+ lng = 84320l;
+ expected = 31 * expected + (int) (lng ^ (lng >>> 32));
+
+ long[] array = {7993l, 84320l};
+ int actual = ObjectUtils.nullSafeHashCode(array);
+
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testNullSafeHashCodeWithLongArrayEqualToNull() {
+ assertEquals(0, ObjectUtils.nullSafeHashCode((long[]) null));
+ }
+
+ @Test
+ public void testNullSafeHashCodeWithObject() {
+ String str = "Luke";
+ assertEquals(str.hashCode(), ObjectUtils.nullSafeHashCode(str));
+ }
+
+ @Test
+ public void testNullSafeHashCodeWithObjectArray() {
+ int expected = 31 * 7 + "Leia".hashCode();
+ expected = 31 * expected + "Han".hashCode();
+
+ Object[] array = {"Leia", "Han"};
+ int actual = ObjectUtils.nullSafeHashCode(array);
+
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testNullSafeHashCodeWithObjectArrayEqualToNull() {
+ assertEquals(0, ObjectUtils.nullSafeHashCode((Object[]) null));
+ }
+
+ @Test
+ public void testNullSafeHashCodeWithObjectBeingBooleanArray() {
+ Object array = new boolean[] {true, false};
+ int expected = ObjectUtils.nullSafeHashCode((boolean[]) array);
+ assertEqualHashCodes(expected, array);
+ }
+
+ @Test
+ public void testNullSafeHashCodeWithObjectBeingByteArray() {
+ Object array = new byte[] {6, 39};
+ int expected = ObjectUtils.nullSafeHashCode((byte[]) array);
+ assertEqualHashCodes(expected, array);
+ }
+
+ @Test
+ public void testNullSafeHashCodeWithObjectBeingCharArray() {
+ Object array = new char[] {'l', 'M'};
+ int expected = ObjectUtils.nullSafeHashCode((char[]) array);
+ assertEqualHashCodes(expected, array);
+ }
+
+ @Test
+ public void testNullSafeHashCodeWithObjectBeingDoubleArray() {
+ Object array = new double[] {68930.993, 9022.009};
+ int expected = ObjectUtils.nullSafeHashCode((double[]) array);
+ assertEqualHashCodes(expected, array);
+ }
+
+ @Test
+ public void testNullSafeHashCodeWithObjectBeingFloatArray() {
+ Object array = new float[] {9.9f, 9.54f};
+ int expected = ObjectUtils.nullSafeHashCode((float[]) array);
+ assertEqualHashCodes(expected, array);
+ }
+
+ @Test
+ public void testNullSafeHashCodeWithObjectBeingIntArray() {
+ Object array = new int[] {89, 32};
+ int expected = ObjectUtils.nullSafeHashCode((int[]) array);
+ assertEqualHashCodes(expected, array);
+ }
+
+ @Test
+ public void testNullSafeHashCodeWithObjectBeingLongArray() {
+ Object array = new long[] {4389, 320};
+ int expected = ObjectUtils.nullSafeHashCode((long[]) array);
+ assertEqualHashCodes(expected, array);
+ }
+
+ @Test
+ public void testNullSafeHashCodeWithObjectBeingObjectArray() {
+ Object array = new Object[] {"Luke", "Anakin"};
+ int expected = ObjectUtils.nullSafeHashCode((Object[]) array);
+ assertEqualHashCodes(expected, array);
+ }
+
+ @Test
+ public void testNullSafeHashCodeWithObjectBeingShortArray() {
+ Object array = new short[] {5, 3};
+ int expected = ObjectUtils.nullSafeHashCode((short[]) array);
+ assertEqualHashCodes(expected, array);
+ }
+
+ @Test
+ public void testNullSafeHashCodeWithObjectEqualToNull() {
+ assertEquals(0, ObjectUtils.nullSafeHashCode((Object) null));
+ }
+
+ @Test
+ public void testNullSafeHashCodeWithShortArray() {
+ int expected = 31 * 7 + 70;
+ expected = 31 * expected + 8;
+
+ short[] array = {70, 8};
+ int actual = ObjectUtils.nullSafeHashCode(array);
+
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testNullSafeHashCodeWithShortArrayEqualToNull() {
+ assertEquals(0, ObjectUtils.nullSafeHashCode((short[]) null));
+ }
+
+ @Test
+ public void testNullSafeToStringWithBooleanArray() {
+ boolean[] array = {true, false};
+ assertEquals("{true, false}", ObjectUtils.nullSafeToString(array));
+ }
+
+ @Test
+ public void testNullSafeToStringWithBooleanArrayBeingEmpty() {
+ boolean[] array = {};
+ assertEquals("{}", ObjectUtils.nullSafeToString(array));
+ }
+
+ @Test
+ public void testNullSafeToStringWithBooleanArrayEqualToNull() {
+ assertEquals("null", ObjectUtils.nullSafeToString((boolean[]) null));
+ }
+
+ @Test
+ public void testNullSafeToStringWithByteArray() {
+ byte[] array = {5, 8};
+ assertEquals("{5, 8}", ObjectUtils.nullSafeToString(array));
+ }
+
+ @Test
+ public void testNullSafeToStringWithByteArrayBeingEmpty() {
+ byte[] array = {};
+ assertEquals("{}", ObjectUtils.nullSafeToString(array));
+ }
+
+ @Test
+ public void testNullSafeToStringWithByteArrayEqualToNull() {
+ assertEquals("null", ObjectUtils.nullSafeToString((byte[]) null));
+ }
+
+ @Test
+ public void testNullSafeToStringWithCharArray() {
+ char[] array = {'A', 'B'};
+ assertEquals("{'A', 'B'}", ObjectUtils.nullSafeToString(array));
+ }
+
+ @Test
+ public void testNullSafeToStringWithCharArrayBeingEmpty() {
+ char[] array = {};
+ assertEquals("{}", ObjectUtils.nullSafeToString(array));
+ }
+
+ @Test
+ public void testNullSafeToStringWithCharArrayEqualToNull() {
+ assertEquals("null", ObjectUtils.nullSafeToString((char[]) null));
+ }
+
+ @Test
+ public void testNullSafeToStringWithDoubleArray() {
+ double[] array = {8594.93, 8594023.95};
+ assertEquals("{8594.93, 8594023.95}", ObjectUtils.nullSafeToString(array));
+ }
+
+ @Test
+ public void testNullSafeToStringWithDoubleArrayBeingEmpty() {
+ double[] array = {};
+ assertEquals("{}", ObjectUtils.nullSafeToString(array));
+ }
+
+ @Test
+ public void testNullSafeToStringWithDoubleArrayEqualToNull() {
+ assertEquals("null", ObjectUtils.nullSafeToString((double[]) null));
+ }
+
+ @Test
+ public void testNullSafeToStringWithFloatArray() {
+ float[] array = {8.6f, 43.8f};
+ assertEquals("{8.6, 43.8}", ObjectUtils.nullSafeToString(array));
+ }
+
+ @Test
+ public void testNullSafeToStringWithFloatArrayBeingEmpty() {
+ float[] array = {};
+ assertEquals("{}", ObjectUtils.nullSafeToString(array));
+ }
+
+ @Test
+ public void testNullSafeToStringWithFloatArrayEqualToNull() {
+ assertEquals("null", ObjectUtils.nullSafeToString((float[]) null));
+ }
+
+ @Test
+ public void testNullSafeToStringWithIntArray() {
+ int[] array = {9, 64};
+ assertEquals("{9, 64}", ObjectUtils.nullSafeToString(array));
+ }
+
+ @Test
+ public void testNullSafeToStringWithIntArrayBeingEmpty() {
+ int[] array = {};
+ assertEquals("{}", ObjectUtils.nullSafeToString(array));
+ }
+
+ @Test
+ public void testNullSafeToStringWithIntArrayEqualToNull() {
+ assertEquals("null", ObjectUtils.nullSafeToString((int[]) null));
+ }
+
+ @Test
+ public void testNullSafeToStringWithLongArray() {
+ long[] array = {434l, 23423l};
+ assertEquals("{434, 23423}", ObjectUtils.nullSafeToString(array));
+ }
+
+ @Test
+ public void testNullSafeToStringWithLongArrayBeingEmpty() {
+ long[] array = {};
+ assertEquals("{}", ObjectUtils.nullSafeToString(array));
+ }
+
+ @Test
+ public void testNullSafeToStringWithLongArrayEqualToNull() {
+ assertEquals("null", ObjectUtils.nullSafeToString((long[]) null));
+ }
+
+ @Test
+ public void testNullSafeToStringWithPlainOldString() {
+ assertEquals("I shoh love tha taste of mangoes", ObjectUtils.nullSafeToString("I shoh love tha taste of mangoes"));
+ }
+
+ @Test
+ public void testNullSafeToStringWithObjectArray() {
+ Object[] array = {"Han", new Long(43)};
+ assertEquals("{Han, 43}", ObjectUtils.nullSafeToString(array));
+ }
+
+ @Test
+ public void testNullSafeToStringWithObjectArrayBeingEmpty() {
+ Object[] array = {};
+ assertEquals("{}", ObjectUtils.nullSafeToString(array));
+ }
+
+ @Test
+ public void testNullSafeToStringWithObjectArrayEqualToNull() {
+ assertEquals("null", ObjectUtils.nullSafeToString((Object[]) null));
+ }
+
+ @Test
+ public void testNullSafeToStringWithShortArray() {
+ short[] array = {7, 9};
+ assertEquals("{7, 9}", ObjectUtils.nullSafeToString(array));
+ }
+
+ @Test
+ public void testNullSafeToStringWithShortArrayBeingEmpty() {
+ short[] array = {};
+ assertEquals("{}", ObjectUtils.nullSafeToString(array));
+ }
+
+ @Test
+ public void testNullSafeToStringWithShortArrayEqualToNull() {
+ assertEquals("null", ObjectUtils.nullSafeToString((short[]) null));
+ }
+
+ @Test
+ public void testNullSafeToStringWithStringArray() {
+ String[] array = {"Luke", "Anakin"};
+ assertEquals("{Luke, Anakin}", ObjectUtils.nullSafeToString(array));
+ }
+
+ @Test
+ public void testNullSafeToStringWithStringArrayBeingEmpty() {
+ String[] array = {};
+ assertEquals("{}", ObjectUtils.nullSafeToString(array));
+ }
+
+ @Test
+ public void testNullSafeToStringWithStringArrayEqualToNull() {
+ assertEquals("null", ObjectUtils.nullSafeToString((String[]) null));
+ }
+
+ @Test
+ public void testContainsConstant() {
+ assertThat(ObjectUtils.containsConstant(Tropes.values(), "FOO"), is(true));
+ assertThat(ObjectUtils.containsConstant(Tropes.values(), "foo"), is(true));
+ assertThat(ObjectUtils.containsConstant(Tropes.values(), "BaR"), is(true));
+ assertThat(ObjectUtils.containsConstant(Tropes.values(), "bar"), is(true));
+ assertThat(ObjectUtils.containsConstant(Tropes.values(), "BAZ"), is(true));
+ assertThat(ObjectUtils.containsConstant(Tropes.values(), "baz"), is(true));
+
+ assertThat(ObjectUtils.containsConstant(Tropes.values(), "BOGUS"), is(false));
+
+ assertThat(ObjectUtils.containsConstant(Tropes.values(), "FOO", true), is(true));
+ assertThat(ObjectUtils.containsConstant(Tropes.values(), "foo", true), is(false));
+ }
+
+ @Test
+ public void testCaseInsensitiveValueOf() {
+ assertThat(ObjectUtils.caseInsensitiveValueOf(Tropes.values(), "foo"), is(Tropes.FOO));
+ assertThat(ObjectUtils.caseInsensitiveValueOf(Tropes.values(), "BAR"), is(Tropes.BAR));
+ try {
+ ObjectUtils.caseInsensitiveValueOf(Tropes.values(), "bogus");
+ fail("expected IllegalArgumentException");
+ }
+ catch (IllegalArgumentException ex) {
+ assertThat(ex.getMessage(),
+ is("constant [bogus] does not exist in enum type " +
+ "org.springframework.util.ObjectUtilsTests$Tropes"));
+ }
+ }
+
+ private void assertEqualHashCodes(int expected, Object array) {
+ int actual = ObjectUtils.nullSafeHashCode(array);
+ assertEquals(expected, actual);
+ assertTrue(array.hashCode() != actual);
+ }
+
+
+ enum Tropes { FOO, BAR, baz }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/PatternMatchUtilsTests.java b/spring-core/src/test/java/org/springframework/util/PatternMatchUtilsTests.java
new file mode 100644
index 00000000..8128cee6
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/PatternMatchUtilsTests.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Juergen Hoeller
+ * @author Johan Gorter
+ */
+public class PatternMatchUtilsTests extends TestCase {
+
+ public void testTrivial() {
+ assertEquals(false, PatternMatchUtils.simpleMatch((String) null, ""));
+ assertEquals(false, PatternMatchUtils.simpleMatch("1", null));
+ doTest("*", "123", true);
+ doTest("123", "123", true);
+ }
+
+ public void testStartsWith() {
+ doTest("get*", "getMe", true);
+ doTest("get*", "setMe", false);
+ }
+
+ public void testEndsWith() {
+ doTest("*Test", "getMeTest", true);
+ doTest("*Test", "setMe", false);
+ }
+
+ public void testBetween() {
+ doTest("*stuff*", "getMeTest", false);
+ doTest("*stuff*", "getstuffTest", true);
+ doTest("*stuff*", "stuffTest", true);
+ doTest("*stuff*", "getstuff", true);
+ doTest("*stuff*", "stuff", true);
+ }
+
+ public void testStartsEnds() {
+ doTest("on*Event", "onMyEvent", true);
+ doTest("on*Event", "onEvent", true);
+ doTest("3*3", "3", false);
+ doTest("3*3", "33", true);
+ }
+
+ public void testStartsEndsBetween() {
+ doTest("12*45*78", "12345678", true);
+ doTest("12*45*78", "123456789", false);
+ doTest("12*45*78", "012345678", false);
+ doTest("12*45*78", "124578", true);
+ doTest("12*45*78", "1245457878", true);
+ doTest("3*3*3", "33", false);
+ doTest("3*3*3", "333", true);
+ }
+
+ public void testRidiculous() {
+ doTest("*1*2*3*", "0011002001010030020201030", true);
+ doTest("1*2*3*4", "10300204", false);
+ doTest("1*2*3*3", "10300203", false);
+ doTest("*1*2*3*", "123", true);
+ doTest("*1*2*3*", "132", false);
+ }
+
+ private void doTest(String pattern, String str, boolean shouldMatch) {
+ assertEquals(shouldMatch, PatternMatchUtils.simpleMatch(pattern, str));
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/PropertiesPersisterTests.java b/spring-core/src/test/java/org/springframework/util/PropertiesPersisterTests.java
new file mode 100644
index 00000000..0fcc4238
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/PropertiesPersisterTests.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.Properties;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Juergen Hoeller
+ * @since 11.01.2005
+ */
+public class PropertiesPersisterTests extends TestCase {
+
+ public void testPropertiesPersister() throws IOException {
+ String propString = "code1=message1\ncode2:message2";
+ Properties props = loadProperties(propString, false);
+ String propCopy = storeProperties(props, null, false);
+ loadProperties(propCopy, false);
+ }
+
+ public void testPropertiesPersisterWithWhitespace() throws IOException {
+ String propString = " code1\t= \tmessage1\n code2 \t :\t mess\\\n \t age2";
+ Properties props = loadProperties(propString, false);
+ String propCopy = storeProperties(props, null, false);
+ loadProperties(propCopy, false);
+ }
+
+ public void testPropertiesPersisterWithHeader() throws IOException {
+ String propString = "code1=message1\ncode2:message2";
+ Properties props = loadProperties(propString, false);
+ String propCopy = storeProperties(props, "myHeader", false);
+ loadProperties(propCopy, false);
+ }
+
+ public void testPropertiesPersisterWithEmptyValue() throws IOException {
+ String propString = "code1=message1\ncode2:message2\ncode3=";
+ Properties props = loadProperties(propString, false);
+ String propCopy = storeProperties(props, null, false);
+ loadProperties(propCopy, false);
+ }
+
+ public void testPropertiesPersisterWithReader() throws IOException {
+ String propString = "code1=message1\ncode2:message2";
+ Properties props = loadProperties(propString, true);
+ String propCopy = storeProperties(props, null, true);
+ loadProperties(propCopy, false);
+ }
+
+ public void testPropertiesPersisterWithReaderAndWhitespace() throws IOException {
+ String propString = " code1\t= \tmessage1\n code2 \t :\t mess\\\n \t age2";
+ Properties props = loadProperties(propString, true);
+ String propCopy = storeProperties(props, null, true);
+ loadProperties(propCopy, false);
+ }
+
+ public void testPropertiesPersisterWithReaderAndHeader() throws IOException {
+ String propString = "code1\t=\tmessage1\n code2 \t : \t message2";
+ Properties props = loadProperties(propString, true);
+ String propCopy = storeProperties(props, "myHeader", true);
+ loadProperties(propCopy, false);
+ }
+
+ public void testPropertiesPersisterWithReaderAndEmptyValue() throws IOException {
+ String propString = "code1=message1\ncode2:message2\ncode3=";
+ Properties props = loadProperties(propString, true);
+ String propCopy = storeProperties(props, null, true);
+ loadProperties(propCopy, false);
+ }
+
+ private Properties loadProperties(String propString, boolean useReader) throws IOException {
+ DefaultPropertiesPersister persister = new DefaultPropertiesPersister();
+ Properties props = new Properties();
+ if (useReader) {
+ persister.load(props, new StringReader(propString));
+ }
+ else {
+ persister.load(props, new ByteArrayInputStream(propString.getBytes()));
+ }
+ assertEquals("message1", props.getProperty("code1"));
+ assertEquals("message2", props.getProperty("code2"));
+ return props;
+ }
+
+ private String storeProperties(Properties props, String header, boolean useWriter) throws IOException {
+ DefaultPropertiesPersister persister = new DefaultPropertiesPersister();
+ String propCopy = null;
+ if (useWriter) {
+ StringWriter propWriter = new StringWriter();
+ persister.store(props, propWriter, header);
+ propCopy = propWriter.toString();
+ }
+ else {
+ ByteArrayOutputStream propOut = new ByteArrayOutputStream();
+ persister.store(props, propOut, header);
+ propCopy = new String(propOut.toByteArray());
+ }
+ if (header != null) {
+ assertTrue(propCopy.indexOf(header) != -1);
+ }
+ assertTrue(propCopy.indexOf("\ncode1=message1") != -1);
+ assertTrue(propCopy.indexOf("\ncode2=message2") != -1);
+ return propCopy;
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/PropertyPlaceholderHelperTests.java b/spring-core/src/test/java/org/springframework/util/PropertyPlaceholderHelperTests.java
new file mode 100644
index 00000000..20bb969c
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/PropertyPlaceholderHelperTests.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util;
+
+import java.util.Properties;
+
+import static org.junit.Assert.*;
+import org.junit.Test;
+
+/**
+ * @author Rob Harrop
+ */
+public class PropertyPlaceholderHelperTests {
+
+ private final PropertyPlaceholderHelper helper = new PropertyPlaceholderHelper("${", "}");
+
+ @Test
+ public void testWithProperties() {
+ String text = "foo=${foo}";
+ Properties props = new Properties();
+ props.setProperty("foo", "bar");
+
+ assertEquals("foo=bar", this.helper.replacePlaceholders(text, props));
+ }
+
+ @Test
+ public void testWithMultipleProperties() {
+ String text = "foo=${foo},bar=${bar}";
+ Properties props = new Properties();
+ props.setProperty("foo", "bar");
+ props.setProperty("bar", "baz");
+
+ assertEquals("foo=bar,bar=baz", this.helper.replacePlaceholders(text, props));
+ }
+
+ @Test
+ public void testRecurseInProperty() {
+ String text = "foo=${bar}";
+ Properties props = new Properties();
+ props.setProperty("bar", "${baz}");
+ props.setProperty("baz", "bar");
+
+ assertEquals("foo=bar", this.helper.replacePlaceholders(text, props));
+ }
+
+ @Test
+ public void testRecurseInPlaceholder() {
+ String text = "foo=${b${inner}}";
+ Properties props = new Properties();
+ props.setProperty("bar", "bar");
+ props.setProperty("inner", "ar");
+
+ assertEquals("foo=bar", this.helper.replacePlaceholders(text, props));
+
+ text = "${top}";
+ props = new Properties();
+ props.setProperty("top", "${child}+${child}");
+ props.setProperty("child", "${${differentiator}.grandchild}");
+ props.setProperty("differentiator", "first");
+ props.setProperty("first.grandchild", "actualValue");
+
+ assertEquals("actualValue+actualValue", this.helper.replacePlaceholders(text, props));
+ }
+
+ @Test
+ public void testWithResolver() {
+ String text = "foo=${foo}";
+
+ assertEquals("foo=bar",
+ this.helper.replacePlaceholders(text, new PropertyPlaceholderHelper.PlaceholderResolver() {
+ @Override
+ public String resolvePlaceholder(String placeholderName) {
+ if ("foo".equals(placeholderName)) {
+ return "bar";
+ }
+ else {
+ return null;
+ }
+ }
+ }));
+ }
+
+ @Test
+ public void testUnresolvedPlaceholderIsIgnored() {
+ String text = "foo=${foo},bar=${bar}";
+ Properties props = new Properties();
+ props.setProperty("foo", "bar");
+
+ assertEquals("foo=bar,bar=${bar}", this.helper.replacePlaceholders(text, props));
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void testUnresolvedPlaceholderAsError() {
+ String text = "foo=${foo},bar=${bar}";
+ Properties props = new Properties();
+ props.setProperty("foo", "bar");
+
+ PropertyPlaceholderHelper helper = new PropertyPlaceholderHelper("${", "}", null, false);
+ assertEquals("foo=bar,bar=${bar}", helper.replacePlaceholders(text, props));
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/ReflectionUtilsTests.java b/spring-core/src/test/java/org/springframework/util/ReflectionUtilsTests.java
new file mode 100644
index 00000000..7d555076
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/ReflectionUtilsTests.java
@@ -0,0 +1,457 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.rmi.ConnectException;
+import java.rmi.RemoteException;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.hamcrest.Matchers;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+import org.springframework.tests.Assume;
+import org.springframework.tests.TestGroup;
+import org.springframework.tests.sample.objects.TestObject;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.*;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ * @author Sam Brannen
+ * @author Arjen Poutsma
+ */
+public class ReflectionUtilsTests {
+
+ @Test
+ public void findField() {
+ Field field = ReflectionUtils.findField(TestObjectSubclassWithPublicField.class, "publicField", String.class);
+ assertNotNull(field);
+ assertEquals("publicField", field.getName());
+ assertEquals(String.class, field.getType());
+ assertTrue("Field should be public.", Modifier.isPublic(field.getModifiers()));
+
+ field = ReflectionUtils.findField(TestObjectSubclassWithNewField.class, "prot", String.class);
+ assertNotNull(field);
+ assertEquals("prot", field.getName());
+ assertEquals(String.class, field.getType());
+ assertTrue("Field should be protected.", Modifier.isProtected(field.getModifiers()));
+
+ field = ReflectionUtils.findField(TestObjectSubclassWithNewField.class, "name", String.class);
+ assertNotNull(field);
+ assertEquals("name", field.getName());
+ assertEquals(String.class, field.getType());
+ assertTrue("Field should be private.", Modifier.isPrivate(field.getModifiers()));
+ }
+
+ @Test
+ public void setField() {
+ final TestObjectSubclassWithNewField testBean = new TestObjectSubclassWithNewField();
+ final Field field = ReflectionUtils.findField(TestObjectSubclassWithNewField.class, "name", String.class);
+
+ ReflectionUtils.makeAccessible(field);
+
+ ReflectionUtils.setField(field, testBean, "FooBar");
+ assertNotNull(testBean.getName());
+ assertEquals("FooBar", testBean.getName());
+
+ ReflectionUtils.setField(field, testBean, null);
+ assertNull(testBean.getName());
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void setFieldIllegal() {
+ final TestObjectSubclassWithNewField testBean = new TestObjectSubclassWithNewField();
+ final Field field = ReflectionUtils.findField(TestObjectSubclassWithNewField.class, "name", String.class);
+ ReflectionUtils.setField(field, testBean, "FooBar");
+ }
+
+ @Test
+ public void invokeMethod() throws Exception {
+ String rob = "Rob Harrop";
+
+ TestObject bean = new TestObject();
+ bean.setName(rob);
+
+ Method getName = TestObject.class.getMethod("getName", (Class[]) null);
+ Method setName = TestObject.class.getMethod("setName", new Class[] { String.class });
+
+ Object name = ReflectionUtils.invokeMethod(getName, bean);
+ assertEquals("Incorrect name returned", rob, name);
+
+ String juergen = "Juergen Hoeller";
+ ReflectionUtils.invokeMethod(setName, bean, new Object[] { juergen });
+ assertEquals("Incorrect name set", juergen, bean.getName());
+ }
+
+ @Test
+ public void declaresException() throws Exception {
+ Method remoteExMethod = A.class.getDeclaredMethod("foo", new Class[] { Integer.class });
+ assertTrue(ReflectionUtils.declaresException(remoteExMethod, RemoteException.class));
+ assertTrue(ReflectionUtils.declaresException(remoteExMethod, ConnectException.class));
+ assertFalse(ReflectionUtils.declaresException(remoteExMethod, NoSuchMethodException.class));
+ assertFalse(ReflectionUtils.declaresException(remoteExMethod, Exception.class));
+
+ Method illegalExMethod = B.class.getDeclaredMethod("bar", new Class[] { String.class });
+ assertTrue(ReflectionUtils.declaresException(illegalExMethod, IllegalArgumentException.class));
+ assertTrue(ReflectionUtils.declaresException(illegalExMethod, NumberFormatException.class));
+ assertFalse(ReflectionUtils.declaresException(illegalExMethod, IllegalStateException.class));
+ assertFalse(ReflectionUtils.declaresException(illegalExMethod, Exception.class));
+ }
+
+ @Test
+ public void copySrcToDestinationOfIncorrectClass() {
+ TestObject src = new TestObject();
+ String dest = new String();
+ try {
+ ReflectionUtils.shallowCopyFieldState(src, dest);
+ fail();
+ } catch (IllegalArgumentException ex) {
+ // Ok
+ }
+ }
+
+ @Test
+ public void rejectsNullSrc() {
+ TestObject src = null;
+ String dest = new String();
+ try {
+ ReflectionUtils.shallowCopyFieldState(src, dest);
+ fail();
+ } catch (IllegalArgumentException ex) {
+ // Ok
+ }
+ }
+
+ @Test
+ public void rejectsNullDest() {
+ TestObject src = new TestObject();
+ String dest = null;
+ try {
+ ReflectionUtils.shallowCopyFieldState(src, dest);
+ fail();
+ } catch (IllegalArgumentException ex) {
+ // Ok
+ }
+ }
+
+ @Test
+ public void validCopy() {
+ TestObject src = new TestObject();
+ TestObject dest = new TestObject();
+ testValidCopy(src, dest);
+ }
+
+ @Test
+ public void validCopyOnSubTypeWithNewField() {
+ TestObjectSubclassWithNewField src = new TestObjectSubclassWithNewField();
+ TestObjectSubclassWithNewField dest = new TestObjectSubclassWithNewField();
+ src.magic = 11;
+
+ // Will check inherited fields are copied
+ testValidCopy(src, dest);
+
+ // Check subclass fields were copied
+ assertEquals(src.magic, dest.magic);
+ assertEquals(src.prot, dest.prot);
+ }
+
+ @Test
+ public void validCopyToSubType() {
+ TestObject src = new TestObject();
+ TestObjectSubclassWithNewField dest = new TestObjectSubclassWithNewField();
+ dest.magic = 11;
+ testValidCopy(src, dest);
+ // Should have left this one alone
+ assertEquals(11, dest.magic);
+ }
+
+ @Test
+ public void validCopyToSubTypeWithFinalField() {
+ TestObjectSubclassWithFinalField src = new TestObjectSubclassWithFinalField();
+ TestObjectSubclassWithFinalField dest = new TestObjectSubclassWithFinalField();
+ // Check that this doesn't fail due to attempt to assign final
+ testValidCopy(src, dest);
+ }
+
+ private void testValidCopy(TestObject src, TestObject dest) {
+ src.setName("freddie");
+ src.setAge(15);
+ src.setSpouse(new TestObject());
+ assertFalse(src.getAge() == dest.getAge());
+
+ ReflectionUtils.shallowCopyFieldState(src, dest);
+ assertEquals(src.getAge(), dest.getAge());
+ assertEquals(src.getSpouse(), dest.getSpouse());
+ }
+
+ @Test
+ public void doWithProtectedMethods() {
+ ListSavingMethodCallback mc = new ListSavingMethodCallback();
+ ReflectionUtils.doWithMethods(TestObject.class, mc, new ReflectionUtils.MethodFilter() {
+ @Override
+ public boolean matches(Method m) {
+ return Modifier.isProtected(m.getModifiers());
+ }
+ });
+ assertFalse(mc.getMethodNames().isEmpty());
+ assertTrue("Must find protected method on Object", mc.getMethodNames().contains("clone"));
+ assertTrue("Must find protected method on Object", mc.getMethodNames().contains("finalize"));
+ assertFalse("Public, not protected", mc.getMethodNames().contains("hashCode"));
+ assertFalse("Public, not protected", mc.getMethodNames().contains("absquatulate"));
+ }
+
+ @Test
+ public void duplicatesFound() {
+ ListSavingMethodCallback mc = new ListSavingMethodCallback();
+ ReflectionUtils.doWithMethods(TestObjectSubclass.class, mc);
+ int absquatulateCount = 0;
+ for (String name : mc.getMethodNames()) {
+ if (name.equals("absquatulate")) {
+ ++absquatulateCount;
+ }
+ }
+ assertEquals("Found 2 absquatulates", 2, absquatulateCount);
+ }
+
+ @Test
+ public void findMethod() throws Exception {
+ assertNotNull(ReflectionUtils.findMethod(B.class, "bar", String.class));
+ assertNotNull(ReflectionUtils.findMethod(B.class, "foo", Integer.class));
+ assertNotNull(ReflectionUtils.findMethod(B.class, "getClass"));
+ }
+
+ @Ignore("[SPR-8644] findMethod() does not currently support var-args")
+ @Test
+ public void findMethodWithVarArgs() throws Exception {
+ assertNotNull(ReflectionUtils.findMethod(B.class, "add", int.class, int.class, int.class));
+ }
+
+ @Test
+ public void isCglibRenamedMethod() throws SecurityException, NoSuchMethodException {
+ @SuppressWarnings("unused")
+ class C {
+ public void CGLIB$m1$123() {
+ }
+
+ public void CGLIB$m1$0() {
+ }
+
+ public void CGLIB$$0() {
+ }
+
+ public void CGLIB$m1$() {
+ }
+
+ public void CGLIB$m1() {
+ }
+
+ public void m1() {
+ }
+
+ public void m1$() {
+ }
+
+ public void m1$1() {
+ }
+ }
+ assertTrue(ReflectionUtils.isCglibRenamedMethod(C.class.getMethod("CGLIB$m1$123")));
+ assertTrue(ReflectionUtils.isCglibRenamedMethod(C.class.getMethod("CGLIB$m1$0")));
+ assertFalse(ReflectionUtils.isCglibRenamedMethod(C.class.getMethod("CGLIB$$0")));
+ assertFalse(ReflectionUtils.isCglibRenamedMethod(C.class.getMethod("CGLIB$m1$")));
+ assertFalse(ReflectionUtils.isCglibRenamedMethod(C.class.getMethod("CGLIB$m1")));
+ assertFalse(ReflectionUtils.isCglibRenamedMethod(C.class.getMethod("m1")));
+ assertFalse(ReflectionUtils.isCglibRenamedMethod(C.class.getMethod("m1$")));
+ assertFalse(ReflectionUtils.isCglibRenamedMethod(C.class.getMethod("m1$1")));
+ }
+
+ @Test
+ public void getAllDeclaredMethods() throws Exception {
+ class Foo {
+ @Override
+ public String toString() {
+ return super.toString();
+ }
+ }
+ int toStringMethodCount = 0;
+ for (Method method : ReflectionUtils.getAllDeclaredMethods(Foo.class)) {
+ if (method.getName().equals("toString")) {
+ toStringMethodCount++;
+ }
+ }
+ assertThat(toStringMethodCount, is(2));
+ }
+
+ @Test
+ public void getUniqueDeclaredMethods() throws Exception {
+ class Foo {
+ @Override
+ public String toString() {
+ return super.toString();
+ }
+ }
+ int toStringMethodCount = 0;
+ for (Method method : ReflectionUtils.getUniqueDeclaredMethods(Foo.class)) {
+ if (method.getName().equals("toString")) {
+ toStringMethodCount++;
+ }
+ }
+ assertThat(toStringMethodCount, is(1));
+ }
+
+ @Test
+ public void getUniqueDeclaredMethods_withCovariantReturnType() throws Exception {
+ class Parent {
+ @SuppressWarnings("unused")
+ public Number m1() {
+ return new Integer(42);
+ }
+ }
+ class Leaf extends Parent {
+ @Override
+ public Integer m1() {
+ return new Integer(42);
+ }
+ }
+ int m1MethodCount = 0;
+ Method[] methods = ReflectionUtils.getUniqueDeclaredMethods(Leaf.class);
+ for (Method method : methods) {
+ if (method.getName().equals("m1")) {
+ m1MethodCount++;
+ }
+ }
+ assertThat(m1MethodCount, is(1));
+ assertTrue(ObjectUtils.containsElement(methods, Leaf.class.getMethod("m1")));
+ assertFalse(ObjectUtils.containsElement(methods, Parent.class.getMethod("m1")));
+ }
+
+ @Test
+ public void getUniqueDeclaredMethods_isFastEnough() {
+ Assume.group(TestGroup.PERFORMANCE);
+
+ @SuppressWarnings("unused")
+ class C {
+ void m00() { } void m01() { } void m02() { } void m03() { } void m04() { }
+ void m05() { } void m06() { } void m07() { } void m08() { } void m09() { }
+ void m10() { } void m11() { } void m12() { } void m13() { } void m14() { }
+ void m15() { } void m16() { } void m17() { } void m18() { } void m19() { }
+ void m20() { } void m21() { } void m22() { } void m23() { } void m24() { }
+ void m25() { } void m26() { } void m27() { } void m28() { } void m29() { }
+ void m30() { } void m31() { } void m32() { } void m33() { } void m34() { }
+ void m35() { } void m36() { } void m37() { } void m38() { } void m39() { }
+ void m40() { } void m41() { } void m42() { } void m43() { } void m44() { }
+ void m45() { } void m46() { } void m47() { } void m48() { } void m49() { }
+ void m50() { } void m51() { } void m52() { } void m53() { } void m54() { }
+ void m55() { } void m56() { } void m57() { } void m58() { } void m59() { }
+ void m60() { } void m61() { } void m62() { } void m63() { } void m64() { }
+ void m65() { } void m66() { } void m67() { } void m68() { } void m69() { }
+ void m70() { } void m71() { } void m72() { } void m73() { } void m74() { }
+ void m75() { } void m76() { } void m77() { } void m78() { } void m79() { }
+ void m80() { } void m81() { } void m82() { } void m83() { } void m84() { }
+ void m85() { } void m86() { } void m87() { } void m88() { } void m89() { }
+ void m90() { } void m91() { } void m92() { } void m93() { } void m94() { }
+ void m95() { } void m96() { } void m97() { } void m98() { } void m99() { }
+ }
+
+ StopWatch sw = new StopWatch();
+ sw.start();
+ Method[] methods = ReflectionUtils.getUniqueDeclaredMethods(C.class);
+ sw.stop();
+ long totalMs = sw.getTotalTimeMillis();
+ assertThat(methods.length, Matchers.greaterThan(100));
+ assertThat(totalMs, Matchers.lessThan(10L));
+ }
+
+ private static class ListSavingMethodCallback implements ReflectionUtils.MethodCallback {
+
+ private List<String> methodNames = new LinkedList<String>();
+
+ private List<Method> methods = new LinkedList<Method>();
+
+ @Override
+ public void doWith(Method m) throws IllegalArgumentException, IllegalAccessException {
+ this.methodNames.add(m.getName());
+ this.methods.add(m);
+ }
+
+ public List<String> getMethodNames() {
+ return this.methodNames;
+ }
+
+ @SuppressWarnings("unused")
+ public List<Method> getMethods() {
+ return this.methods;
+ }
+ }
+
+ private static class TestObjectSubclass extends TestObject {
+
+ @Override
+ public void absquatulate() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ private static class TestObjectSubclassWithPublicField extends TestObject {
+
+ @SuppressWarnings("unused")
+ public String publicField = "foo";
+ }
+
+ private static class TestObjectSubclassWithNewField extends TestObject {
+
+ private int magic;
+
+ protected String prot = "foo";
+ }
+
+ private static class TestObjectSubclassWithFinalField extends TestObject {
+
+ @SuppressWarnings("unused")
+ private final String foo = "will break naive copy that doesn't exclude statics";
+ }
+
+ private static class A {
+
+ @SuppressWarnings("unused")
+ private void foo(Integer i) throws RemoteException {
+ }
+ }
+
+ @SuppressWarnings("unused")
+ private static class B extends A {
+
+ void bar(String s) throws IllegalArgumentException {
+ }
+
+ int add(int... args) {
+ int sum = 0;
+ for (int i = 0; i < args.length; i++) {
+ sum += args[i];
+ }
+ return sum;
+ }
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/ResourceUtilsTests.java b/spring-core/src/test/java/org/springframework/util/ResourceUtilsTests.java
new file mode 100644
index 00000000..7129e8d2
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/ResourceUtilsTests.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util;
+
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class ResourceUtilsTests extends TestCase {
+
+ public void testIsJarURL() throws Exception {
+ assertTrue(ResourceUtils.isJarURL(new URL("jar:file:myjar.jar!/mypath")));
+ assertTrue(ResourceUtils.isJarURL(new URL(null, "zip:file:myjar.jar!/mypath", new DummyURLStreamHandler())));
+ assertTrue(ResourceUtils.isJarURL(new URL(null, "wsjar:file:myjar.jar!/mypath", new DummyURLStreamHandler())));
+ assertFalse(ResourceUtils.isJarURL(new URL("file:myjar.jar")));
+ assertFalse(ResourceUtils.isJarURL(new URL("http:myserver/myjar.jar")));
+ }
+
+ public void testExtractJarFileURL() throws Exception {
+ assertEquals(new URL("file:myjar.jar"),
+ ResourceUtils.extractJarFileURL(new URL("jar:file:myjar.jar!/mypath")));
+ assertEquals(new URL("file:/myjar.jar"),
+ ResourceUtils.extractJarFileURL(new URL(null, "jar:myjar.jar!/mypath", new DummyURLStreamHandler())));
+ assertEquals(new URL("file:myjar.jar"),
+ ResourceUtils.extractJarFileURL(new URL(null, "zip:file:myjar.jar!/mypath", new DummyURLStreamHandler())));
+ assertEquals(new URL("file:myjar.jar"),
+ ResourceUtils.extractJarFileURL(new URL(null, "wsjar:file:myjar.jar!/mypath", new DummyURLStreamHandler())));
+ assertEquals(new URL("file:myjar.jar"),
+ ResourceUtils.extractJarFileURL(new URL("jar:file:myjar.jar!/")));
+ assertEquals(new URL("file:myjar.jar"),
+ ResourceUtils.extractJarFileURL(new URL(null, "zip:file:myjar.jar!/", new DummyURLStreamHandler())));
+ assertEquals(new URL("file:myjar.jar"),
+ ResourceUtils.extractJarFileURL(new URL(null, "wsjar:file:myjar.jar!/", new DummyURLStreamHandler())));
+ assertEquals(new URL("file:myjar.jar"),
+ ResourceUtils.extractJarFileURL(new URL("file:myjar.jar")));
+ }
+
+
+ /**
+ * Dummy URLStreamHandler that's just specified to suppress the standard
+ * {@code java.net.URL} URLStreamHandler lookup, to be able to
+ * use the standard URL class for parsing "rmi:..." URLs.
+ */
+ private static class DummyURLStreamHandler extends URLStreamHandler {
+
+ @Override
+ protected URLConnection openConnection(URL url) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/SerializationTestUtils.java b/spring-core/src/test/java/org/springframework/util/SerializationTestUtils.java
new file mode 100644
index 00000000..53e67f65
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/SerializationTestUtils.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.NotSerializableException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+
+/**
+ * Utilities for testing serializability of objects.
+ * Exposes static methods for use in other test cases.
+ *
+ * @author Rod Johnson
+ */
+public class SerializationTestUtils {
+
+ public static void testSerialization(Object o) throws IOException {
+ OutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ oos.writeObject(o);
+ }
+
+ public static boolean isSerializable(Object o) throws IOException {
+ try {
+ testSerialization(o);
+ return true;
+ }
+ catch (NotSerializableException ex) {
+ return false;
+ }
+ }
+
+ public static Object serializeAndDeserialize(Object o) throws IOException, ClassNotFoundException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ oos.writeObject(o);
+ oos.flush();
+ baos.flush();
+ byte[] bytes = baos.toByteArray();
+
+ ByteArrayInputStream is = new ByteArrayInputStream(bytes);
+ ObjectInputStream ois = new ObjectInputStream(is);
+ Object o2 = ois.readObject();
+ return o2;
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/SerializationUtilsTests.java b/spring-core/src/test/java/org/springframework/util/SerializationUtilsTests.java
new file mode 100644
index 00000000..5b9c43c1
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/SerializationUtilsTests.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.math.BigInteger;
+
+import org.junit.Test;
+
+import org.springframework.util.SerializationUtils;
+
+/**
+ * Test for static utility to help with serialization.
+ *
+ * @author Dave Syer
+ * @since 3.0.5
+ */
+public class SerializationUtilsTests {
+
+ private static BigInteger FOO = new BigInteger(
+ "-9702942423549012526722364838327831379660941553432801565505143675386108883970811292563757558516603356009681061" +
+ "5697574744209306031461371833798723505120163874786203211176873686513374052845353833564048");
+
+
+ @Test
+ public void serializeCycleSunnyDay() throws Exception {
+ assertEquals("foo", SerializationUtils.deserialize(SerializationUtils.serialize("foo")));
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void deserializeUndefined() throws Exception {
+ byte[] bytes = FOO.toByteArray();
+ Object foo = SerializationUtils.deserialize(bytes);
+ assertNotNull(foo);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void serializeNonSerializable() throws Exception {
+ SerializationUtils.serialize(new Object());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void deserializeNonSerializable() throws Exception {
+ SerializationUtils.deserialize("foo".getBytes());
+ }
+
+ @Test
+ public void serializeNull() throws Exception {
+ assertNull(SerializationUtils.serialize(null));
+ }
+
+ @Test
+ public void deserializeNull() throws Exception {
+ assertNull(SerializationUtils.deserialize(null));
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/StopWatchTests.java b/spring-core/src/test/java/org/springframework/util/StopWatchTests.java
new file mode 100644
index 00000000..4170f556
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/StopWatchTests.java
@@ -0,0 +1,144 @@
+
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Rod Johnson
+ */
+public class StopWatchTests extends TestCase {
+
+ /**
+ * Are timings off in JUnit?
+ */
+ public void testValidUsage() throws Exception {
+ StopWatch sw = new StopWatch();
+ long int1 = 166L;
+ long int2 = 45L;
+ String name1 = "Task 1";
+ String name2 = "Task 2";
+
+ assertFalse(sw.isRunning());
+ sw.start(name1);
+ Thread.sleep(int1);
+ assertTrue(sw.isRunning());
+ sw.stop();
+
+ // TODO are timings off in JUnit? Why do these assertions sometimes fail
+ // under both Ant and Eclipse?
+
+ //long fudgeFactor = 5L;
+ //assertTrue("Unexpected timing " + sw.getTotalTime(), sw.getTotalTime() >= int1);
+ //assertTrue("Unexpected timing " + sw.getTotalTime(), sw.getTotalTime() <= int1 + fudgeFactor);
+ sw.start(name2);
+ Thread.sleep(int2);
+ sw.stop();
+ //assertTrue("Unexpected timing " + sw.getTotalTime(), sw.getTotalTime() >= int1 + int2);
+ //assertTrue("Unexpected timing " + sw.getTotalTime(), sw.getTotalTime() <= int1 + int2 + fudgeFactor);
+
+ assertTrue(sw.getTaskCount() == 2);
+ String pp = sw.prettyPrint();
+ assertTrue(pp.indexOf(name1) != -1);
+ assertTrue(pp.indexOf(name2) != -1);
+
+ StopWatch.TaskInfo[] tasks = sw.getTaskInfo();
+ assertTrue(tasks.length == 2);
+ assertTrue(tasks[0].getTaskName().equals(name1));
+ assertTrue(tasks[1].getTaskName().equals(name2));
+ sw.toString();
+ }
+
+ public void testValidUsageNotKeepingTaskList() throws Exception {
+ StopWatch sw = new StopWatch();
+ sw.setKeepTaskList(false);
+ long int1 = 166L;
+ long int2 = 45L;
+ String name1 = "Task 1";
+ String name2 = "Task 2";
+
+ assertFalse(sw.isRunning());
+ sw.start(name1);
+ Thread.sleep(int1);
+ assertTrue(sw.isRunning());
+ sw.stop();
+
+ // TODO are timings off in JUnit? Why do these assertions sometimes fail
+ // under both Ant and Eclipse?
+
+ //long fudgeFactor = 5L;
+ //assertTrue("Unexpected timing " + sw.getTotalTime(), sw.getTotalTime() >= int1);
+ //assertTrue("Unexpected timing " + sw.getTotalTime(), sw.getTotalTime() <= int1 + fudgeFactor);
+ sw.start(name2);
+ Thread.sleep(int2);
+ sw.stop();
+ //assertTrue("Unexpected timing " + sw.getTotalTime(), sw.getTotalTime() >= int1 + int2);
+ //assertTrue("Unexpected timing " + sw.getTotalTime(), sw.getTotalTime() <= int1 + int2 + fudgeFactor);
+
+ assertTrue(sw.getTaskCount() == 2);
+ String pp = sw.prettyPrint();
+ assertTrue(pp.indexOf("kept") != -1);
+ sw.toString();
+
+ try {
+ sw.getTaskInfo();
+ fail();
+ }
+ catch (UnsupportedOperationException ex) {
+ // Ok
+ }
+ }
+
+ public void testFailureToStartBeforeGettingTimings() {
+ StopWatch sw = new StopWatch();
+ try {
+ sw.getLastTaskTimeMillis();
+ fail("Can't get last interval if no tests run");
+ }
+ catch (IllegalStateException ex) {
+ // Ok
+ }
+ }
+
+ public void testFailureToStartBeforeStop() {
+ StopWatch sw = new StopWatch();
+ try {
+ sw.stop();
+ fail("Can't stop without starting");
+ }
+ catch (IllegalStateException ex) {
+ // Ok
+ }
+ }
+
+ public void testRejectsStartTwice() {
+ StopWatch sw = new StopWatch();
+ try {
+ sw.start("");
+ sw.stop();
+ sw.start("");
+ assertTrue(sw.isRunning());
+ sw.start("");
+ fail("Can't start twice");
+ }
+ catch (IllegalStateException ex) {
+ // Ok
+ }
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/StreamUtilsTests.java b/spring-core/src/test/java/org/springframework/util/StreamUtilsTests.java
new file mode 100644
index 00000000..61810c98
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/StreamUtilsTests.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.charset.Charset;
+import java.util.Random;
+import java.util.UUID;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InOrder;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+import static org.mockito.BDDMockito.*;
+
+/**
+ * Tests for {@link StreamUtils}.
+ *
+ * @author Phillip Webb
+ */
+public class StreamUtilsTests {
+
+ private byte[] bytes = new byte[StreamUtils.BUFFER_SIZE + 10];
+
+ private String string = "";
+
+ @Before
+ public void setup() {
+ new Random().nextBytes(bytes);
+ while (string.length() < StreamUtils.BUFFER_SIZE + 10) {
+ string += UUID.randomUUID().toString();
+ }
+ }
+
+ @Test
+ public void copyToByteArray() throws Exception {
+ InputStream inputStream = spy(new ByteArrayInputStream(bytes));
+ byte[] actual = StreamUtils.copyToByteArray(inputStream);
+ assertThat(actual, equalTo(bytes));
+ verify(inputStream, never()).close();
+ }
+
+ @Test
+ public void copyToString() throws Exception {
+ Charset charset = Charset.defaultCharset();
+ InputStream inputStream = spy(new ByteArrayInputStream(string.getBytes(charset)));
+ String actual = StreamUtils.copyToString(inputStream, charset);
+ assertThat(actual, equalTo(string));
+ verify(inputStream, never()).close();
+ }
+
+ @Test
+ public void copyBytes() throws Exception {
+ ByteArrayOutputStream out = spy(new ByteArrayOutputStream());
+ StreamUtils.copy(bytes, out);
+ assertThat(out.toByteArray(), equalTo(bytes));
+ verify(out, never()).close();
+ }
+
+ @Test
+ public void copyString() throws Exception {
+ Charset charset = Charset.defaultCharset();
+ ByteArrayOutputStream out = spy(new ByteArrayOutputStream());
+ StreamUtils.copy(string, charset, out);
+ assertThat(out.toByteArray(), equalTo(string.getBytes(charset)));
+ verify(out, never()).close();
+ }
+
+ @Test
+ public void copyStream() throws Exception {
+ ByteArrayOutputStream out = spy(new ByteArrayOutputStream());
+ StreamUtils.copy(new ByteArrayInputStream(bytes), out);
+ assertThat(out.toByteArray(), equalTo(bytes));
+ verify(out, never()).close();
+ }
+
+ @Test
+ public void nonClosingInputStream() throws Exception {
+ InputStream source = mock(InputStream.class);
+ InputStream nonClosing = StreamUtils.nonClosing(source);
+ nonClosing.read();
+ nonClosing.read(bytes);
+ nonClosing.read(bytes, 1, 2);
+ nonClosing.close();
+ InOrder ordered = inOrder(source);
+ ordered.verify(source).read();
+ ordered.verify(source).read(bytes, 0, bytes.length);
+ ordered.verify(source).read(bytes, 1, 2);
+ ordered.verify(source, never()).close();
+ }
+
+ @Test
+ public void nonClosingOutputStream() throws Exception {
+ OutputStream source = mock(OutputStream.class);
+ OutputStream nonClosing = StreamUtils.nonClosing(source);
+ nonClosing.write(1);
+ nonClosing.write(bytes);
+ nonClosing.write(bytes, 1, 2);
+ nonClosing.close();
+ InOrder ordered = inOrder(source);
+ ordered.verify(source).write(1);
+ ordered.verify(source).write(bytes, 0, bytes.length);
+ ordered.verify(source).write(bytes, 1, 2);
+ ordered.verify(source, never()).close();
+ }
+}
diff --git a/spring-core/src/test/java/org/springframework/util/StringUtilsTests.java b/spring-core/src/test/java/org/springframework/util/StringUtilsTests.java
new file mode 100644
index 00000000..be40ac2d
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/StringUtilsTests.java
@@ -0,0 +1,703 @@
+/*
+ * Copyright 2002-2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util;
+
+import java.util.Arrays;
+import java.util.Locale;
+import java.util.Properties;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ * @author Rick Evans
+ */
+public class StringUtilsTests {
+
+ @Test
+ public void testHasTextBlank() throws Exception {
+ String blank = " ";
+ assertEquals(false, StringUtils.hasText(blank));
+ }
+
+ @Test
+ public void testHasTextNullEmpty() throws Exception {
+ assertEquals(false, StringUtils.hasText(null));
+ assertEquals(false, StringUtils.hasText(""));
+ }
+
+ @Test
+ public void testHasTextValid() throws Exception {
+ assertEquals(true, StringUtils.hasText("t"));
+ }
+
+ @Test
+ public void testContainsWhitespace() throws Exception {
+ assertFalse(StringUtils.containsWhitespace(null));
+ assertFalse(StringUtils.containsWhitespace(""));
+ assertFalse(StringUtils.containsWhitespace("a"));
+ assertFalse(StringUtils.containsWhitespace("abc"));
+ assertTrue(StringUtils.containsWhitespace(" "));
+ assertTrue(StringUtils.containsWhitespace(" a"));
+ assertTrue(StringUtils.containsWhitespace("abc "));
+ assertTrue(StringUtils.containsWhitespace("a b"));
+ assertTrue(StringUtils.containsWhitespace("a b"));
+ }
+
+ @Test
+ public void testTrimWhitespace() throws Exception {
+ assertEquals(null, StringUtils.trimWhitespace(null));
+ assertEquals("", StringUtils.trimWhitespace(""));
+ assertEquals("", StringUtils.trimWhitespace(" "));
+ assertEquals("", StringUtils.trimWhitespace("\t"));
+ assertEquals("a", StringUtils.trimWhitespace(" a"));
+ assertEquals("a", StringUtils.trimWhitespace("a "));
+ assertEquals("a", StringUtils.trimWhitespace(" a "));
+ assertEquals("a b", StringUtils.trimWhitespace(" a b "));
+ assertEquals("a b c", StringUtils.trimWhitespace(" a b c "));
+ }
+
+ @Test
+ public void testTrimAllWhitespace() throws Exception {
+ assertEquals("", StringUtils.trimAllWhitespace(""));
+ assertEquals("", StringUtils.trimAllWhitespace(" "));
+ assertEquals("", StringUtils.trimAllWhitespace("\t"));
+ assertEquals("a", StringUtils.trimAllWhitespace(" a"));
+ assertEquals("a", StringUtils.trimAllWhitespace("a "));
+ assertEquals("a", StringUtils.trimAllWhitespace(" a "));
+ assertEquals("ab", StringUtils.trimAllWhitespace(" a b "));
+ assertEquals("abc", StringUtils.trimAllWhitespace(" a b c "));
+ }
+
+ @Test
+ public void testTrimLeadingWhitespace() throws Exception {
+ assertEquals(null, StringUtils.trimLeadingWhitespace(null));
+ assertEquals("", StringUtils.trimLeadingWhitespace(""));
+ assertEquals("", StringUtils.trimLeadingWhitespace(" "));
+ assertEquals("", StringUtils.trimLeadingWhitespace("\t"));
+ assertEquals("a", StringUtils.trimLeadingWhitespace(" a"));
+ assertEquals("a ", StringUtils.trimLeadingWhitespace("a "));
+ assertEquals("a ", StringUtils.trimLeadingWhitespace(" a "));
+ assertEquals("a b ", StringUtils.trimLeadingWhitespace(" a b "));
+ assertEquals("a b c ", StringUtils.trimLeadingWhitespace(" a b c "));
+ }
+
+ @Test
+ public void testTrimTrailingWhitespace() throws Exception {
+ assertEquals(null, StringUtils.trimTrailingWhitespace(null));
+ assertEquals("", StringUtils.trimTrailingWhitespace(""));
+ assertEquals("", StringUtils.trimTrailingWhitespace(" "));
+ assertEquals("", StringUtils.trimTrailingWhitespace("\t"));
+ assertEquals("a", StringUtils.trimTrailingWhitespace("a "));
+ assertEquals(" a", StringUtils.trimTrailingWhitespace(" a"));
+ assertEquals(" a", StringUtils.trimTrailingWhitespace(" a "));
+ assertEquals(" a b", StringUtils.trimTrailingWhitespace(" a b "));
+ assertEquals(" a b c", StringUtils.trimTrailingWhitespace(" a b c "));
+ }
+
+ @Test
+ public void testTrimLeadingCharacter() throws Exception {
+ assertEquals(null, StringUtils.trimLeadingCharacter(null, ' '));
+ assertEquals("", StringUtils.trimLeadingCharacter("", ' '));
+ assertEquals("", StringUtils.trimLeadingCharacter(" ", ' '));
+ assertEquals("\t", StringUtils.trimLeadingCharacter("\t", ' '));
+ assertEquals("a", StringUtils.trimLeadingCharacter(" a", ' '));
+ assertEquals("a ", StringUtils.trimLeadingCharacter("a ", ' '));
+ assertEquals("a ", StringUtils.trimLeadingCharacter(" a ", ' '));
+ assertEquals("a b ", StringUtils.trimLeadingCharacter(" a b ", ' '));
+ assertEquals("a b c ", StringUtils.trimLeadingCharacter(" a b c ", ' '));
+ }
+
+ @Test
+ public void testTrimTrailingCharacter() throws Exception {
+ assertEquals(null, StringUtils.trimTrailingCharacter(null, ' '));
+ assertEquals("", StringUtils.trimTrailingCharacter("", ' '));
+ assertEquals("", StringUtils.trimTrailingCharacter(" ", ' '));
+ assertEquals("\t", StringUtils.trimTrailingCharacter("\t", ' '));
+ assertEquals("a", StringUtils.trimTrailingCharacter("a ", ' '));
+ assertEquals(" a", StringUtils.trimTrailingCharacter(" a", ' '));
+ assertEquals(" a", StringUtils.trimTrailingCharacter(" a ", ' '));
+ assertEquals(" a b", StringUtils.trimTrailingCharacter(" a b ", ' '));
+ assertEquals(" a b c", StringUtils.trimTrailingCharacter(" a b c ", ' '));
+ }
+
+ @Test
+ public void testCountOccurrencesOf() {
+ assertTrue("nullx2 = 0",
+ StringUtils.countOccurrencesOf(null, null) == 0);
+ assertTrue("null string = 0",
+ StringUtils.countOccurrencesOf("s", null) == 0);
+ assertTrue("null substring = 0",
+ StringUtils.countOccurrencesOf(null, "s") == 0);
+ String s = "erowoiueoiur";
+ assertTrue("not found = 0",
+ StringUtils.countOccurrencesOf(s, "WERWER") == 0);
+ assertTrue("not found char = 0",
+ StringUtils.countOccurrencesOf(s, "x") == 0);
+ assertTrue("not found ws = 0",
+ StringUtils.countOccurrencesOf(s, " ") == 0);
+ assertTrue("not found empty string = 0",
+ StringUtils.countOccurrencesOf(s, "") == 0);
+ assertTrue("found char=2", StringUtils.countOccurrencesOf(s, "e") == 2);
+ assertTrue("found substring=2",
+ StringUtils.countOccurrencesOf(s, "oi") == 2);
+ assertTrue("found substring=2",
+ StringUtils.countOccurrencesOf(s, "oiu") == 2);
+ assertTrue("found substring=3",
+ StringUtils.countOccurrencesOf(s, "oiur") == 1);
+ assertTrue("test last", StringUtils.countOccurrencesOf(s, "r") == 2);
+ }
+
+ @Test
+ public void testReplace() throws Exception {
+ String inString = "a6AazAaa77abaa";
+ String oldPattern = "aa";
+ String newPattern = "foo";
+
+ // Simple replace
+ String s = StringUtils.replace(inString, oldPattern, newPattern);
+ assertTrue("Replace 1 worked", s.equals("a6AazAfoo77abfoo"));
+
+ // Non match: no change
+ s = StringUtils.replace(inString, "qwoeiruqopwieurpoqwieur", newPattern);
+ assertTrue("Replace non matched is equal", s.equals(inString));
+
+ // Null new pattern: should ignore
+ s = StringUtils.replace(inString, oldPattern, null);
+ assertTrue("Replace non matched is equal", s.equals(inString));
+
+ // Null old pattern: should ignore
+ s = StringUtils.replace(inString, null, newPattern);
+ assertTrue("Replace non matched is equal", s.equals(inString));
+ }
+
+ @Test
+ public void testDelete() throws Exception {
+ String inString = "The quick brown fox jumped over the lazy dog";
+
+ String noThe = StringUtils.delete(inString, "the");
+ assertTrue("Result has no the [" + noThe + "]",
+ noThe.equals("The quick brown fox jumped over lazy dog"));
+
+ String nohe = StringUtils.delete(inString, "he");
+ assertTrue("Result has no he [" + nohe + "]",
+ nohe.equals("T quick brown fox jumped over t lazy dog"));
+
+ String nosp = StringUtils.delete(inString, " ");
+ assertTrue("Result has no spaces",
+ nosp.equals("Thequickbrownfoxjumpedoverthelazydog"));
+
+ String killEnd = StringUtils.delete(inString, "dog");
+ assertTrue("Result has no dog",
+ killEnd.equals("The quick brown fox jumped over the lazy "));
+
+ String mismatch = StringUtils.delete(inString, "dxxcxcxog");
+ assertTrue("Result is unchanged", mismatch.equals(inString));
+
+ String nochange = StringUtils.delete(inString, "");
+ assertTrue("Result is unchanged", nochange.equals(inString));
+ }
+
+ @Test
+ public void testDeleteAny() throws Exception {
+ String inString = "Able was I ere I saw Elba";
+
+ String res = StringUtils.deleteAny(inString, "I");
+ assertTrue("Result has no Is [" + res + "]", res.equals("Able was ere saw Elba"));
+
+ res = StringUtils.deleteAny(inString, "AeEba!");
+ assertTrue("Result has no Is [" + res + "]", res.equals("l ws I r I sw l"));
+
+ String mismatch = StringUtils.deleteAny(inString, "#@$#$^");
+ assertTrue("Result is unchanged", mismatch.equals(inString));
+
+ String whitespace = "This is\n\n\n \t a messagy string with whitespace\n";
+ assertTrue("Has CR", whitespace.contains("\n"));
+ assertTrue("Has tab", whitespace.contains("\t"));
+ assertTrue("Has sp", whitespace.contains(" "));
+ String cleaned = StringUtils.deleteAny(whitespace, "\n\t ");
+ assertTrue("Has no CR", !cleaned.contains("\n"));
+ assertTrue("Has no tab", !cleaned.contains("\t"));
+ assertTrue("Has no sp", !cleaned.contains(" "));
+ assertTrue("Still has chars", cleaned.length() > 10);
+ }
+
+
+ @Test
+ public void testQuote() {
+ assertEquals("'myString'", StringUtils.quote("myString"));
+ assertEquals("''", StringUtils.quote(""));
+ assertNull(StringUtils.quote(null));
+ }
+
+ @Test
+ public void testQuoteIfString() {
+ assertEquals("'myString'", StringUtils.quoteIfString("myString"));
+ assertEquals("''", StringUtils.quoteIfString(""));
+ assertEquals(new Integer(5), StringUtils.quoteIfString(5));
+ assertNull(StringUtils.quoteIfString(null));
+ }
+
+ @Test
+ public void testUnqualify() {
+ String qualified = "i.am.not.unqualified";
+ assertEquals("unqualified", StringUtils.unqualify(qualified));
+ }
+
+ @Test
+ public void testCapitalize() {
+ String capitalized = "i am not capitalized";
+ assertEquals("I am not capitalized", StringUtils.capitalize(capitalized));
+ }
+
+ @Test
+ public void testUncapitalize() {
+ String capitalized = "I am capitalized";
+ assertEquals("i am capitalized", StringUtils.uncapitalize(capitalized));
+ }
+
+ @Test
+ public void testGetFilename() {
+ assertEquals(null, StringUtils.getFilename(null));
+ assertEquals("", StringUtils.getFilename(""));
+ assertEquals("myfile", StringUtils.getFilename("myfile"));
+ assertEquals("myfile", StringUtils.getFilename("mypath/myfile"));
+ assertEquals("myfile.", StringUtils.getFilename("myfile."));
+ assertEquals("myfile.", StringUtils.getFilename("mypath/myfile."));
+ assertEquals("myfile.txt", StringUtils.getFilename("myfile.txt"));
+ assertEquals("myfile.txt", StringUtils.getFilename("mypath/myfile.txt"));
+ }
+
+ @Test
+ public void testGetFilenameExtension() {
+ assertEquals(null, StringUtils.getFilenameExtension(null));
+ assertEquals(null, StringUtils.getFilenameExtension(""));
+ assertEquals(null, StringUtils.getFilenameExtension("myfile"));
+ assertEquals(null, StringUtils.getFilenameExtension("myPath/myfile"));
+ assertEquals(null, StringUtils.getFilenameExtension("/home/user/.m2/settings/myfile"));
+ assertEquals("", StringUtils.getFilenameExtension("myfile."));
+ assertEquals("", StringUtils.getFilenameExtension("myPath/myfile."));
+ assertEquals("txt", StringUtils.getFilenameExtension("myfile.txt"));
+ assertEquals("txt", StringUtils.getFilenameExtension("mypath/myfile.txt"));
+ assertEquals("txt", StringUtils.getFilenameExtension("/home/user/.m2/settings/myfile.txt"));
+ }
+
+ @Test
+ public void testStripFilenameExtension() {
+ assertEquals(null, StringUtils.stripFilenameExtension(null));
+ assertEquals("", StringUtils.stripFilenameExtension(""));
+ assertEquals("myfile", StringUtils.stripFilenameExtension("myfile"));
+ assertEquals("myfile", StringUtils.stripFilenameExtension("myfile."));
+ assertEquals("myfile", StringUtils.stripFilenameExtension("myfile.txt"));
+ assertEquals("mypath/myfile", StringUtils.stripFilenameExtension("mypath/myfile"));
+ assertEquals("mypath/myfile", StringUtils.stripFilenameExtension("mypath/myfile."));
+ assertEquals("mypath/myfile", StringUtils.stripFilenameExtension("mypath/myfile.txt"));
+ assertEquals("/home/user/.m2/settings/myfile", StringUtils.stripFilenameExtension("/home/user/.m2/settings/myfile"));
+ assertEquals("/home/user/.m2/settings/myfile", StringUtils.stripFilenameExtension("/home/user/.m2/settings/myfile."));
+ assertEquals("/home/user/.m2/settings/myfile", StringUtils.stripFilenameExtension("/home/user/.m2/settings/myfile.txt"));
+ }
+
+ @Test
+ public void testCleanPath() {
+ assertEquals("mypath/myfile", StringUtils.cleanPath("mypath/myfile"));
+ assertEquals("mypath/myfile", StringUtils.cleanPath("mypath\\myfile"));
+ assertEquals("mypath/myfile", StringUtils.cleanPath("mypath/../mypath/myfile"));
+ assertEquals("mypath/myfile", StringUtils.cleanPath("mypath/myfile/../../mypath/myfile"));
+ assertEquals("../mypath/myfile", StringUtils.cleanPath("../mypath/myfile"));
+ assertEquals("../mypath/myfile", StringUtils.cleanPath("../mypath/../mypath/myfile"));
+ assertEquals("../mypath/myfile", StringUtils.cleanPath("mypath/../../mypath/myfile"));
+ assertEquals("/../mypath/myfile", StringUtils.cleanPath("/../mypath/myfile"));
+ assertEquals("/mypath/myfile", StringUtils.cleanPath("/a/:b/../../mypath/myfile"));
+ assertEquals("file:///c:/path/to/the%20file.txt", StringUtils.cleanPath("file:///c:/some/../path/to/the%20file.txt"));
+ }
+
+ @Test
+ public void testPathEquals() {
+ assertTrue("Must be true for the same strings",
+ StringUtils.pathEquals("/dummy1/dummy2/dummy3",
+ "/dummy1/dummy2/dummy3"));
+ assertTrue("Must be true for the same win strings",
+ StringUtils.pathEquals("C:\\dummy1\\dummy2\\dummy3",
+ "C:\\dummy1\\dummy2\\dummy3"));
+ assertTrue("Must be true for one top path on 1",
+ StringUtils.pathEquals("/dummy1/bin/../dummy2/dummy3",
+ "/dummy1/dummy2/dummy3"));
+ assertTrue("Must be true for one win top path on 2",
+ StringUtils.pathEquals("C:\\dummy1\\dummy2\\dummy3",
+ "C:\\dummy1\\bin\\..\\dummy2\\dummy3"));
+ assertTrue("Must be true for two top paths on 1",
+ StringUtils.pathEquals("/dummy1/bin/../dummy2/bin/../dummy3",
+ "/dummy1/dummy2/dummy3"));
+ assertTrue("Must be true for two win top paths on 2",
+ StringUtils.pathEquals("C:\\dummy1\\dummy2\\dummy3",
+ "C:\\dummy1\\bin\\..\\dummy2\\bin\\..\\dummy3"));
+ assertTrue("Must be true for double top paths on 1",
+ StringUtils.pathEquals("/dummy1/bin/tmp/../../dummy2/dummy3",
+ "/dummy1/dummy2/dummy3"));
+ assertTrue("Must be true for double top paths on 2 with similarity",
+ StringUtils.pathEquals("/dummy1/dummy2/dummy3",
+ "/dummy1/dum/dum/../../dummy2/dummy3"));
+ assertTrue("Must be true for current paths",
+ StringUtils.pathEquals("./dummy1/dummy2/dummy3",
+ "dummy1/dum/./dum/../../dummy2/dummy3"));
+ assertFalse("Must be false for relative/absolute paths",
+ StringUtils.pathEquals("./dummy1/dummy2/dummy3",
+ "/dummy1/dum/./dum/../../dummy2/dummy3"));
+ assertFalse("Must be false for different strings",
+ StringUtils.pathEquals("/dummy1/dummy2/dummy3",
+ "/dummy1/dummy4/dummy3"));
+ assertFalse("Must be false for one false path on 1",
+ StringUtils.pathEquals("/dummy1/bin/tmp/../dummy2/dummy3",
+ "/dummy1/dummy2/dummy3"));
+ assertFalse("Must be false for one false win top path on 2",
+ StringUtils.pathEquals("C:\\dummy1\\dummy2\\dummy3",
+ "C:\\dummy1\\bin\\tmp\\..\\dummy2\\dummy3"));
+ assertFalse("Must be false for top path on 1 + difference",
+ StringUtils.pathEquals("/dummy1/bin/../dummy2/dummy3",
+ "/dummy1/dummy2/dummy4"));
+ }
+
+ @Test
+ public void testConcatenateStringArrays() {
+ String[] input1 = new String[] {"myString2"};
+ String[] input2 = new String[] {"myString1", "myString2"};
+ String[] result = StringUtils.concatenateStringArrays(input1, input2);
+ assertEquals(3, result.length);
+ assertEquals("myString2", result[0]);
+ assertEquals("myString1", result[1]);
+ assertEquals("myString2", result[2]);
+
+ assertArrayEquals(input1, StringUtils.concatenateStringArrays(input1, null));
+ assertArrayEquals(input2, StringUtils.concatenateStringArrays(null, input2));
+ assertNull(StringUtils.concatenateStringArrays(null, null));
+ }
+
+ @Test
+ public void testMergeStringArrays() {
+ String[] input1 = new String[] {"myString2"};
+ String[] input2 = new String[] {"myString1", "myString2"};
+ String[] result = StringUtils.mergeStringArrays(input1, input2);
+ assertEquals(2, result.length);
+ assertEquals("myString2", result[0]);
+ assertEquals("myString1", result[1]);
+
+ assertArrayEquals(input1, StringUtils.mergeStringArrays(input1, null));
+ assertArrayEquals(input2, StringUtils.mergeStringArrays(null, input2));
+ assertNull(StringUtils.mergeStringArrays(null, null));
+ }
+
+ @Test
+ public void testSortStringArray() {
+ String[] input = new String[] {"myString2"};
+ input = StringUtils.addStringToArray(input, "myString1");
+ assertEquals("myString2", input[0]);
+ assertEquals("myString1", input[1]);
+
+ StringUtils.sortStringArray(input);
+ assertEquals("myString1", input[0]);
+ assertEquals("myString2", input[1]);
+ }
+
+ @Test
+ public void testRemoveDuplicateStrings() {
+ String[] input = new String[] {"myString2", "myString1", "myString2"};
+ input = StringUtils.removeDuplicateStrings(input);
+ assertEquals("myString1", input[0]);
+ assertEquals("myString2", input[1]);
+ }
+
+ @Test
+ public void testSplitArrayElementsIntoProperties() {
+ String[] input = new String[] {"key1=value1 ", "key2 =\"value2\""};
+ Properties result = StringUtils.splitArrayElementsIntoProperties(input, "=");
+ assertEquals("value1", result.getProperty("key1"));
+ assertEquals("\"value2\"", result.getProperty("key2"));
+ }
+
+ @Test
+ public void testSplitArrayElementsIntoPropertiesAndDeletedChars() {
+ String[] input = new String[] {"key1=value1 ", "key2 =\"value2\""};
+ Properties result = StringUtils.splitArrayElementsIntoProperties(input, "=", "\"");
+ assertEquals("value1", result.getProperty("key1"));
+ assertEquals("value2", result.getProperty("key2"));
+ }
+
+ @Test
+ public void testTokenizeToStringArray() {
+ String[] sa = StringUtils.tokenizeToStringArray("a,b , ,c", ",");
+ assertEquals(3, sa.length);
+ assertTrue("components are correct",
+ sa[0].equals("a") && sa[1].equals("b") && sa[2].equals("c"));
+ }
+
+ @Test
+ public void testTokenizeToStringArrayWithNotIgnoreEmptyTokens() {
+ String[] sa = StringUtils.tokenizeToStringArray("a,b , ,c", ",", true, false);
+ assertEquals(4, sa.length);
+ assertTrue("components are correct",
+ sa[0].equals("a") && sa[1].equals("b") && sa[2].equals("") && sa[3].equals("c"));
+ }
+
+ @Test
+ public void testTokenizeToStringArrayWithNotTrimTokens() {
+ String[] sa = StringUtils.tokenizeToStringArray("a,b ,c", ",", false, true);
+ assertEquals(3, sa.length);
+ assertTrue("components are correct",
+ sa[0].equals("a") && sa[1].equals("b ") && sa[2].equals("c"));
+ }
+
+ @Test
+ public void testCommaDelimitedListToStringArrayWithNullProducesEmptyArray() {
+ String[] sa = StringUtils.commaDelimitedListToStringArray(null);
+ assertTrue("String array isn't null with null input", sa != null);
+ assertTrue("String array length == 0 with null input", sa.length == 0);
+ }
+
+ @Test
+ public void testCommaDelimitedListToStringArrayWithEmptyStringProducesEmptyArray() {
+ String[] sa = StringUtils.commaDelimitedListToStringArray("");
+ assertTrue("String array isn't null with null input", sa != null);
+ assertTrue("String array length == 0 with null input", sa.length == 0);
+ }
+
+ @Test
+ public void testDelimitedListToStringArrayWithComma() {
+ String[] sa = StringUtils.delimitedListToStringArray("a,b", ",");
+ assertEquals(2, sa.length);
+ assertEquals("a", sa[0]);
+ assertEquals("b", sa[1]);
+ }
+
+ @Test
+ public void testDelimitedListToStringArrayWithSemicolon() {
+ String[] sa = StringUtils.delimitedListToStringArray("a;b", ";");
+ assertEquals(2, sa.length);
+ assertEquals("a", sa[0]);
+ assertEquals("b", sa[1]);
+ }
+
+ @Test
+ public void testDelimitedListToStringArrayWithEmptyString() {
+ String[] sa = StringUtils.delimitedListToStringArray("a,b", "");
+ assertEquals(3, sa.length);
+ assertEquals("a", sa[0]);
+ assertEquals(",", sa[1]);
+ assertEquals("b", sa[2]);
+ }
+
+ @Test
+ public void testDelimitedListToStringArrayWithNullDelimiter() {
+ String[] sa = StringUtils.delimitedListToStringArray("a,b", null);
+ assertEquals(1, sa.length);
+ assertEquals("a,b", sa[0]);
+ }
+
+ @Test
+ public void testCommaDelimitedListToStringArrayMatchWords() {
+ // Could read these from files
+ String[] sa = new String[] {"foo", "bar", "big"};
+ doTestCommaDelimitedListToStringArrayLegalMatch(sa);
+ doTestStringArrayReverseTransformationMatches(sa);
+
+ sa = new String[] {"a", "b", "c"};
+ doTestCommaDelimitedListToStringArrayLegalMatch(sa);
+ doTestStringArrayReverseTransformationMatches(sa);
+
+ // Test same words
+ sa = new String[] {"AA", "AA", "AA", "AA", "AA"};
+ doTestCommaDelimitedListToStringArrayLegalMatch(sa);
+ doTestStringArrayReverseTransformationMatches(sa);
+ }
+
+ private void doTestStringArrayReverseTransformationMatches(String[] sa) {
+ String[] reverse =
+ StringUtils.commaDelimitedListToStringArray(StringUtils.arrayToCommaDelimitedString(sa));
+ assertEquals("Reverse transformation is equal",
+ Arrays.asList(sa),
+ Arrays.asList(reverse));
+ }
+
+ @Test
+ public void testCommaDelimitedListToStringArraySingleString() {
+ // Could read these from files
+ String s = "woeirqupoiewuropqiewuorpqiwueopriquwopeiurqopwieur";
+ String[] sa = StringUtils.commaDelimitedListToStringArray(s);
+ assertTrue("Found one String with no delimiters", sa.length == 1);
+ assertTrue("Single array entry matches input String with no delimiters",
+ sa[0].equals(s));
+ }
+
+ @Test
+ public void testCommaDelimitedListToStringArrayWithOtherPunctuation() {
+ // Could read these from files
+ String[] sa = new String[] {"xcvwert4456346&*.", "///", ".!", ".", ";"};
+ doTestCommaDelimitedListToStringArrayLegalMatch(sa);
+ }
+
+ /**
+ * We expect to see the empty Strings in the output.
+ */
+ @Test
+ public void testCommaDelimitedListToStringArrayEmptyStrings() {
+ // Could read these from files
+ String[] sa = StringUtils.commaDelimitedListToStringArray("a,,b");
+ assertEquals("a,,b produces array length 3", 3, sa.length);
+ assertTrue("components are correct",
+ sa[0].equals("a") && sa[1].equals("") && sa[2].equals("b"));
+
+ sa = new String[] {"", "", "a", ""};
+ doTestCommaDelimitedListToStringArrayLegalMatch(sa);
+ }
+
+ private void doTestCommaDelimitedListToStringArrayLegalMatch(String[] components) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < components.length; i++) {
+ if (i != 0) {
+ sb.append(",");
+ }
+ sb.append(components[i]);
+ }
+ String[] sa = StringUtils.commaDelimitedListToStringArray(sb.toString());
+ assertTrue("String array isn't null with legal match", sa != null);
+ assertEquals("String array length is correct with legal match", components.length, sa.length);
+ assertTrue("Output equals input", Arrays.equals(sa, components));
+ }
+
+ @Test
+ public void testEndsWithIgnoreCase() {
+ String suffix = "fOo";
+ assertTrue(StringUtils.endsWithIgnoreCase("foo", suffix));
+ assertTrue(StringUtils.endsWithIgnoreCase("Foo", suffix));
+ assertTrue(StringUtils.endsWithIgnoreCase("barfoo", suffix));
+ assertTrue(StringUtils.endsWithIgnoreCase("barbarfoo", suffix));
+ assertTrue(StringUtils.endsWithIgnoreCase("barFoo", suffix));
+ assertTrue(StringUtils.endsWithIgnoreCase("barBarFoo", suffix));
+ assertTrue(StringUtils.endsWithIgnoreCase("barfoO", suffix));
+ assertTrue(StringUtils.endsWithIgnoreCase("barFOO", suffix));
+ assertTrue(StringUtils.endsWithIgnoreCase("barfOo", suffix));
+ assertFalse(StringUtils.endsWithIgnoreCase(null, suffix));
+ assertFalse(StringUtils.endsWithIgnoreCase("barfOo", null));
+ assertFalse(StringUtils.endsWithIgnoreCase("b", suffix));
+ }
+
+
+ @Test
+ public void testParseLocaleStringSunnyDay() throws Exception {
+ Locale expectedLocale = Locale.UK;
+ Locale locale = StringUtils.parseLocaleString(expectedLocale.toString());
+ assertNotNull("When given a bona-fide Locale string, must not return null.", locale);
+ assertEquals(expectedLocale, locale);
+ }
+
+ @Test
+ public void testParseLocaleStringWithMalformedLocaleString() throws Exception {
+ Locale locale = StringUtils.parseLocaleString("_banjo_on_my_knee");
+ assertNotNull("When given a malformed Locale string, must not return null.", locale);
+ }
+
+ @Test
+ public void testParseLocaleStringWithEmptyLocaleStringYieldsNullLocale() throws Exception {
+ Locale locale = StringUtils.parseLocaleString("");
+ assertNull("When given an empty Locale string, must return null.", locale);
+ }
+
+ // SPR-8637
+ @Test
+ public void testParseLocaleWithMultiSpecialCharactersInVariant() throws Exception {
+ final String variant = "proper-northern";
+ final String localeString = "en_GB_" + variant;
+ Locale locale = StringUtils.parseLocaleString(localeString);
+ assertEquals("Multi-valued variant portion of the Locale not extracted correctly.", variant, locale.getVariant());
+ }
+
+ // SPR-3671
+ @Test
+ public void testParseLocaleWithMultiValuedVariant() throws Exception {
+ final String variant = "proper_northern";
+ final String localeString = "en_GB_" + variant;
+ Locale locale = StringUtils.parseLocaleString(localeString);
+ assertEquals("Multi-valued variant portion of the Locale not extracted correctly.", variant, locale.getVariant());
+ }
+
+ // SPR-3671
+ @Test
+ public void testParseLocaleWithMultiValuedVariantUsingSpacesAsSeparators() throws Exception {
+ final String variant = "proper northern";
+ final String localeString = "en GB " + variant;
+ Locale locale = StringUtils.parseLocaleString(localeString);
+ assertEquals("Multi-valued variant portion of the Locale not extracted correctly.", variant, locale.getVariant());
+ }
+
+ // SPR-3671
+ @Test
+ public void testParseLocaleWithMultiValuedVariantUsingMixtureOfUnderscoresAndSpacesAsSeparators() throws Exception {
+ final String variant = "proper northern";
+ final String localeString = "en_GB_" + variant;
+ Locale locale = StringUtils.parseLocaleString(localeString);
+ assertEquals("Multi-valued variant portion of the Locale not extracted correctly.", variant, locale.getVariant());
+ }
+
+ // SPR-3671
+ @Test
+ public void testParseLocaleWithMultiValuedVariantUsingSpacesAsSeparatorsWithLotsOfLeadingWhitespace() throws Exception {
+ final String variant = "proper northern";
+ final String localeString = "en GB " + variant; // lots of whitespace
+ Locale locale = StringUtils.parseLocaleString(localeString);
+ assertEquals("Multi-valued variant portion of the Locale not extracted correctly.", variant, locale.getVariant());
+ }
+
+ // SPR-3671
+ @Test
+ public void testParseLocaleWithMultiValuedVariantUsingUnderscoresAsSeparatorsWithLotsOfLeadingWhitespace() throws Exception {
+ final String variant = "proper_northern";
+ final String localeString = "en_GB_____" + variant; // lots of underscores
+ Locale locale = StringUtils.parseLocaleString(localeString);
+ assertEquals("Multi-valued variant portion of the Locale not extracted correctly.", variant, locale.getVariant());
+ }
+
+ // SPR-7779
+ @Test
+ public void testParseLocaleWithInvalidCharacters() {
+ try {
+ StringUtils.parseLocaleString("%0D%0AContent-length:30%0D%0A%0D%0A%3Cscript%3Ealert%28123%29%3C/script%3E");
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException ex) {
+ // expected
+ }
+ }
+
+ // SPR-9420
+ @Test
+ public void testParseLocaleWithSameLowercaseTokenForLanguageAndCountry() {
+ assertEquals("tr_TR", StringUtils.parseLocaleString("tr_tr").toString());
+ assertEquals("bg_BG_vnt", StringUtils.parseLocaleString("bg_bg_vnt").toString());
+ }
+
+ // SPR-11806
+ @Test
+ public void testParseLocaleWithVariantContainingCountryCode() {
+ String variant = "GBtest";
+ String localeString = "en_GB_" + variant;
+ Locale locale = StringUtils.parseLocaleString(localeString);
+ assertEquals("Variant containing country code not extracted correctly", variant, locale.getVariant());
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/SystemPropertyUtilsTests.java b/spring-core/src/test/java/org/springframework/util/SystemPropertyUtilsTests.java
new file mode 100644
index 00000000..d1fb6f8f
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/SystemPropertyUtilsTests.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2002-2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util;
+
+import java.util.Map;
+
+import static org.junit.Assert.*;
+import org.junit.Test;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ */
+public class SystemPropertyUtilsTests {
+
+ @Test
+ public void testReplaceFromSystemProperty() {
+ System.setProperty("test.prop", "bar");
+ try {
+ String resolved = SystemPropertyUtils.resolvePlaceholders("${test.prop}");
+ assertEquals("bar", resolved);
+ }
+ finally {
+ System.getProperties().remove("test.prop");
+ }
+ }
+
+ @Test
+ public void testReplaceFromSystemPropertyWithDefault() {
+ System.setProperty("test.prop", "bar");
+ try {
+ String resolved = SystemPropertyUtils.resolvePlaceholders("${test.prop:foo}");
+ assertEquals("bar", resolved);
+ }
+ finally {
+ System.getProperties().remove("test.prop");
+ }
+ }
+
+ @Test
+ public void testReplaceFromSystemPropertyWithExpressionDefault() {
+ System.setProperty("test.prop", "bar");
+ try {
+ String resolved = SystemPropertyUtils.resolvePlaceholders("${test.prop:#{foo.bar}}");
+ assertEquals("bar", resolved);
+ }
+ finally {
+ System.getProperties().remove("test.prop");
+ }
+ }
+
+ @Test
+ public void testReplaceFromSystemPropertyWithExpressionContainingDefault() {
+ System.setProperty("test.prop", "bar");
+ try {
+ String resolved = SystemPropertyUtils.resolvePlaceholders("${test.prop:Y#{foo.bar}X}");
+ assertEquals("bar", resolved);
+ }
+ finally {
+ System.getProperties().remove("test.prop");
+ }
+ }
+
+ @Test
+ public void testReplaceWithDefault() {
+ String resolved = SystemPropertyUtils.resolvePlaceholders("${test.prop:foo}");
+ assertEquals("foo", resolved);
+ }
+
+ @Test
+ public void testReplaceWithExpressionDefault() {
+ String resolved = SystemPropertyUtils.resolvePlaceholders("${test.prop:#{foo.bar}}");
+ assertEquals("#{foo.bar}", resolved);
+ }
+
+ @Test
+ public void testReplaceWithExpressionContainingDefault() {
+ String resolved = SystemPropertyUtils.resolvePlaceholders("${test.prop:Y#{foo.bar}X}");
+ assertEquals("Y#{foo.bar}X", resolved);
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void testReplaceWithNoDefault() {
+ String resolved = SystemPropertyUtils.resolvePlaceholders("${test.prop}");
+ assertEquals("", resolved);
+ }
+
+ @Test
+ public void testReplaceWithNoDefaultIgnored() {
+ String resolved = SystemPropertyUtils.resolvePlaceholders("${test.prop}", true);
+ assertEquals("${test.prop}", resolved);
+ }
+
+ @Test
+ public void testReplaceWithEmptyDefault() {
+ String resolved = SystemPropertyUtils.resolvePlaceholders("${test.prop:}");
+ assertEquals("", resolved);
+ }
+
+ @Test
+ public void testRecursiveFromSystemProperty() {
+ System.setProperty("test.prop", "foo=${bar}");
+ System.setProperty("bar", "baz");
+ try {
+ String resolved = SystemPropertyUtils.resolvePlaceholders("${test.prop}");
+ assertEquals("foo=baz", resolved);
+ }
+ finally {
+ System.getProperties().remove("test.prop");
+ System.getProperties().remove("bar");
+ }
+ }
+
+ @Test
+ public void testReplaceFromEnv() {
+ Map<String,String> env = System.getenv();
+ if (env.containsKey("PATH")) {
+ String text = "${PATH}";
+ assertEquals(env.get("PATH"), SystemPropertyUtils.resolvePlaceholders(text));
+ }
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/TypeUtilsTests.java b/spring-core/src/test/java/org/springframework/util/TypeUtilsTests.java
new file mode 100644
index 00000000..b32dbbbb
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/TypeUtilsTests.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2002-2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link TypeUtils}.
+ *
+ * @author Juergen Hoeller
+ * @author Chris Beams
+ */
+public class TypeUtilsTests {
+
+ public static Object object;
+
+ public static String string;
+
+ public static Integer number;
+
+ public static List<Object> objects;
+
+ public static List<String> strings;
+
+ public static List<? extends Object> openObjects;
+
+ public static List<? extends Number> openNumbers;
+
+ public static List<? super Object> storableObjectList;
+
+ public static List<Number>[] array;
+
+ public static List<? extends Number>[] openArray;
+
+
+ @Test
+ public void withClasses() {
+ assertTrue(TypeUtils.isAssignable(Object.class, Object.class));
+ assertTrue(TypeUtils.isAssignable(Object.class, String.class));
+ assertFalse(TypeUtils.isAssignable(String.class, Object.class));
+ assertTrue(TypeUtils.isAssignable(List.class, List.class));
+ assertTrue(TypeUtils.isAssignable(List.class, LinkedList.class));
+ assertFalse(TypeUtils.isAssignable(List.class, Collection.class));
+ assertFalse(TypeUtils.isAssignable(List.class, HashSet.class));
+ }
+
+ @Test
+ public void withParameterizedTypes() throws Exception {
+ Type objectsType = getClass().getField("objects").getGenericType();
+ Type openObjectsType = getClass().getField("openObjects").getGenericType();
+ Type stringsType = getClass().getField("strings").getGenericType();
+ assertTrue(TypeUtils.isAssignable(Object.class, objectsType));
+ assertTrue(TypeUtils.isAssignable(Object.class, openObjectsType));
+ assertTrue(TypeUtils.isAssignable(Object.class, stringsType));
+ assertTrue(TypeUtils.isAssignable(List.class, objectsType));
+ assertTrue(TypeUtils.isAssignable(List.class, openObjectsType));
+ assertTrue(TypeUtils.isAssignable(List.class, stringsType));
+ assertTrue(TypeUtils.isAssignable(objectsType, List.class));
+ assertTrue(TypeUtils.isAssignable(openObjectsType, List.class));
+ assertTrue(TypeUtils.isAssignable(stringsType, List.class));
+ assertTrue(TypeUtils.isAssignable(objectsType, objectsType));
+ assertTrue(TypeUtils.isAssignable(openObjectsType, openObjectsType));
+ assertTrue(TypeUtils.isAssignable(stringsType, stringsType));
+ assertTrue(TypeUtils.isAssignable(openObjectsType, objectsType));
+ assertTrue(TypeUtils.isAssignable(openObjectsType, stringsType));
+ assertFalse(TypeUtils.isAssignable(stringsType, objectsType));
+ assertFalse(TypeUtils.isAssignable(objectsType, stringsType));
+ }
+
+ @Test
+ public void withWildcardTypes() throws Exception {
+ ParameterizedType openObjectsType = (ParameterizedType) getClass().getField("openObjects").getGenericType();
+ ParameterizedType openNumbersType = (ParameterizedType) getClass().getField("openNumbers").getGenericType();
+ Type storableObjectListType = getClass().getField("storableObjectList").getGenericType();
+
+ Type objectType = getClass().getField("object").getGenericType();
+ Type numberType = getClass().getField("number").getGenericType();
+ Type stringType = getClass().getField("string").getGenericType();
+
+ Type openWildcard = openObjectsType.getActualTypeArguments()[0]; // '?'
+ Type openNumbersWildcard = openNumbersType.getActualTypeArguments()[0]; // '? extends number'
+
+ assertTrue(TypeUtils.isAssignable(openWildcard, objectType));
+ assertTrue(TypeUtils.isAssignable(openNumbersWildcard, numberType));
+ assertFalse(TypeUtils.isAssignable(openNumbersWildcard, stringType));
+ assertFalse(TypeUtils.isAssignable(storableObjectListType, openObjectsType));
+ }
+
+ @Test
+ public void withGenericArrayTypes() throws Exception {
+ Type arrayType = getClass().getField("array").getGenericType();
+ Type openArrayType = getClass().getField("openArray").getGenericType();
+ assertTrue(TypeUtils.isAssignable(Object.class, arrayType));
+ assertTrue(TypeUtils.isAssignable(Object.class, openArrayType));
+ assertTrue(TypeUtils.isAssignable(List[].class, arrayType));
+ assertTrue(TypeUtils.isAssignable(List[].class, openArrayType));
+ assertTrue(TypeUtils.isAssignable(arrayType, List[].class));
+ assertTrue(TypeUtils.isAssignable(openArrayType, List[].class));
+ assertTrue(TypeUtils.isAssignable(arrayType, arrayType));
+ assertTrue(TypeUtils.isAssignable(openArrayType, openArrayType));
+ assertTrue(TypeUtils.isAssignable(openArrayType, arrayType));
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/comparator/BooleanComparatorTests.java b/spring-core/src/test/java/org/springframework/util/comparator/BooleanComparatorTests.java
new file mode 100644
index 00000000..4074cc1b
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/comparator/BooleanComparatorTests.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util.comparator;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.*;
+
+import java.util.Comparator;
+
+import org.junit.Test;
+
+/**
+ * Tests for {@link BooleanComparator}.
+ *
+ * @author Keith Donald
+ * @author Chris Beams
+ * @author Phillip Webb
+ */
+public class BooleanComparatorTests {
+
+ @Test
+ public void shouldCompareWithTrueLow() {
+ Comparator<Boolean> c = new BooleanComparator(true);
+ assertThat(c.compare(new Boolean(true), new Boolean(false)), is(-1));
+ assertThat(c.compare(Boolean.TRUE, Boolean.TRUE), is(0));
+ }
+
+ @Test
+ public void shouldCompareWithTrueHigh() {
+ Comparator<Boolean> c = new BooleanComparator(false);
+ assertThat(c.compare(new Boolean(true), new Boolean(false)), is(1));
+ assertThat(c.compare(Boolean.TRUE, Boolean.TRUE), is(0));
+ }
+
+ @Test
+ public void shouldCompareFromTrueLow() {
+ Comparator<Boolean> c = BooleanComparator.TRUE_LOW;
+ assertThat(c.compare(true, false), is(-1));
+ assertThat(c.compare(Boolean.TRUE, Boolean.TRUE), is(0));
+ }
+
+ @Test
+ public void shouldCompareFromTrueHigh() {
+ Comparator<Boolean> c = BooleanComparator.TRUE_HIGH;
+ assertThat(c.compare(true, false), is(1));
+ assertThat(c.compare(Boolean.TRUE, Boolean.TRUE), is(0));
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/comparator/ComparableComparatorTests.java b/spring-core/src/test/java/org/springframework/util/comparator/ComparableComparatorTests.java
new file mode 100644
index 00000000..450442f2
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/comparator/ComparableComparatorTests.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util.comparator;
+
+import static org.junit.Assert.assertTrue;
+
+import java.util.Comparator;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+/**
+ * Tests for {@link ComparableComparator}.
+ *
+ * @author Keith Donald
+ * @author Chris Beams
+ * @author Phillip Webb
+ */
+public class ComparableComparatorTests {
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void testComparableComparator() {
+ Comparator<String> c = new ComparableComparator<String>();
+ String s1 = "abc";
+ String s2 = "cde";
+ assertTrue(c.compare(s1, s2) < 0);
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Test
+ public void shouldNeedComparable() {
+ Comparator c = new ComparableComparator();
+ Object o1 = new Object();
+ Object o2 = new Object();
+ thrown.expect(ClassCastException.class);
+ c.compare(o1, o2);
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/comparator/CompoundComparatorTests.java b/spring-core/src/test/java/org/springframework/util/comparator/CompoundComparatorTests.java
new file mode 100644
index 00000000..10d5ca33
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/comparator/CompoundComparatorTests.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util.comparator;
+
+import java.util.Comparator;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+/**
+ * Test for {@link ComparableComparator}.
+ *
+ * @author Keith Donald
+ * @author Chris Beams
+ * @author Phillip Webb
+ */
+public class CompoundComparatorTests {
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void shouldNeedAtLeastOneComparator() {
+ Comparator<String> c = new CompoundComparator<String>();
+ thrown.expect(IllegalStateException.class);
+ c.compare("foo", "bar");
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/comparator/InstanceComparatorTests.java b/spring-core/src/test/java/org/springframework/util/comparator/InstanceComparatorTests.java
new file mode 100644
index 00000000..8a483dcb
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/comparator/InstanceComparatorTests.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util.comparator;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.*;
+
+import java.util.Comparator;
+
+import org.junit.Test;
+
+/**
+ * Tests for {@link InstanceComparator}.
+ *
+ * @author Phillip Webb
+ */
+public class InstanceComparatorTests {
+
+ private C1 c1 = new C1();
+
+ private C2 c2 = new C2();
+
+ private C3 c3 = new C3();
+
+ private C4 c4 = new C4();
+
+ @Test
+ public void shouldCompareClasses() throws Exception {
+ Comparator<Object> comparator = new InstanceComparator<Object>(C1.class, C2.class);
+ assertThat(comparator.compare(c1, c1), is(0));
+ assertThat(comparator.compare(c1, c2), is(-1));
+ assertThat(comparator.compare(c2, c1), is(1));
+ assertThat(comparator.compare(c2, c3), is(-1));
+ assertThat(comparator.compare(c2, c4), is(-1));
+ assertThat(comparator.compare(c3, c4), is(0));
+ }
+
+ @Test
+ public void shouldCompareInterfaces() throws Exception {
+ Comparator<Object> comparator = new InstanceComparator<Object>(I1.class, I2.class);
+ assertThat(comparator.compare(c1, c1), is(0));
+ assertThat(comparator.compare(c1, c2), is(0));
+ assertThat(comparator.compare(c2, c1), is(0));
+ assertThat(comparator.compare(c1, c3), is(-1));
+ assertThat(comparator.compare(c3, c1), is(1));
+ assertThat(comparator.compare(c3, c4), is(0));
+ }
+
+ @Test
+ public void shouldCompareMix() throws Exception {
+ Comparator<Object> comparator = new InstanceComparator<Object>(I1.class, C3.class);
+ assertThat(comparator.compare(c1, c1), is(0));
+ assertThat(comparator.compare(c3, c4), is(-1));
+ assertThat(comparator.compare(c3, null), is(-1));
+ assertThat(comparator.compare(c4, null), is(0));
+ }
+
+ private static interface I1 {
+
+ }
+
+ private static interface I2 {
+
+ }
+
+ private static class C1 implements I1 {
+ }
+
+ private static class C2 implements I1 {
+ }
+
+ private static class C3 implements I2 {
+ }
+
+ private static class C4 implements I2 {
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/comparator/InvertibleComparatorTests.java b/spring-core/src/test/java/org/springframework/util/comparator/InvertibleComparatorTests.java
new file mode 100644
index 00000000..c8afa7a6
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/comparator/InvertibleComparatorTests.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util.comparator;
+
+import java.util.Comparator;
+
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+/**
+ * Tests for {@link InvertibleComparator}.
+ *
+ * @author Keith Donald
+ * @author Chris Beams
+ * @author Phillip Webb
+ */
+
+public class InvertibleComparatorTests {
+
+ private Comparator<Integer> comparator = new ComparableComparator<Integer>();
+
+ @Test(expected=IllegalArgumentException.class)
+ public void shouldNeedComparator() throws Exception {
+ new InvertibleComparator<Object>(null);
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void shouldNeedComparatorWithAscending() throws Exception {
+ new InvertibleComparator<Object>(null, true);
+ }
+
+ @Test
+ public void shouldDefaultToAscending() throws Exception {
+ InvertibleComparator<Integer> invertibleComparator =
+ new InvertibleComparator<Integer>(comparator);
+ assertThat(invertibleComparator.isAscending(), is(true));
+ assertThat(invertibleComparator.compare(1, 2), is(-1));
+ }
+
+ @Test
+ public void shouldInvert() throws Exception {
+ InvertibleComparator<Integer> invertibleComparator =
+ new InvertibleComparator<Integer>(comparator);
+ assertThat(invertibleComparator.isAscending(), is(true));
+ assertThat(invertibleComparator.compare(1, 2), is(-1));
+ invertibleComparator.invertOrder();
+ assertThat(invertibleComparator.isAscending(), is(false));
+ assertThat(invertibleComparator.compare(1, 2), is(1));
+ }
+
+ @Test
+ public void shouldCompareAscending() throws Exception {
+ InvertibleComparator<Integer> invertibleComparator =
+ new InvertibleComparator<Integer>(comparator, true);
+ assertThat(invertibleComparator.compare(1, 2), is(-1));
+ }
+
+ @Test
+ public void shouldCompareDescending() throws Exception {
+ InvertibleComparator<Integer> invertibleComparator =
+ new InvertibleComparator<Integer>(comparator, false);
+ assertThat(invertibleComparator.compare(1, 2), is(1));
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/comparator/NullSafeComparatorTests.java b/spring-core/src/test/java/org/springframework/util/comparator/NullSafeComparatorTests.java
new file mode 100644
index 00000000..9615f0c0
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/comparator/NullSafeComparatorTests.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util.comparator;
+
+import static org.junit.Assert.*;
+
+import java.util.Comparator;
+
+import org.junit.Test;
+
+/**
+ * Tests for {@link NullSafeComparator}.
+ *
+ * @author Keith Donald
+ * @author Chris Beams
+ * @author Phillip Webb
+ */
+public class NullSafeComparatorTests {
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void shouldCompareWithNullsLow() {
+ Comparator<String> c = NullSafeComparator.NULLS_LOW;
+ assertTrue(c.compare(null, "boo") < 0);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void shouldCompareWithNullsHigh() {
+ Comparator<String> c = NullSafeComparator.NULLS_HIGH;
+ assertTrue(c.compare(null, "boo") > 0);
+ assertTrue(c.compare(null, null) == 0);
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/xml/AbstractStaxContentHandlerTestCase.java b/spring-core/src/test/java/org/springframework/util/xml/AbstractStaxContentHandlerTestCase.java
new file mode 100644
index 00000000..9cab8c0d
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/xml/AbstractStaxContentHandlerTestCase.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2002-2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util.xml;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import javax.xml.stream.XMLStreamException;
+
+import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
+import org.junit.Before;
+import org.junit.Test;
+import org.xml.sax.InputSource;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+public abstract class AbstractStaxContentHandlerTestCase {
+
+ private static final String XML_CONTENT_HANDLER =
+ "<?xml version='1.0' encoding='UTF-8'?><?pi content?><root xmlns='namespace'><prefix:child xmlns:prefix='namespace2' prefix:attr='value'>content</prefix:child></root>"
+ ;
+
+ private XMLReader xmlReader;
+
+ @Before
+ public void createXMLReader() throws Exception {
+ xmlReader = XMLReaderFactory.createXMLReader();
+ }
+
+ @Test
+ public void contentHandler() throws Exception {
+ StringWriter stringWriter = new StringWriter();
+ AbstractStaxContentHandler handler = createStaxContentHandler(stringWriter);
+ xmlReader.setFeature("http://xml.org/sax/features/namespace-prefixes", false);
+ xmlReader.setContentHandler(handler);
+ xmlReader.parse(new InputSource(new StringReader(XML_CONTENT_HANDLER)));
+ assertXMLEqual("Invalid result", XML_CONTENT_HANDLER, stringWriter.toString());
+ }
+
+ @Test
+ public void contentHandlerNamespacePrefixes() throws Exception {
+ StringWriter stringWriter = new StringWriter();
+ AbstractStaxContentHandler handler = createStaxContentHandler(stringWriter);
+ xmlReader.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
+ xmlReader.setContentHandler(handler);
+ xmlReader.parse(new InputSource(new StringReader(XML_CONTENT_HANDLER)));
+ assertXMLEqual("Invalid result", XML_CONTENT_HANDLER, stringWriter.toString());
+ }
+
+ protected abstract AbstractStaxContentHandler createStaxContentHandler(Writer writer) throws XMLStreamException;
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/xml/AbstractStaxXMLReaderTestCase.java b/spring-core/src/test/java/org/springframework/util/xml/AbstractStaxXMLReaderTestCase.java
new file mode 100644
index 00000000..d28ad6e3
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/xml/AbstractStaxXMLReaderTestCase.java
@@ -0,0 +1,267 @@
+/*
+ * Copyright 2002-2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util.xml;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.sax.SAXSource;
+
+import static org.junit.Assert.assertEquals;
+import org.junit.Before;
+import org.junit.Test;
+import static org.mockito.BDDMockito.*;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.w3c.dom.Node;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
+import org.xml.sax.XMLReader;
+import org.xml.sax.ext.LexicalHandler;
+import org.xml.sax.helpers.AttributesImpl;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+import org.springframework.tests.MockitoUtils;
+import org.springframework.tests.MockitoUtils.InvocationArgumentsAdapter;
+
+public abstract class AbstractStaxXMLReaderTestCase {
+
+ protected static XMLInputFactory inputFactory;
+
+ private XMLReader standardReader;
+
+ private ContentHandler standardContentHandler;
+
+ @Before
+ public void setUp() throws Exception {
+ inputFactory = XMLInputFactory.newInstance();
+ standardReader = XMLReaderFactory.createXMLReader();
+ standardContentHandler = mockContentHandler();
+ standardReader.setContentHandler(standardContentHandler);
+ }
+
+ @Test
+ public void contentHandlerNamespacesNoPrefixes() throws Exception {
+ standardReader.setFeature("http://xml.org/sax/features/namespaces", true);
+ standardReader.setFeature("http://xml.org/sax/features/namespace-prefixes", false);
+ standardReader.parse(new InputSource(createTestInputStream()));
+
+ AbstractStaxXMLReader staxXmlReader = createStaxXmlReader(createTestInputStream());
+ ContentHandler contentHandler = mockContentHandler();
+ staxXmlReader.setFeature("http://xml.org/sax/features/namespaces", true);
+ staxXmlReader.setFeature("http://xml.org/sax/features/namespace-prefixes", false);
+ staxXmlReader.setContentHandler(contentHandler);
+ staxXmlReader.parse(new InputSource());
+
+ verifyIdenticalInvocations(standardContentHandler, contentHandler);
+ }
+
+ @Test
+ public void contentHandlerNamespacesPrefixes() throws Exception {
+ standardReader.setFeature("http://xml.org/sax/features/namespaces", true);
+ standardReader.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
+ standardReader.parse(new InputSource(createTestInputStream()));
+
+ AbstractStaxXMLReader staxXmlReader = createStaxXmlReader(createTestInputStream());
+ ContentHandler contentHandler = mockContentHandler();
+ staxXmlReader.setFeature("http://xml.org/sax/features/namespaces", true);
+ staxXmlReader.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
+ staxXmlReader.setContentHandler(contentHandler);
+ staxXmlReader.parse(new InputSource());
+
+ verifyIdenticalInvocations(standardContentHandler, contentHandler);
+ }
+
+ @Test
+ public void contentHandlerNoNamespacesPrefixes() throws Exception {
+ standardReader.setFeature("http://xml.org/sax/features/namespaces", false);
+ standardReader.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
+ standardReader.parse(new InputSource(createTestInputStream()));
+
+ AbstractStaxXMLReader staxXmlReader = createStaxXmlReader(createTestInputStream());
+ ContentHandler contentHandler = mockContentHandler();
+ staxXmlReader.setFeature("http://xml.org/sax/features/namespaces", false);
+ staxXmlReader.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
+ staxXmlReader.setContentHandler(contentHandler);
+ staxXmlReader.parse(new InputSource());
+
+ verifyIdenticalInvocations(standardContentHandler, contentHandler);
+ }
+
+ @Test
+ public void whitespace() throws Exception {
+ String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><test><node1> </node1><node2> Some text </node2></test>";
+
+ Transformer transformer = TransformerFactory.newInstance().newTransformer();
+
+ AbstractStaxXMLReader staxXmlReader = createStaxXmlReader(
+ new ByteArrayInputStream(xml.getBytes("UTF-8")));
+
+ SAXSource source = new SAXSource(staxXmlReader, new InputSource());
+ DOMResult result = new DOMResult();
+
+ transformer.transform(source, result);
+
+ Node node1 = result.getNode().getFirstChild().getFirstChild();
+ assertEquals(" ", node1.getTextContent());
+ assertEquals(" Some text ", node1.getNextSibling().getTextContent());
+ }
+
+ @Test
+ public void lexicalHandler() throws Exception {
+ Resource testLexicalHandlerXml = new ClassPathResource("testLexicalHandler.xml", getClass());
+
+ LexicalHandler expectedLexicalHandler = mockLexicalHandler();
+ standardReader.setContentHandler(null);
+ standardReader.setProperty("http://xml.org/sax/properties/lexical-handler", expectedLexicalHandler);
+ standardReader.parse(new InputSource(testLexicalHandlerXml.getInputStream()));
+ inputFactory.setProperty("javax.xml.stream.isCoalescing", Boolean.FALSE);
+ inputFactory.setProperty("http://java.sun.com/xml/stream/properties/report-cdata-event", Boolean.TRUE);
+ inputFactory.setProperty("javax.xml.stream.isReplacingEntityReferences", Boolean.FALSE);
+ inputFactory.setProperty("javax.xml.stream.isSupportingExternalEntities", Boolean.FALSE);
+
+ LexicalHandler actualLexicalHandler = mockLexicalHandler();
+ willAnswer(new Answer<Object>() {
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ return invocation.getArguments()[0] = "element";
+ }
+ }).given(actualLexicalHandler).startDTD(anyString(), anyString(), anyString());
+ AbstractStaxXMLReader staxXmlReader = createStaxXmlReader(testLexicalHandlerXml.getInputStream());
+ staxXmlReader.setProperty("http://xml.org/sax/properties/lexical-handler", actualLexicalHandler);
+ staxXmlReader.parse(new InputSource());
+
+ verifyIdenticalInvocations(expectedLexicalHandler, actualLexicalHandler);
+ }
+
+ private LexicalHandler mockLexicalHandler() throws Exception {
+ LexicalHandler lexicalHandler = mock(LexicalHandler.class);
+ willAnswer(new CopyCharsAnswer()).given(lexicalHandler).comment(any(char[].class), anyInt(), anyInt());
+ return lexicalHandler;
+ }
+
+ private InputStream createTestInputStream() {
+ return getClass().getResourceAsStream("testContentHandler.xml");
+ }
+
+ protected abstract AbstractStaxXMLReader createStaxXmlReader(InputStream inputStream) throws XMLStreamException;
+
+ protected final ContentHandler mockContentHandler() throws Exception {
+ ContentHandler contentHandler = mock(ContentHandler.class);
+ willAnswer(new CopyCharsAnswer()).given(contentHandler).characters(any(char[].class), anyInt(), anyInt());
+ willAnswer(new CopyCharsAnswer()).given(contentHandler).ignorableWhitespace(any(char[].class), anyInt(), anyInt());
+ willAnswer(new Answer<Object>() {
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ invocation.getArguments()[3] = new AttributesImpl((Attributes) invocation.getArguments()[3]);
+ return null;
+ }
+ }).given(contentHandler).startElement(anyString(), anyString(), anyString(), any(Attributes.class));
+ return contentHandler;
+ }
+
+ protected <T> void verifyIdenticalInvocations(T expected, T actual) {
+ MockitoUtils.verifySameInvocations(expected, actual,
+ new SkipLocatorArgumentsAdapter(), new CharArrayToStringAdapter(), new PartialAttributesAdapter());
+ }
+
+ private static class SkipLocatorArgumentsAdapter implements InvocationArgumentsAdapter {
+ public Object[] adaptArguments(Object[] arguments) {
+ for(int i=0; i<arguments.length; i++) {
+ if(arguments[i] instanceof Locator) {
+ arguments[i] = null;
+ }
+ }
+ return arguments;
+ }
+ }
+
+ private static class CharArrayToStringAdapter implements InvocationArgumentsAdapter {
+ public Object[] adaptArguments(Object[] arguments) {
+ if(arguments.length == 3 && arguments[0] instanceof char[]
+ && arguments[1] instanceof Integer && arguments[2] instanceof Integer) {
+ return new Object[] {new String((char[]) arguments[0], (Integer) arguments[1], (Integer) arguments[2])};
+ }
+ return arguments;
+ }
+ }
+
+ private static class PartialAttributesAdapter implements InvocationArgumentsAdapter {
+ public Object[] adaptArguments(Object[] arguments) {
+ for (int i = 0; i < arguments.length; i++) {
+ if(arguments[i] instanceof Attributes) {
+ arguments[i] = new PartialAttributes((Attributes) arguments[i]);
+ }
+ };
+ return arguments;
+ }
+ }
+
+ private static class CopyCharsAnswer implements Answer<Object> {
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ char[] chars = (char[]) invocation.getArguments()[0];
+ char[] copy = new char[chars.length];
+ System.arraycopy(chars, 0, copy, 0, chars.length);
+ invocation.getArguments()[0] = copy;
+ return null;
+ }
+ }
+
+ private static class PartialAttributes {
+
+ private Attributes attributes;
+
+ public PartialAttributes(Attributes attributes) {
+ this.attributes = attributes;
+ }
+
+ @Override
+ public int hashCode() {
+ return 1;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ Attributes other = ((PartialAttributes) obj).attributes;
+ if (this.attributes.getLength() != other.getLength()) {
+ return false;
+ }
+ for (int i = 0; i < other.getLength(); i++) {
+ boolean found = false;
+ for (int j = 0; j < attributes.getLength(); j++) {
+ if (other.getURI(i).equals(attributes.getURI(j))
+ && other.getQName(i).equals(attributes.getQName(j))
+ && other.getType(i).equals(attributes.getType(j))
+ && other.getValue(i).equals(attributes.getValue(j))) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+}
diff --git a/spring-core/src/test/java/org/springframework/util/xml/DomContentHandlerTest.java b/spring-core/src/test/java/org/springframework/util/xml/DomContentHandlerTest.java
new file mode 100644
index 00000000..40ee7e6a
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/xml/DomContentHandlerTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2002-2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util.xml;
+
+import java.io.StringReader;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
+import org.junit.Before;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.InputSource;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+public class DomContentHandlerTest {
+
+ private static final String XML_1 =
+ "<?xml version='1.0' encoding='UTF-8'?>" + "<?pi content?>" + "<root xmlns='namespace'>" +
+ "<prefix:child xmlns:prefix='namespace2' xmlns:prefix2='namespace3' prefix2:attr='value'>content</prefix:child>" +
+ "</root>";
+
+ private static final String XML_2_EXPECTED =
+ "<?xml version='1.0' encoding='UTF-8'?>" + "<root xmlns='namespace'>" + "<child xmlns='namespace2' />" +
+ "</root>";
+
+ private static final String XML_2_SNIPPET =
+ "<?xml version='1.0' encoding='UTF-8'?>" + "<child xmlns='namespace2' />";
+
+ private Document expected;
+
+ private DomContentHandler handler;
+
+ private Document result;
+
+ private XMLReader xmlReader;
+
+ private DocumentBuilder documentBuilder;
+
+ @Before
+ public void setUp() throws Exception {
+ DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+ documentBuilderFactory.setNamespaceAware(true);
+ documentBuilder = documentBuilderFactory.newDocumentBuilder();
+ result = documentBuilder.newDocument();
+ xmlReader = XMLReaderFactory.createXMLReader();
+ }
+
+ @Test
+ public void contentHandlerDocumentNamespacePrefixes() throws Exception {
+ xmlReader.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
+ handler = new DomContentHandler(result);
+ expected = documentBuilder.parse(new InputSource(new StringReader(XML_1)));
+ xmlReader.setContentHandler(handler);
+ xmlReader.parse(new InputSource(new StringReader(XML_1)));
+ assertXMLEqual("Invalid result", expected, result);
+ }
+
+ @Test
+ public void contentHandlerDocumentNoNamespacePrefixes() throws Exception {
+ handler = new DomContentHandler(result);
+ expected = documentBuilder.parse(new InputSource(new StringReader(XML_1)));
+ xmlReader.setContentHandler(handler);
+ xmlReader.parse(new InputSource(new StringReader(XML_1)));
+ assertXMLEqual("Invalid result", expected, result);
+ }
+
+ @Test
+ public void contentHandlerElement() throws Exception {
+ Element rootElement = result.createElementNS("namespace", "root");
+ result.appendChild(rootElement);
+ handler = new DomContentHandler(rootElement);
+ expected = documentBuilder.parse(new InputSource(new StringReader(XML_2_EXPECTED)));
+ xmlReader.setContentHandler(handler);
+ xmlReader.parse(new InputSource(new StringReader(XML_2_SNIPPET)));
+ assertXMLEqual("Invalid result", expected, result);
+
+ }
+} \ No newline at end of file
diff --git a/spring-core/src/test/java/org/springframework/util/xml/SimpleNamespaceContextTests.java b/spring-core/src/test/java/org/springframework/util/xml/SimpleNamespaceContextTests.java
new file mode 100644
index 00000000..64f7de88
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/xml/SimpleNamespaceContextTests.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2002-2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.util.xml;
+
+import java.util.Collections;
+import java.util.Iterator;
+import javax.xml.XMLConstants;
+
+import static org.junit.Assert.*;
+import org.junit.Before;
+import org.junit.Test;
+
+public class SimpleNamespaceContextTests {
+
+ private SimpleNamespaceContext context;
+
+ @Before
+ public void createContext() throws Exception {
+ context = new SimpleNamespaceContext();
+ context.bindNamespaceUri("prefix", "namespaceURI");
+ }
+
+ @Test
+ public void getNamespaceURI() {
+ assertEquals("Invalid namespaceURI for default namespace", "",
+ context.getNamespaceURI(XMLConstants.DEFAULT_NS_PREFIX));
+ String defaultNamespaceUri = "defaultNamespace";
+ context.bindNamespaceUri(XMLConstants.DEFAULT_NS_PREFIX, defaultNamespaceUri);
+ assertEquals("Invalid namespaceURI for default namespace", defaultNamespaceUri,
+ context.getNamespaceURI(XMLConstants.DEFAULT_NS_PREFIX));
+ assertEquals("Invalid namespaceURI for bound prefix", "namespaceURI", context.getNamespaceURI("prefix"));
+ assertEquals("Invalid namespaceURI for unbound prefix", "", context.getNamespaceURI("unbound"));
+ assertEquals("Invalid namespaceURI for namespace prefix", XMLConstants.XML_NS_URI,
+ context.getNamespaceURI(XMLConstants.XML_NS_PREFIX));
+ assertEquals("Invalid namespaceURI for attribute prefix", XMLConstants.XMLNS_ATTRIBUTE_NS_URI,
+ context.getNamespaceURI(XMLConstants.XMLNS_ATTRIBUTE));
+
+ }
+
+ @Test
+ public void getPrefix() {
+ assertEquals("Invalid prefix for default namespace", XMLConstants.DEFAULT_NS_PREFIX, context.getPrefix(""));
+ assertEquals("Invalid prefix for bound namespace", "prefix", context.getPrefix("namespaceURI"));
+ assertNull("Invalid prefix for unbound namespace", context.getPrefix("unbound"));
+ assertEquals("Invalid prefix for namespace", XMLConstants.XML_NS_PREFIX,
+ context.getPrefix(XMLConstants.XML_NS_URI));
+ assertEquals("Invalid prefix for attribute namespace", XMLConstants.XMLNS_ATTRIBUTE,
+ context.getPrefix(XMLConstants.XMLNS_ATTRIBUTE_NS_URI));
+ }
+
+ @Test
+ public void getPrefixes() {
+ assertPrefixes("", XMLConstants.DEFAULT_NS_PREFIX);
+ assertPrefixes("namespaceURI", "prefix");
+ assertFalse("Invalid prefix for unbound namespace", context.getPrefixes("unbound").hasNext());
+ assertPrefixes(XMLConstants.XML_NS_URI, XMLConstants.XML_NS_PREFIX);
+ assertPrefixes(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, XMLConstants.XMLNS_ATTRIBUTE);
+ }
+
+ @Test
+ public void multiplePrefixes() {
+ context.bindNamespaceUri("prefix1", "namespace");
+ context.bindNamespaceUri("prefix2", "namespace");
+ Iterator iterator = context.getPrefixes("namespace");
+ assertNotNull("getPrefixes returns null", iterator);
+ assertTrue("iterator is empty", iterator.hasNext());
+ String result = (String) iterator.next();
+ assertTrue("Invalid prefix", result.equals("prefix1") || result.equals("prefix2"));
+ assertTrue("iterator is empty", iterator.hasNext());
+ result = (String) iterator.next();
+ assertTrue("Invalid prefix", result.equals("prefix1") || result.equals("prefix2"));
+ assertFalse("iterator contains more than two values", iterator.hasNext());
+ }
+
+ private void assertPrefixes(String namespaceUri, String prefix) {
+ Iterator iterator = context.getPrefixes(namespaceUri);
+ assertNotNull("getPrefixes returns null", iterator);
+ assertTrue("iterator is empty", iterator.hasNext());
+ String result = (String) iterator.next();
+ assertEquals("Invalid prefix", prefix, result);
+ assertFalse("iterator contains multiple values", iterator.hasNext());
+ }
+
+ @Test
+ public void getBoundPrefixes() throws Exception {
+ Iterator iterator = context.getBoundPrefixes();
+ assertNotNull("getPrefixes returns null", iterator);
+ assertTrue("iterator is empty", iterator.hasNext());
+ String result = (String) iterator.next();
+ assertEquals("Invalid prefix", "prefix", result);
+ assertFalse("iterator contains multiple values", iterator.hasNext());
+ }
+
+ @Test
+ public void setBindings() throws Exception {
+ context.setBindings(Collections.singletonMap("prefix", "namespace"));
+ assertEquals("Invalid namespace uri", "namespace", context.getNamespaceURI("prefix"));
+ }
+
+ @Test
+ public void removeBinding() throws Exception {
+ context.removeBinding("prefix");
+ assertNull("Invalid prefix for unbound namespace", context.getPrefix("prefix"));
+
+
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/xml/StaxEventContentHandlerTests.java b/spring-core/src/test/java/org/springframework/util/xml/StaxEventContentHandlerTests.java
new file mode 100644
index 00000000..da1657b8
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/xml/StaxEventContentHandlerTests.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2002-2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util.xml;
+
+import java.io.Writer;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+
+public class StaxEventContentHandlerTests extends AbstractStaxContentHandlerTestCase {
+
+ @Override
+ protected AbstractStaxContentHandler createStaxContentHandler(Writer writer) throws XMLStreamException {
+ XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
+ return new StaxEventContentHandler(outputFactory.createXMLEventWriter(writer));
+ }
+} \ No newline at end of file
diff --git a/spring-core/src/test/java/org/springframework/util/xml/StaxEventXMLReaderTests.java b/spring-core/src/test/java/org/springframework/util/xml/StaxEventXMLReaderTests.java
new file mode 100644
index 00000000..355cb944
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/xml/StaxEventXMLReaderTests.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util.xml;
+
+import java.io.InputStream;
+import java.io.StringReader;
+
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.helpers.AttributesImpl;
+
+import static org.mockito.BDDMockito.*;
+
+public class StaxEventXMLReaderTests extends AbstractStaxXMLReaderTestCase {
+
+ public static final String CONTENT = "<root xmlns='http://springframework.org/spring-ws'><child/></root>";
+
+ @Override
+ protected AbstractStaxXMLReader createStaxXmlReader(InputStream inputStream) throws XMLStreamException {
+ return new StaxEventXMLReader(inputFactory.createXMLEventReader(inputStream));
+ }
+
+ public void testPartial() throws Exception {
+ XMLInputFactory inputFactory = XMLInputFactory.newInstance();
+ XMLEventReader eventReader = inputFactory.createXMLEventReader(new StringReader(CONTENT));
+ eventReader.nextTag(); // skip to root
+ StaxEventXMLReader xmlReader = new StaxEventXMLReader(eventReader);
+ ContentHandler contentHandler = mock(ContentHandler.class);
+ xmlReader.setContentHandler(contentHandler);
+ xmlReader.parse(new InputSource());
+ verify(contentHandler).startDocument();
+ verify(contentHandler).startElement("http://springframework.org/spring-ws", "child", "child", new AttributesImpl());
+ verify(contentHandler).endElement("http://springframework.org/spring-ws", "child", "child");
+ verify(contentHandler).endDocument();
+ }
+}
+
diff --git a/spring-core/src/test/java/org/springframework/util/xml/StaxResultTests.java b/spring-core/src/test/java/org/springframework/util/xml/StaxResultTests.java
new file mode 100644
index 00000000..ecd6a26e
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/xml/StaxResultTests.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2002-2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util.xml;
+
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import javax.xml.stream.XMLEventWriter;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamWriter;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamSource;
+
+import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import org.junit.Before;
+import org.junit.Test;
+
+public class StaxResultTests {
+
+ private static final String XML = "<root xmlns='namespace'><child/></root>";
+
+ private Transformer transformer;
+
+ private XMLOutputFactory inputFactory;
+
+ @Before
+ public void setUp() throws Exception {
+ TransformerFactory transformerFactory = TransformerFactory.newInstance();
+ transformer = transformerFactory.newTransformer();
+ inputFactory = XMLOutputFactory.newInstance();
+ }
+
+ @Test
+ public void streamWriterSource() throws Exception {
+ StringWriter stringWriter = new StringWriter();
+ XMLStreamWriter streamWriter = inputFactory.createXMLStreamWriter(stringWriter);
+ Reader reader = new StringReader(XML);
+ Source source = new StreamSource(reader);
+ StaxResult result = new StaxResult(streamWriter);
+ assertEquals("Invalid streamWriter returned", streamWriter, result.getXMLStreamWriter());
+ assertNull("EventWriter returned", result.getXMLEventWriter());
+ transformer.transform(source, result);
+ assertXMLEqual("Invalid result", XML, stringWriter.toString());
+ }
+
+ @Test
+ public void eventWriterSource() throws Exception {
+ StringWriter stringWriter = new StringWriter();
+ XMLEventWriter eventWriter = inputFactory.createXMLEventWriter(stringWriter);
+ Reader reader = new StringReader(XML);
+ Source source = new StreamSource(reader);
+ StaxResult result = new StaxResult(eventWriter);
+ assertEquals("Invalid eventWriter returned", eventWriter, result.getXMLEventWriter());
+ assertNull("StreamWriter returned", result.getXMLStreamWriter());
+ transformer.transform(source, result);
+ assertXMLEqual("Invalid result", XML, stringWriter.toString());
+ }
+
+} \ No newline at end of file
diff --git a/spring-core/src/test/java/org/springframework/util/xml/StaxSourceTests.java b/spring-core/src/test/java/org/springframework/util/xml/StaxSourceTests.java
new file mode 100644
index 00000000..638b997b
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/xml/StaxSourceTests.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util.xml;
+
+import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.stream.StreamResult;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
+
+public class StaxSourceTests {
+
+ private static final String XML = "<root xmlns='namespace'><child/></root>";
+
+ private Transformer transformer;
+
+ private XMLInputFactory inputFactory;
+
+ private DocumentBuilder documentBuilder;
+
+ @Before
+ public void setUp() throws Exception {
+ TransformerFactory transformerFactory = TransformerFactory.newInstance();
+ transformer = transformerFactory.newTransformer();
+ inputFactory = XMLInputFactory.newInstance();
+ DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+ documentBuilderFactory.setNamespaceAware(true);
+ documentBuilder = documentBuilderFactory.newDocumentBuilder();
+ }
+
+ @Test
+ public void streamReaderSourceToStreamResult() throws Exception {
+ XMLStreamReader streamReader = inputFactory.createXMLStreamReader(new StringReader(XML));
+ StaxSource source = new StaxSource(streamReader);
+ assertEquals("Invalid streamReader returned", streamReader, source.getXMLStreamReader());
+ assertNull("EventReader returned", source.getXMLEventReader());
+ StringWriter writer = new StringWriter();
+ transformer.transform(source, new StreamResult(writer));
+ assertXMLEqual("Invalid result", XML, writer.toString());
+ }
+
+ @Test
+ public void streamReaderSourceToDOMResult() throws Exception {
+ XMLStreamReader streamReader = inputFactory.createXMLStreamReader(new StringReader(XML));
+ StaxSource source = new StaxSource(streamReader);
+ assertEquals("Invalid streamReader returned", streamReader, source.getXMLStreamReader());
+ assertNull("EventReader returned", source.getXMLEventReader());
+
+ Document expected = documentBuilder.parse(new InputSource(new StringReader(XML)));
+ Document result = documentBuilder.newDocument();
+ transformer.transform(source, new DOMResult(result));
+ assertXMLEqual("Invalid result", expected, result);
+ }
+
+ @Test
+ public void eventReaderSourceToStreamResult() throws Exception {
+ XMLEventReader eventReader = inputFactory.createXMLEventReader(new StringReader(XML));
+ StaxSource source = new StaxSource(eventReader);
+ assertEquals("Invalid eventReader returned", eventReader, source.getXMLEventReader());
+ assertNull("StreamReader returned", source.getXMLStreamReader());
+ StringWriter writer = new StringWriter();
+ transformer.transform(source, new StreamResult(writer));
+ assertXMLEqual("Invalid result", XML, writer.toString());
+ }
+
+ @Test
+ public void eventReaderSourceToDOMResult() throws Exception {
+ XMLEventReader eventReader = inputFactory.createXMLEventReader(new StringReader(XML));
+ StaxSource source = new StaxSource(eventReader);
+ assertEquals("Invalid eventReader returned", eventReader, source.getXMLEventReader());
+ assertNull("StreamReader returned", source.getXMLStreamReader());
+
+ Document expected = documentBuilder.parse(new InputSource(new StringReader(XML)));
+ Document result = documentBuilder.newDocument();
+ transformer.transform(source, new DOMResult(result));
+ assertXMLEqual("Invalid result", expected, result);
+ }
+}
diff --git a/spring-core/src/test/java/org/springframework/util/xml/StaxStreamContentHandlerTests.java b/spring-core/src/test/java/org/springframework/util/xml/StaxStreamContentHandlerTests.java
new file mode 100644
index 00000000..f39f0bff
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/xml/StaxStreamContentHandlerTests.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2002-2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util.xml;
+
+import java.io.Writer;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+
+public class StaxStreamContentHandlerTests extends AbstractStaxContentHandlerTestCase {
+
+ @Override
+ protected AbstractStaxContentHandler createStaxContentHandler(Writer writer) throws XMLStreamException {
+ XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
+ return new StaxStreamContentHandler(outputFactory.createXMLStreamWriter(writer));
+ }
+} \ No newline at end of file
diff --git a/spring-core/src/test/java/org/springframework/util/xml/StaxStreamXMLReaderTests.java b/spring-core/src/test/java/org/springframework/util/xml/StaxStreamXMLReaderTests.java
new file mode 100644
index 00000000..e074085f
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/xml/StaxStreamXMLReaderTests.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util.xml;
+
+import java.io.InputStream;
+import java.io.StringReader;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.junit.Test;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
+
+import static org.junit.Assert.*;
+import static org.mockito.Matchers.*;
+import static org.mockito.BDDMockito.*;
+
+public class StaxStreamXMLReaderTests extends AbstractStaxXMLReaderTestCase {
+
+ public static final String CONTENT = "<root xmlns='http://springframework.org/spring-ws'><child/></root>";
+
+ @Override
+ protected AbstractStaxXMLReader createStaxXmlReader(InputStream inputStream) throws XMLStreamException {
+ return new StaxStreamXMLReader(inputFactory.createXMLStreamReader(inputStream));
+ }
+
+ @Test
+ public void testPartial() throws Exception {
+ XMLInputFactory inputFactory = XMLInputFactory.newInstance();
+ XMLStreamReader streamReader = inputFactory.createXMLStreamReader(new StringReader(CONTENT));
+ streamReader.nextTag(); // skip to root
+ assertEquals("Invalid element", new QName("http://springframework.org/spring-ws", "root"),
+ streamReader.getName());
+ streamReader.nextTag(); // skip to child
+ assertEquals("Invalid element", new QName("http://springframework.org/spring-ws", "child"),
+ streamReader.getName());
+ StaxStreamXMLReader xmlReader = new StaxStreamXMLReader(streamReader);
+
+ ContentHandler contentHandler = mock(ContentHandler.class);
+ xmlReader.setContentHandler(contentHandler);
+ xmlReader.parse(new InputSource());
+
+ verify(contentHandler).setDocumentLocator(any(Locator.class));
+ verify(contentHandler).startDocument();
+ verify(contentHandler).startElement(eq("http://springframework.org/spring-ws"), eq("child"), eq("child"), any(Attributes.class));
+ verify(contentHandler).endElement("http://springframework.org/spring-ws", "child", "child");
+ verify(contentHandler).endDocument();
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/xml/StaxUtilsTest.java b/spring-core/src/test/java/org/springframework/util/xml/StaxUtilsTest.java
new file mode 100644
index 00000000..abe11528
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/xml/StaxUtilsTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2002-2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util.xml;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.sax.SAXResult;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.stax.StAXResult;
+import javax.xml.transform.stax.StAXSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import static org.junit.Assert.*;
+import org.junit.Test;
+
+public class StaxUtilsTest {
+
+ @Test
+ public void isStaxSourceInvalid() throws Exception {
+ assertFalse("A StAX Source", StaxUtils.isStaxSource(new DOMSource()));
+ assertFalse("A StAX Source", StaxUtils.isStaxSource(new SAXSource()));
+ assertFalse("A StAX Source", StaxUtils.isStaxSource(new StreamSource()));
+ }
+
+ @Test
+ public void isStaxSource() throws Exception {
+ XMLInputFactory inputFactory = XMLInputFactory.newInstance();
+ String expected = "<element/>";
+ XMLStreamReader streamReader = inputFactory.createXMLStreamReader(new StringReader(expected));
+ Source source = StaxUtils.createCustomStaxSource(streamReader);
+
+ assertTrue("Not a StAX Source", StaxUtils.isStaxSource(source));
+ }
+
+ @Test
+ public void isStaxSourceJaxp14() throws Exception {
+ XMLInputFactory inputFactory = XMLInputFactory.newInstance();
+ String expected = "<element/>";
+ XMLStreamReader streamReader = inputFactory.createXMLStreamReader(new StringReader(expected));
+ StAXSource source = new StAXSource(streamReader);
+
+ assertTrue("Not a StAX Source", StaxUtils.isStaxSource(source));
+ }
+
+ @Test
+ public void isStaxResultInvalid() throws Exception {
+ assertFalse("A StAX Result", StaxUtils.isStaxResult(new DOMResult()));
+ assertFalse("A StAX Result", StaxUtils.isStaxResult(new SAXResult()));
+ assertFalse("A StAX Result", StaxUtils.isStaxResult(new StreamResult()));
+ }
+
+ @Test
+ public void isStaxResult() throws Exception {
+ XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
+ XMLStreamWriter streamWriter = outputFactory.createXMLStreamWriter(new StringWriter());
+ Result result = StaxUtils.createCustomStaxResult(streamWriter);
+
+ assertTrue("Not a StAX Result", StaxUtils.isStaxResult(result));
+ }
+
+ @Test
+ public void isStaxResultJaxp14() throws Exception {
+ XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
+ XMLStreamWriter streamWriter = outputFactory.createXMLStreamWriter(new StringWriter());
+ StAXResult result = new StAXResult(streamWriter);
+
+ assertTrue("Not a StAX Result", StaxUtils.isStaxResult(result));
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/xml/TransformerUtilsTests.java b/spring-core/src/test/java/org/springframework/util/xml/TransformerUtilsTests.java
new file mode 100644
index 00000000..21eb30b7
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/xml/TransformerUtilsTests.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util.xml;
+
+import java.util.Properties;
+import javax.xml.transform.ErrorListener;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.URIResolver;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import org.junit.Test;
+
+/**
+ * @author Rick Evans
+ * @author Arjen Poutsma
+ */
+public class TransformerUtilsTests {
+
+ @Test
+ public void enableIndentingSunnyDay() throws Exception {
+ Transformer transformer = new StubTransformer();
+ TransformerUtils.enableIndenting(transformer);
+ String indent = transformer.getOutputProperty(OutputKeys.INDENT);
+ assertNotNull(indent);
+ assertEquals("yes", indent);
+ String indentAmount = transformer.getOutputProperty("{http://xml.apache.org/xslt}indent-amount");
+ assertNotNull(indentAmount);
+ assertEquals(String.valueOf(TransformerUtils.DEFAULT_INDENT_AMOUNT), indentAmount);
+ }
+
+ @Test
+ public void enableIndentingSunnyDayWithCustomKosherIndentAmount() throws Exception {
+ final String indentAmountProperty = "10";
+ Transformer transformer = new StubTransformer();
+ TransformerUtils.enableIndenting(transformer, Integer.valueOf(indentAmountProperty));
+ String indent = transformer.getOutputProperty(OutputKeys.INDENT);
+ assertNotNull(indent);
+ assertEquals("yes", indent);
+ String indentAmount = transformer.getOutputProperty("{http://xml.apache.org/xslt}indent-amount");
+ assertNotNull(indentAmount);
+ assertEquals(indentAmountProperty, indentAmount);
+ }
+
+ @Test
+ public void disableIndentingSunnyDay() throws Exception {
+ Transformer transformer = new StubTransformer();
+ TransformerUtils.disableIndenting(transformer);
+ String indent = transformer.getOutputProperty(OutputKeys.INDENT);
+ assertNotNull(indent);
+ assertEquals("no", indent);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void enableIndentingWithNullTransformer() throws Exception {
+ TransformerUtils.enableIndenting(null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void disableIndentingWithNullTransformer() throws Exception {
+ TransformerUtils.disableIndenting(null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void enableIndentingWithNegativeIndentAmount() throws Exception {
+ TransformerUtils.enableIndenting(new StubTransformer(), -21938);
+ }
+
+ @Test
+ public void enableIndentingWithZeroIndentAmount() throws Exception {
+ TransformerUtils.enableIndenting(new StubTransformer(), 0);
+ }
+
+ private static class StubTransformer extends Transformer {
+
+ private Properties outputProperties = new Properties();
+
+ @Override
+ public void transform(Source xmlSource, Result outputTarget) throws TransformerException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setParameter(String name, Object value) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Object getParameter(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void clearParameters() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setURIResolver(URIResolver resolver) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public URIResolver getURIResolver() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setOutputProperties(Properties oformat) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Properties getOutputProperties() {
+ return this.outputProperties;
+ }
+
+ @Override
+ public void setOutputProperty(String name, String value) throws IllegalArgumentException {
+ this.outputProperties.setProperty(name, value);
+ }
+
+ @Override
+ public String getOutputProperty(String name) throws IllegalArgumentException {
+ return this.outputProperties.getProperty(name);
+ }
+
+ @Override
+ public void setErrorListener(ErrorListener listener) throws IllegalArgumentException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ErrorListener getErrorListener() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+}
diff --git a/spring-core/src/test/java/org/springframework/util/xml/XMLEventStreamReaderTests.java b/spring-core/src/test/java/org/springframework/util/xml/XMLEventStreamReaderTests.java
new file mode 100644
index 00000000..6e752b9d
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/xml/XMLEventStreamReaderTests.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2002-2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util.xml;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.custommonkey.xmlunit.XMLAssert.*;
+
+public class XMLEventStreamReaderTests {
+
+ private static final String XML =
+ "<?pi content?><root xmlns='namespace'><prefix:child xmlns:prefix='namespace2'>content</prefix:child></root>"
+ ;
+
+ private XMLEventStreamReader streamReader;
+
+ @Before
+ public void createStreamReader() throws Exception {
+ XMLInputFactory inputFactory = XMLInputFactory.newInstance();
+ XMLEventReader eventReader = inputFactory.createXMLEventReader(new StringReader(XML));
+ streamReader = new XMLEventStreamReader(eventReader);
+ }
+
+ @Test
+ public void readAll() throws Exception {
+ while (streamReader.hasNext()) {
+ streamReader.next();
+ }
+ }
+
+ @Test
+ public void readCorrect() throws Exception {
+ Transformer transformer = TransformerFactory.newInstance().newTransformer();
+ StaxSource source = new StaxSource(streamReader);
+ StringWriter writer = new StringWriter();
+ transformer.transform(source, new StreamResult(writer));
+ assertXMLEqual(XML, writer.toString());
+ }
+
+} \ No newline at end of file
diff --git a/spring-core/src/test/java/org/springframework/util/xml/XMLEventStreamWriterTests.java b/spring-core/src/test/java/org/springframework/util/xml/XMLEventStreamWriterTests.java
new file mode 100644
index 00000000..00fb47bd
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/util/xml/XMLEventStreamWriterTests.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.util.xml;
+
+import java.io.StringWriter;
+import javax.xml.stream.XMLEventFactory;
+import javax.xml.stream.XMLEventWriter;
+import javax.xml.stream.XMLOutputFactory;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.custommonkey.xmlunit.XMLAssert.*;
+
+public class XMLEventStreamWriterTests {
+
+ private static final String XML =
+ "<?pi content?><root xmlns='namespace'><prefix:child xmlns:prefix='namespace2'><!--comment-->content</prefix:child></root>";
+
+ private XMLEventStreamWriter streamWriter;
+
+ private StringWriter stringWriter;
+
+ @Before
+ public void createStreamReader() throws Exception {
+ stringWriter = new StringWriter();
+ XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
+ XMLEventWriter eventWriter = outputFactory.createXMLEventWriter(stringWriter);
+ streamWriter = new XMLEventStreamWriter(eventWriter, XMLEventFactory.newInstance());
+ }
+
+ @Test
+ public void write() throws Exception {
+ streamWriter.writeStartDocument();
+ streamWriter.writeProcessingInstruction("pi", "content");
+ streamWriter.writeStartElement("namespace", "root");
+ streamWriter.writeDefaultNamespace("namespace");
+ streamWriter.writeStartElement("prefix", "child", "namespace2");
+ streamWriter.writeNamespace("prefix", "namespace2");
+ streamWriter.writeComment("comment");
+ streamWriter.writeCharacters("content");
+ streamWriter.writeEndElement();
+ streamWriter.writeEndElement();
+ streamWriter.writeEndDocument();
+
+ assertXMLEqual(XML, stringWriter.toString());
+ }
+
+
+}