diff --git a/org.springframework.expression/src/test/java/org/springframework/expression/spel/TestScenarioCreator.java b/org.springframework.expression/src/test/java/org/springframework/expression/spel/TestScenarioCreator.java
new file mode 100644
index 0000000000..1e2899efa4
--- /dev/null
+++ b/org.springframework.expression/src/test/java/org/springframework/expression/spel/TestScenarioCreator.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2004-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.expression.spel;
+
+import java.awt.Color;
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.springframework.expression.spel.standard.StandardEvaluationContext;
+import org.springframework.expression.spel.testresources.Fruit;
+import org.springframework.expression.spel.testresources.Inventor;
+import org.springframework.expression.spel.testresources.Person;
+import org.springframework.expression.spel.testresources.PlaceOfBirth;
+
+/**
+ * Builds an evaluation context for test expressions. Features of the test evaluation context are:
+ *
+ * - The root context object is an Inventor instance {@link Inventor}
+ *
+ */
+public class TestScenarioCreator {
+
+ public static StandardEvaluationContext getTestEvaluationContext() {
+ StandardEvaluationContext testContext = new StandardEvaluationContext();
+ setupRootContextObject(testContext);
+ populateContextMap(testContext);
+ createTestClassloader(testContext);
+ populateVariables(testContext);
+ populateFunctions(testContext);
+ return testContext;
+ }
+
+ /**
+ * Register some Java reflect methods as well known functions that can be called from an expression.
+ * @param testContext the test evaluation context
+ */
+ private static void populateFunctions(StandardEvaluationContext testContext) {
+ try {
+ testContext.registerFunction("isEven", TestScenarioCreator.class.getDeclaredMethod("isEven",
+ new Class[] { Integer.TYPE }));
+ testContext.registerFunction("reverseInt", TestScenarioCreator.class.getDeclaredMethod("reverseInt",
+ new Class[] { Integer.TYPE, Integer.TYPE, Integer.TYPE }));
+ testContext.registerFunction("reverseString", TestScenarioCreator.class.getDeclaredMethod("reverseString",
+ new Class[] { String.class }));
+ } catch (SecurityException e) {
+ e.printStackTrace();
+ } catch (NoSuchMethodException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Register some variables that can be referenced from the tests
+ * @param testContext the test evaluation context
+ */
+ private static void populateVariables(StandardEvaluationContext testContext) {
+ testContext.setVariable("answer", 42);
+ }
+
+ /**
+ * Include a testcode jar on the default context classpath so that tests can lookup entries in it.
+ * @param testContext the test evaluation context
+ */
+ private static void createTestClassloader(StandardEvaluationContext testContext) {
+ try {
+ ClassLoader cl = new URLClassLoader(new URL[] { new File("target/test-classes/testcode.jar").toURL() },
+ Thread.currentThread().getContextClassLoader());
+ testContext.setClassLoader(cl);
+ } catch (MalformedURLException mue) {
+ mue.printStackTrace();
+ }
+ }
+
+ /**
+ * Create the root context object, an Inventor instance. Non-qualified property and method references will be
+ * resolved against this context object.
+ *
+ * @param testContext the evaluation context in which to set the root object
+ */
+ private static void setupRootContextObject(StandardEvaluationContext testContext) {
+ Inventor tesla = new Inventor("Nikola Tesla", new Date(1856, 7, 9), "Serbian");
+ tesla.setPlaceOfBirth(new PlaceOfBirth("SmilJan"));
+ tesla.setInventions(new String[] { "Telephone repeater", "Rotating magnetic field principle",
+ "Polyphase alternating-current system", "Induction motor", "Alternating-current power transmission",
+ "Tesla coil transformer", "Wireless communication", "Radio", "Fluorescent lights" });
+ testContext.setRootObject(tesla);
+ }
+
+ /**
+ * Create a context configuration that tests can reference into using the
+ * @() language construct.
+ * @(context:objectName) will index a particular object within a particular context. The 'root' context will be used
+ * for references where no context is specified, eg.
+ * @(orange).
+ *
+ * @param testContext the evaluation context in which to register the new references
+ */
+ private static void populateContextMap(StandardEvaluationContext testContext) {
+ Map> contextToReferencesMap = new HashMap>();
+
+ Person andy, christian, julie, stefanie, rob, rod, adrian;
+ andy = new Person("Andy");
+ christian = new Person("Christian");
+ julie = new Person("Julie");
+ stefanie = new Person("Stefanie");
+ rod = new Person("Rod");
+ rob = new Person("Rob");
+ adrian = new Person("Adrian");
+
+ Map people = new HashMap();
+ people.put("Andy", andy);
+ people.put("Christian", christian);
+ people.put("Julie", julie);
+ people.put("Stefanie", stefanie);
+
+ Map colors = new HashMap();
+ colors.put("red", Color.red);
+ colors.put("orange", Color.orange);
+ colors.put("yellow", Color.yellow);
+ colors.put("green", Color.red);
+ colors.put("blue", Color.orange);
+ contextToReferencesMap.put("colors", colors);
+
+ Map fruits = new HashMap();
+ fruits.put("orange", new Fruit("Orange", Color.orange, "orange"));
+ fruits.put("apple", new Fruit("Apple", Color.green, "green"));
+ fruits.put("banana", new Fruit("Banana", Color.yellow, "yellow"));
+
+ Map root = new HashMap();
+ root.put("orange", new Fruit("Orange", Color.orange, "orange"));
+ root.put("apple", new Fruit("Apple", Color.green, "green"));
+ root.put("banana", new Fruit("Banana", Color.yellow, "yellow"));
+ root.put("red", Color.red);
+ root.put("orange", Color.orange);
+ root.put("yellow", Color.yellow);
+ root.put("green", Color.red);
+ root.put("blue", Color.orange);
+ root.put("Andy", andy);
+ root.put("Christian", christian);
+ root.put("Julie", julie);
+ root.put("Stefanie", stefanie);
+ root.put("Adrian", adrian);
+ root.put("Rob", rob);
+ root.put("Rod", rod);
+
+ contextToReferencesMap.put("people", people);
+ contextToReferencesMap.put("fruits", fruits);
+ contextToReferencesMap.put("root", root); // used if no context
+ // specified
+
+ contextToReferencesMap.put("a.b.c", fruits);
+ java.util.Set contextKeys = contextToReferencesMap.keySet();
+ for (String contextName : contextKeys) {
+ Map elements = contextToReferencesMap.get(contextName);
+ Set objectNames = elements.keySet();
+ for (String objectName : objectNames) {
+ testContext.addReference(contextName, objectName, elements.get(objectName));
+ }
+ }
+ }
+
+ // These methods are registered in the test context and therefore accessible through function calls
+ // in test expressions
+
+ public static String isEven(int i) {
+ if ((i % 2) == 0)
+ return "y";
+ return "n";
+ }
+
+ public static int[] reverseInt(int i, int j, int k) {
+ return new int[] { k, j, i };
+ }
+
+ public static String reverseString(String input) {
+ StringBuffer backwards = new StringBuffer();
+ for (int i = 0; i < input.length(); i++) {
+ backwards.append(input.charAt(input.length() - 1 - i));
+ }
+ return backwards.toString();
+ }
+}
diff --git a/org.springframework.expression/src/test/java/org/springframework/expression/spel/TypeReferencing.java b/org.springframework.expression/src/test/java/org/springframework/expression/spel/TypeReferencing.java
new file mode 100644
index 0000000000..aa7f031e76
--- /dev/null
+++ b/org.springframework.expression/src/test/java/org/springframework/expression/spel/TypeReferencing.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2004-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.expression.spel;
+
+import org.springframework.expression.spel.standard.StandardTypeLocator;
+
+/**
+ * Tests referring to system types, custom types, unqualified types.
+ *
+ * @author Andy Clement
+ */
+public class TypeReferencing extends ExpressionTestCase {
+
+ public void testFromAJar() {
+ evaluate("new SimpleType().sayHi('Andy')", "Hi! Andy", String.class);
+ }
+
+ public void testFromAJar2() {
+ evaluate("new a.b.c.PackagedType().sayHi('Andy')", "Hi! Andy", String.class);
+ }
+
+ public void testFromAJar3() {
+ evaluateAndCheckError("new PackagedType().sayHi('Andy')", SpelMessages.TYPE_NOT_FOUND);
+ }
+
+ public void testFromAJar4() {
+ ((StandardTypeLocator) eContext.getTypeUtils().getTypeLocator()).registerImport("a.b.c");
+ evaluate("new PackagedType().sayHi('Andy')", "Hi! Andy", String.class);
+ }
+
+}