001: /**
002: * Copyright 2006 Webmedia Group Ltd.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: **/package org.araneaframework.http.util;
016:
017: import java.util.Enumeration;
018: import java.util.HashMap;
019: import java.util.Iterator;
020: import java.util.Map;
021: import java.util.ResourceBundle;
022: import javax.servlet.ServletContext;
023: import javax.servlet.ServletRequest;
024: import javax.servlet.http.HttpServletRequest;
025: import javax.servlet.http.HttpServletResponse;
026: import javax.servlet.jsp.jstl.core.Config;
027: import org.apache.commons.logging.Log;
028: import org.apache.commons.logging.LogFactory;
029: import org.araneaframework.Environment;
030: import org.araneaframework.InputData;
031: import org.araneaframework.OutputData;
032: import org.araneaframework.core.ApplicationWidget;
033: import org.araneaframework.framework.LocalizationContext;
034: import org.araneaframework.http.HttpInputData;
035: import org.araneaframework.http.HttpOutputData;
036: import org.araneaframework.jsp.tag.context.WidgetContextTag;
037: import org.araneaframework.jsp.tag.uilib.WidgetTag;
038:
039: /**
040: * Utility methods for Aranea framework running inside a servlet container. Includes
041: * functions for rendering JSP pages and direct access to <code>HttpServletResponse</code>
042: * and <code>HttpServletRequest</code>.
043: *
044: * @author "Toomas Römer" <toomas@webmedia.ee>
045: * @author Jevgeni Kabanov (ekabanov <i>at</i> araneaframework <i>dot</i> org)
046: * @author Alar Kvell (alar@araneaframework.org)
047: */
048: public abstract class ServletUtil {
049:
050: private static final Log log = LogFactory.getLog(ServletUtil.class);
051:
052: /** @since 1.1 */
053: public static final String UIWIDGET_KEY = "org.araneaframework.http.util.ServletUtil.UIWIDGET";
054: /** @since 1.1 */
055: public static final String LOCALIZATION_CONTEXT_KEY = Config.FMT_LOCALIZATION_CONTEXT
056: + ".request";
057:
058: /**
059: * Includes the jsp specified by filePath using the the request and response streams
060: * of the output. The pathname must begin with a "/" and is interpreted as relative to
061: * the current context root. The context root in the env under the key ServletContext.class
062: * is used.
063: */
064: public static void include(String filePath, Environment env,
065: OutputData output) throws Exception {
066: include(filePath, env, output, null);
067: }
068:
069: /**
070: * Includes the jsp specified by filePath using the the request and response streams
071: * of the output. The pathname must begin with a "/" and is interpreted as relative to
072: * the current context root. The context root in the env under the key ServletContext.class
073: * is used.
074: *
075: * Widget is made available to JSP, so contextWidget tag can be used.
076: *
077: * @since 1.1
078: */
079: public static void include(String filePath,
080: ApplicationWidget widget, OutputData output)
081: throws Exception {
082: include(filePath, widget.getChildEnvironment(), output, widget);
083: }
084:
085: public static void include(String filePath,
086: ApplicationWidget widget, HttpServletRequest req,
087: HttpServletResponse res) throws Exception {
088: include(filePath, widget, widget.getChildEnvironment(), req,
089: res);
090: }
091:
092: public static void include(String filePath, Environment env,
093: HttpServletRequest req, HttpServletResponse res)
094: throws Exception {
095: include(filePath, null, env, req, res);
096: }
097:
098: private static void include(String filePath, Environment env,
099: OutputData output, ApplicationWidget widget)
100: throws Exception {
101: include(filePath, widget, env,
102: getRequest(output.getInputData()), getResponse(output));
103: }
104:
105: private static void include(String filePath,
106: ApplicationWidget widget, Environment env,
107: HttpServletRequest req, HttpServletResponse res)
108: throws Exception {
109: if (log.isDebugEnabled())
110: log.debug("Including a resource from the absolute path '"
111: + filePath + "'");
112:
113: Map attributeBackupMap = new HashMap();
114: if (widget != null) {
115: setAttribute(req, attributeBackupMap, UIWIDGET_KEY, widget);
116: setAttribute(req, attributeBackupMap,
117: WidgetContextTag.CONTEXT_WIDGET_KEY, widget);
118: String fullId = widget.getScope() != null ? widget
119: .getScope().toString() : null;
120: ApplicationWidget.WidgetViewModel viewModel = (ApplicationWidget.WidgetViewModel) widget
121: ._getViewable().getViewModel();
122: setAttribute(req, attributeBackupMap, WidgetTag.WIDGET_KEY,
123: widget);
124: setAttribute(req, attributeBackupMap,
125: WidgetTag.WIDGET_ID_KEY, fullId);
126: setAttribute(req, attributeBackupMap,
127: WidgetTag.WIDGET_VIEW_MODEL_KEY, viewModel);
128: setAttribute(req, attributeBackupMap,
129: WidgetTag.WIDGET_VIEW_DATA_KEY, viewModel.getData());
130: } else {
131: setAttribute(req, attributeBackupMap, UIWIDGET_KEY, null);
132: setAttribute(req, attributeBackupMap,
133: WidgetContextTag.CONTEXT_WIDGET_KEY, null);
134: setAttribute(req, attributeBackupMap, WidgetTag.WIDGET_KEY,
135: null);
136: setAttribute(req, attributeBackupMap,
137: WidgetTag.WIDGET_ID_KEY, null);
138: setAttribute(req, attributeBackupMap,
139: WidgetTag.WIDGET_VIEW_MODEL_KEY, null);
140: setAttribute(req, attributeBackupMap,
141: WidgetTag.WIDGET_VIEW_DATA_KEY, null);
142: }
143: setAttribute(req, attributeBackupMap,
144: Environment.ENVIRONMENT_KEY, env);
145: setAttribute(req, attributeBackupMap, LOCALIZATION_CONTEXT_KEY,
146: buildLocalizationContext(env));
147:
148: ServletContext servletContext = (ServletContext) env
149: .requireEntry(ServletContext.class);
150: servletContext.getRequestDispatcher(filePath).include(req, res);
151:
152: restoreAttributes(req, attributeBackupMap);
153: }
154:
155: private static void setAttribute(HttpServletRequest req,
156: Map attributeBackupMap, String name, Object value) {
157: attributeBackupMap.put(name, req.getAttribute(name));
158: if (value != null) {
159: req.setAttribute(name, value);
160: } else {
161: req.removeAttribute(name);
162: }
163: }
164:
165: private static void restoreAttributes(HttpServletRequest req,
166: Map attributeBackupMap) {
167: for (Iterator i = attributeBackupMap.entrySet().iterator(); i
168: .hasNext();) {
169: Map.Entry entry = (Map.Entry) i.next();
170: if (entry.getValue() != null) {
171: req.setAttribute((String) entry.getKey(), entry
172: .getValue());
173: } else {
174: req.removeAttribute((String) entry.getKey());
175: }
176: }
177: }
178:
179: /**
180: * Includes the jsp specified by file using the the request and response streams
181: * of the output. The pathname specified may be relative, although it cannot extend
182: * outside the current servlet context. If the path begins with a "/" it is interpreted
183: * as relative to the current context root.
184: */
185: public static void includeRelative(String filePath,
186: Environment env, OutputData output) throws Exception {
187: log.debug("Including a resource from the relative path '"
188: + filePath + "'");
189:
190: getRequest(output.getInputData())
191: .getRequestDispatcher(filePath).include(
192: getRequest(output.getInputData()),
193: getResponse(output));
194: }
195:
196: public static void publishModel(InputData input, String name,
197: Object model) {
198: getRequest(input).setAttribute(name, model);
199: }
200:
201: public static HttpServletRequest getRequest(InputData input) {
202: return (HttpServletRequest) input
203: .narrow(HttpServletRequest.class);
204: }
205:
206: public static void setRequest(InputData input,
207: HttpServletRequest req) {
208: input.extend(HttpServletRequest.class, req);
209: }
210:
211: public static HttpServletResponse getResponse(OutputData output) {
212: return (HttpServletResponse) output
213: .narrow(HttpServletResponse.class);
214: }
215:
216: public static void setResponse(OutputData output,
217: HttpServletResponse res) {
218: output.extend(HttpServletResponse.class, res);
219: }
220:
221: public static HttpInputData getInputData(ServletRequest req) {
222: return (HttpInputData) req
223: .getAttribute(InputData.INPUT_DATA_KEY);
224: }
225:
226: public static HttpOutputData getOutputData(ServletRequest req) {
227: return (HttpOutputData) req
228: .getAttribute(OutputData.OUTPUT_DATA_KEY);
229: }
230:
231: /** @since 1.1 */
232: public static Environment getEnvironment(ServletRequest req) {
233: return (Environment) req
234: .getAttribute(Environment.ENVIRONMENT_KEY);
235: }
236:
237: /** @since 1.1 */
238: public static javax.servlet.jsp.jstl.fmt.LocalizationContext buildLocalizationContext(
239: Environment env) {
240: LocalizationContext localizationContext = (LocalizationContext) env
241: .getEntry(LocalizationContext.class);
242: if (localizationContext == null)
243: return null;
244: return new javax.servlet.jsp.jstl.fmt.LocalizationContext(
245: new StringAdapterResourceBundle(localizationContext
246: .getResourceBundle()), localizationContext
247: .getLocale());
248: }
249:
250: /**
251: * Adapter resource bundle that converts all objects to string.
252: *
253: * @since 1.1
254: */
255: public static class StringAdapterResourceBundle extends
256: ResourceBundle {
257: protected ResourceBundle bundle;
258:
259: public StringAdapterResourceBundle(ResourceBundle bundle) {
260: this .bundle = bundle;
261: }
262:
263: protected Object handleGetObject(String key) {
264: Object object = bundle.getObject(key);
265: return (object != null) ? object.toString() : null;
266: }
267:
268: public Enumeration getKeys() {
269: return bundle.getKeys();
270: }
271: }
272:
273: }
|