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.orchestra.frameworkAdapter.basic;
20  
21  import org.apache.commons.logging.Log;
22  import org.apache.commons.logging.LogFactory;
23  import org.apache.myfaces.orchestra.conversation.ConversationMessager;
24  import org.apache.myfaces.orchestra.conversation.basic.LogConversationMessager;
25  import org.apache.myfaces.orchestra.frameworkAdapter.FrameworkAdapter;
26  import org.apache.myfaces.orchestra.lib._ClassUtils;
27  
28  import javax.servlet.ServletContext;
29  import javax.servlet.ServletRequest;
30  import javax.servlet.ServletResponse;
31  import javax.servlet.http.HttpServletRequest;
32  import javax.servlet.http.HttpServletResponse;
33  import java.io.IOException;
34  
35  /**
36   * An implementation of the FrameworkAdapter for plain servlet environments.
37   * <p>
38   * This class requires the BasicFrameworkAdapterFilter to be configured to run
39   * for every request.
40   * 
41   * <h2>Configuring the ConversationMessager</h2>
42   * 
43   * This class allows the concrete ConversationMessager instance returned
44   * by the getConversationMessager method to be configured
45   * in a number of ways:
46   * <ul>
47   * <li>By calling an explicit setter, passing an instance.</li>
48   * <li>By specifying a conversationMessagerName parameter to the constructor
49   * of this method which matches a bean name defined in the dependency injection
50   * framework.</li>
51   * <li>By specifying a conversationMessagerName that is the fully-qualified
52   * name of a ConversationMessager class to be instantiated</li>
53   * <li>Otherwise, method createDefaultConversationMessager is called which
54   * returns a LogConversationMessager instance (unless overridden in a subclass).</li>
55   * </ul>
56   * 
57   * See also the BasicFrameworkAdapterFilter class.
58   */
59  public class BasicFrameworkAdapter extends FrameworkAdapter
60  {
61      private final static String ISE_MESSAGE="No request/response data available"; // NON-NLS
62  
63      private final static ThreadLocal httpServletRequestThreadLocal = new ThreadLocal();
64      private final static ThreadLocal httpServletResponseThreadLocal = new ThreadLocal();
65  
66      private final Log log = LogFactory.getLog(BasicFrameworkAdapter.class);
67  
68      private final ServletContext servletContext;
69      private final String conversationMessagerClass;
70  
71      public BasicFrameworkAdapter(ServletContext context, String conversationMessagerClass)
72      {
73          servletContext = context;
74          this.conversationMessagerClass = conversationMessagerClass;
75      }
76  
77      protected ConversationMessager createConversationMessager()
78      {
79          if (conversationMessagerClass == null)
80          {
81              return createDefaultConversationMessager();
82          }
83  
84          // First try to find a bean of that name in the dependency-injection
85          // framework.
86          Object instance = getBean(conversationMessagerClass);
87          if (instance instanceof ConversationMessager)
88          {
89              return (ConversationMessager) instance;
90          }
91  
92          // Now resort to trying the value as a classname.
93          return (ConversationMessager) _ClassUtils.newInstance(conversationMessagerClass);
94      }
95  
96      protected ConversationMessager createDefaultConversationMessager()
97      {
98          return new LogConversationMessager();
99      }
100 
101     private HttpServletRequest getRequest()
102     {
103         return (HttpServletRequest) httpServletRequestThreadLocal.get();
104     }
105 
106     private HttpServletResponse getResponse()
107     {
108         return (HttpServletResponse) httpServletResponseThreadLocal.get();
109     }
110 
111     public void beginRequest(ServletRequest req, ServletResponse rsp)
112     {
113         if (log.isDebugEnabled())
114         {
115             log.debug("Beginning request");
116         }
117         if (req instanceof HttpServletRequest)
118         {
119             httpServletRequestThreadLocal.set(req);
120         }
121         if (rsp instanceof HttpServletResponse)
122         {
123             httpServletResponseThreadLocal.set(rsp);
124         }
125 
126         FrameworkAdapter.setCurrentInstance(this);
127     }
128 
129     public void endRequest()
130     {
131         if (log.isDebugEnabled())
132         {
133             log.debug("Ending request");
134         }
135         FrameworkAdapter.setCurrentInstance(null);
136         httpServletRequestThreadLocal.set(null);
137         httpServletResponseThreadLocal.set(null);
138     }
139 
140     public String getInitParameter(String key)
141     {
142         return servletContext.getInitParameter(key);
143     }
144 
145     public Object getRequestParameterAttribute(String key)
146     {
147         HttpServletRequest request = getRequest();
148         if (request != null)
149         {
150             return request.getParameter(key);
151         }
152 
153         throw new IllegalStateException(ISE_MESSAGE);
154     }
155 
156     public boolean containsRequestParameterAttribute(String key)
157     {
158         HttpServletRequest request = getRequest();
159         if (request != null)
160         {
161             return request.getParameter(key) != null;
162         }
163 
164         throw new IllegalStateException(ISE_MESSAGE);
165     }
166 
167     public Object getRequestAttribute(String key)
168     {
169         HttpServletRequest request = getRequest();
170         if (request != null)
171         {
172             return request.getAttribute(key);
173         }
174 
175         throw new IllegalStateException(ISE_MESSAGE);
176     }
177 
178     public void setRequestAttribute(String key, Object value)
179     {
180         HttpServletRequest request = getRequest();
181         if (request != null)
182         {
183             request.setAttribute(key, value);
184             return;
185         }
186 
187         throw new IllegalStateException(ISE_MESSAGE);
188     }
189 
190     public boolean containsRequestAttribute(String key)
191     {
192         HttpServletRequest request = getRequest();
193         if (request != null)
194         {
195             return request.getAttribute(key) != null;
196         }
197 
198         throw new IllegalStateException(ISE_MESSAGE);
199     }
200 
201     public Object getSessionAttribute(String key)
202     {
203         HttpServletRequest request = getRequest();
204         if (request != null && request.getSession(true) != null)
205         {
206             return request.getSession(true).getAttribute(key);
207         }
208 
209         throw new IllegalStateException(ISE_MESSAGE);
210     }
211 
212     public void setSessionAttribute(String key, Object value)
213     {
214         HttpServletRequest request = getRequest();
215         if (request != null && request.getSession(true) != null)
216         {
217             request.getSession(true).setAttribute(key, value);
218             return;
219         }
220 
221     }
222 
223     public boolean containsSessionAttribute(String key)
224     {
225         HttpServletRequest request = getRequest();
226         if (request != null && request.getSession(true) != null)
227         {
228             return request.getSession(true).getAttribute(key) != null;
229         }
230 
231         throw new IllegalStateException(ISE_MESSAGE);
232     }
233 
234     protected String getRequestContextPath()
235     {
236         HttpServletRequest request = getRequest();
237         if (request != null)
238         {
239             return request.getContextPath();
240         }
241 
242         throw new IllegalStateException(ISE_MESSAGE);
243     }
244 
245     public void redirect(String url) throws IOException
246     {
247         StringBuffer redir = new StringBuffer();
248         if (url.startsWith("/"))
249         {
250             redir.append(getRequestContextPath());
251         }
252         redir.append(url);
253 
254         HttpServletResponse rsp = getResponse();
255         String dstUrl = rsp.encodeRedirectURL(redir.toString());
256         rsp.sendRedirect(dstUrl);
257     }
258 
259     /**
260      * Look in the request and session scopes for an entry
261      * with the specified name.
262      * <p>
263      * This basic adapter class does not support invoking the JSP expression
264      * evaluator; no "variable resolver" will ever be used to look up the
265      * specified name.
266      * <p>
267      * TODO: also look in the application scope.
268      * <p>
269      * TODO: investigate invoking the jsp.ExpressionFactory class to look up
270      * the variable. Possibly that could be done in a different JspFrameworkAdapter
271      * class.
272      */
273     public Object getBean(String name)
274     {
275         Object obj;
276 
277         obj = getRequestAttribute(name);
278         if (obj != null)
279         {
280             return obj;
281         }
282 
283         obj = getSessionAttribute(name);
284         if (obj != null)
285         {
286             return obj;
287         }
288 
289         // TODO: look up application-scoped objects.
290 
291         return null;
292     }
293 
294     /**
295      * Perform a redirect to the specified url.
296      * <p>
297      * A redirect is done rather than a forward so that the remote browser has its
298      * current url updated appropriately. Note that a redirect does cause any
299      * request-scoped variables to be discarded.
300      */
301     public void invokeNavigation(String navigationName) throws IOException
302     {
303         redirect(navigationName);
304     }
305 }