1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2000-2007 Sun Microsystems, Inc. All rights reserved. 5 * 6 * The contents of this file are subject to the terms of either the GNU 7 * General Public License Version 2 only ("GPL") or the Common Development 8 * and Distribution License ("CDDL") (collectively, the "License"). You may 9 * not use this file except in compliance with the License. You can obtain 10 * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html 11 * or mq/legal/LICENSE.txt. See the License for the specific language 12 * governing permissions and limitations under the License. 13 * 14 * When distributing the software, include this License Header Notice in each 15 * file and include the License file at mq/legal/LICENSE.txt. Sun designates 16 * this particular file as subject to the "Classpath" exception as provided by 17 * Sun in the GPL Version 2 section of the License file that accompanied this 18 * code. If applicable, add the following below the License Header, with the 19 * fields enclosed by brackets [] replaced by your own identifying information: 20 * "Portions Copyrighted [year] [name of copyright owner]" 21 * 22 * Contributor(s): 23 * 24 * If you wish your version of this file to be governed by only the CDDL or 25 * only the GPL Version 2, indicate your decision by adding "[Contributor] 26 * elects to include this software in this distribution under the [CDDL or GPL 27 * Version 2] license." If you don't indicate a single choice of license, a 28 * recipient has the option to distribute your version of this file under 29 * either the CDDL, the GPL Version 2 or to extend the choice of license to 30 * its licensees as provided above. However, if you add GPL Version 2 code 31 * and therefore, elected the GPL Version 2 license, then the option applies 32 * only if the new code is made subject to such option by the copyright holder. 33 */ 34 35 /* 36 * @(#)JAXMServlet.java 1.6 07/02/07 37 */ 38 39 package javax.xml.messaging; 40 41 import javax.xml.soap; 42 43 import javax.servlet; 44 import javax.servlet.http; 45 46 import java.io.IOException; 47 import java.io.InputStream; 48 import java.io.OutputStream; 49 import java.util.Enumeration; 50 import java.util.Iterator; 51 import java.util.StringTokenizer; 52 53 import com.sun.messaging.AdministeredObject; 54 55 /** 56 * The superclass for components that 57 * live in a servlet container that receives JAXM messages. 58 * A <code>JAXMServlet</code> object is notified of a message's arrival 59 * using the HTTP-SOAP binding. 60 * <P> 61 * The <code>JAXMServlet</code> class is a support/utility class and is 62 * provided purely as a convenience. It is not a mandatory component, and 63 * there is no requirement that it be implemented or extended. 64 * <P> 65 * Note that when a component that receives messages extends 66 * <code>JAXMServlet</code>, it also needs to implement either a 67 * <code>ReqRespListener</code> object or a 68 * <code>OnewayListener</code> object, 69 * depending on whether the component is written for a request-response 70 * style of interaction or for a one-way (asynchronous) style of interaction. 71 */ 72 public abstract class JAXMServlet 73 extends HttpServlet 74 { 75 /** 76 * The <code>MessageFactory</code> object that will be used internally 77 * to create the <code>SOAPMessage</code> object to be passed to the 78 * method <code>onMessage</code>. This new message will contain the data 79 * from the message that was posted to the servlet. Using the 80 * <code>MessageFactory</code> object that is the value for this field 81 * to create the new message ensures that the correct profile is used. 82 */ 83 protected MessageFactory msgFactory = null; 84 85 /** 86 * Initializes this <code>JAXMServlet</code> object using the given 87 * <code>ServletConfig</code> object and initializing the 88 * <code>msgFactory</code> field with a default 89 * <code>MessageFactory</code> object. 90 * 91 * @param servletConfig the <code>ServletConfig</code> object to be 92 * used in initializing this <code>JAXMServlet</code> object 93 */ 94 public void init(ServletConfig servletConfig) 95 throws ServletException 96 { 97 super.init(servletConfig); 98 try { 99 // Initialize it to the default. 100 msgFactory = MessageFactory.newInstance(); 101 } catch (SOAPException ex) { 102 String fctryMsg = AdministeredObject.cr.getKString(AdministeredObject.cr.X_MESSAGEFACTORY_ERROR); 103 throw new ServletException(fctryMsg + "\n" + ex.getMessage()); 104 //throw new ServletException("Unable to create message factory"+ex.getMessage()); 105 } 106 } 107 108 109 /** 110 * Sets this <code>JAXMServlet</code> object's <code>msgFactory</code> 111 * field with the given <code>MessageFactory</code> object. 112 * A <code>MessageFactory</code> object for a particular profile needs to 113 * be set before a message is received in order for the message to be 114 * successfully internalized. 115 * 116 * @param msgFactory the <code>MessageFactory</code> object that will 117 * be used to create the <code>SOAPMessage</code> object that 118 * will be used to internalize the message that was posted to 119 * the servlet 120 */ 121 public void setMessageFactory(MessageFactory msgFactory) { 122 this.msgFactory = msgFactory; 123 } 124 125 /** 126 * Returns a <code>MimeHeaders</code> object that contains the headers 127 * in the given <code>HttpServletRequest</code> object. 128 * 129 * @param req the <code>HttpServletRequest</code> object that a 130 * messaging provider sent to the servlet 131 * @return a new <code>MimeHeaders</code> object containing the headers 132 * in the message sent to the servlet 133 */ 134 protected static 135 MimeHeaders getHeaders(HttpServletRequest req) 136 { 137 Enumeration enm = req.getHeaderNames(); 138 MimeHeaders headers = new MimeHeaders(); 139 140 while (enm.hasMoreElements()) { 141 String headerName = (String)enm.nextElement(); 142 String headerValue = req.getHeader(headerName); 143 144 StringTokenizer values = new StringTokenizer(headerValue, ","); 145 while (values.hasMoreTokens()) 146 headers.addHeader(headerName, values.nextToken().trim()); 147 } 148 149 return headers; 150 } 151 152 /** 153 * Sets the given <code>HttpServletResponse</code> object with the 154 * headers in the given <code>MimeHeaders</code> object. 155 * 156 * @param headers the <code>MimeHeaders</code> object containing the 157 * the headers in the message sent to the servlet 158 * @param res the <code>HttpServletResponse</code> object to which the 159 * headers are to be written 160 * @see #getHeaders 161 */ 162 protected static 163 void putHeaders(MimeHeaders headers, HttpServletResponse res) 164 { 165 Iterator it = headers.getAllHeaders(); 166 while (it.hasNext()) { 167 MimeHeader header = (MimeHeader)it.next(); 168 169 String[] values = headers.getHeader(header.getName()); 170 if (values.length == 1) 171 res.setHeader(header.getName(), header.getValue()); 172 else 173 { 174 StringBuffer concat = new StringBuffer(); 175 int i = 0; 176 while (i < values.length) { 177 if (i != 0) 178 concat.append(','); 179 concat.append(values[i++]); 180 } 181 182 res.setHeader(header.getName(), 183 concat.toString()); 184 } 185 } 186 } 187 188 /** 189 * Internalizes the given <code>HttpServletRequest</code> object 190 * and writes the reply to the given <code>HttpServletResponse</code> 191 * object. 192 * <P> 193 * Note that the value for the <code>msgFactory</code> field will be used to 194 * internalize the message. This ensures that the message 195 * factory for the correct profile is used. 196 * 197 * @param req the <code>HttpServletRequest</code> object containing the 198 * message that was sent to the servlet 199 * @param resp the <code>HttpServletResponse</code> object to which the 200 * response to the message will be written 201 * @throws ServletException if there is a servlet error 202 * @throws IOException if there is an input or output error 203 */ 204 public void doPost(HttpServletRequest req, 205 HttpServletResponse resp) 206 throws ServletException, IOException 207 { 208 try { 209 // Get all the headers from the HTTP request. 210 MimeHeaders headers = getHeaders(req); 211 212 // Get the body of the HTTP request. 213 InputStream is = req.getInputStream(); 214 215 // Now internalize the contents of a HTTP request and 216 // create a SOAPMessage 217 SOAPMessage msg = msgFactory.createMessage(headers, is); 218 219 SOAPMessage reply = null; 220 221 // There are no replies in case of an OnewayListener. 222 if (this instanceof ReqRespListener) 223 reply = ((ReqRespListener) this).onMessage(msg); 224 else if (this instanceof OnewayListener) 225 ((OnewayListener) this).onMessage(msg); 226 else { 227 String lstnrMsg = AdministeredObject.cr.getKString(AdministeredObject.cr.X_NO_JAXMSERVLET_LISTENER, 228 this.getClass().getName()); 229 throw new ServletException(lstnrMsg); 230 //throw new ServletException("JAXM component: " 231 //+this.getClass().getName()+" also has to"+ 232 //" implement ReqRespListener or OnewayListener"); 233 } 234 235 if (reply != null) { 236 237 // Need to saveChanges 'cos we're going to use the 238 // MimeHeaders to set HTTP response information. These 239 // MimeHeaders are generated as part of the save. 240 241 if (reply.saveRequired()) { 242 reply.saveChanges(); 243 } 244 245 resp.setStatus(HttpServletResponse.SC_OK); 246 247 putHeaders(reply.getMimeHeaders(), resp); 248 249 // Write out the message on the response stream. 250 OutputStream os = resp.getOutputStream(); 251 reply.writeTo(os); 252 253 os.flush(); 254 255 } else 256 resp.setStatus(HttpServletResponse.SC_NO_CONTENT); 257 } 258 catch(Exception ex) { 259 String postMsg = AdministeredObject.cr.getKString(AdministeredObject.cr.X_JAXM_POST_FAILED); 260 throw new ServletException(postMsg + "\n" + ex.getMessage()); 261 //throw new ServletException("JAXM POST failed "+ex.getMessage()); 262 } 263 } 264 }