View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.custom.ppr;
20  
21  import javax.el.ELContext;
22  import javax.faces.application.Application;
23  import javax.faces.application.FacesMessage;
24  import javax.faces.component.UIViewRoot;
25  import javax.faces.context.ExternalContext;
26  import javax.faces.context.FacesContext;
27  import javax.faces.context.ResponseStream;
28  import javax.faces.context.ResponseWriter;
29  import javax.faces.render.RenderKit;
30  import java.lang.reflect.InvocationTargetException;
31  import java.lang.reflect.Method;
32  import java.util.Iterator;
33  
34  /**
35   * Convenient class to wrap the current FacesContext.
36   * <p>
37   * A class of this name is provided in JSF1.2, but not in JSF1.1.
38   * <p>
39   * Any methods that do not actually need to be overridden are declared final
40   * in order to improve performance (helps the JVM to optimise away the call).
41   */
42  class PPRFacesContextWrapper extends FacesContext
43  {
44      //~ Instance fields -------------------------------------------------------
45  
46      private final FacesContext _facesContext;
47      private Method methodGetELContext = null;
48  
49      public PPRFacesContextWrapper(FacesContext facesContext)
50      {
51          _facesContext = facesContext;
52      }
53  
54      //~ Non-Final Methods -----------------------------------------------------
55  
56      public void release()
57      {
58          _facesContext.release();
59      }
60  
61      //~ Final Methods ---------------------------------------------------------
62  
63      public final Application getApplication()
64      {
65          return _facesContext.getApplication();
66      }
67  
68      public final Iterator getClientIdsWithMessages()
69      {
70          return _facesContext.getClientIdsWithMessages();
71      }
72  
73      public final ExternalContext getExternalContext()
74      {
75          return _facesContext.getExternalContext();
76      }
77  
78      public final FacesMessage.Severity getMaximumSeverity()
79      {
80          return _facesContext.getMaximumSeverity();
81      }
82  
83      public final Iterator getMessages()
84      {
85          return _facesContext.getMessages();
86      }
87  
88      public final Iterator getMessages(String clientId)
89      {
90          return _facesContext.getMessages(clientId);
91      }
92  
93      public final RenderKit getRenderKit()
94      {
95          return _facesContext.getRenderKit();
96      }
97  
98      public final boolean getRenderResponse()
99      {
100         return _facesContext.getRenderResponse();
101     }
102 
103     public final boolean getResponseComplete()
104     {
105         return _facesContext.getResponseComplete();
106     }
107 
108     public final void setResponseStream(ResponseStream responsestream)
109     {
110         _facesContext.setResponseStream(responsestream);
111     }
112 
113     public final ResponseStream getResponseStream()
114     {
115         return _facesContext.getResponseStream();
116     }
117 
118     public final void setResponseWriter(ResponseWriter responsewriter)
119     {
120         _facesContext.setResponseWriter(responsewriter);
121     }
122 
123     public final ResponseWriter getResponseWriter()
124     {
125         return _facesContext.getResponseWriter();
126     }
127 
128     public final void setViewRoot(UIViewRoot viewRoot)
129     {
130         _facesContext.setViewRoot(viewRoot);
131     }
132 
133     public UIViewRoot getViewRoot()
134     {
135         return _facesContext.getViewRoot();
136     }
137 
138     public final void addMessage(String clientId, FacesMessage message)
139     {
140         _facesContext.addMessage(clientId, message);
141     }
142 
143     public final void renderResponse()
144     {
145         _facesContext.renderResponse();
146     }
147 
148     public final void responseComplete()
149     {
150         _facesContext.responseComplete();
151     }
152 
153     /**
154      * Implement getELContext by delegating call to another instance.
155      * <p>
156      * Note that this method was added in JSF1.2. In order for a JSF1.2
157      * implementation to be backwards-compatible with JSF1.1, the base
158      * class FacesContext therefore has to automatically do the delegation.
159      * Without automatic delegation, any JSF1.1 class that applies the decorator
160      * pattern to a FacesContext will just break in JSF1.2; the getELContext
161      * method is there (inherited from the base class) but does not correctly
162      * delegate.
163      * <p>
164      * Unfortunately, due to a design flaw in JSF1.2 it is simply not possible
165      * for the base class to delegate; the object to delegate to is not known
166      * to the base class! A partial solution that works in most cases is for
167      * the base class to delegate to the "core" instance of FacesContext for
168      * methods that are not overridden; Sun's RI does this correctly but
169      * unfortunately MyFaces 1.2.0-1.2.2 do not. See MYFACES-1820 for details.
170      * <p>
171      * The solution *here* is to require that a javax.el implementation is in
172      * the classpath even when running JSF1.1. It is then possible for this
173      * wrapper to override the method defined in JSF1.2 even when being
174      * compiled against the JSF1.1 implementation. It is mildly annoying to
175      * have to include javax.el in a JSF environment (ie when it will never
176      * be used) but better than the alternatives. Actually, for at least some
177      * JVMs, classes needed by a method are not loaded unless that method is
178      * actually referenced, so in some cases (including Sun Java 1.4-1.6) the
179      * el library *can* be omitted from the classpath with JSF1.1.
180      */
181     public final ELContext getELContext()
182     {
183         // Here, we cannot call getELContext on FacesContext as it does not
184         // exist for JSF1.1; the solution is to use reflection instead. This
185         // method will never be called unless we are in a JSF1.2 environment
186         // so the target method will always exist when this is called.
187         try
188         {
189             if (methodGetELContext == null)
190             {
191                 // Performance optimisation: find method, and cache it for later.
192                 methodGetELContext = FacesContext.class.getDeclaredMethod("getELContext", (Class[]) null);
193             }
194             return (ELContext) methodGetELContext.invoke(_facesContext, (Object[]) null);
195         }
196         catch(NoSuchMethodException e)
197         {
198             // should never happen
199             throw (IllegalStateException) new IllegalStateException("JSF1.2 method invoked in non-JSF-1.2 environment").initCause(e);
200         }
201         catch(InvocationTargetException e)
202         {
203             // should never happen
204             throw (IllegalStateException) new IllegalStateException("Method getELContext on wrapped instance threw exception").initCause(e);
205         }
206         catch(IllegalAccessException e)
207         {
208             // should never happen
209             throw (IllegalStateException) new IllegalStateException("Method getElContext on wrapped instance is not accessable").initCause(e);
210         }
211     }
212 }