001: /*
002: * Returns the XML text verbatim, doesn't encode it as swf
003: */
004:
005: /* *****************************************************************************
006: * XMLConverter.java
007: * ****************************************************************************/
008:
009: /* J_LZ_COPYRIGHT_BEGIN *******************************************************
010: * Copyright 2001-2008 Laszlo Systems, Inc. All Rights Reserved. *
011: * Use is subject to license terms. *
012: * J_LZ_COPYRIGHT_END *********************************************************/
013:
014: package org.openlaszlo.data;
015:
016: import java.io.*;
017: import java.util.Properties;
018:
019: import javax.servlet.http.HttpServletRequest;
020: import javax.servlet.http.HttpServletResponse;
021:
022: import org.apache.log4j.*;
023:
024: import org.openlaszlo.utils.ContentEncoding;
025: import org.openlaszlo.utils.LZHttpUtils;
026:
027: import org.openlaszlo.media.MimeType;
028: import org.openlaszlo.server.LPS;
029:
030: import org.jdom.Attribute;
031: import org.jdom.Comment;
032: import org.jdom.Document;
033: import org.jdom.Element;
034: import org.jdom.JDOMException;
035: import org.jdom.input.SAXBuilder;
036: import org.jdom.output.XMLOutputter;
037:
038: import org.apache.commons.httpclient.*;
039: import org.apache.commons.httpclient.methods.*;
040: import org.apache.commons.httpclient.util.*;
041:
042: import org.xmlpull.v1.*;
043:
044: /**
045: * XML Converter
046: *
047: */
048: public class XMLGrabber extends Converter {
049:
050: private static Logger mLogger = Logger.getLogger(XMLGrabber.class);
051: private static XmlPullParserFactory factory = null;
052:
053: private static XmlPullParserFactory getXPPFactory() {
054: if (factory == null) {
055: // Set up the XML Parser factory
056: try {
057: String sys = null;
058: try {
059: sys = System
060: .getProperty(XmlPullParserFactory.PROPERTY_NAME);
061: } catch (SecurityException se) {
062: }
063: factory = XmlPullParserFactory.newInstance(sys, null);
064: factory.setNamespaceAware(false);
065: factory.setValidating(false);
066: } catch (XmlPullParserException e) {
067: throw new RuntimeException(e.getMessage());
068: }
069: }
070: return factory;
071: }
072:
073: /**
074: * Convert incoming XML to ... XML
075: *
076: * This method is called convertToSWF for historical reasons, and nobody
077: * has changed the API call name yet.
078: *
079: * A dataset will look like this:
080: * <resultset>
081: * <body>
082: * <weather sourceurl="http://www.srh.noaa.gov/zipcity.php?inputstring=02460">
083: * <radar src="http://www.laszlosystems.com:80/weather/small/kbox.jpg"/>
084: * <satellite src="http://www.laszlosystems.com:80/weather/thumbs/ECI8.JPG"/>
085: * </weather>
086: * </body>
087: * <headers>
088: * <header name="Date" value="Thu, 29 Dec 2005 03:49:46 GMT"/>
089: * <header name="Server" value="Apache/2.0.44 (Unix) mod_ssl/2.0.44 OpenSSL/0.9.6b DAV/2 mod_jk/1.2.1 PHP/4.3.0"/>
090: * </headers>
091: * </resultset>
092: */
093:
094: public InputStream convertToSWF(Data data, HttpServletRequest req,
095: HttpServletResponse res) throws ConversionException,
096: IOException {
097:
098: try {
099: PipedOutputStream pout = new PipedOutputStream();
100: PipedInputStream in = new PipedInputStream(pout);
101:
102: XmlSerializer serializer;
103: XmlPullParser parser;
104: parser = getXPPFactory().newPullParser();
105: InputStream dstream = data.getInputStream();
106: parser.setInput(dstream, null);
107: serializer = factory.newSerializer();
108: serializer.setOutput(pout, "UTF-8");
109:
110: HttpMethodBase request = ((HttpData) data).getRequest();
111:
112: final String sendheaders = req.getParameter("sendheaders");
113:
114: XMLCopyThread worker = new XMLCopyThread(pout, parser,
115: serializer, request, sendheaders);
116: worker.start();
117:
118: return in;
119:
120: } catch (XmlPullParserException ex) {
121: throw new ConversionException("Parsing XML: "
122: + ex.getMessage());
123: }
124: }
125:
126: // Worker thread to parse XML (which serves to translate obscure
127: // charsets to UTF-8) and wrap it in <resultset>, possibly adding
128: // proxied HTTP headers from backedn response.
129: // This is written to the PipedOutputStream which we were passed.
130: class XMLCopyThread extends Thread implements Runnable {
131: OutputStream pout = null;
132: XmlPullParser parser;
133: XmlSerializer serializer;
134: HttpMethodBase request;
135: String sendheaders = null;
136:
137: XMLCopyThread(OutputStream pout, XmlPullParser parser,
138: XmlSerializer serializer, HttpMethodBase request,
139: String sendheaders) {
140: this .pout = pout;
141: this .parser = parser;
142: this .serializer = serializer;
143: this .request = request;
144: this .sendheaders = sendheaders;
145: }
146:
147: public void run() {
148: try {
149: writeXMLDataToOutputStream();
150: } catch (Exception e) {
151: } finally {
152: try {
153: pout.flush();
154: pout.close();
155: } catch (Exception e) {
156: }
157: }
158: }
159:
160: // Generates an XML document with this structure
161: // <resultset>
162: // <body> [PROXIED_XMLDOC] </body>
163: // <headers> ... </headers>
164: // </resultset>
165: void writeXMLDataToOutputStream()
166: throws XmlPullParserException, IOException {
167: //Run through XML PULL parser, to convert to UTF8, and
168: // wrap in <resultset> tag, plus optional headers
169:
170: // Start a standalone document;
171: //serializer.startDocument("UTF-8", Boolean.TRUE);
172:
173: serializer.startTag("", "resultset");
174: serializer.startTag("", "body");
175:
176: parser.nextToken(); // read first token
177:
178: while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
179: writeToken(parser.getEventType());
180: parser.nextToken();
181: }
182:
183: serializer.endTag("", "body");
184:
185: // <headers> ... </headers>
186: serializer.startTag("", "headers");
187:
188: // Get headers
189: if (sendheaders == null || sendheaders.equals("true")) {
190: Header[] hedz = request.getResponseHeaders();
191: for (int i = 0; i < hedz.length; i++) {
192: String name = hedz[i].getName();
193: if (LZHttpUtils.allowForward(name, null)) {
194: serializer.startTag("", "header");
195:
196: serializer.attribute(null, "name", name);
197: serializer.attribute(null, "value", hedz[i]
198: .getValue());
199: serializer.endTag("", "header");
200: }
201: }
202: }
203: serializer.endTag("", "headers");
204:
205: serializer.endTag("", "resultset");
206: serializer.endDocument();
207: }
208:
209: private void writeStartTag() throws XmlPullParserException,
210: IOException {
211: if (!parser
212: .getFeature(XmlPullParser.FEATURE_REPORT_NAMESPACE_ATTRIBUTES)) {
213: for (int i = parser
214: .getNamespaceCount(parser.getDepth() - 1); i <= parser
215: .getNamespaceCount(parser.getDepth()) - 1; i++) {
216: serializer.setPrefix(parser.getNamespacePrefix(i),
217: parser.getNamespaceUri(i));
218: }
219: }
220: serializer
221: .startTag(parser.getNamespace(), parser.getName());
222:
223: for (int i = 0; i < parser.getAttributeCount(); i++) {
224: serializer.attribute(parser.getAttributeNamespace(i),
225: parser.getAttributeName(i), parser
226: .getAttributeValue(i));
227: }
228: }
229:
230: private void writeToken(int eventType)
231: throws XmlPullParserException, IOException {
232: switch (eventType) {
233:
234: case XmlPullParser.START_TAG:
235: writeStartTag();
236: break;
237:
238: case XmlPullParser.END_TAG:
239: serializer.endTag(parser.getNamespace(), parser
240: .getName());
241: break;
242:
243: case XmlPullParser.START_DOCUMENT:
244: //use Boolean.TRUE to make it standalone
245: //Boolean standalone = (Boolean) parser.getProperty(PROPERTY_XMLDECL_STANDALONE);
246: //serializer.startDocument(parser.getInputEncoding(), standalone);
247: break;
248:
249: case XmlPullParser.END_DOCUMENT:
250: //serializer.endDocument();
251: break;
252:
253: case XmlPullParser.IGNORABLE_WHITESPACE:
254: //comment it to remove ignorable whtespaces from XML infoset
255: String s = parser.getText();
256: serializer.ignorableWhitespace(s);
257: break;
258:
259: case XmlPullParser.TEXT:
260: serializer.text(parser.getText());
261: break;
262:
263: case XmlPullParser.ENTITY_REF:
264: serializer.entityRef(parser.getName());
265: break;
266:
267: case XmlPullParser.CDSECT:
268: serializer.cdsect(parser.getText());
269: break;
270:
271: case XmlPullParser.PROCESSING_INSTRUCTION:
272: // serializer.processingInstruction( parser.getText ());
273: break;
274:
275: case XmlPullParser.COMMENT:
276: //serializer.comment (parser.getText ());
277: break;
278:
279: case XmlPullParser.DOCDECL:
280: // serializer.docdecl (parser.getText ());
281: break;
282: }
283: }
284:
285: }
286:
287: /**
288: * @return the encoding that should be used when responding
289: * to this request or null for no encoding. For now, the only
290: * acceptable values besides null are "gzip" and "deflate".
291: */
292: public String chooseEncoding(HttpServletRequest req) {
293:
294: String e = req.getParameter("enc");
295: if (e == null || e.equals("false")) {
296: return null;
297: }
298:
299: String enc = ContentEncoding.chooseEncoding(req);
300: mLogger.debug("Encoding: " + enc);
301: return enc;
302: }
303:
304: }
|