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]

Reply via email to