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.cocoon.generation;
018:
019: import java.io.IOException;
020: import java.io.StringReader;
021: import java.io.UnsupportedEncodingException;
022: import java.util.Enumeration;
023: import java.util.Map;
024:
025: import org.apache.avalon.framework.CascadingRuntimeException;
026: import org.apache.avalon.framework.parameters.ParameterException;
027: import org.apache.avalon.framework.parameters.Parameterizable;
028: import org.apache.avalon.framework.parameters.Parameters;
029: import org.apache.cocoon.ProcessingException;
030: import org.apache.cocoon.environment.ObjectModelHelper;
031: import org.apache.cocoon.environment.Request;
032: import org.apache.cocoon.environment.SourceResolver;
033: import org.apache.cocoon.xml.XMLUtils;
034: import org.apache.cocoon.xml.IncludeXMLConsumer;
035: import org.apache.excalibur.xml.sax.SAXParser;
036: import org.xml.sax.InputSource;
037: import org.xml.sax.SAXException;
038: import org.xml.sax.helpers.AttributesImpl;
039:
040: /**
041: * @cocoon.sitemap.component.documentation
042: * Generates an XML representation of the incoming request.
043: *
044: * @cocoon.sitemap.component.name request
045: * @cocoon.sitemap.component.label content
046: * @cocoon.sitemap.component.logger sitemap.generator.request
047: *
048: * @cocoon.sitemap.component.pooling.max 16
049: *
050: * <p>
051: * <b>Configuration options:</b>
052: * <dl>
053: * <dt> <i>container-encoding</i> (optional)
054: * <dd> The encoding used by container. Default value is ISO-8859-1.
055: * <dt> <i>form-encoding</i> (optional)
056: * <dd> The supposed encoding of the request parameter. Default is null.
057: * <dt> <i>generate-attributes</i> (optional)
058: * <dd> If true, request attributes were also included. Default is false.
059: * </dl>
060: * These configuration options are supported at both declaration and use time.
061: * The configuration at use time takes priority over declaration time.
062: *
063: * @author <a href="mailto:pier@apache.org">Pierpaolo Fumagalli</a>
064: * @author <a href="mailto:Giacomo.Pati@pwr.ch">Giacomo Pati</a>
065: * @author <a href="mailto:vgritsenko@apache.org">Vadim Gritsenko</a>
066: * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
067: * @version CVS $Id: RequestGenerator.java 433543 2006-08-22 06:22:54Z crossley $
068: */
069: public class RequestGenerator extends ServiceableGenerator implements
070: Parameterizable {
071:
072: /** The namespace prefix of this generator. */
073: private final static String PREFIX = "h";
074: /** The namespace URI of this generator. */
075: private final static String URI = "http://apache.org/cocoon/request/2.0";
076:
077: /** The configured container encoding at declaration time. */
078: private String global_container_encoding;
079: /** The configured container encoding at use time. */
080: private String container_encoding;
081:
082: /** The configured form encoding at declaration time. */
083: private String global_form_encoding;
084: /** The configured form encoding at use time. */
085: private String form_encoding;
086:
087: /** The configuration for including request attributes at declaration time. */
088: private boolean global_generate_attributes;
089: /** The configuration for including request attributes at use time. */
090: private boolean generate_attributes;
091:
092: public void parameterize(Parameters parameters)
093: throws ParameterException {
094: global_container_encoding = parameters.getParameter(
095: "container-encoding", "ISO-8859-1");
096: global_form_encoding = parameters.getParameter("form-encoding",
097: null);
098: global_generate_attributes = parameters.getParameterAsBoolean(
099: "generate-attributes", false);
100: }
101:
102: public void setup(SourceResolver resolver, Map objectModel,
103: String src, Parameters parameters)
104: throws ProcessingException, SAXException, IOException {
105: super .setup(resolver, objectModel, src, parameters);
106: container_encoding = parameters.getParameter(
107: "container-encoding", global_container_encoding);
108: form_encoding = parameters.getParameter("form-encoding",
109: global_form_encoding);
110: generate_attributes = parameters.getParameterAsBoolean(
111: "generate-attributes", global_generate_attributes);
112: }
113:
114: /**
115: * Generate XML data.
116: */
117: public void generate() throws SAXException {
118: final Request request = ObjectModelHelper
119: .getRequest(objectModel);
120: final AttributesImpl attr = new AttributesImpl();
121:
122: this .contentHandler.startDocument();
123: this .contentHandler.startPrefixMapping(PREFIX, URI);
124:
125: attribute(attr, "target", request.getRequestURI());
126: attribute(attr, "sitemap", request.getSitemapURI());
127: attribute(attr, "source", (this .source != null ? this .source
128: : ""));
129: start("request", attr);
130:
131: start("requestHeaders", attr);
132: Enumeration headers = request.getHeaderNames();
133: if (headers != null) {
134: while (headers.hasMoreElements()) {
135: String header = (String) headers.nextElement();
136: attribute(attr, "name", header);
137: start("header", attr);
138: data(request.getHeader(header));
139: end("header");
140: }
141: }
142: end("requestHeaders");
143:
144: start("requestParameters", attr);
145: Enumeration parameters = request.getParameterNames();
146: while (parameters.hasMoreElements()) {
147: String parameter = (String) parameters.nextElement();
148: attribute(attr, "name", parameter);
149: start("parameter", attr);
150: String values[] = request.getParameterValues(parameter);
151: if (values != null) {
152: for (int x = 0; x < values.length; x++) {
153: start("value", attr);
154: if (form_encoding != null) {
155: try {
156: data(values[x], container_encoding,
157: form_encoding);
158: } catch (UnsupportedEncodingException uee) {
159: throw new CascadingRuntimeException(
160: "The suggested encoding is not supported.",
161: uee);
162: }
163: } else if (parameter.startsWith("xml:")) {
164: try {
165: parse(values[x]);
166: } catch (Exception e) {
167: throw new CascadingRuntimeException(
168: "Could not parse the xml parameter",
169: e);
170: }
171: } else {
172: data(values[x]);
173: }
174: end("value");
175: }
176: }
177: end("parameter");
178: }
179: end("requestParameters");
180:
181: if (generate_attributes) {
182: start("requestAttributes", attr);
183: Enumeration attributes = request.getAttributeNames();
184: while (attributes.hasMoreElements()) {
185: String attribute = (String) attributes.nextElement();
186: attribute(attr, "name", attribute);
187: start("attribute", attr);
188: Object value = request.getAttribute(attribute);
189: if (value != null) {
190: start("value", attr);
191: XMLUtils.valueOf(this .contentHandler, value);
192: end("value");
193: }
194: end("attribute");
195: }
196: end("requestAttributes");
197: }
198:
199: this .start("configurationParameters", attr);
200: String[] confparams = super .parameters.getNames();
201: for (int i = 0; i < confparams.length; i++) {
202: attribute(attr, "name", confparams[i]);
203: start("parameter", attr);
204: data(super .parameters.getParameter(confparams[i], ""));
205: end("parameter");
206: }
207: end("configurationParameters");
208:
209: start("remoteUser", attr);
210: if (request.getRemoteUser() != null) {
211: data(request.getRemoteUser());
212: }
213: end("remoteUser");
214:
215: end("request");
216:
217: this .contentHandler.endPrefixMapping(PREFIX);
218: this .contentHandler.endDocument();
219: }
220:
221: private void attribute(AttributesImpl attr, String name,
222: String value) {
223: attr.addAttribute("", name, name, "CDATA", value);
224: }
225:
226: private void start(String name, AttributesImpl attr)
227: throws SAXException {
228: super .contentHandler.startElement(URI, name, PREFIX + ":"
229: + name, attr);
230: attr.clear();
231: }
232:
233: private void end(String name) throws SAXException {
234: super .contentHandler.endElement(URI, name, PREFIX + ":" + name);
235: }
236:
237: private void data(String data) throws SAXException {
238: super .contentHandler.characters(data.toCharArray(), 0, data
239: .length());
240: }
241:
242: private void data(String data, String container_encoding,
243: String form_encoding) throws SAXException,
244: UnsupportedEncodingException {
245: this .data(new String(data.getBytes(container_encoding),
246: form_encoding));
247: }
248:
249: private void parse(String data) throws Exception {
250: SAXParser parser = null;
251: try {
252: parser = (SAXParser) manager.lookup(SAXParser.ROLE);
253: InputSource is = new InputSource(new StringReader(data));
254: parser.parse(is, new IncludeXMLConsumer(super.xmlConsumer));
255: } finally {
256: manager.release(parser);
257: }
258: }
259: }
|