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  
18  package org.apache.shale.view.faces;
19  
20  import java.io.IOException;
21  import java.util.ArrayList;
22  import java.util.List;
23  import java.util.Map;
24  import javax.faces.component.UINamingContainer;
25  import javax.faces.context.ExternalContext;
26  import javax.faces.context.FacesContext;
27  import org.apache.commons.logging.Log;
28  import org.apache.commons.logging.LogFactory;
29  import org.apache.shale.util.Messages;
30  import org.apache.shale.view.Constants;
31  import org.apache.shale.view.ExceptionHandler;
32  import org.apache.shale.view.ViewController;
33  
34  /***
35   * <p>Specialized implementation of <code>UINamingContainer</code> that
36   * provides {@link ViewController} functionality for subviews.</p>
37   *
38   * $Id: SubviewComponent.java 464373 2006-10-16 04:21:54Z rahul $
39   */
40  public class SubviewComponent extends UINamingContainer {
41  
42  
43      // -------------------------------------------------------- Static Variables
44  
45  
46      /***
47       * <p>Log instance for this class.</p>
48       */
49      private static final Log log = LogFactory.getLog(SubviewComponent.class);
50  
51  
52      /***
53       * <p>Message resources for this class.</p>
54       */
55      private static Messages messages =
56        new Messages("org.apache.shale.view.resources.Bundle",
57                     SubviewComponent.class.getClassLoader());
58  
59  
60      // ----------------------------------------------------- UIComponent Methods
61  
62  
63      /***
64       * <p>Return the component family for this component.</p>
65       */
66      public String getFamily() {
67  
68          return "org.apache.shale.view.Subview";
69  
70      }
71  
72  
73      /***
74       * <p>Prior to the standard processing, call the <code>prerender()</code>
75       * callback on the {@link ViewController} associated with this subview,
76       * if any.</p>
77       *
78       * @param context <code>FacesContext</code> for the current request
79       *
80       * @exception IOException if an input/output error occurs
81       */
82      public void encodeBegin(FacesContext context) throws IOException {
83  
84          Object vc = getViewController(context, false);
85          if (vc != null) {
86              try {
87                  getViewControllerCallbacks(context).prerender(vc);
88              } catch (Exception e) {
89                  handleException(context, e);
90              }
91          }
92          super.encodeBegin(context);
93  
94      }
95  
96  
97      /***
98       * <p>Prior to the standard processing, call the <code>preprocess()</code>
99       * callback on the {@link ViewController} associated with this subview,
100      * if any.</p>
101      *
102      * @param context <code>FacesContext</code> for the current request
103      */
104     public void processDecodes(FacesContext context) {
105 
106         Object vc = getViewController(context, true);
107         if (vc != null) {
108             try {
109                 getViewControllerCallbacks(context).preprocess(vc);
110             } catch (Exception e) {
111                 handleException(context, e);
112             }
113         }
114         super.processDecodes(context);
115 
116     }
117 
118 
119     // --------------------------------------------------------- Private Methods
120 
121 
122     /***
123      * <p>Return the {@link ViewController} associated with this component,
124      * if any; otherwise, return <code>null</code>.  Note that the signature
125      * for this method is <code>Object</code>, because the instance might
126      * have the <code>@View</code> annotation rather than implementing the
127      * <code>ViewController</code> interface.</p>
128      *
129      * @param context <code>FacesContext</code> for the current request
130      * @param postback Are we processing a postback?
131      */
132     private Object getViewController(FacesContext context,
133                                      boolean postback) {
134 
135         // If there is an existing ViewController instance, return it
136         // FIXME - different exception for class cast problems?
137         String name = getId(); // Name of the managed bean we are looking for
138         ExternalContext econtext = context.getExternalContext();
139         Object vc = null;
140         vc = econtext.getRequestMap().get(name);
141         if (vc == null) {
142             vc = econtext.getSessionMap().get(name);
143         }
144         if (vc == null) {
145             vc = econtext.getApplicationMap().get(name);
146         }
147         if (vc != null) {
148             return vc;
149         }
150 
151         // Construct and initialize a new ViewController, if any is associated
152         String expr = "#{" + name + "}";
153         vc = context.getApplication().
154            createValueBinding(expr).getValue(context);
155         if (vc == null) {
156             log.debug(messages.getMessage("subview.noBean",
157                                           new Object[] { getId() }));
158             return null;
159         }
160 
161         // Initialize the ViewController as needed
162         if (vc instanceof ViewController) {
163             ((ViewController) vc).setPostBack(postback);
164         }
165 
166         // Schedule this instance for later processing as needed
167         Map map = econtext.getRequestMap();
168         List list = (List) map.get(FacesConstants.VIEWS_INITIALIZED);
169         if (list == null) {
170             list = new ArrayList();
171             map.put(FacesConstants.VIEWS_INITIALIZED, list);
172         }
173         list.add(vc);
174 
175         // Return the initialized ViewController
176         return vc;
177 
178     }
179 
180 
181     /***
182      * <p>Return the <code>ViewControllerCallbacks</code> instance to be used
183      * to forward prerender and preprocess callbacks to our view controller,
184      * whether or not it implements the <code>ViewController</code> interface
185      * (it may not if it is using the <code>@View</code> annotation from the
186      * shale-tiger module).</p>
187      *
188      * @param context <code>FacesContext</code> for the current request
189      */
190     private ViewControllerCallbacks getViewControllerCallbacks(FacesContext context) {
191 
192         ViewControllerCallbacks vcb = (ViewControllerCallbacks)
193           context.getApplication().getVariableResolver().resolveVariable
194                 (context, FacesConstants.VIEW_CALLBACKS);
195         return vcb;
196 
197     }
198 
199 
200     /***
201      * <p>Handle the specified exception according to the strategy
202      * defined by our current {@link ExceptionHandler}.</p>
203      *
204      * @param context FacesContext for the current request
205      * @param exception Exception to be handled
206      */
207     private void handleException(FacesContext context, Exception exception) {
208 
209         if (context == null) {
210             exception.printStackTrace(System.out);
211             return;
212         }
213         ExceptionHandler handler = (ExceptionHandler)
214           context.getApplication().getVariableResolver().resolveVariable
215                 (context, Constants.EXCEPTION_HANDLER);
216         handler.handleException(exception);
217 
218     }
219 
220 
221 }