001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.pluto.internal.impl;
018:
019: import org.apache.commons.logging.Log;
020: import org.apache.commons.logging.LogFactory;
021: import org.apache.pluto.Constants;
022: import org.apache.pluto.PortletContainer;
023: import org.apache.pluto.internal.InternalPortletWindow;
024: import org.apache.pluto.internal.InternalPortletRequest;
025: import org.apache.pluto.internal.InternalRenderRequest;
026:
027: import javax.portlet.PortletPreferences;
028: import javax.portlet.RenderRequest;
029: import javax.servlet.ServletInputStream;
030: import javax.servlet.http.HttpServletRequest;
031:
032: import java.io.BufferedReader;
033: import java.io.IOException;
034: import java.io.UnsupportedEncodingException;
035: import java.util.ArrayList;
036: import java.util.HashMap;
037: import java.util.Iterator;
038: import java.util.List;
039: import java.util.Map;
040: import java.util.StringTokenizer;
041:
042: /**
043: * Implementation of the <code>javax.portlet.RenderRequest</code> interface.
044: *
045: */
046: public class RenderRequestImpl extends PortletRequestImpl implements
047: RenderRequest, InternalRenderRequest {
048:
049: /** Logger. */
050: private static final Log LOG = LogFactory
051: .getLog(RenderRequestImpl.class);
052:
053: // Private Member Variables ------------------------------------------------
054:
055: /** True if we are in an include call. */
056: private boolean included = false;
057:
058: /** The parameters including parameters appended to the dispatching URI. */
059: private Map parameters;
060:
061: /** The portlet preferences. */
062: private PortletPreferences portletPreferences;
063:
064: // Constructors ------------------------------------------------------------
065:
066: public RenderRequestImpl(InternalPortletRequest request) {
067: super (request);
068: }
069:
070: public RenderRequestImpl(PortletContainer container,
071: InternalPortletWindow internalPortletWindow,
072: HttpServletRequest servletRequest) {
073: super (container, internalPortletWindow, servletRequest);
074: if (LOG.isDebugEnabled()) {
075: LOG.debug("Created render request for: "
076: + internalPortletWindow);
077: }
078: }
079:
080: // RenderRequest Impl ------------------------------------------------------
081:
082: public PortletPreferences getPreferences() {
083: if (portletPreferences == null) {
084: portletPreferences = new PortletPreferencesImpl(
085: getPortletContainer(), getInternalPortletWindow(),
086: this , Constants.METHOD_RENDER);
087: }
088: return portletPreferences;
089: }
090:
091: /**
092: * Checks the included flag and returns the content type. If the included
093: * flag is set to true, this method returns null.
094: */
095: public String getContentType() {
096: return included ? null : super .getContentType();
097: }
098:
099: /**
100: * Checks the included flag and returns the content length. If the included
101: * flag is set to true, this method returns 0.
102: */
103: public int getContentLength() {
104: return included ? 0 : super .getContentLength();
105: }
106:
107: /**
108: * Checks the included flag and returns the reader to this rende response.
109: * If the included flag is set to true, this method returns null.
110: */
111: public BufferedReader getReader()
112: throws UnsupportedEncodingException, IOException {
113: return included ? null : super .getReader();
114: }
115:
116: /**
117: * Checks the included flag and returns the input stream to this render
118: * response. If the included flag is set to true, this method returns null.
119: */
120: public ServletInputStream getInputStream() throws IOException {
121: return included ? null : super .getInputStream();
122: }
123:
124: // PortletRequestImpl Overwriting ------------------------------------------
125:
126: protected Map baseGetParameterMap() {
127: if (included && parameters != null) {
128: super .setBodyAccessed();
129: return parameters;
130: } else {
131: return super .baseGetParameterMap();
132: }
133: }
134:
135: // InternalRenderRequest Impl ----------------------------------------------
136:
137: public void setIncluded(boolean included) {
138: this .included = included;
139: if (!included) {
140: this .parameters = null;
141: }
142: if (LOG.isDebugEnabled()) {
143: LOG.debug("Render request's included mode: " + included);
144: }
145: }
146:
147: public boolean isIncluded() {
148: return included;
149: }
150:
151: public void setIncludedQueryString(String queryString)
152: throws IllegalStateException {
153: if (!included) {
154: throw new IllegalStateException(
155: "Parameters cannot be appended to "
156: + "render request which is not included in a dispatch.");
157: }
158: if (queryString != null && queryString.trim().length() > 0) {
159: // Copy all the original render parameters.
160: parameters = new HashMap(super .getParameterMap());
161: // Merge the appended parameters to the render parameter map.
162: // The original render parameters should not be overwritten.
163: mergeQueryString(parameters, queryString);
164: // Log the new render parameter map.
165: if (LOG.isDebugEnabled()) {
166: LOG
167: .debug("Merged parameters: "
168: + parameters.toString());
169: }
170: } else {
171: if (LOG.isDebugEnabled()) {
172: LOG
173: .debug("No query string appended to the included request.");
174: }
175: }
176: }
177:
178: // Included HttpServletRequest (Limited) Impl ------------------------------
179:
180: /*
181: * -------------------------------------------------------------------------
182: * (non-javadoc)
183: * Portlet Spec. PLT. 16.3.3.
184: * The following methods of the HttpServletRequest must return the path and
185: * query string information used to obtain the PortletRequestDispatcher
186: * object:
187: * getPathInfo
188: * getPathTranslated
189: * getQueryString
190: * getRequestURI
191: * getServletPath
192: * -------------------------------------------------------------------------
193: */
194:
195: public String getPathInfo() {
196: String attr = (String) super
197: .getAttribute("javax.servlet.include.path_info");
198: return (included && attr != null) ? attr : super .getPathInfo();
199: }
200:
201: public String getQueryString() {
202: String attr = (String) super
203: .getAttribute("javax.servlet.include.query_string");
204: return (included && attr != null) ? attr : super
205: .getQueryString();
206: }
207:
208: /**
209: * TODO: check PLT.16.3.3. page 67, line 10.
210: */
211: public String getPathTranslated() {
212: // TODO:
213: return null;
214: }
215:
216: public String getRequestURI() {
217: String attr = (String) super
218: .getAttribute("javax.servlet.include.request_uri");
219: return (included && attr != null) ? attr : super
220: .getRequestURI();
221: }
222:
223: public String getServletPath() {
224: String attr = (String) super
225: .getAttribute("javax.servlet.include.servlet_path");
226: return (included && attr != null) ? attr : super
227: .getServletPath();
228: }
229:
230: /*
231: * -------------------------------------------------------------------------
232: * (non-Javadoc)
233: * Portlet Spec. PLT. 16.3.3.
234: * The following methods of the HttpServletRequest must return null:
235: * getProtocol
236: * getRemoteAddr
237: * getRemoteHost
238: * getRealPath
239: * getRequestURL
240: * -------------------------------------------------------------------------
241: */
242:
243: public String getProtocol() {
244: return included ? null : super .getProtocol();
245: }
246:
247: public String getRemoteAddr() {
248: return included ? null : super .getRemoteAddr();
249: }
250:
251: public String getRemoteHost() {
252: return included ? null : super .getRemoteHost();
253: }
254:
255: public String getRealPath(String path) {
256: return included ? null : super .getRealPath(path);
257: }
258:
259: public StringBuffer getRequestURL() {
260: return included ? null : super .getRequestURL();
261: }
262:
263: /*
264: * -------------------------------------------------------------------------
265: * (non-Javadoc)
266: * Portlet Spec. PLT. 16.3.3.
267: * The following methods of the HttpServletRequest must do no operations
268: * and return null:
269: * getCharacterEncoding
270: * setCharacterEncoding
271: * getContentType
272: * getInputStream
273: * getReader
274: * The getContentLength method of the HttpServletRequest must return 0.
275: * -------------------------------------------------------------------------
276: */
277:
278: public String getCharacterEncoding() {
279: return included ? null : super .getCharacterEncoding();
280: }
281:
282: public void setCharacterEncoding(String encoding)
283: throws UnsupportedEncodingException {
284: if (!included) {
285: super .setCharacterEncoding(encoding);
286: }
287: }
288:
289: /*
290: * -------------------------------------------------------------------------
291: * (non-javadoc)
292: * Portlet Spec. PLT. 16.3.3.
293: * The getMethod method of the HttpServletRequest must always return 'GET'.
294: * -------------------------------------------------------------------------
295: */
296:
297: public String getMethod() {
298: return "GET";
299: }
300:
301: // Private Methods ---------------------------------------------------------
302:
303: /**
304: * Parses the appended query string and merges the appended parameters to
305: * the original parameters. Query parameters are name-value pairs separated
306: * by the '<code>&</code>' character.
307: * @param parameters the original parameters map.
308: * @param queryString the appended query string.
309: */
310: private void mergeQueryString(Map parameters, String queryString) {
311:
312: // Create the appended parameters map:
313: // key is the parameter name as a string,
314: // value is a List of parameter values (List of String).
315: Map appendedParameters = new HashMap();
316:
317: // Parse the appended query string.
318: if (LOG.isDebugEnabled()) {
319: LOG.debug("Parsing appended query string: " + queryString);
320: }
321: StringTokenizer st = new StringTokenizer(queryString, "&",
322: false);
323: while (st.hasMoreTokens()) {
324: String token = st.nextToken();
325: int equalIndex = token.indexOf("=");
326: if (equalIndex > 0) {
327: String key = token.substring(0, equalIndex);
328: String value = null;
329: if (equalIndex < token.length() - 1) {
330: value = token.substring(equalIndex + 1);
331: } else {
332: value = "";
333: }
334: List values = (List) appendedParameters.get(key);
335: if (values == null) {
336: values = new ArrayList();
337: }
338: values.add(value);
339: appendedParameters.put(key, values);
340: }
341: }
342: if (LOG.isDebugEnabled()) {
343: LOG.debug(appendedParameters.size()
344: + " parameters appended.");
345: }
346:
347: // Merge the appended parameters and the original parameters.
348: if (LOG.isDebugEnabled()) {
349: LOG
350: .debug("Merging appended parameters and original parameters...");
351: }
352: for (Iterator it = appendedParameters.keySet().iterator(); it
353: .hasNext();) {
354: String key = (String) it.next();
355: List values = (List) appendedParameters.get(key);
356: // If the parameter name (key) exists, merge parameter values.
357: if (parameters.containsKey(key)) {
358: String[] originalValues = (String[]) parameters
359: .get(key);
360: if (originalValues != null) {
361: for (int i = 0; i < originalValues.length; i++) {
362: values.add(originalValues[i]);
363: }
364: }
365: }
366: parameters.put(key, values
367: .toArray(new String[values.size()]));
368: }
369: }
370:
371: }
|