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: + * + */ +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); + } + +}