001: /*
002: * Copyright 2005-2007 Noelios Consulting.
003: *
004: * The contents of this file are subject to the terms of the Common Development
005: * and Distribution License (the "License"). You may not use this file except in
006: * compliance with the License.
007: *
008: * You can obtain a copy of the license at
009: * http://www.opensource.org/licenses/cddl1.txt See the License for the specific
010: * language governing permissions and limitations under the License.
011: *
012: * When distributing Covered Code, include this CDDL HEADER in each file and
013: * include the License file at http://www.opensource.org/licenses/cddl1.txt If
014: * applicable, add the following below this CDDL HEADER, with the fields
015: * enclosed by brackets "[]" replaced with your own identifying information:
016: * Portions Copyright [yyyy] [name of copyright owner]
017: */
018:
019: package org.restlet.resource;
020:
021: import java.io.IOException;
022: import java.io.OutputStream;
023:
024: import javax.xml.namespace.QName;
025: import javax.xml.parsers.DocumentBuilder;
026: import javax.xml.parsers.DocumentBuilderFactory;
027: import javax.xml.parsers.ParserConfigurationException;
028: import javax.xml.transform.OutputKeys;
029: import javax.xml.transform.Transformer;
030: import javax.xml.transform.TransformerConfigurationException;
031: import javax.xml.transform.TransformerException;
032: import javax.xml.transform.TransformerFactory;
033: import javax.xml.transform.TransformerFactoryConfigurationError;
034: import javax.xml.transform.dom.DOMSource;
035: import javax.xml.transform.stream.StreamResult;
036: import javax.xml.xpath.XPath;
037: import javax.xml.xpath.XPathFactory;
038:
039: import org.restlet.data.MediaType;
040: import org.w3c.dom.Document;
041: import org.xml.sax.SAXException;
042:
043: /**
044: * XML representation based on a DOM document. DOM is a standard XML object
045: * model defined by the W3C.
046: *
047: * @author Jerome Louvel (contact@noelios.com)
048: */
049: public class DomRepresentation extends XmlRepresentation {
050: /** The wrapped DOM document. */
051: private Document dom;
052:
053: /** The source XML representation. */
054: private Representation xmlRepresentation;
055:
056: /**
057: * Constructor for an empty document.
058: *
059: * @param mediaType
060: * The representation's media type.
061: */
062: public DomRepresentation(MediaType mediaType) throws IOException {
063: super (mediaType);
064: this .dom = getDocumentBuilder().newDocument();
065: }
066:
067: /**
068: * Constructor from an existing DOM document.
069: *
070: * @param mediaType
071: * The representation's media type.
072: * @param xmlDocument
073: * The source DOM document.
074: */
075: public DomRepresentation(MediaType mediaType, Document xmlDocument) {
076: super (mediaType);
077: this .dom = xmlDocument;
078: }
079:
080: /**
081: * Constructor.
082: *
083: * @param xmlRepresentation
084: * A source XML representation to parse.
085: */
086: public DomRepresentation(Representation xmlRepresentation) {
087: super (xmlRepresentation.getMediaType());
088: this .xmlRepresentation = xmlRepresentation;
089: }
090:
091: @Override
092: public Object evaluate(String expression, QName returnType)
093: throws Exception {
094: XPath xpath = XPathFactory.newInstance().newXPath();
095: xpath.setNamespaceContext(this );
096: return xpath.evaluate(expression, getDocument(), returnType);
097: }
098:
099: /**
100: * Returns the wrapped DOM document.
101: *
102: * @return The wrapped DOM document.
103: */
104: public Document getDocument() throws IOException {
105: if ((this .dom == null) && (this .xmlRepresentation != null)) {
106: try {
107: this .dom = getDocumentBuilder().parse(
108: xmlRepresentation.getStream());
109: } catch (SAXException se) {
110: throw new IOException(
111: "Couldn't read the XML representation. "
112: + se.getMessage());
113: }
114: }
115:
116: return this .dom;
117: }
118:
119: /**
120: * Returns a document builder properly configured.
121: *
122: * @return A document builder properly configured.
123: */
124: private DocumentBuilder getDocumentBuilder() throws IOException {
125: try {
126: DocumentBuilderFactory dbf = DocumentBuilderFactory
127: .newInstance();
128: dbf.setNamespaceAware(isNamespaceAware());
129: dbf.setValidating(false);
130: return dbf.newDocumentBuilder();
131: } catch (ParserConfigurationException pce) {
132: throw new IOException(
133: "Couldn't create the empty document: "
134: + pce.getMessage());
135: }
136: }
137:
138: /**
139: * Sets the wrapped DOM document.
140: *
141: * @param dom
142: * The wrapped DOM document.
143: */
144: public void setDocument(Document dom) {
145: this .dom = dom;
146: }
147:
148: /**
149: * Writes the representation to a byte stream.
150: *
151: * @param outputStream
152: * The output stream.
153: */
154: public void write(OutputStream outputStream) throws IOException {
155: try {
156: if (getDocument() != null) {
157: Transformer transformer = TransformerFactory
158: .newInstance().newTransformer();
159:
160: if (getDocument().getDoctype() != null) {
161: transformer.setOutputProperty(
162: OutputKeys.DOCTYPE_SYSTEM, getDocument()
163: .getDoctype().getSystemId());
164: transformer.setOutputProperty(
165: OutputKeys.DOCTYPE_PUBLIC, getDocument()
166: .getDoctype().getPublicId());
167: }
168:
169: transformer.transform(new DOMSource(getDocument()),
170: new StreamResult(outputStream));
171: }
172: } catch (TransformerConfigurationException tce) {
173: throw new IOException(
174: "Couldn't write the XML representation: "
175: + tce.getMessage());
176: } catch (TransformerException te) {
177: throw new IOException(
178: "Couldn't write the XML representation: "
179: + te.getMessage());
180: } catch (TransformerFactoryConfigurationError tfce) {
181: throw new IOException(
182: "Couldn't write the XML representation: "
183: + tfce.getMessage());
184: }
185: }
186: }
|