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.commons.util;
20
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.lang.reflect.Method;
24
25 import javax.faces.context.ExternalContext;
26
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29
30 /**
31 * This provides some functionality for determining some things about the
32 * native request object that is not provided by JSF. This class is useful
33 * for use in places where Portlet API's may or may not be present and can
34 * also provide access to some request-specific items which are not available on
35 * the JSF ExternalContext. If portlet API's are not present, this class simply
36 * handles the Servlet Request type.
37 */
38 public final class ExternalContextUtils
39 {
40 // prevent this from being instantiated
41 private ExternalContextUtils()
42 {
43 }
44
45 /**
46 * Returns the content length or -1 if the unknown.
47 *
48 * @param externalContext
49 * the ExternalContext
50 * @return the length or -1
51 */
52 public static final int getContentLength(ExternalContext externalContext)
53 {
54 RequestType type = getRequestType(externalContext);
55
56 if(type.isRequestFromClient())
57 {
58 try
59 {
60 Object request = externalContext.getRequest();
61 Method contentLenMethod = request.getClass().getMethod("getContentLength");
62 return (Integer) contentLenMethod.invoke(request); //this will autobox
63 }
64 catch(Exception e)
65 {
66 _LOG.error("Unsupported request type.", e);
67 }
68 }
69
70 return -1;
71 }
72
73 /**
74 * Returns the request input stream if one is available
75 *
76 * @param externalContext
77 * @return
78 * @throws IOException
79 */
80 public static final InputStream getRequestInputStream(ExternalContext externalContext)
81 throws IOException
82 {
83 RequestType type = getRequestType(externalContext);
84
85 if(type.isRequestFromClient())
86 {
87 try
88 {
89 Object request = externalContext.getRequest();
90
91 Method method = request.getClass().getMethod(type.isPortlet()?"getPortletInputStream":"getInputStream");
92 return (InputStream) method.invoke(request);
93 }
94 catch (Exception e)
95 {
96 _LOG.error("Unable to get the request input stream because of an error", e);
97 }
98 }
99 return null;
100 }
101
102 /**
103 * Returns the requestType of this ExternalContext.
104 *
105 * @param externalContext the current external context
106 * @return the appropriate RequestType for this external context
107 * @see RequestType
108 */
109 public static final RequestType getRequestType(ExternalContext externalContext)
110 {
111 //Stuff is laid out strangely in this class in order to optimize
112 //performance. We want to do as few instanceof's as possible so
113 //things are laid out according to the expected frequency of the
114 //various requests occurring.
115 if(_PORTLET_CONTEXT_CLASS != null)
116 {
117 if (_PORTLET_CONTEXT_CLASS.isInstance(externalContext.getContext()))
118 {
119 //We are inside of a portlet container
120 Object request = externalContext.getRequest();
121
122 if(_PORTLET_RENDER_REQUEST_CLASS.isInstance(request))
123 {
124 return RequestType.RENDER;
125 }
126
127 if(_PORTLET_RESOURCE_REQUEST_CLASS != null)
128 {
129 if(_PORTLET_ACTION_REQUEST_CLASS.isInstance(request))
130 {
131 return RequestType.ACTION;
132 }
133
134 //We are in a JSR-286 container
135 if(_PORTLET_RESOURCE_REQUEST_CLASS.isInstance(request))
136 {
137 return RequestType.RESOURCE;
138 }
139
140 return RequestType.EVENT;
141 }
142
143 return RequestType.ACTION;
144 }
145 }
146
147 return RequestType.SERVLET;
148 }
149
150 /**
151 * This method is used when a ExternalContext object is not available,
152 * like in TomahawkFacesContextFactory.
153 *
154 * According to TOMAHAWK-1331, the object context could receive an
155 * instance of javax.portlet.PortletContext or javax.portlet.PortletConfig,
156 * so we check both cases.
157 *
158 * @param context
159 * @param request
160 * @return
161 */
162 public static final RequestType getRequestType(Object context, Object request)
163 {
164 //Stuff is laid out strangely in this class in order to optimize
165 //performance. We want to do as few instanceof's as possible so
166 //things are laid out according to the expected frequency of the
167 //various requests occurring.
168
169 if(_PORTLET_CONTEXT_CLASS != null)
170 {
171 if (_PORTLET_CONFIG_CLASS.isInstance(context) ||
172 _PORTLET_CONTEXT_CLASS.isInstance(context))
173 {
174 //We are inside of a portlet container
175
176 if(_PORTLET_RENDER_REQUEST_CLASS.isInstance(request))
177 {
178 return RequestType.RENDER;
179 }
180
181 if(_PORTLET_RESOURCE_REQUEST_CLASS != null)
182 {
183 if(_PORTLET_ACTION_REQUEST_CLASS.isInstance(request))
184 {
185 return RequestType.ACTION;
186 }
187
188 //We are in a JSR-286 container
189 if(_PORTLET_RESOURCE_REQUEST_CLASS.isInstance(request))
190 {
191 return RequestType.RESOURCE;
192 }
193
194 return RequestType.EVENT;
195 }
196
197 return RequestType.ACTION;
198 }
199 }
200
201 return RequestType.SERVLET;
202 }
203
204 private static final Log _LOG = LogFactory.getLog(ExternalContextUtils.class);
205
206 private static final Class<?> _PORTLET_ACTION_REQUEST_CLASS;
207 private static final Class<?> _PORTLET_RENDER_REQUEST_CLASS;
208 private static final Class<?> _PORTLET_RESOURCE_REQUEST_CLASS; //Will be present in JSR-286 containers only
209 private static final Class<?> _PORTLET_CONTEXT_CLASS;
210 private static final Class<?> _PORTLET_CONFIG_CLASS;
211
212 static
213 {
214 Class<?> context;
215 Class<?> config;
216 Class<?> actionRequest;
217 Class<?> renderRequest;
218 Class<?> resourceRequest;
219 try
220 {
221 ClassLoader loader = Thread.currentThread().getContextClassLoader();
222 context = loader.loadClass("javax.portlet.PortletContext");
223 config = loader.loadClass("javax.portlet.PortletConfig");
224 actionRequest = loader.loadClass("javax.portlet.ActionRequest");
225 renderRequest = loader.loadClass("javax.portlet.RenderRequest");
226
227 try
228 {
229 resourceRequest = loader.loadClass("javax.portlet.ResourceRequest");
230 }
231 catch (ClassNotFoundException e)
232 {
233 resourceRequest = null;
234 }
235 }
236 catch (ClassNotFoundException e)
237 {
238 context = null;
239 config = null;
240 actionRequest = null;
241 renderRequest = null;
242 resourceRequest = null;
243 }
244
245 _PORTLET_CONTEXT_CLASS = context;
246 _PORTLET_CONFIG_CLASS = config;
247 _PORTLET_ACTION_REQUEST_CLASS = actionRequest;
248 _PORTLET_RENDER_REQUEST_CLASS = renderRequest;
249 _PORTLET_RESOURCE_REQUEST_CLASS = resourceRequest;
250 }
251 }