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.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 }