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 }