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: SAAJServlet.java,v 1.2 2007/07/16 16:41:15 ofung Exp $
022: * $Revision: 1.2 $
023: * $Date: 2007/07/16 16:41:15 $
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.soap.server;
062:
063: import java.io.*;
064: import java.util.*;
065:
066: import javax.servlet.ServletConfig;
067: import javax.servlet.ServletException;
068: import javax.servlet.http.*;
069: import javax.xml.soap.*;
070:
071: /**
072: * The superclass for components that
073: * live in a servlet container that receives SAAJ messages.
074: * A <code>SAAJServlet</code> object is notified of a message's arrival
075: * using the HTTP-SOAP binding.
076: * <P>
077: * The <code>SAAJServlet</code> class is a support/utility class and is
078: * provided purely as a convenience. It is not a mandatory component, and
079: * there is no requirement that it be implemented or extended.
080: * <P>
081: */
082: public abstract class SAAJServlet extends HttpServlet {
083:
084: /**
085: * A <code>SOAPConnection</code> for use of the <code>SAAJServlet</code>.
086: */
087: protected SOAPConnection conn = null;
088:
089: /**
090: * The <code>MessageFactory</code> object that will be used internally
091: * to create the <code>SOAPMessage</code> object to be passed to the
092: * method <code>onMessage</code>. This new message will contain the data
093: * from the message that was posted to the servlet.
094: * Based on the incoming message's content type a SOAP 1.1 or 1.2 Message
095: * reply is created. A dynamic messageFactory is created which automatically
096: * figures out the SOAP version.
097: */
098: protected MessageFactory msgFactory = null;
099:
100: /**
101: * Initializes this <code>SAAJServlet</code> object using the given
102: * <code>ServletConfig</code> object and initializing the
103: * <code>msgFactory</code> field with a default
104: * <code>MessageFactory</code> object.
105: *
106: * @param servletConfig the <code>ServletConfig</code> object to be
107: * used in initializing this <code>SAAJServlet</code> object
108: */
109: public void init(ServletConfig servletConfig)
110: throws ServletException {
111: super .init(servletConfig);
112: try {
113: msgFactory = MessageFactory.newInstance();
114: SOAPConnectionFactory connFactory = SOAPConnectionFactory
115: .newInstance();
116: conn = connFactory.createConnection();
117: } catch (SOAPException ex) {
118: throw new ServletException(
119: "Unable to create message factory"
120: + ex.getMessage());
121: }
122: }
123:
124: /**
125: * Sets this <code>SAAJServlet</code> object's <code>msgFactory</code>
126: * field with the given <code>MessageFactory</code> object.
127: * A <code>MessageFactory</code> object for a particular profile needs to
128: * be set before a message is received in order for the message to be
129: * successfully internalized.
130: *
131: * @param msgFactory the <code>MessageFactory</code> object that will
132: * be used to create the <code>SOAPMessage</code> object that
133: * will be used to internalize the message that was posted to
134: * the servlet
135: */
136: public void setMessageFactory(MessageFactory msgFactory) {
137: this .msgFactory = msgFactory;
138: }
139:
140: /**
141: * Returns a <code>MimeHeaders</code> object that contains the headers
142: * in the given <code>HttpServletRequest</code> object.
143: *
144: * @param req the <code>HttpServletRequest</code> object that a
145: * messaging provider sent to the servlet
146: * @return a new <code>MimeHeaders</code> object containing the headers
147: * in the message sent to the servlet
148: */
149: protected static MimeHeaders getHeaders(HttpServletRequest req) {
150: Enumeration enumeration = req.getHeaderNames();
151: MimeHeaders headers = new MimeHeaders();
152:
153: while (enumeration.hasMoreElements()) {
154: String headerName = (String) enumeration.nextElement();
155: String headerValue = req.getHeader(headerName);
156:
157: StringTokenizer values = new StringTokenizer(headerValue,
158: ",");
159:
160: while (values.hasMoreTokens()) {
161: headers
162: .addHeader(headerName, values.nextToken()
163: .trim());
164: }
165: }
166:
167: return headers;
168: }
169:
170: /**
171: * Sets the given <code>HttpServletResponse</code> object with the
172: * headers in the given <code>MimeHeaders</code> object.
173: *
174: * @param headers the <code>MimeHeaders</code> object containing the
175: * the headers in the message sent to the servlet
176: * @param res the <code>HttpServletResponse</code> object to which the
177: * headers are to be written
178: * @see #getHeaders
179: */
180: protected static void putHeaders(MimeHeaders headers,
181: HttpServletResponse res) {
182: Iterator it = headers.getAllHeaders();
183:
184: while (it.hasNext()) {
185: MimeHeader header = (MimeHeader) it.next();
186:
187: String[] values = headers.getHeader(header.getName());
188:
189: if (values.length == 1) {
190: res.setHeader(header.getName(), header.getValue());
191: } else {
192: StringBuffer concat = new StringBuffer();
193: int i = 0;
194:
195: while (i < values.length) {
196: if (i != 0) {
197: concat.append(',');
198: }
199: concat.append(values[i++]);
200: }
201: res.setHeader(header.getName(), concat.toString());
202: }
203: }
204: }
205:
206: /**
207: * Internalizes the given <code>HttpServletRequest</code> object
208: * and writes the reply to the given <code>HttpServletResponse</code>
209: * object.
210: * <P>
211: * Note that the value for the <code>msgFactory</code> field will be used to
212: * internalize the message. This ensures that the message
213: * factory for the correct profile is used.
214: *
215: * @param req the <code>HttpServletRequest</code> object containing the
216: * message that was sent to the servlet
217: * @param resp the <code>HttpServletResponse</code> object to which the
218: * response to the message will be written
219: * @throws ServletException if there is a servlet error
220: * @throws IOException if there is an input or output error
221: */
222: public void doPost(HttpServletRequest req, HttpServletResponse resp)
223: throws ServletException, IOException {
224: try {
225: // Get all the headers from the HTTP request.
226: MimeHeaders headers = getHeaders(req);
227:
228: // Get the body of the HTTP request.
229: InputStream is = req.getInputStream();
230:
231: // Now internalize the contents of a HTTP request and
232: // create a SOAPMessage
233: SOAPMessage msg = msgFactory.createMessage(headers, is);
234:
235: SOAPMessage reply = null;
236:
237: // There are no replies in case of an OnewayListener.
238: reply = onMessage(msg);
239:
240: if (reply != null) {
241:
242: // Need to saveChanges 'cos we're going to use the
243: // MimeHeaders to set HTTP response information. These
244: // MimeHeaders are generated as part of the save.
245:
246: if (reply.saveRequired()) {
247: reply.saveChanges();
248: }
249:
250: resp.setStatus(HttpServletResponse.SC_OK);
251:
252: putHeaders(reply.getMimeHeaders(), resp);
253:
254: // Write out the message on the response stream.
255: OutputStream os = resp.getOutputStream();
256:
257: reply.writeTo(os);
258:
259: os.flush();
260:
261: } else {
262: resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
263: }
264: } catch (Exception ex) {
265: throw new ServletException("SAAJ POST failed "
266: + ex.getMessage());
267: }
268: }
269:
270: public abstract SOAPMessage onMessage(SOAPMessage message);
271:
272: }
|