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 httpServletRequest = new ThreadLocal();
64  	private final static ThreadLocal httpServletResponse = 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) httpServletRequest.get();
104 	}
105 
106 	private HttpServletResponse getResponse()
107 	{
108 		return (HttpServletResponse) httpServletResponse.get();
109 	}
110 
111 	public void beginRequest(ServletRequest req, ServletResponse rsp)
112 	{
113 		log.debug("Beginning request");
114 		if (req instanceof HttpServletRequest)
115 		{
116 			httpServletRequest.set(req);
117 		}
118 		if (rsp instanceof HttpServletResponse)
119 		{
120 			httpServletResponse.set(rsp);
121 		}
122 
123 		FrameworkAdapter.setCurrentInstance(this);
124 	}
125 
126 	public void endRequest()
127 	{
128 		log.debug("Ending request");
129 		FrameworkAdapter.setCurrentInstance(null);
130 		httpServletRequest.set(null);
131 		httpServletResponse.set(null);
132 	}
133 
134 	public String getInitParameter(String key)
135 	{
136 		return servletContext.getInitParameter(key);
137 	}
138 
139 	public Object getRequestParameterAttribute(String key)
140 	{
141 		HttpServletRequest request = getRequest();
142 		if (request != null)
143 		{
144 			return request.getParameter(key);
145 		}
146 
147 		throw new IllegalStateException(ISE_MESSAGE);
148 	}
149 
150 	public boolean containsRequestParameterAttribute(String key)
151 	{
152 		HttpServletRequest request = getRequest();
153 		if (request != null)
154 		{
155 			return request.getParameter(key) != null;
156 		}
157 
158 		throw new IllegalStateException(ISE_MESSAGE);
159 	}
160 
161 	public Object getRequestAttribute(String key)
162 	{
163 		HttpServletRequest request = getRequest();
164 		if (request != null)
165 		{
166 			return request.getAttribute(key);
167 		}
168 
169 		throw new IllegalStateException(ISE_MESSAGE);
170 	}
171 
172 	public void setRequestAttribute(String key, Object value)
173 	{
174 		HttpServletRequest request = getRequest();
175 		if (request != null)
176 		{
177 			request.setAttribute(key, value);
178 			return;
179 		}
180 
181 		throw new IllegalStateException(ISE_MESSAGE);
182 	}
183 
184 	public boolean containsRequestAttribute(String key)
185 	{
186 		HttpServletRequest request = getRequest();
187 		if (request != null)
188 		{
189 			return request.getAttribute(key) != null;
190 		}
191 
192 		throw new IllegalStateException(ISE_MESSAGE);
193 	}
194 
195 	public Object getSessionAttribute(String key)
196 	{
197 		HttpServletRequest request = getRequest();
198 		if (request != null && request.getSession(true) != null)
199 		{
200 			return request.getSession(true).getAttribute(key);
201 		}
202 
203 		throw new IllegalStateException(ISE_MESSAGE);
204 	}
205 
206 	public void setSessionAttribute(String key, Object value)
207 	{
208 		HttpServletRequest request = getRequest();
209 		if (request != null && request.getSession(true) != null)
210 		{
211 			request.getSession(true).setAttribute(key, value);
212 			return;
213 		}
214 
215 	}
216 
217 	public boolean containsSessionAttribute(String key)
218 	{
219 		HttpServletRequest request = getRequest();
220 		if (request != null && request.getSession(true) != null)
221 		{
222 			return request.getSession(true).getAttribute(key) != null;
223 		}
224 
225 		throw new IllegalStateException(ISE_MESSAGE);
226 	}
227 
228 	protected String getRequestContextPath()
229 	{
230 		HttpServletRequest request = getRequest();
231 		if (request != null)
232 		{
233 			return request.getContextPath();
234 		}
235 
236 		throw new IllegalStateException(ISE_MESSAGE);
237 	}
238 
239 	public void redirect(String url) throws IOException
240 	{
241 		StringBuffer redir = new StringBuffer();
242 		if (url.startsWith("/"))
243 		{
244 			redir.append(getRequestContextPath());
245 		}
246 		redir.append(url);
247 
248 		HttpServletResponse rsp = getResponse();
249 		String dstUrl = rsp.encodeRedirectURL(redir.toString());
250 		rsp.sendRedirect(dstUrl);
251 	}
252 
253 	/***
254 	 * Look in the request and session scopes for an entry
255 	 * with the specified name.
256 	 * <p>
257 	 * This basic adapter class does not support invoking the JSP expression
258 	 * evaluator; no "variable resolver" will ever be used to look up the
259 	 * specified name.
260 	 * <p>
261 	 * TODO: also look in the application scope.
262 	 * <p>
263 	 * TODO: investigate invoking the jsp.ExpressionFactory class to look up
264 	 * the variable. Possibly that could be done in a different JspFrameworkAdapter
265 	 * class.
266 	 */
267 	public Object getBean(String name)
268 	{
269 		Object obj;
270 
271 		obj = getRequestAttribute(name);
272 		if (obj != null) return obj;
273 
274 		obj = getSessionAttribute(name);
275 		if (obj != null) return obj;
276 
277 		// TODO: look up application-scoped objects.
278 
279 		return null;
280 	}
281 
282 	/***
283 	 * Perform a redirect to the specified url.
284 	 * <p>
285 	 * A redirect is done rather than a forward so that the remote browser has its
286 	 * current url updated appropriately. Note that a redirect does cause any
287 	 * request-scoped variables to be discarded.
288 	 */
289 	public void invokeNavigation(String navigationName) throws IOException
290 	{
291 		redirect(navigationName);
292 	}
293 }