001: /*
002: * Copyright 2005 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.ws.server.endpoint;
018:
019: import javax.xml.parsers.DocumentBuilder;
020: import javax.xml.parsers.DocumentBuilderFactory;
021: import javax.xml.parsers.ParserConfigurationException;
022: import javax.xml.transform.Source;
023: import javax.xml.transform.dom.DOMResult;
024: import javax.xml.transform.dom.DOMSource;
025:
026: import org.springframework.xml.transform.TransformerObjectSupport;
027: import org.w3c.dom.Document;
028: import org.w3c.dom.Element;
029:
030: /**
031: * Abstract base class for endpoints that handle the message payload as DOM elements.
032: * <p/>
033: * <p>Offers the message payload as a DOM <code>Element</code>, and allows subclasses to create a response by returning
034: * an <code>Element</code>.
035: * <p/>
036: * <p>An <code>AbstractDomPayloadEndpoint</code> only accept <i>one</i> payload element. Multiple payload elements are
037: * not in accordance with WS-I.
038: *
039: * @author Arjen Poutsma
040: * @author Alef Arendsen
041: * @see #invokeInternal(org.w3c.dom.Element,org.w3c.dom.Document)
042: * @since 1.0.0
043: */
044: public abstract class AbstractDomPayloadEndpoint extends
045: TransformerObjectSupport implements PayloadEndpoint {
046:
047: private DocumentBuilderFactory documentBuilderFactory;
048:
049: private boolean validating = false;
050:
051: private boolean namespaceAware = true;
052:
053: /** Set whether or not the XML parser should be XML namespace aware. Default is <code>true</code>. */
054: public void setNamespaceAware(boolean namespaceAware) {
055: this .namespaceAware = namespaceAware;
056: }
057:
058: /** Set if the XML parser should validate the document. Default is <code>false</code>. */
059: public void setValidating(boolean validating) {
060: this .validating = validating;
061: }
062:
063: public final Source invoke(Source request) throws Exception {
064: if (documentBuilderFactory == null) {
065: documentBuilderFactory = createDocumentBuilderFactory();
066: }
067: DocumentBuilder documentBuilder = createDocumentBuilder(documentBuilderFactory);
068: Element requestElement = null;
069: if (request != null) {
070: Document requestDocument = documentBuilder.newDocument();
071: DOMResult domResult = new DOMResult(requestDocument);
072: transform(request, domResult);
073: requestElement = (Element) requestDocument.getFirstChild();
074: }
075: Document responseDocument = documentBuilder.newDocument();
076: Element responseElement = invokeInternal(requestElement,
077: responseDocument);
078: if (responseElement != null) {
079: return new DOMSource(responseElement);
080: } else {
081: return null;
082: }
083: }
084:
085: /**
086: * Create a <code>DocumentBuilder</code> that this endpoint will use for parsing XML documents. Can be overridden in
087: * subclasses, adding further initialization of the builder.
088: *
089: * @param factory the <code>DocumentBuilderFactory</code> that the DocumentBuilder should be created with
090: * @return the <code>DocumentBuilder</code>
091: * @throws ParserConfigurationException if thrown by JAXP methods
092: */
093: protected DocumentBuilder createDocumentBuilder(
094: DocumentBuilderFactory factory)
095: throws ParserConfigurationException {
096: return factory.newDocumentBuilder();
097: }
098:
099: /**
100: * Create a <code>DocumentBuilderFactory</code> that this endpoint will use for constructing XML documents. Can be
101: * overridden in subclasses, adding further initialization of the factory. The resulting
102: * <code>DocumentBuilderFactory</code> is cached, so this method will only be called once.
103: *
104: * @return the DocumentBuilderFactory
105: * @throws ParserConfigurationException if thrown by JAXP methods
106: */
107: protected DocumentBuilderFactory createDocumentBuilderFactory()
108: throws ParserConfigurationException {
109: DocumentBuilderFactory factory = DocumentBuilderFactory
110: .newInstance();
111: factory.setValidating(validating);
112: factory.setNamespaceAware(namespaceAware);
113: return factory;
114: }
115:
116: /**
117: * Template method that subclasses must implement to process the request.
118: * <p/>
119: * <p>Offers the request payload as a DOM <code>Element</code>, and allows subclasses to return a response
120: * <code>Element</code>.
121: * <p/>
122: * <p>The given DOM <code>Document</code> is to be used for constructing <code>Node</code>s, by using the various
123: * <code>create</code> methods.
124: *
125: * @param requestElement the contents of the SOAP message as DOM elements
126: * @param responseDocument a DOM document to be used for constructing <code>Node</code>s
127: * @return the response element. Can be <code>null</code> to specify no response.
128: */
129: protected abstract Element invokeInternal(Element requestElement,
130: Document responseDocument) throws Exception;
131: }
|