Author: craigmcc Date: Sat Jan 14 18:25:29 2006 New Revision: 369163 URL: http://svn.apache.org/viewcvs?rev=369163&view=rev Log: Fully implement view controller callbacks via annotations (instead of requiring a backing bean to implement ViewController) when running on a Java SE 5 or later platform. These features are enabled automatically by virtue of including "shale-tiger.jar" with your web application -- no special configuration is required.
Added: struts/shale/trunk/tiger/src/java/org/apache/shale/tiger/view/faces/ struts/shale/trunk/tiger/src/java/org/apache/shale/tiger/view/faces/ViewControllerCallbacks2.java struts/shale/trunk/tiger/src/java/org/apache/shale/tiger/view/faces/package.html struts/shale/trunk/tiger/src/test/org/apache/shale/tiger/view/ struts/shale/trunk/tiger/src/test/org/apache/shale/tiger/view/faces/ struts/shale/trunk/tiger/src/test/org/apache/shale/tiger/view/faces/CallbacksFactoryTestCase.java struts/shale/trunk/tiger/src/test/org/apache/shale/tiger/view/faces/TestViewController.java struts/shale/trunk/tiger/src/test/org/apache/shale/tiger/view/faces/ViewControllerCallbacks2TestCase.java Modified: struts/shale/trunk/tiger/build.xml struts/shale/trunk/tiger/src/java/org/apache/shale/tiger/view/Destroy.java struts/shale/trunk/tiger/src/java/org/apache/shale/tiger/view/Init.java struts/shale/trunk/tiger/src/java/org/apache/shale/tiger/view/Prerender.java struts/shale/trunk/tiger/src/java/org/apache/shale/tiger/view/package.html Modified: struts/shale/trunk/tiger/build.xml URL: http://svn.apache.org/viewcvs/struts/shale/trunk/tiger/build.xml?rev=369163&r1=369162&r2=369163&view=diff ============================================================================== --- struts/shale/trunk/tiger/build.xml (original) +++ struts/shale/trunk/tiger/build.xml Sat Jan 14 18:25:29 2006 @@ -176,6 +176,7 @@ <copy todir="${build.home}/classes"> <fileset dir="src/java"> <exclude name="**/*.java"/> + <exclude name="**/package.html"/> </fileset> </copy> Modified: struts/shale/trunk/tiger/src/java/org/apache/shale/tiger/view/Destroy.java URL: http://svn.apache.org/viewcvs/struts/shale/trunk/tiger/src/java/org/apache/shale/tiger/view/Destroy.java?rev=369163&r1=369162&r2=369163&view=diff ============================================================================== --- struts/shale/trunk/tiger/src/java/org/apache/shale/tiger/view/Destroy.java (original) +++ struts/shale/trunk/tiger/src/java/org/apache/shale/tiger/view/Destroy.java Sat Jan 14 18:25:29 2006 @@ -22,7 +22,7 @@ import java.lang.annotation.Target; /** - * <p>Methoid-level annotation indicating that the decorated method should + * <p>Method-level annotation indicating that the decorated method should * have the semantics of * <code>org.apache.shale.view.ViewController.destroy()</code>, * even if it is named differently.</p> Modified: struts/shale/trunk/tiger/src/java/org/apache/shale/tiger/view/Init.java URL: http://svn.apache.org/viewcvs/struts/shale/trunk/tiger/src/java/org/apache/shale/tiger/view/Init.java?rev=369163&r1=369162&r2=369163&view=diff ============================================================================== --- struts/shale/trunk/tiger/src/java/org/apache/shale/tiger/view/Init.java (original) +++ struts/shale/trunk/tiger/src/java/org/apache/shale/tiger/view/Init.java Sat Jan 14 18:25:29 2006 @@ -22,7 +22,7 @@ import java.lang.annotation.Target; /** - * <p>Methoid-level annotation indicating that the decorated method should + * <p>Method-level annotation indicating that the decorated method should * have the semantics of * <code>org.apache.shale.view.ViewController.init()</code>, * even if it is named differently.</p> Modified: struts/shale/trunk/tiger/src/java/org/apache/shale/tiger/view/Prerender.java URL: http://svn.apache.org/viewcvs/struts/shale/trunk/tiger/src/java/org/apache/shale/tiger/view/Prerender.java?rev=369163&r1=369162&r2=369163&view=diff ============================================================================== --- struts/shale/trunk/tiger/src/java/org/apache/shale/tiger/view/Prerender.java (original) +++ struts/shale/trunk/tiger/src/java/org/apache/shale/tiger/view/Prerender.java Sat Jan 14 18:25:29 2006 @@ -22,7 +22,7 @@ import java.lang.annotation.Target; /** - * <p>Methoid-level annotation indicating that the decorated method should + * <p>Method-level annotation indicating that the decorated method should * have the semantics of * <code>org.apache.shale.view.ViewController.prerender()</code>, * even if it is named differently.</p> Added: struts/shale/trunk/tiger/src/java/org/apache/shale/tiger/view/faces/ViewControllerCallbacks2.java URL: http://svn.apache.org/viewcvs/struts/shale/trunk/tiger/src/java/org/apache/shale/tiger/view/faces/ViewControllerCallbacks2.java?rev=369163&view=auto ============================================================================== --- struts/shale/trunk/tiger/src/java/org/apache/shale/tiger/view/faces/ViewControllerCallbacks2.java (added) +++ struts/shale/trunk/tiger/src/java/org/apache/shale/tiger/view/faces/ViewControllerCallbacks2.java Sat Jan 14 18:25:29 2006 @@ -0,0 +1,237 @@ +/* + * Copyright 2006 The Apache Software Foundation. + * + * 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.apache.shale.tiger.view.faces; + +import java.lang.annotation.Annotation; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; +import javax.faces.FacesException; +import org.apache.shale.tiger.view.Destroy; +import org.apache.shale.tiger.view.Init; +import org.apache.shale.tiger.view.Preprocess; +import org.apache.shale.tiger.view.Prerender; +import org.apache.shale.tiger.view.View; +import org.apache.shale.view.ViewController; +import org.apache.shale.view.faces.ViewControllerCallbacks; + +/** + * <p>Utility class to perform the event callbacks specified by the + * [EMAIL PROTECTED] ViewController} interface. This version will call through + * to ViewController methods if the bean class actually implements this + * interface, or ituses annotations to identify the relevant methods.</p> + * + * <p><strong>NOTE</strong> - The annotated callback methods must be + * public, and take no arguments. They may exist on the class of the + * instance being passed in, or be inherited from a superclass.</p> + * + * $Id: ViewPhaseListener.java 367148 2006-01-09 01:01:56Z craigmcc $ + * + * @since 1.0.1 + */ +public class ViewControllerCallbacks2 extends ViewControllerCallbacks { + + + // ------------------------------------------------------------ Constructors + + + // ------------------------------------------------------ Instance Variables + + + // ---------------------------------------------------------- Public Methods + + + /** + * <p>Perform the <code>init</code> callback on the specified + * instance.</p> + * + * @param instance Bean instance on which to perform this callback + */ + public void init(Object instance) { + + if (instance instanceof ViewController) { + ((ViewController) instance).init(); + return; + } + + Method method = method(instance, Init.class); + if (method != null) { + try { + method.invoke(instance, new Object[0]); + } catch (IllegalAccessException e) { + throw new FacesException(e); + } catch (InvocationTargetException e) { + throw new FacesException(e.getCause()); + } + } + + } + + + /** + * <p>Perform the <code>preprocess</code> callback on the specified + * instance.</p> + * + * @param instance Bean instance on which to perform this callback + */ + public void preprocess(Object instance) { + + if (instance instanceof ViewController) { + ((ViewController) instance).preprocess(); + return; + } + + Method method = method(instance, Preprocess.class); + if (method != null) { + try { + method.invoke(instance, new Object[0]); + } catch (IllegalAccessException e) { + throw new FacesException(e); + } catch (InvocationTargetException e) { + throw new FacesException(e.getCause()); + } + } + + } + + + /** + * <p>Perform the <code>prerender</code> callback on the specified + * instance.</p> + * + * @param instance Bean instance on which to perform this callback + */ + public void prerender(Object instance) { + + if (instance instanceof ViewController) { + ((ViewController) instance).prerender(); + return; + } + + Method method = method(instance, Prerender.class); + if (method != null) { + try { + method.invoke(instance, new Object[0]); + } catch (IllegalAccessException e) { + throw new FacesException(e); + } catch (InvocationTargetException e) { + throw new FacesException(e.getCause()); + } + } + + } + + + /** + * <p>Perform the <code>destroy</code> callback on the specified + * instance.</p> + * + * @param instance Bean instance on which to perform this callback + */ + public void destroy(Object instance) { + + if (instance instanceof ViewController) { + ((ViewController) instance).destroy(); + return; + } + + Method method = method(instance, Destroy.class); + if (method != null) { + try { + method.invoke(instance, new Object[0]); + } catch (IllegalAccessException e) { + throw new FacesException(e); + } catch (InvocationTargetException e) { + throw new FacesException(e.getCause()); + } + } + + } + + + // --------------------------------------------------------- Private Methods + + + /** + * <p>The set of method annotations for callbacks of interest.</p> + */ + private static final Class annotations[] = + { Init.class, Preprocess.class, Prerender.class, Destroy.class }; + + + + /** + * <p>Data structure to maintain information about annotated + * methods. In this map, the key is the Class being analyzed, + * and the value is an inner map. In the inner map, the key + * is an Annotation class, and the value is the corresponding + * Method instance.</p> + */ + private transient Map<Class,Map<Class,Method>> maps = + new HashMap<Class,Map<Class,Method>>(); + + + /** + * <p>Return the <code>Method</code> to be called for the specified + * annotation on the specified instance, if any. If there is no such + * method, return <code>null</code>.</p> + * + * @param instance Instance on which callbacks will be performed + * @param annotation Annotation for which to return a method + */ + private Method method(Object instance, Class annotation) { + + // Does the underlying class implement the View annotation? + // If not, exit early + Class clazz = instance.getClass(); + if (clazz.getAnnotation(View.class) == null) { + return null; + } + + synchronized (maps) { + + // If we have seen this Class already, simply return the + // previously located Method (if any) + Map<Class,Method> map = maps.get(clazz); + if (map != null) { + return map.get(annotation); + } + + // Construct and cache a new Map identifying the + // methods of interest for these callbacks + map = new HashMap<Class,Method>(); + Method methods[] = clazz.getMethods(); + for (int i = 0; i < methods.length; i++) { + if (methods[i].getParameterTypes().length > 0) { + continue; + } + for (int j = 0; j < annotations.length; j++) { + if (methods[i].getAnnotation(annotations[j]) != null) { + map.put(annotations[j], methods[i]); + } + } + } + maps.put(clazz, map); + return map.get(annotation); + + } + + } + + +} Added: struts/shale/trunk/tiger/src/java/org/apache/shale/tiger/view/faces/package.html URL: http://svn.apache.org/viewcvs/struts/shale/trunk/tiger/src/java/org/apache/shale/tiger/view/faces/package.html?rev=369163&view=auto ============================================================================== --- struts/shale/trunk/tiger/src/java/org/apache/shale/tiger/view/faces/package.html (added) +++ struts/shale/trunk/tiger/src/java/org/apache/shale/tiger/view/faces/package.html Sat Jan 14 18:25:29 2006 @@ -0,0 +1,26 @@ +<!-- + * Copyright 2004-2005 The Apache Software Foundation. + * + * 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. +--> + +<!-- $Id: package.html 293010 2005-10-01 17:58:52Z wsmoak $ --> + +<body> + +<p>This package contains implementations of the event callback support +described in the <code>org.apache.shale.tiger.view</code> package.</p> + [EMAIL PROTECTED] 1.0.1 + +</body> Modified: struts/shale/trunk/tiger/src/java/org/apache/shale/tiger/view/package.html URL: http://svn.apache.org/viewcvs/struts/shale/trunk/tiger/src/java/org/apache/shale/tiger/view/package.html?rev=369163&r1=369162&r2=369163&view=diff ============================================================================== --- struts/shale/trunk/tiger/src/java/org/apache/shale/tiger/view/package.html (original) +++ struts/shale/trunk/tiger/src/java/org/apache/shale/tiger/view/package.html Sat Jan 14 18:25:29 2006 @@ -41,7 +41,7 @@ <p>API STATUS: Experimental.</p> -<p>IMPLEMENTATION STATUS: Not yet implemented.</p> +<p>IMPLEMENTATION STATUS: Implemented, but only lightly tested.</p> @since 1.0.1 Added: struts/shale/trunk/tiger/src/test/org/apache/shale/tiger/view/faces/CallbacksFactoryTestCase.java URL: http://svn.apache.org/viewcvs/struts/shale/trunk/tiger/src/test/org/apache/shale/tiger/view/faces/CallbacksFactoryTestCase.java?rev=369163&view=auto ============================================================================== --- struts/shale/trunk/tiger/src/test/org/apache/shale/tiger/view/faces/CallbacksFactoryTestCase.java (added) +++ struts/shale/trunk/tiger/src/test/org/apache/shale/tiger/view/faces/CallbacksFactoryTestCase.java Sat Jan 14 18:25:29 2006 @@ -0,0 +1,99 @@ +/* + * Copyright 2006 The Apache Software Foundation. + * + * 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.apache.shale.tiger.view.faces; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; +import org.apache.shale.view.faces.CallbacksFactory; +import org.apache.shale.view.faces.ViewControllerCallbacks; + +/** + * <p>Test case for <code>org.apache.shale.view.faces.CallbacksFactory</code> + * when the Shale Tiger extensions are available.</p> + */ +public class CallbacksFactoryTestCase extends TestCase { + + + // ------------------------------------------------------------ Constructors + + + // Construct a new instance of this test case. + public CallbacksFactoryTestCase(String name) { + super(name); + } + + + // ---------------------------------------------------- Overall Test Methods + + + // Set up instance variables required by this test case. + public void setUp() { + + factory = CallbacksFactory.getInstance(); + + } + + + // Return the tests included in this test case. + public static Test suite() { + + return (new TestSuite(CallbacksFactoryTestCase.class)); + + } + + + // Tear down instance variables required by this test case. + public void tearDown() { + + factory = null; + + } + + + // ------------------------------------------------------ Instance Variables + + + private CallbacksFactory factory = null; + + + // ------------------------------------------------------------ Test Methods + + + + // Test a prisine instance + public void testPristine() { + + ; + + } + + + // Test returning a ViewControllerCallbacks instance + public void testViewControllerCallbacks() { + + ViewControllerCallbacks vcc = factory.getViewControllerCallbacks(); + assertNotNull(vcc); + assertEquals("org.apache.shale.tiger.view.faces.ViewControllerCallbacks2", + vcc.getClass().getName()); + + } + + + + +} Added: struts/shale/trunk/tiger/src/test/org/apache/shale/tiger/view/faces/TestViewController.java URL: http://svn.apache.org/viewcvs/struts/shale/trunk/tiger/src/test/org/apache/shale/tiger/view/faces/TestViewController.java?rev=369163&view=auto ============================================================================== --- struts/shale/trunk/tiger/src/test/org/apache/shale/tiger/view/faces/TestViewController.java (added) +++ struts/shale/trunk/tiger/src/test/org/apache/shale/tiger/view/faces/TestViewController.java Sat Jan 14 18:25:29 2006 @@ -0,0 +1,55 @@ +/* + * Copyright 2006 The Apache Software Foundation. + * + * 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.apache.shale.tiger.view.faces; + +import org.apache.shale.tiger.view.Destroy; +import org.apache.shale.tiger.view.Init; +import org.apache.shale.tiger.view.Preprocess; +import org.apache.shale.tiger.view.Prerender; +import org.apache.shale.tiger.view.View; +import org.apache.shale.view.ViewController; + +/** + * <p>Test implementation of a view controller that is marked + * with annotations, rather than implementing the + * <code>ViewController</code> interface directly.</p> + */ [EMAIL PROTECTED] public class TestViewController { + + private StringBuffer sb = new StringBuffer(); + + @Prerender public void doPrerender() { + sb.append("prerender/"); + } + + @Preprocess public void doPreprocess() { + sb.append("preprocess/"); + } + + @Destroy public void doDestroy() { + sb.append("destroy/"); + } + + @Init public void doInit() { + sb.append("init/"); + } + + public String log() { + return sb.toString(); + } + +} Added: struts/shale/trunk/tiger/src/test/org/apache/shale/tiger/view/faces/ViewControllerCallbacks2TestCase.java URL: http://svn.apache.org/viewcvs/struts/shale/trunk/tiger/src/test/org/apache/shale/tiger/view/faces/ViewControllerCallbacks2TestCase.java?rev=369163&view=auto ============================================================================== --- struts/shale/trunk/tiger/src/test/org/apache/shale/tiger/view/faces/ViewControllerCallbacks2TestCase.java (added) +++ struts/shale/trunk/tiger/src/test/org/apache/shale/tiger/view/faces/ViewControllerCallbacks2TestCase.java Sat Jan 14 18:25:29 2006 @@ -0,0 +1,97 @@ +/* + * Copyright 2006 The Apache Software Foundation. + * + * 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.apache.shale.tiger.view.faces; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * <p>Test case for <code>org.apache.shale.tiger.view.faces.ViewControllerCallbacks2</code>.</p> + */ +public class ViewControllerCallbacks2TestCase extends TestCase { + + + // ------------------------------------------------------------ Constructors + + + // Construct a new instance of this test case. + public ViewControllerCallbacks2TestCase(String name) { + super(name); + } + + + // ---------------------------------------------------- Overall Test Methods + + + // Set up instance variables required by this test case. + public void setUp() { + + callbacks = new ViewControllerCallbacks2(); + + } + + + // Return the tests included in this test case. + public static Test suite() { + + return (new TestSuite(ViewControllerCallbacks2TestCase.class)); + + } + + + // Tear down instance variables required by this test case. + public void tearDown() { + + callbacks = null; + + } + + + // ------------------------------------------------------ Instance Variables + + + private ViewControllerCallbacks2 callbacks = null; + + + // ------------------------------------------------------------ Test Methods + + + + // Test a prisine instance + public void testPristine() { + + ; + + } + + + // Test calling all of the appropriate methods in order + public void testViewControllerCallbacks() { + + TestViewController tvc = new TestViewController(); + callbacks.init(tvc); + callbacks.preprocess(tvc); + callbacks.prerender(tvc); + callbacks.destroy(tvc); + assertEquals("init/preprocess/prerender/destroy/", + tvc.log()); + + } + + +} --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]