001: /*
002: * The contents of this file are subject to the terms
003: * of the Common Development and Distribution License
004: * (the "License"). You may not use this file except
005: * in compliance with the License.
006: *
007: * You can obtain a copy of the license at
008: * https://jwsdp.dev.java.net/CDDLv1.0.html
009: * See the License for the specific language governing
010: * permissions and limitations under the License.
011: *
012: * When distributing Covered Code, include this CDDL
013: * HEADER in each file and include the License file at
014: * https://jwsdp.dev.java.net/CDDLv1.0.html If applicable,
015: * add the following below this CDDL HEADER, with the
016: * fields enclosed by brackets "[]" replaced with your
017: * own identifying information: Portions Copyright [yyyy]
018: * [name of copyright owner]
019: */
020: /*
021: * $Id: EnvelopeImpl.java,v 1.3 2007/07/16 16:41:23 ofung Exp $
022: * $Revision: 1.3 $
023: * $Date: 2007/07/16 16:41:23 $
024: */
025:
026: /*
027: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
028: *
029: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
030: *
031: * The contents of this file are subject to the terms of either the GNU
032: * General Public License Version 2 only ("GPL") or the Common Development
033: * and Distribution License("CDDL") (collectively, the "License"). You
034: * may not use this file except in compliance with the License. You can obtain
035: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
036: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
037: * language governing permissions and limitations under the License.
038: *
039: * When distributing the software, include this License Header Notice in each
040: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
041: * Sun designates this particular file as subject to the "Classpath" exception
042: * as provided by Sun in the GPL Version 2 section of the License file that
043: * accompanied this code. If applicable, add the following below the License
044: * Header, with the fields enclosed by brackets [] replaced by your own
045: * identifying information: "Portions Copyrighted [year]
046: * [name of copyright owner]"
047: *
048: * Contributor(s):
049: *
050: * If you wish your version of this file to be governed by only the CDDL or
051: * only the GPL Version 2, indicate your decision by adding "[Contributor]
052: * elects to include this software in this distribution under the [CDDL or GPL
053: * Version 2] license." If you don't indicate a single choice of license, a
054: * recipient has the option to distribute your version of this file under
055: * either the CDDL, the GPL Version 2 or to extend the choice of license to
056: * its licensees as provided above. However, if you add GPL Version 2 code
057: * and therefore, elected the GPL Version 2 license, then the option applies
058: * only if the new code is made subject to such option by the copyright
059: * holder.
060: */
061: package com.sun.xml.messaging.saaj.soap.impl;
062:
063: import java.io.IOException;
064: import java.io.OutputStream;
065: import java.io.OutputStreamWriter;
066:
067: import java.util.Iterator;
068: import java.util.logging.Level;
069: import org.w3c.dom.Document;
070:
071: import javax.xml.namespace.QName;
072: import javax.xml.soap.*;
073: import javax.xml.transform.*;
074: import javax.xml.transform.dom.DOMSource;
075: import javax.xml.transform.stream.StreamResult;
076: import javax.xml.transform.sax.*;
077:
078: import com.sun.xml.messaging.saaj.SOAPExceptionImpl;
079: import com.sun.xml.messaging.saaj.soap.Envelope;
080: import com.sun.xml.messaging.saaj.soap.SOAPDocumentImpl;
081: import com.sun.xml.messaging.saaj.soap.name.NameImpl;
082: import com.sun.xml.messaging.saaj.util.FastInfosetReflection;
083: import com.sun.xml.messaging.saaj.util.transform.EfficientStreamingTransformer;
084:
085: /**
086: * Our implementation of the SOAP envelope.
087: *
088: * @author Anil Vijendran (anil@sun.com)
089: */
090: public abstract class EnvelopeImpl extends ElementImpl implements
091: Envelope {
092: protected HeaderImpl header;
093: protected BodyImpl body;
094: String omitXmlDecl = "yes";
095: String charset = "utf-8";
096: String xmlDecl = null;
097:
098: protected EnvelopeImpl(SOAPDocumentImpl ownerDoc, Name name) {
099: super (ownerDoc, name);
100: }
101:
102: protected EnvelopeImpl(SOAPDocumentImpl ownerDoc, QName name) {
103: super (ownerDoc, name);
104: }
105:
106: protected EnvelopeImpl(SOAPDocumentImpl ownerDoc, NameImpl name,
107: boolean createHeader, boolean createBody)
108: throws SOAPException {
109: this (ownerDoc, name);
110:
111: ensureNamespaceIsDeclared(getElementQName().getPrefix(),
112: getElementQName().getNamespaceURI());
113:
114: // XXX
115: if (createHeader)
116: addHeader();
117:
118: if (createBody)
119: addBody();
120: }
121:
122: protected abstract NameImpl getHeaderName(String prefix);
123:
124: protected abstract NameImpl getBodyName(String prefix);
125:
126: public SOAPHeader addHeader() throws SOAPException {
127: return addHeader(null);
128: }
129:
130: public SOAPHeader addHeader(String prefix) throws SOAPException {
131:
132: if (prefix == null || prefix.equals("")) {
133: prefix = getPrefix();
134: }
135:
136: NameImpl headerName = getHeaderName(prefix);
137: NameImpl bodyName = getBodyName(prefix);
138:
139: HeaderImpl header = null;
140: SOAPElement firstChild = null;
141:
142: Iterator eachChild = getChildElementNodes();
143: if (eachChild.hasNext()) {
144: firstChild = (SOAPElement) eachChild.next();
145: if (firstChild.getElementName().equals(headerName)) {
146: log.severe("SAAJ0120.impl.header.already.exists");
147: throw new SOAPExceptionImpl(
148: "Can't add a header when one is already present.");
149: } else if (!firstChild.getElementName().equals(bodyName)) {
150: log
151: .severe("SAAJ0121.impl.invalid.first.child.of.envelope");
152: throw new SOAPExceptionImpl(
153: "First child of Envelope must be either a Header or Body");
154: }
155: }
156:
157: header = (HeaderImpl) createElement(headerName);
158: insertBefore(header, firstChild);
159: header.ensureNamespaceIsDeclared(headerName.getPrefix(),
160: headerName.getURI());
161:
162: return header;
163: }
164:
165: protected void lookForHeader() throws SOAPException {
166: NameImpl headerName = getHeaderName(null);
167:
168: HeaderImpl hdr = (HeaderImpl) findChild(headerName);
169: header = hdr;
170: }
171:
172: public SOAPHeader getHeader() throws SOAPException {
173: lookForHeader();
174: return header;
175: }
176:
177: protected void lookForBody() throws SOAPException {
178: NameImpl bodyName = getBodyName(null);
179:
180: BodyImpl bodyChildElement = (BodyImpl) findChild(bodyName);
181: body = bodyChildElement;
182: }
183:
184: public SOAPBody addBody() throws SOAPException {
185: return addBody(null);
186: }
187:
188: public SOAPBody addBody(String prefix) throws SOAPException {
189: lookForBody();
190:
191: if (prefix == null || prefix.equals("")) {
192: prefix = getPrefix();
193: }
194:
195: if (body == null) {
196: NameImpl bodyName = getBodyName(prefix);
197: body = (BodyImpl) createElement(bodyName);
198: insertBefore(body, null);
199: body.ensureNamespaceIsDeclared(bodyName.getPrefix(),
200: bodyName.getURI());
201: } else {
202: log.severe("SAAJ0122.impl.body.already.exists");
203: throw new SOAPExceptionImpl(
204: "Can't add a body when one is already present.");
205: }
206:
207: return body;
208: }
209:
210: protected SOAPElement addElement(Name name) throws SOAPException {
211: if (getBodyName(null).equals(name)) {
212: return addBody(name.getPrefix());
213: }
214: if (getHeaderName(null).equals(name)) {
215: return addHeader(name.getPrefix());
216: }
217:
218: return super .addElement(name);
219: }
220:
221: protected SOAPElement addElement(QName name) throws SOAPException {
222: if (getBodyName(null).equals(NameImpl.convertToName(name))) {
223: return addBody(name.getPrefix());
224: }
225: if (getHeaderName(null).equals(NameImpl.convertToName(name))) {
226: return addHeader(name.getPrefix());
227: }
228:
229: return super .addElement(name);
230: }
231:
232: public SOAPBody getBody() throws SOAPException {
233: lookForBody();
234: return body;
235: }
236:
237: public Source getContent() {
238: return new DOMSource(getOwnerDocument());
239: }
240:
241: public Name createName(String localName, String prefix, String uri)
242: throws SOAPException {
243:
244: // validating parameters before passing them on
245: // to make sure that the namespace specification rules are followed
246:
247: // reserved xmlns prefix cannot be used.
248: if ("xmlns".equals(prefix)) {
249: log.severe("SAAJ0123.impl.no.reserved.xmlns");
250: throw new SOAPExceptionImpl(
251: "Cannot declare reserved xmlns prefix");
252: }
253: // Qualified name cannot be xmlns.
254: if ((prefix == null) && ("xmlns".equals(localName))) {
255: log.severe("SAAJ0124.impl.qualified.name.cannot.be.xmlns");
256: throw new SOAPExceptionImpl(
257: "Qualified name cannot be xmlns");
258: }
259:
260: return NameImpl.create(localName, prefix, uri);
261: }
262:
263: public Name createName(String localName, String prefix)
264: throws SOAPException {
265: String namespace = getNamespaceURI(prefix);
266: if (namespace == null) {
267: log.log(Level.SEVERE, "SAAJ0126.impl.cannot.locate.ns",
268: new String[] { prefix });
269: throw new SOAPExceptionImpl(
270: "Unable to locate namespace for prefix " + prefix);
271: }
272: return NameImpl.create(localName, prefix, namespace);
273: }
274:
275: public Name createName(String localName) throws SOAPException {
276: return NameImpl.createFromUnqualifiedName(localName);
277: }
278:
279: public void setOmitXmlDecl(String value) {
280: this .omitXmlDecl = value;
281: }
282:
283: public void setXmlDecl(String value) {
284: this .xmlDecl = value;
285: }
286:
287: private String getOmitXmlDecl() {
288: return this .omitXmlDecl;
289: }
290:
291: public void setCharsetEncoding(String value) {
292: charset = value;
293: }
294:
295: public void output(OutputStream out) throws IOException {
296: try {
297: Transformer transformer = EfficientStreamingTransformer
298: .newTransformer();
299:
300: transformer.setOutputProperty(
301: OutputKeys.OMIT_XML_DECLARATION, "yes");
302: /*omitXmlDecl);*/
303: // no equivalent for "setExpandEmptyElements"
304: transformer.setOutputProperty(OutputKeys.ENCODING, charset);
305:
306: if (omitXmlDecl.equals("no") && xmlDecl == null) {
307: xmlDecl = "<?xml version=\""
308: + getOwnerDocument().getXmlVersion()
309: + "\" encoding=\"" + charset + "\" ?>";
310: }
311:
312: StreamResult result = new StreamResult(out);
313: if (xmlDecl != null) {
314: OutputStreamWriter writer = new OutputStreamWriter(out,
315: charset);
316: writer.write(xmlDecl);
317: writer.flush();
318: result = new StreamResult(writer);
319: }
320:
321: log.log(Level.FINE, "SAAJ0190.impl.set.xml.declaration",
322: new String[] { omitXmlDecl });
323: log.log(Level.FINE, "SAAJ0191.impl.set.encoding",
324: new String[] { charset });
325:
326: //StreamResult result = new StreamResult(out);
327: transformer.transform(getContent(), result);
328: } catch (Exception ex) {
329: throw new IOException(ex.getMessage());
330: }
331: }
332:
333: /**
334: * Serialize to FI if boolean parameter set.
335: */
336: public void output(OutputStream out, boolean isFastInfoset)
337: throws IOException {
338: if (!isFastInfoset) {
339: output(out);
340: } else {
341: try {
342: // Run transform and generate FI output from content
343: Source source = getContent();
344: Transformer transformer = EfficientStreamingTransformer
345: .newTransformer();
346: transformer.transform(getContent(),
347: FastInfosetReflection
348: .FastInfosetResult_new(out));
349: } catch (Exception ex) {
350: throw new IOException(ex.getMessage());
351: }
352: }
353: }
354:
355: // public void prettyPrint(OutputStream out) throws IOException {
356: // if (getDocument() == null)
357: // initDocument();
358: //
359: // OutputFormat format = OutputFormat.createPrettyPrint();
360: //
361: // format.setIndentSize(2);
362: // format.setNewlines(true);
363: // format.setTrimText(true);
364: // format.setPadText(true);
365: // format.setExpandEmptyElements(false);
366: //
367: // XMLWriter writer = new XMLWriter(out, format);
368: // writer.write(getDocument());
369: // }
370: //
371: // public void prettyPrint(Writer out) throws IOException {
372: // if (getDocument() == null)
373: // initDocument();
374: //
375: // OutputFormat format = OutputFormat.createPrettyPrint();
376: //
377: // format.setIndentSize(2);
378: // format.setNewlines(true);
379: // format.setTrimText(true);
380: // format.setPadText(true);
381: // format.setExpandEmptyElements(false);
382: //
383: // XMLWriter writer = new XMLWriter(out, format);
384: // writer.write(getDocument());
385: // }
386:
387: public SOAPElement setElementQName(QName newName)
388: throws SOAPException {
389: log.log(Level.SEVERE,
390: "SAAJ0146.impl.invalid.name.change.requested",
391: new Object[] { elementQName.getLocalPart(),
392: newName.getLocalPart() });
393: throw new SOAPException("Cannot change name for "
394: + elementQName.getLocalPart() + " to "
395: + newName.getLocalPart());
396: }
397: }
|