2009/05/20 - Apache Shale has been retired.

For more information, please explore the Attic.

View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to you under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   *
17   * $Id: FacesComponent.java 372303 2006-01-25 20:09:24Z craigmcc $
18   */
19  
20  package org.apache.shale.tiger.register.faces;
21  
22  import java.lang.reflect.InvocationTargetException;
23  import java.lang.reflect.Method;
24  import javax.faces.FacesException;
25  import javax.faces.event.PhaseEvent;
26  import javax.faces.event.PhaseId;
27  import javax.faces.event.PhaseListener;
28  import org.apache.shale.tiger.register.AfterPhase;
29  import org.apache.shale.tiger.register.BeforePhase;
30  import org.apache.shale.tiger.register.FacesPhaseListener;
31  
32  /***
33   * <p>Adapter class for a phase listener that specifies the
34   * {@link FacesPhaseListener} annotation, but does not actually
35   * implement the <code>PhaseListener</code> interface.</p>
36   */
37  public final class PhaseListenerAdapter implements PhaseListener {
38  
39  
40      /***
41       * Serial version UID.
42       */
43      private static final long serialVersionUID = -8684913975588239869L;
44  
45  
46      /***
47       * <p>Construct a new adapter instance around the specified object
48       * instance, whose defining class MUST specify the
49       * {@link FacesPhaseListener} annotation, and whose implementation
50       * MUST NOT be an implementation of <code>javax.faces.event.PhaseListener</code>.</p>
51       *
52       * @param instance The object instance for which we should
53       *  construct a call-through adapter
54       *
55       * @exception IllegalArgumentException if the class for the specified
56       *  instance does not have a @FacesPhaseListener annotation
57       * @exception IllegalArgumentException if the method specified by the
58       *  @BeforePhase or @AfterPhase annotaion does not take exactly one
59       *  parameter of type <code>javax.faces.event.PhaseEvent</code>
60       */
61      public PhaseListenerAdapter(Object instance) {
62  
63          // Save the instance that we are adapting for
64          this.instance = instance;
65  
66          // Look up the @FacesFacesListener annotation for this class
67          FacesPhaseListener fpl = instance.getClass().getAnnotation(FacesPhaseListener.class);
68          if (fpl == null) {
69              throw new IllegalArgumentException("Implementing class "
70                + instance.getClass().getName()
71                + " does not have the @FacesPhaseListener annotation");
72          }
73  
74          // Extract the relevant before and after event methods from the
75          // underlying class
76          Method[] methods = instance.getClass().getMethods();
77          for (int i = 0; i < methods.length; i++) {
78              Method method = methods[i];
79              Class[] signature = method.getParameterTypes();
80              if (method.getAnnotation(BeforePhase.class) != null) {
81                  if (signature.length != 1) {
82                      throw new IllegalArgumentException("Method " + method.getName()
83                              + " of class " + instance.getClass().getName()
84                              + " does not take a exactly one parameter");
85                  } else if (!(signature[0] == PhaseEvent.class)) {
86                      throw new IllegalArgumentException("Method " + method.getName()
87                              + " of class " + instance.getClass().getName()
88                              + " does not take a javax.faces.event.PhaaseEvent parameter");
89                  } else {
90                      this.beforePhase = method;
91                  }
92              } else if (method.getAnnotation(AfterPhase.class) != null) {
93                  if (signature.length != 1) {
94                      throw new IllegalArgumentException("Method " + method.getName()
95                              + " of class " + instance.getClass().getName()
96                              + " does not take a exactly one parameter");
97                  } else if (!(signature[0] == PhaseEvent.class)) {
98                      throw new IllegalArgumentException("Method " + method.getName()
99                              + " of class " + instance.getClass().getName()
100                             + " does not take a javax.faces.event.PhaaseEvent parameter");
101                 } else {
102                     this.afterPhase = method;
103                 }
104             }
105         }
106 
107         // Extract the relevant phase identifer from the underlying class
108         FacesPhaseListener.PhaseId pi = fpl.phaseId();
109         if (pi == FacesPhaseListener.PhaseId.ANY_PHASE) {
110             this.phaseId = PhaseId.ANY_PHASE;
111         } else if (pi == FacesPhaseListener.PhaseId.RESTORE_VIEW) {
112             this.phaseId = PhaseId.RESTORE_VIEW;
113         } else if (pi == FacesPhaseListener.PhaseId.APPLY_REQUEST_VALUES) {
114             this.phaseId = PhaseId.APPLY_REQUEST_VALUES;
115         } else if (pi == FacesPhaseListener.PhaseId.PROCESS_VALIDATIONS) {
116             this.phaseId = PhaseId.PROCESS_VALIDATIONS;
117         } else if (pi == FacesPhaseListener.PhaseId.UPDATE_MODEL_VALUES) {
118             this.phaseId = PhaseId.UPDATE_MODEL_VALUES;
119         } else if (pi == FacesPhaseListener.PhaseId.INVOKE_APPLICATION) {
120             this.phaseId = PhaseId.INVOKE_APPLICATION;
121         } else if (pi == FacesPhaseListener.PhaseId.RENDER_RESPONSE) {
122             this.phaseId = PhaseId.RENDER_RESPONSE;
123         }
124 
125     }
126 
127 
128     // ------------------------------------------------------ Instance Variables
129 
130 
131     /***
132      * <p>Method definition for the {@link AfterPhase} method for this
133      * phase listener class.</p>
134      */
135     private Method afterPhase;
136 
137 
138     /***
139      * <p>Method definition for the {@link BeforePhase} method for this
140      * phase listener class.</p>
141      */
142     private Method beforePhase;
143 
144 
145     /***
146      * <p>The listener instance for which we are an adapter.</p>
147      */
148     private Object instance;
149 
150 
151     /***
152      * <p>The <code>PhaseId</code> to be returned by our
153      * <code>getPhaseId()</code> method.</p>
154      */
155     private PhaseId phaseId;
156 
157 
158     // --------------------------------------------------- PhaseListener Methods
159 
160 
161     /***
162      * <p>Process an "after phase" event.</p>
163      *
164      * @param event The <code>PhaseEvent</code> to be processed
165      *
166      * @exception FacesException if an exception occurs invoking the
167      *  appropriate event handling method
168      */
169     public void afterPhase(PhaseEvent event) {
170 
171         if (afterPhase == null) {
172             return;
173         }
174         try {
175             afterPhase.invoke(instance, event);
176         } catch (InvocationTargetException e) {
177             throw new FacesException(e.getTargetException());
178         } catch (Exception e) {
179             throw new FacesException(e);
180         }
181 
182     }
183 
184 
185     /***
186      * <p>Process a "before phase" event.</p>
187      *
188      * @param event The <code>PhaseEvent</code> to be processed
189      *
190      * @exception FacesException if an exception occurs invoking the
191      *  appropriate event handling method
192      */
193     public void beforePhase(PhaseEvent event) {
194 
195         if (beforePhase == null) {
196             return;
197         }
198         try {
199             beforePhase.invoke(instance, event);
200         } catch (InvocationTargetException e) {
201             throw new FacesException(e.getTargetException());
202         } catch (Exception e) {
203             throw new FacesException(e);
204         }
205 
206     }
207 
208 
209     /***
210      * <p>Return the identifier of the phase(s) we are interested in.</p>
211      */
212     public PhaseId getPhaseId() {
213 
214         return this.phaseId;
215 
216     }
217 
218 
219 }