Mon, 04 May 2009 21:10:41 -0700
6658158: Mutable statics in SAAJ (findbugs)
6658163: txw2.DatatypeWriter.BUILDIN is a mutable static (findbugs)
Reviewed-by: darcy
duke@1 | 1 | /* |
tbell@45 | 2 | * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. |
duke@1 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
duke@1 | 4 | * |
duke@1 | 5 | * This code is free software; you can redistribute it and/or modify it |
duke@1 | 6 | * under the terms of the GNU General Public License version 2 only, as |
duke@1 | 7 | * published by the Free Software Foundation. Sun designates this |
duke@1 | 8 | * particular file as subject to the "Classpath" exception as provided |
duke@1 | 9 | * by Sun in the LICENSE file that accompanied this code. |
duke@1 | 10 | * |
duke@1 | 11 | * This code is distributed in the hope that it will be useful, but WITHOUT |
duke@1 | 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
duke@1 | 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
duke@1 | 14 | * version 2 for more details (a copy is included in the LICENSE file that |
duke@1 | 15 | * accompanied this code). |
duke@1 | 16 | * |
duke@1 | 17 | * You should have received a copy of the GNU General Public License version |
duke@1 | 18 | * 2 along with this work; if not, write to the Free Software Foundation, |
duke@1 | 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
duke@1 | 20 | * |
duke@1 | 21 | * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
duke@1 | 22 | * CA 95054 USA or visit www.sun.com if you need additional information or |
duke@1 | 23 | * have any questions. |
duke@1 | 24 | */ |
tbell@45 | 25 | /* |
tbell@50 | 26 | * |
tbell@50 | 27 | * |
tbell@50 | 28 | * |
tbell@45 | 29 | */ |
tbell@45 | 30 | |
tbell@45 | 31 | |
duke@1 | 32 | package com.sun.xml.internal.messaging.saaj.soap; |
duke@1 | 33 | |
duke@1 | 34 | import java.io.*; |
duke@1 | 35 | import java.util.*; |
duke@1 | 36 | import java.util.logging.Level; |
duke@1 | 37 | import java.util.logging.Logger; |
duke@1 | 38 | |
duke@1 | 39 | import javax.activation.DataHandler; |
duke@1 | 40 | import javax.activation.DataSource; |
duke@1 | 41 | import javax.xml.soap.*; |
duke@1 | 42 | import javax.xml.transform.Source; |
duke@1 | 43 | import javax.xml.transform.stream.StreamSource; |
duke@1 | 44 | |
duke@1 | 45 | import com.sun.xml.internal.messaging.saaj.packaging.mime.Header; |
duke@1 | 46 | import com.sun.xml.internal.messaging.saaj.packaging.mime.internet.*; |
duke@1 | 47 | import com.sun.xml.internal.messaging.saaj.packaging.mime.util.*; |
duke@1 | 48 | import com.sun.xml.internal.messaging.saaj.packaging.mime.MessagingException; |
duke@1 | 49 | |
duke@1 | 50 | import com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl; |
duke@1 | 51 | import com.sun.xml.internal.messaging.saaj.soap.impl.EnvelopeImpl; |
duke@1 | 52 | import com.sun.xml.internal.messaging.saaj.util.*; |
duke@1 | 53 | |
duke@1 | 54 | /** |
duke@1 | 55 | * The message implementation for SOAP messages with |
duke@1 | 56 | * attachments. Messages for specific profiles will likely extend this |
duke@1 | 57 | * MessageImpl class and add more value for that particular profile. |
duke@1 | 58 | * |
duke@1 | 59 | * @author Anil Vijendran (akv@eng.sun.com) |
duke@1 | 60 | * @author Rajiv Mordani (rajiv.mordani@sun.com) |
duke@1 | 61 | * @author Manveen Kaur (manveen.kaur@sun.com) |
duke@1 | 62 | */ |
duke@1 | 63 | |
duke@1 | 64 | public abstract class MessageImpl |
duke@1 | 65 | extends SOAPMessage |
duke@1 | 66 | implements SOAPConstants { |
duke@1 | 67 | |
duke@1 | 68 | |
duke@1 | 69 | public static final String CONTENT_ID = "Content-ID"; |
duke@1 | 70 | public static final String CONTENT_LOCATION = "Content-Location"; |
duke@1 | 71 | |
tbell@50 | 72 | protected static final Logger log = |
duke@1 | 73 | Logger.getLogger(LogDomainConstants.SOAP_DOMAIN, |
duke@1 | 74 | "com.sun.xml.internal.messaging.saaj.soap.LocalStrings"); |
duke@1 | 75 | |
duke@1 | 76 | protected static final int PLAIN_XML_FLAG = 1; // 00001 |
duke@1 | 77 | protected static final int MIME_MULTIPART_FLAG = 2; // 00010 |
duke@1 | 78 | protected static final int SOAP1_1_FLAG = 4; // 00100 |
duke@1 | 79 | protected static final int SOAP1_2_FLAG = 8; // 01000 |
duke@1 | 80 | protected static final int MIME_MULTIPART_XOP_FLAG = 14; // 01110 |
duke@1 | 81 | protected static final int XOP_FLAG = 13; // 01101 |
duke@1 | 82 | protected static final int FI_ENCODED_FLAG = 16; // 10000 |
duke@1 | 83 | |
duke@1 | 84 | protected MimeHeaders headers; |
duke@1 | 85 | protected SOAPPartImpl soapPart; |
duke@1 | 86 | protected FinalArrayList attachments; |
duke@1 | 87 | protected boolean saved = false; |
duke@1 | 88 | protected byte[] messageBytes; |
duke@1 | 89 | protected int messageByteCount; |
duke@1 | 90 | protected HashMap properties = new HashMap(); |
duke@1 | 91 | |
duke@1 | 92 | // used for lazy attachment initialization |
duke@1 | 93 | protected MimeMultipart multiPart = null; |
duke@1 | 94 | protected boolean attachmentsInitialized = false; |
duke@1 | 95 | |
duke@1 | 96 | /** |
duke@1 | 97 | * True if this part is encoded using Fast Infoset. |
duke@1 | 98 | * MIME -> application/fastinfoset |
duke@1 | 99 | */ |
duke@1 | 100 | protected boolean isFastInfoset = false; |
duke@1 | 101 | |
duke@1 | 102 | /** |
duke@1 | 103 | * True if the Accept header of this message includes |
duke@1 | 104 | * application/fastinfoset |
duke@1 | 105 | */ |
duke@1 | 106 | protected boolean acceptFastInfoset = false; |
duke@1 | 107 | |
duke@1 | 108 | protected MimeMultipart mmp = null; |
duke@1 | 109 | |
duke@1 | 110 | // if attachments are present, don't read the entire message in byte stream in saveTo() |
duke@1 | 111 | private boolean optimizeAttachmentProcessing = true; |
duke@1 | 112 | |
duke@1 | 113 | // switch back to old MimeMultipart incase of problem |
duke@1 | 114 | private static boolean switchOffBM = false; |
duke@1 | 115 | private static boolean switchOffLazyAttachment = false; |
duke@1 | 116 | |
duke@1 | 117 | static { |
duke@1 | 118 | try { |
duke@1 | 119 | String s = System.getProperty("saaj.mime.optimization"); |
duke@1 | 120 | if ((s != null) && s.equals("false")) { |
duke@1 | 121 | switchOffBM = true; |
duke@1 | 122 | } |
duke@1 | 123 | s = System.getProperty("saaj.lazy.mime.optimization"); |
duke@1 | 124 | if ((s != null) && s.equals("false")) { |
duke@1 | 125 | switchOffLazyAttachment = true; |
duke@1 | 126 | } |
duke@1 | 127 | } catch (SecurityException ex) { |
duke@1 | 128 | // ignore it |
duke@1 | 129 | } |
duke@1 | 130 | } |
duke@1 | 131 | |
duke@1 | 132 | //property to indicate optimized serialization for lazy attachments |
duke@1 | 133 | private boolean lazyAttachments = false; |
duke@1 | 134 | |
duke@1 | 135 | // most of the times, Content-Types are already all lower cased. |
duke@1 | 136 | // String.toLowerCase() works faster in this case, so even if you |
duke@1 | 137 | // are only doing one comparison, it pays off to use String.toLowerCase() |
duke@1 | 138 | // than String.equalsIgnoreCase(). When you do more than one comparison, |
duke@1 | 139 | // the benefits of String.toLowerCase() dominates. |
duke@1 | 140 | // |
duke@1 | 141 | // |
duke@1 | 142 | // for FI, |
duke@1 | 143 | // use application/fastinfoset for SOAP 1.1 |
duke@1 | 144 | // use application/soap+fastinfoset for SOAP 1.2 |
duke@1 | 145 | // to speed up comparisons, test methods always use lower cases. |
duke@1 | 146 | |
duke@1 | 147 | /** |
duke@1 | 148 | * @param primary |
duke@1 | 149 | * must be all lower case |
duke@1 | 150 | * @param sub |
duke@1 | 151 | * must be all lower case |
duke@1 | 152 | */ |
duke@1 | 153 | private static boolean isSoap1_1Type(String primary, String sub) { |
duke@1 | 154 | return primary.equals("text") && sub.equals("xml") |
duke@1 | 155 | || primary.equals("application") |
duke@1 | 156 | && sub.equals("fastinfoset"); |
duke@1 | 157 | } |
duke@1 | 158 | |
duke@1 | 159 | /** |
duke@1 | 160 | * @param type |
duke@1 | 161 | * must be all lower case |
duke@1 | 162 | */ |
duke@1 | 163 | private static boolean isEqualToSoap1_1Type(String type) { |
duke@1 | 164 | return type.startsWith("text/xml") || |
duke@1 | 165 | type.startsWith("application/fastinfoset"); |
duke@1 | 166 | } |
duke@1 | 167 | |
duke@1 | 168 | /** |
duke@1 | 169 | * @param primary |
duke@1 | 170 | * must be all lower case |
duke@1 | 171 | * @param sub |
duke@1 | 172 | * must be all lower case |
duke@1 | 173 | */ |
duke@1 | 174 | private static boolean isSoap1_2Type(String primary, String sub) { |
duke@1 | 175 | return primary.equals("application") |
duke@1 | 176 | && (sub.equals("soap+xml") |
duke@1 | 177 | || sub.equals("soap+fastinfoset")); |
duke@1 | 178 | } |
duke@1 | 179 | |
duke@1 | 180 | /** |
duke@1 | 181 | * @param type |
duke@1 | 182 | * must be all lower case |
duke@1 | 183 | */ |
duke@1 | 184 | private static boolean isEqualToSoap1_2Type(String type) { |
duke@1 | 185 | return type.startsWith("application/soap+xml") || |
duke@1 | 186 | type.startsWith("application/soap+fastinfoset"); |
duke@1 | 187 | } |
duke@1 | 188 | |
duke@1 | 189 | /** |
duke@1 | 190 | * Construct a new message. This will be invoked before message |
duke@1 | 191 | * sends. |
duke@1 | 192 | */ |
duke@1 | 193 | protected MessageImpl() { |
duke@1 | 194 | this(false, false); |
duke@1 | 195 | attachmentsInitialized = true; |
duke@1 | 196 | } |
duke@1 | 197 | |
duke@1 | 198 | /** |
duke@1 | 199 | * Construct a new message. This will be invoked before message |
duke@1 | 200 | * sends. |
duke@1 | 201 | */ |
duke@1 | 202 | protected MessageImpl(boolean isFastInfoset, boolean acceptFastInfoset) { |
duke@1 | 203 | this.isFastInfoset = isFastInfoset; |
duke@1 | 204 | this.acceptFastInfoset = acceptFastInfoset; |
duke@1 | 205 | |
duke@1 | 206 | headers = new MimeHeaders(); |
duke@1 | 207 | headers.setHeader("Accept", getExpectedAcceptHeader()); |
duke@1 | 208 | } |
duke@1 | 209 | |
duke@1 | 210 | /** |
duke@1 | 211 | * Shallow copy. |
duke@1 | 212 | */ |
duke@1 | 213 | protected MessageImpl(SOAPMessage msg) { |
duke@1 | 214 | if (!(msg instanceof MessageImpl)) { |
duke@1 | 215 | // don't know how to handle this. |
duke@1 | 216 | } |
duke@1 | 217 | MessageImpl src = (MessageImpl) msg; |
duke@1 | 218 | this.headers = src.headers; |
duke@1 | 219 | this.soapPart = src.soapPart; |
duke@1 | 220 | this.attachments = src.attachments; |
duke@1 | 221 | this.saved = src.saved; |
duke@1 | 222 | this.messageBytes = src.messageBytes; |
duke@1 | 223 | this.messageByteCount = src.messageByteCount; |
duke@1 | 224 | this.properties = src.properties; |
duke@1 | 225 | } |
duke@1 | 226 | |
duke@1 | 227 | /** |
duke@1 | 228 | * @param stat |
duke@1 | 229 | * the mask value obtained from {@link #identifyContentType(ContentType)} |
duke@1 | 230 | */ |
duke@1 | 231 | protected static boolean isSoap1_1Content(int stat) { |
duke@1 | 232 | return (stat & SOAP1_1_FLAG) != 0; |
duke@1 | 233 | } |
duke@1 | 234 | |
duke@1 | 235 | /** |
duke@1 | 236 | * @param stat |
duke@1 | 237 | * the mask value obtained from {@link #identifyContentType(ContentType)} |
duke@1 | 238 | */ |
duke@1 | 239 | protected static boolean isSoap1_2Content(int stat) { |
duke@1 | 240 | return (stat & SOAP1_2_FLAG) != 0; |
duke@1 | 241 | } |
duke@1 | 242 | |
duke@1 | 243 | private static boolean isMimeMultipartXOPPackage(ContentType contentType) { |
duke@1 | 244 | String type = contentType.getParameter("type"); |
duke@1 | 245 | if(type==null) |
duke@1 | 246 | return false; |
duke@1 | 247 | |
duke@1 | 248 | type = type.toLowerCase(); |
duke@1 | 249 | if(!type.startsWith("application/xop+xml")) |
duke@1 | 250 | return false; |
duke@1 | 251 | |
duke@1 | 252 | String startinfo = contentType.getParameter("start-info"); |
duke@1 | 253 | if(startinfo == null) |
duke@1 | 254 | return false; |
duke@1 | 255 | startinfo = startinfo.toLowerCase(); |
duke@1 | 256 | return isEqualToSoap1_2Type(startinfo) || isEqualToSoap1_1Type(startinfo); |
duke@1 | 257 | } |
duke@1 | 258 | |
duke@1 | 259 | private static boolean isSOAPBodyXOPPackage(ContentType contentType){ |
duke@1 | 260 | String primary = contentType.getPrimaryType(); |
duke@1 | 261 | String sub = contentType.getSubType(); |
duke@1 | 262 | |
duke@1 | 263 | if (primary.equalsIgnoreCase("application")) { |
duke@1 | 264 | if (sub.equalsIgnoreCase("xop+xml")) { |
duke@1 | 265 | String type = getTypeParameter(contentType); |
duke@1 | 266 | return isEqualToSoap1_2Type(type) || isEqualToSoap1_1Type(type); |
duke@1 | 267 | } |
duke@1 | 268 | } |
duke@1 | 269 | return false; |
duke@1 | 270 | } |
duke@1 | 271 | |
duke@1 | 272 | /** |
duke@1 | 273 | * Construct a message from an input stream. When messages are |
duke@1 | 274 | * received, there's two parts -- the transport headers and the |
duke@1 | 275 | * message content in a transport specific stream. |
duke@1 | 276 | */ |
duke@1 | 277 | protected MessageImpl(MimeHeaders headers, final InputStream in) |
duke@1 | 278 | throws SOAPExceptionImpl { |
duke@1 | 279 | ContentType ct = parseContentType(headers); |
duke@1 | 280 | init(headers,identifyContentType(ct),ct,in); |
duke@1 | 281 | } |
duke@1 | 282 | |
duke@1 | 283 | private static ContentType parseContentType(MimeHeaders headers) throws SOAPExceptionImpl { |
duke@1 | 284 | final String ct; |
duke@1 | 285 | if (headers != null) |
duke@1 | 286 | ct = getContentType(headers); |
duke@1 | 287 | else { |
duke@1 | 288 | log.severe("SAAJ0550.soap.null.headers"); |
duke@1 | 289 | throw new SOAPExceptionImpl("Cannot create message: " + |
duke@1 | 290 | "Headers can't be null"); |
duke@1 | 291 | } |
duke@1 | 292 | |
duke@1 | 293 | if (ct == null) { |
duke@1 | 294 | log.severe("SAAJ0532.soap.no.Content-Type"); |
duke@1 | 295 | throw new SOAPExceptionImpl("Absent Content-Type"); |
duke@1 | 296 | } |
duke@1 | 297 | try { |
duke@1 | 298 | return new ContentType(ct); |
duke@1 | 299 | } catch (Throwable ex) { |
duke@1 | 300 | log.severe("SAAJ0535.soap.cannot.internalize.message"); |
duke@1 | 301 | throw new SOAPExceptionImpl("Unable to internalize message", ex); |
duke@1 | 302 | } |
duke@1 | 303 | } |
duke@1 | 304 | |
duke@1 | 305 | /** |
duke@1 | 306 | * Construct a message from an input stream. When messages are |
duke@1 | 307 | * received, there's two parts -- the transport headers and the |
duke@1 | 308 | * message content in a transport specific stream. |
duke@1 | 309 | * |
duke@1 | 310 | * @param contentType |
duke@1 | 311 | * The parsed content type header from the headers variable. |
duke@1 | 312 | * This is redundant parameter, but it avoids reparsing this header again. |
duke@1 | 313 | * @param stat |
duke@1 | 314 | * The result of {@link #identifyContentType(ContentType)} over |
duke@1 | 315 | * the contentType parameter. This redundant parameter, but it avoids |
duke@1 | 316 | * recomputing this information again. |
duke@1 | 317 | */ |
duke@1 | 318 | protected MessageImpl(MimeHeaders headers, final ContentType contentType, int stat, final InputStream in) throws SOAPExceptionImpl { |
duke@1 | 319 | init(headers, stat, contentType, in); |
duke@1 | 320 | |
duke@1 | 321 | } |
duke@1 | 322 | |
duke@1 | 323 | private void init(MimeHeaders headers, int stat, final ContentType contentType, final InputStream in) throws SOAPExceptionImpl { |
duke@1 | 324 | this.headers = headers; |
duke@1 | 325 | |
duke@1 | 326 | try { |
duke@1 | 327 | |
duke@1 | 328 | // Set isFastInfoset/acceptFastInfoset flag based on MIME type |
duke@1 | 329 | if ((stat & FI_ENCODED_FLAG) > 0) { |
duke@1 | 330 | isFastInfoset = acceptFastInfoset = true; |
duke@1 | 331 | } |
duke@1 | 332 | |
duke@1 | 333 | // If necessary, inspect Accept header to set acceptFastInfoset |
duke@1 | 334 | if (!isFastInfoset) { |
duke@1 | 335 | String[] values = headers.getHeader("Accept"); |
duke@1 | 336 | if (values != null) { |
duke@1 | 337 | for (int i = 0; i < values.length; i++) { |
duke@1 | 338 | StringTokenizer st = new StringTokenizer(values[i], ","); |
duke@1 | 339 | while (st.hasMoreTokens()) { |
duke@1 | 340 | final String token = st.nextToken().trim(); |
duke@1 | 341 | if (token.equalsIgnoreCase("application/fastinfoset") || |
duke@1 | 342 | token.equalsIgnoreCase("application/soap+fastinfoset")) { |
duke@1 | 343 | acceptFastInfoset = true; |
duke@1 | 344 | break; |
duke@1 | 345 | } |
duke@1 | 346 | } |
duke@1 | 347 | } |
duke@1 | 348 | } |
duke@1 | 349 | } |
duke@1 | 350 | |
duke@1 | 351 | if (!isCorrectSoapVersion(stat)) { |
duke@1 | 352 | log.log( |
duke@1 | 353 | Level.SEVERE, |
duke@1 | 354 | "SAAJ0533.soap.incorrect.Content-Type", |
duke@1 | 355 | new String[] { |
duke@1 | 356 | contentType.toString(), |
duke@1 | 357 | getExpectedContentType()}); |
duke@1 | 358 | throw new SOAPVersionMismatchException( |
duke@1 | 359 | "Cannot create message: incorrect content-type for SOAP version. Got: " |
duke@1 | 360 | + contentType |
duke@1 | 361 | + " Expected: " |
duke@1 | 362 | + getExpectedContentType()); |
duke@1 | 363 | } |
duke@1 | 364 | |
duke@1 | 365 | if ((stat & PLAIN_XML_FLAG) != 0) { |
duke@1 | 366 | if (isFastInfoset) { |
duke@1 | 367 | getSOAPPart().setContent( |
duke@1 | 368 | FastInfosetReflection.FastInfosetSource_new(in)); |
duke@1 | 369 | } else { |
duke@1 | 370 | initCharsetProperty(contentType); |
duke@1 | 371 | getSOAPPart().setContent(new StreamSource(in)); |
duke@1 | 372 | } |
duke@1 | 373 | } |
duke@1 | 374 | else if ((stat & MIME_MULTIPART_FLAG) != 0) { |
duke@1 | 375 | DataSource ds = new DataSource() { |
duke@1 | 376 | public InputStream getInputStream() { |
duke@1 | 377 | return in; |
duke@1 | 378 | } |
duke@1 | 379 | |
duke@1 | 380 | public OutputStream getOutputStream() { |
duke@1 | 381 | return null; |
duke@1 | 382 | } |
duke@1 | 383 | |
duke@1 | 384 | public String getContentType() { |
duke@1 | 385 | return contentType.toString(); |
duke@1 | 386 | } |
duke@1 | 387 | |
duke@1 | 388 | public String getName() { |
duke@1 | 389 | return ""; |
duke@1 | 390 | } |
duke@1 | 391 | }; |
duke@1 | 392 | |
duke@1 | 393 | multiPart = null; |
duke@1 | 394 | if (switchOffBM) { |
duke@1 | 395 | multiPart = new MimeMultipart(ds,contentType); |
duke@1 | 396 | } else { |
duke@1 | 397 | multiPart = new BMMimeMultipart(ds,contentType); |
duke@1 | 398 | } |
duke@1 | 399 | |
duke@1 | 400 | String startParam = contentType.getParameter("start"); |
duke@1 | 401 | MimeBodyPart soapMessagePart = null; |
duke@1 | 402 | String contentID = null; |
duke@1 | 403 | if (switchOffBM || switchOffLazyAttachment) { |
duke@1 | 404 | if(startParam == null) { |
duke@1 | 405 | soapMessagePart = multiPart.getBodyPart(0); |
duke@1 | 406 | for (int i = 1; i < multiPart.getCount(); i++) { |
duke@1 | 407 | initializeAttachment(multiPart, i); |
duke@1 | 408 | } |
duke@1 | 409 | } else { |
duke@1 | 410 | soapMessagePart = multiPart.getBodyPart(startParam); |
duke@1 | 411 | for (int i = 0; i < multiPart.getCount(); i++) { |
duke@1 | 412 | contentID = multiPart.getBodyPart(i).getContentID(); |
duke@1 | 413 | if(!contentID.equals(startParam)) |
duke@1 | 414 | initializeAttachment(multiPart, i); |
duke@1 | 415 | } |
duke@1 | 416 | } |
duke@1 | 417 | } else { |
duke@1 | 418 | BMMimeMultipart bmMultipart = |
duke@1 | 419 | (BMMimeMultipart)multiPart; |
duke@1 | 420 | InputStream stream = bmMultipart.initStream(); |
duke@1 | 421 | |
duke@1 | 422 | SharedInputStream sin = null; |
duke@1 | 423 | if (stream instanceof SharedInputStream) { |
duke@1 | 424 | sin = (SharedInputStream)stream; |
duke@1 | 425 | } |
duke@1 | 426 | |
duke@1 | 427 | String boundary = "--" + |
duke@1 | 428 | contentType.getParameter("boundary"); |
duke@1 | 429 | byte[] bndbytes = ASCIIUtility.getBytes(boundary); |
duke@1 | 430 | if (startParam == null) { |
duke@1 | 431 | soapMessagePart = |
duke@1 | 432 | bmMultipart.getNextPart(stream, bndbytes, sin); |
duke@1 | 433 | bmMultipart.removeBodyPart(soapMessagePart); |
duke@1 | 434 | } else { |
duke@1 | 435 | MimeBodyPart bp = null; |
duke@1 | 436 | try { |
duke@1 | 437 | while(!startParam.equals(contentID)) { |
duke@1 | 438 | bp = bmMultipart.getNextPart( |
duke@1 | 439 | stream, bndbytes, sin); |
duke@1 | 440 | contentID = bp.getContentID(); |
duke@1 | 441 | } |
duke@1 | 442 | soapMessagePart = bp; |
duke@1 | 443 | bmMultipart.removeBodyPart(bp); |
duke@1 | 444 | } catch (Exception e) { |
duke@1 | 445 | throw new SOAPExceptionImpl(e); |
duke@1 | 446 | } |
duke@1 | 447 | } |
duke@1 | 448 | } |
duke@1 | 449 | |
duke@1 | 450 | ContentType soapPartCType = new ContentType( |
duke@1 | 451 | soapMessagePart.getContentType()); |
duke@1 | 452 | initCharsetProperty(soapPartCType); |
duke@1 | 453 | String baseType = soapPartCType.getBaseType().toLowerCase(); |
duke@1 | 454 | if(!(isEqualToSoap1_1Type(baseType) |
duke@1 | 455 | || isEqualToSoap1_2Type(baseType) |
duke@1 | 456 | || isSOAPBodyXOPPackage(soapPartCType))) { |
duke@1 | 457 | log.log(Level.SEVERE, |
duke@1 | 458 | "SAAJ0549.soap.part.invalid.Content-Type", |
duke@1 | 459 | new Object[] {baseType}); |
duke@1 | 460 | throw new SOAPExceptionImpl( |
duke@1 | 461 | "Bad Content-Type for SOAP Part : " + |
duke@1 | 462 | baseType); |
duke@1 | 463 | } |
duke@1 | 464 | |
duke@1 | 465 | SOAPPart soapPart = getSOAPPart(); |
duke@1 | 466 | setMimeHeaders(soapPart, soapMessagePart); |
duke@1 | 467 | soapPart.setContent(isFastInfoset ? |
duke@1 | 468 | (Source) FastInfosetReflection.FastInfosetSource_new( |
duke@1 | 469 | soapMessagePart.getInputStream()) : |
duke@1 | 470 | (Source) new StreamSource(soapMessagePart.getInputStream())); |
duke@1 | 471 | } else { |
duke@1 | 472 | log.severe("SAAJ0534.soap.unknown.Content-Type"); |
duke@1 | 473 | throw new SOAPExceptionImpl("Unrecognized Content-Type"); |
duke@1 | 474 | } |
duke@1 | 475 | } catch (Throwable ex) { |
duke@1 | 476 | log.severe("SAAJ0535.soap.cannot.internalize.message"); |
duke@1 | 477 | throw new SOAPExceptionImpl("Unable to internalize message", ex); |
duke@1 | 478 | } |
duke@1 | 479 | needsSave(); |
duke@1 | 480 | } |
duke@1 | 481 | |
duke@1 | 482 | public boolean isFastInfoset() { |
duke@1 | 483 | return isFastInfoset; |
duke@1 | 484 | } |
duke@1 | 485 | |
duke@1 | 486 | public boolean acceptFastInfoset() { |
duke@1 | 487 | return acceptFastInfoset; |
duke@1 | 488 | } |
duke@1 | 489 | |
duke@1 | 490 | public void setIsFastInfoset(boolean value) { |
duke@1 | 491 | if (value != isFastInfoset) { |
duke@1 | 492 | isFastInfoset = value; |
duke@1 | 493 | if (isFastInfoset) { |
duke@1 | 494 | acceptFastInfoset = true; |
duke@1 | 495 | } |
duke@1 | 496 | saved = false; // ensure transcoding if necessary |
duke@1 | 497 | } |
duke@1 | 498 | } |
duke@1 | 499 | |
duke@1 | 500 | public Object getProperty(String property) { |
duke@1 | 501 | return (String) properties.get(property); |
duke@1 | 502 | } |
duke@1 | 503 | |
duke@1 | 504 | public void setProperty(String property, Object value) { |
duke@1 | 505 | verify(property, value); |
duke@1 | 506 | properties.put(property, value); |
duke@1 | 507 | } |
duke@1 | 508 | |
duke@1 | 509 | private void verify(String property, Object value) { |
duke@1 | 510 | if (property.equalsIgnoreCase(SOAPMessage.WRITE_XML_DECLARATION)) { |
duke@1 | 511 | if (!("true".equals(value) || "false".equals(value))) |
duke@1 | 512 | throw new RuntimeException( |
duke@1 | 513 | property + " must have value false or true"); |
duke@1 | 514 | |
duke@1 | 515 | try { |
duke@1 | 516 | EnvelopeImpl env = (EnvelopeImpl) getSOAPPart().getEnvelope(); |
duke@1 | 517 | if ("true".equalsIgnoreCase((String)value)) { |
duke@1 | 518 | env.setOmitXmlDecl("no"); |
duke@1 | 519 | } else if ("false".equalsIgnoreCase((String)value)) { |
duke@1 | 520 | env.setOmitXmlDecl("yes"); |
duke@1 | 521 | } |
duke@1 | 522 | } catch (Exception e) { |
duke@1 | 523 | log.log(Level.SEVERE, "SAAJ0591.soap.exception.in.set.property", |
duke@1 | 524 | new Object[] {e.getMessage(), "javax.xml.soap.write-xml-declaration"}); |
duke@1 | 525 | throw new RuntimeException(e); |
duke@1 | 526 | } |
duke@1 | 527 | return; |
duke@1 | 528 | } |
duke@1 | 529 | |
duke@1 | 530 | if (property.equalsIgnoreCase(SOAPMessage.CHARACTER_SET_ENCODING)) { |
duke@1 | 531 | try { |
duke@1 | 532 | ((EnvelopeImpl) getSOAPPart().getEnvelope()).setCharsetEncoding((String)value); |
duke@1 | 533 | } catch (Exception e) { |
duke@1 | 534 | log.log(Level.SEVERE, "SAAJ0591.soap.exception.in.set.property", |
duke@1 | 535 | new Object[] {e.getMessage(), "javax.xml.soap.character-set-encoding"}); |
duke@1 | 536 | throw new RuntimeException(e); |
duke@1 | 537 | } |
duke@1 | 538 | } |
duke@1 | 539 | } |
duke@1 | 540 | |
duke@1 | 541 | protected abstract boolean isCorrectSoapVersion(int contentTypeId); |
duke@1 | 542 | |
duke@1 | 543 | protected abstract String getExpectedContentType(); |
duke@1 | 544 | protected abstract String getExpectedAcceptHeader(); |
duke@1 | 545 | |
duke@1 | 546 | /** |
duke@1 | 547 | * Sniffs the Content-Type header so that we can determine how to process. |
duke@1 | 548 | * |
duke@1 | 549 | * <p> |
duke@1 | 550 | * In the absence of type attribute we assume it to be text/xml. |
duke@1 | 551 | * That would mean we're easy on accepting the message and |
duke@1 | 552 | * generate the correct thing (as the SWA spec also specifies |
duke@1 | 553 | * that the type parameter should always be text/xml) |
duke@1 | 554 | * |
duke@1 | 555 | * @return |
duke@1 | 556 | * combination of flags, such as PLAIN_XML_CODE and MIME_MULTIPART_CODE. |
duke@1 | 557 | */ |
duke@1 | 558 | // SOAP1.2 allow SOAP1.2 content type |
duke@1 | 559 | static int identifyContentType(ContentType contentType) |
duke@1 | 560 | throws SOAPExceptionImpl { |
duke@1 | 561 | // TBD |
duke@1 | 562 | // Is there anything else we need to verify here? |
duke@1 | 563 | |
duke@1 | 564 | String primary = contentType.getPrimaryType().toLowerCase(); |
duke@1 | 565 | String sub = contentType.getSubType().toLowerCase(); |
duke@1 | 566 | |
duke@1 | 567 | if (primary.equals("multipart")) { |
duke@1 | 568 | if (sub.equals("related")) { |
duke@1 | 569 | String type = getTypeParameter(contentType); |
duke@1 | 570 | if (isEqualToSoap1_1Type(type)) { |
duke@1 | 571 | return (type.equals("application/fastinfoset") ? |
duke@1 | 572 | FI_ENCODED_FLAG : 0) | MIME_MULTIPART_FLAG | SOAP1_1_FLAG; |
duke@1 | 573 | } |
duke@1 | 574 | else if (isEqualToSoap1_2Type(type)) { |
duke@1 | 575 | return (type.equals("application/soap+fastinfoset") ? |
duke@1 | 576 | FI_ENCODED_FLAG : 0) | MIME_MULTIPART_FLAG | SOAP1_2_FLAG; |
duke@1 | 577 | } else if (isMimeMultipartXOPPackage(contentType)) { |
duke@1 | 578 | return MIME_MULTIPART_XOP_FLAG; |
duke@1 | 579 | } else { |
duke@1 | 580 | log.severe("SAAJ0536.soap.content-type.mustbe.multipart"); |
duke@1 | 581 | throw new SOAPExceptionImpl( |
duke@1 | 582 | "Content-Type needs to be Multipart/Related " |
duke@1 | 583 | + "and with \"type=text/xml\" " |
duke@1 | 584 | + "or \"type=application/soap+xml\""); |
duke@1 | 585 | } |
duke@1 | 586 | } else { |
duke@1 | 587 | log.severe("SAAJ0537.soap.invalid.content-type"); |
duke@1 | 588 | throw new SOAPExceptionImpl( |
duke@1 | 589 | "Invalid Content-Type: " + primary + '/' + sub); |
duke@1 | 590 | } |
duke@1 | 591 | } |
duke@1 | 592 | else if (isSoap1_1Type(primary, sub)) { |
duke@1 | 593 | return (primary.equalsIgnoreCase("application") |
duke@1 | 594 | && sub.equalsIgnoreCase("fastinfoset") ? |
duke@1 | 595 | FI_ENCODED_FLAG : 0) |
duke@1 | 596 | | PLAIN_XML_FLAG | SOAP1_1_FLAG; |
duke@1 | 597 | } |
duke@1 | 598 | else if (isSoap1_2Type(primary, sub)) { |
duke@1 | 599 | return (primary.equalsIgnoreCase("application") |
duke@1 | 600 | && sub.equalsIgnoreCase("soap+fastinfoset") ? |
duke@1 | 601 | FI_ENCODED_FLAG : 0) |
duke@1 | 602 | | PLAIN_XML_FLAG | SOAP1_2_FLAG; |
duke@1 | 603 | } else if(isSOAPBodyXOPPackage(contentType)){ |
duke@1 | 604 | return XOP_FLAG; |
duke@1 | 605 | } else { |
duke@1 | 606 | log.severe("SAAJ0537.soap.invalid.content-type"); |
duke@1 | 607 | throw new SOAPExceptionImpl( |
duke@1 | 608 | "Invalid Content-Type:" |
duke@1 | 609 | + primary |
duke@1 | 610 | + '/' |
duke@1 | 611 | + sub |
duke@1 | 612 | + ". Is this an error message instead of a SOAP response?"); |
duke@1 | 613 | } |
duke@1 | 614 | } |
duke@1 | 615 | |
duke@1 | 616 | /** |
duke@1 | 617 | * Obtains the type parameter of the Content-Type header. Defaults to "text/xml". |
duke@1 | 618 | */ |
duke@1 | 619 | private static String getTypeParameter(ContentType contentType) { |
duke@1 | 620 | String p = contentType.getParameter("type"); |
duke@1 | 621 | if(p!=null) |
duke@1 | 622 | return p.toLowerCase(); |
duke@1 | 623 | else |
duke@1 | 624 | return "text/xml"; |
duke@1 | 625 | } |
duke@1 | 626 | |
duke@1 | 627 | public MimeHeaders getMimeHeaders() { |
duke@1 | 628 | return this.headers; |
duke@1 | 629 | } |
duke@1 | 630 | |
duke@1 | 631 | final static String getContentType(MimeHeaders headers) { |
duke@1 | 632 | String[] values = headers.getHeader("Content-Type"); |
duke@1 | 633 | if (values == null) |
duke@1 | 634 | return null; |
duke@1 | 635 | else |
duke@1 | 636 | return values[0]; |
duke@1 | 637 | } |
duke@1 | 638 | |
duke@1 | 639 | /* |
duke@1 | 640 | * Get the complete ContentType value along with optional parameters. |
duke@1 | 641 | */ |
duke@1 | 642 | public String getContentType() { |
duke@1 | 643 | return getContentType(this.headers); |
duke@1 | 644 | } |
duke@1 | 645 | |
duke@1 | 646 | public void setContentType(String type) { |
duke@1 | 647 | headers.setHeader("Content-Type", type); |
duke@1 | 648 | needsSave(); |
duke@1 | 649 | } |
duke@1 | 650 | |
duke@1 | 651 | private ContentType ContentType() { |
duke@1 | 652 | ContentType ct = null; |
duke@1 | 653 | try { |
duke@1 | 654 | ct = new ContentType(getContentType()); |
duke@1 | 655 | } catch (Exception e) { |
duke@1 | 656 | // what to do here? |
duke@1 | 657 | } |
duke@1 | 658 | return ct; |
duke@1 | 659 | } |
duke@1 | 660 | |
duke@1 | 661 | /* |
duke@1 | 662 | * Return the MIME type string, without the parameters. |
duke@1 | 663 | */ |
duke@1 | 664 | public String getBaseType() { |
duke@1 | 665 | return ContentType().getBaseType(); |
duke@1 | 666 | } |
duke@1 | 667 | |
duke@1 | 668 | public void setBaseType(String type) { |
duke@1 | 669 | ContentType ct = ContentType(); |
duke@1 | 670 | ct.setParameter("type", type); |
duke@1 | 671 | headers.setHeader("Content-Type", ct.toString()); |
duke@1 | 672 | needsSave(); |
duke@1 | 673 | } |
duke@1 | 674 | |
duke@1 | 675 | public String getAction() { |
duke@1 | 676 | return ContentType().getParameter("action"); |
duke@1 | 677 | } |
duke@1 | 678 | |
duke@1 | 679 | public void setAction(String action) { |
duke@1 | 680 | ContentType ct = ContentType(); |
duke@1 | 681 | ct.setParameter("action", action); |
duke@1 | 682 | headers.setHeader("Content-Type", ct.toString()); |
duke@1 | 683 | needsSave(); |
duke@1 | 684 | } |
duke@1 | 685 | |
duke@1 | 686 | public String getCharset() { |
duke@1 | 687 | return ContentType().getParameter("charset"); |
duke@1 | 688 | } |
duke@1 | 689 | |
duke@1 | 690 | public void setCharset(String charset) { |
duke@1 | 691 | ContentType ct = ContentType(); |
duke@1 | 692 | ct.setParameter("charset", charset); |
duke@1 | 693 | headers.setHeader("Content-Type", ct.toString()); |
duke@1 | 694 | needsSave(); |
duke@1 | 695 | } |
duke@1 | 696 | |
duke@1 | 697 | /** |
duke@1 | 698 | * All write methods (i.e setters) should call this method in |
duke@1 | 699 | * order to make sure that a save is necessary since the state |
duke@1 | 700 | * has been modified. |
duke@1 | 701 | */ |
duke@1 | 702 | private final void needsSave() { |
duke@1 | 703 | saved = false; |
duke@1 | 704 | } |
duke@1 | 705 | |
duke@1 | 706 | public boolean saveRequired() { |
duke@1 | 707 | return saved != true; |
duke@1 | 708 | } |
duke@1 | 709 | |
duke@1 | 710 | public String getContentDescription() { |
duke@1 | 711 | String[] values = headers.getHeader("Content-Description"); |
duke@1 | 712 | if (values != null && values.length > 0) |
duke@1 | 713 | return values[0]; |
duke@1 | 714 | return null; |
duke@1 | 715 | } |
duke@1 | 716 | |
duke@1 | 717 | public void setContentDescription(String description) { |
duke@1 | 718 | headers.setHeader("Content-Description", description); |
duke@1 | 719 | needsSave(); |
duke@1 | 720 | } |
duke@1 | 721 | |
duke@1 | 722 | public abstract SOAPPart getSOAPPart(); |
duke@1 | 723 | |
duke@1 | 724 | public void removeAllAttachments() { |
duke@1 | 725 | try { |
duke@1 | 726 | initializeAllAttachments(); |
duke@1 | 727 | } catch (Exception e) { |
duke@1 | 728 | throw new RuntimeException(e); |
duke@1 | 729 | } |
duke@1 | 730 | |
duke@1 | 731 | if (attachments != null) { |
duke@1 | 732 | attachments.clear(); |
duke@1 | 733 | needsSave(); |
duke@1 | 734 | } |
duke@1 | 735 | } |
duke@1 | 736 | |
duke@1 | 737 | public int countAttachments() { |
duke@1 | 738 | try { |
duke@1 | 739 | initializeAllAttachments(); |
duke@1 | 740 | } catch (Exception e) { |
duke@1 | 741 | throw new RuntimeException(e); |
duke@1 | 742 | } |
duke@1 | 743 | if (attachments != null) |
duke@1 | 744 | return attachments.size(); |
duke@1 | 745 | return 0; |
duke@1 | 746 | } |
duke@1 | 747 | |
duke@1 | 748 | public void addAttachmentPart(AttachmentPart attachment) { |
duke@1 | 749 | try { |
duke@1 | 750 | initializeAllAttachments(); |
duke@1 | 751 | } catch (Exception e) { |
duke@1 | 752 | throw new RuntimeException(e); |
duke@1 | 753 | } |
duke@1 | 754 | if (attachments == null) |
duke@1 | 755 | attachments = new FinalArrayList(); |
duke@1 | 756 | |
duke@1 | 757 | attachments.add(attachment); |
duke@1 | 758 | |
duke@1 | 759 | needsSave(); |
duke@1 | 760 | } |
duke@1 | 761 | |
duke@1 | 762 | static private final Iterator nullIter = Collections.EMPTY_LIST.iterator(); |
duke@1 | 763 | |
duke@1 | 764 | public Iterator getAttachments() { |
duke@1 | 765 | try { |
duke@1 | 766 | initializeAllAttachments(); |
duke@1 | 767 | } catch (Exception e) { |
duke@1 | 768 | throw new RuntimeException(e); |
duke@1 | 769 | } |
duke@1 | 770 | if (attachments == null) |
duke@1 | 771 | return nullIter; |
duke@1 | 772 | return attachments.iterator(); |
duke@1 | 773 | } |
duke@1 | 774 | |
duke@1 | 775 | private class MimeMatchingIterator implements Iterator { |
duke@1 | 776 | public MimeMatchingIterator(MimeHeaders headers) { |
duke@1 | 777 | this.headers = headers; |
duke@1 | 778 | this.iter = attachments.iterator(); |
duke@1 | 779 | } |
duke@1 | 780 | |
duke@1 | 781 | private Iterator iter; |
duke@1 | 782 | private MimeHeaders headers; |
duke@1 | 783 | private Object nextAttachment; |
duke@1 | 784 | |
duke@1 | 785 | public boolean hasNext() { |
duke@1 | 786 | if (nextAttachment == null) |
duke@1 | 787 | nextAttachment = nextMatch(); |
duke@1 | 788 | return nextAttachment != null; |
duke@1 | 789 | } |
duke@1 | 790 | |
duke@1 | 791 | public Object next() { |
duke@1 | 792 | if (nextAttachment != null) { |
duke@1 | 793 | Object ret = nextAttachment; |
duke@1 | 794 | nextAttachment = null; |
duke@1 | 795 | return ret; |
duke@1 | 796 | } |
duke@1 | 797 | |
duke@1 | 798 | if (hasNext()) |
duke@1 | 799 | return nextAttachment; |
duke@1 | 800 | |
duke@1 | 801 | return null; |
duke@1 | 802 | } |
duke@1 | 803 | |
duke@1 | 804 | Object nextMatch() { |
duke@1 | 805 | while (iter.hasNext()) { |
duke@1 | 806 | AttachmentPartImpl ap = (AttachmentPartImpl) iter.next(); |
duke@1 | 807 | if (ap.hasAllHeaders(headers)) |
duke@1 | 808 | return ap; |
duke@1 | 809 | } |
duke@1 | 810 | return null; |
duke@1 | 811 | } |
duke@1 | 812 | |
duke@1 | 813 | public void remove() { |
duke@1 | 814 | iter.remove(); |
duke@1 | 815 | } |
duke@1 | 816 | } |
duke@1 | 817 | |
duke@1 | 818 | public Iterator getAttachments(MimeHeaders headers) { |
duke@1 | 819 | try { |
duke@1 | 820 | initializeAllAttachments(); |
duke@1 | 821 | } catch (Exception e) { |
duke@1 | 822 | throw new RuntimeException(e); |
duke@1 | 823 | } |
duke@1 | 824 | if (attachments == null) |
duke@1 | 825 | return nullIter; |
duke@1 | 826 | |
duke@1 | 827 | return new MimeMatchingIterator(headers); |
duke@1 | 828 | } |
duke@1 | 829 | |
duke@1 | 830 | public void removeAttachments(MimeHeaders headers) { |
duke@1 | 831 | try { |
duke@1 | 832 | initializeAllAttachments(); |
duke@1 | 833 | } catch (Exception e) { |
duke@1 | 834 | throw new RuntimeException(e); |
duke@1 | 835 | } |
duke@1 | 836 | if (attachments == null) |
duke@1 | 837 | return ; |
duke@1 | 838 | |
duke@1 | 839 | Iterator it = new MimeMatchingIterator(headers); |
duke@1 | 840 | while (it.hasNext()) { |
duke@1 | 841 | int index = attachments.indexOf(it.next()); |
duke@1 | 842 | attachments.set(index, null); |
duke@1 | 843 | } |
duke@1 | 844 | FinalArrayList f = new FinalArrayList(); |
duke@1 | 845 | for (int i = 0; i < attachments.size(); i++) { |
duke@1 | 846 | if (attachments.get(i) != null) { |
duke@1 | 847 | f.add(attachments.get(i)); |
duke@1 | 848 | } |
duke@1 | 849 | } |
duke@1 | 850 | attachments = f; |
duke@1 | 851 | } |
duke@1 | 852 | |
duke@1 | 853 | public AttachmentPart createAttachmentPart() { |
duke@1 | 854 | return new AttachmentPartImpl(); |
duke@1 | 855 | } |
duke@1 | 856 | |
duke@1 | 857 | public AttachmentPart getAttachment(SOAPElement element) |
duke@1 | 858 | throws SOAPException { |
duke@1 | 859 | try { |
duke@1 | 860 | initializeAllAttachments(); |
duke@1 | 861 | } catch (Exception e) { |
duke@1 | 862 | throw new RuntimeException(e); |
duke@1 | 863 | } |
duke@1 | 864 | String uri; |
duke@1 | 865 | String hrefAttr = element.getAttribute("href"); |
duke@1 | 866 | if ("".equals(hrefAttr)) { |
duke@1 | 867 | Node node = getValueNodeStrict(element); |
duke@1 | 868 | String swaRef = null; |
duke@1 | 869 | if (node != null) { |
duke@1 | 870 | swaRef = node.getValue(); |
duke@1 | 871 | } |
duke@1 | 872 | if (swaRef == null || "".equals(swaRef)) { |
duke@1 | 873 | return null; |
duke@1 | 874 | } else { |
duke@1 | 875 | uri = swaRef; |
duke@1 | 876 | } |
duke@1 | 877 | } else { |
duke@1 | 878 | uri = hrefAttr; |
duke@1 | 879 | } |
duke@1 | 880 | return getAttachmentPart(uri); |
duke@1 | 881 | } |
duke@1 | 882 | |
duke@1 | 883 | private Node getValueNodeStrict(SOAPElement element) { |
duke@1 | 884 | Node node = (Node)element.getFirstChild(); |
duke@1 | 885 | if (node != null) { |
duke@1 | 886 | if (node.getNextSibling() == null |
duke@1 | 887 | && node.getNodeType() == org.w3c.dom.Node.TEXT_NODE) { |
duke@1 | 888 | return node; |
duke@1 | 889 | } else { |
duke@1 | 890 | return null; |
duke@1 | 891 | } |
duke@1 | 892 | } |
duke@1 | 893 | return null; |
duke@1 | 894 | } |
duke@1 | 895 | |
duke@1 | 896 | |
duke@1 | 897 | private AttachmentPart getAttachmentPart(String uri) throws SOAPException { |
duke@1 | 898 | AttachmentPart _part; |
duke@1 | 899 | try { |
duke@1 | 900 | if (uri.startsWith("cid:")) { |
duke@1 | 901 | // rfc2392 |
duke@1 | 902 | uri = '<'+uri.substring("cid:".length())+'>'; |
duke@1 | 903 | |
duke@1 | 904 | MimeHeaders headersToMatch = new MimeHeaders(); |
duke@1 | 905 | headersToMatch.addHeader(CONTENT_ID, uri); |
duke@1 | 906 | |
duke@1 | 907 | Iterator i = this.getAttachments(headersToMatch); |
duke@1 | 908 | _part = (i == null) ? null : (AttachmentPart)i.next(); |
duke@1 | 909 | } else { |
duke@1 | 910 | // try content-location |
duke@1 | 911 | MimeHeaders headersToMatch = new MimeHeaders(); |
duke@1 | 912 | headersToMatch.addHeader(CONTENT_LOCATION, uri); |
duke@1 | 913 | |
duke@1 | 914 | Iterator i = this.getAttachments(headersToMatch); |
duke@1 | 915 | _part = (i == null) ? null : (AttachmentPart)i.next(); |
duke@1 | 916 | } |
duke@1 | 917 | |
duke@1 | 918 | // try auto-generated JAXRPC CID |
duke@1 | 919 | if (_part == null) { |
duke@1 | 920 | Iterator j = this.getAttachments(); |
duke@1 | 921 | |
duke@1 | 922 | while (j.hasNext()) { |
duke@1 | 923 | AttachmentPart p = (AttachmentPart)j.next(); |
duke@1 | 924 | String cl = p.getContentId(); |
duke@1 | 925 | if (cl != null) { |
duke@1 | 926 | // obtain the partname |
duke@1 | 927 | int eqIndex = cl.indexOf("="); |
duke@1 | 928 | if (eqIndex > -1) { |
duke@1 | 929 | cl = cl.substring(1, eqIndex); |
duke@1 | 930 | if (cl.equalsIgnoreCase(uri)) { |
duke@1 | 931 | _part = p; |
duke@1 | 932 | break; |
duke@1 | 933 | } |
duke@1 | 934 | } |
duke@1 | 935 | } |
duke@1 | 936 | } |
duke@1 | 937 | } |
duke@1 | 938 | |
duke@1 | 939 | } catch (Exception se) { |
duke@1 | 940 | log.log(Level.SEVERE, "SAAJ0590.soap.unable.to.locate.attachment", new Object[] {uri}); |
duke@1 | 941 | throw new SOAPExceptionImpl(se); |
duke@1 | 942 | } |
duke@1 | 943 | return _part; |
duke@1 | 944 | } |
duke@1 | 945 | |
duke@1 | 946 | private final ByteInputStream getHeaderBytes() |
duke@1 | 947 | throws IOException { |
duke@1 | 948 | SOAPPartImpl sp = (SOAPPartImpl) getSOAPPart(); |
duke@1 | 949 | return sp.getContentAsStream(); |
duke@1 | 950 | } |
duke@1 | 951 | |
duke@1 | 952 | private String convertToSingleLine(String contentType) { |
duke@1 | 953 | StringBuffer buffer = new StringBuffer(); |
duke@1 | 954 | for (int i = 0; i < contentType.length(); i ++) { |
duke@1 | 955 | char c = contentType.charAt(i); |
duke@1 | 956 | if (c != '\r' && c != '\n' && c != '\t') |
duke@1 | 957 | buffer.append(c); |
duke@1 | 958 | } |
duke@1 | 959 | return buffer.toString(); |
duke@1 | 960 | } |
duke@1 | 961 | |
duke@1 | 962 | private MimeMultipart getMimeMessage() throws SOAPException { |
duke@1 | 963 | try { |
duke@1 | 964 | SOAPPartImpl soapPart = (SOAPPartImpl) getSOAPPart(); |
duke@1 | 965 | MimeBodyPart mimeSoapPart = soapPart.getMimePart(); |
duke@1 | 966 | |
duke@1 | 967 | /* |
duke@1 | 968 | * Get content type from this message instead of soapPart |
duke@1 | 969 | * to ensure agreement if soapPart is transcoded (XML <-> FI) |
duke@1 | 970 | */ |
duke@1 | 971 | ContentType soapPartCtype = new ContentType(getExpectedContentType()); |
duke@1 | 972 | |
duke@1 | 973 | if (!isFastInfoset) { |
duke@1 | 974 | soapPartCtype.setParameter("charset", initCharset()); |
duke@1 | 975 | } |
duke@1 | 976 | mimeSoapPart.setHeader("Content-Type", soapPartCtype.toString()); |
duke@1 | 977 | |
duke@1 | 978 | MimeMultipart headerAndBody = null; |
duke@1 | 979 | |
duke@1 | 980 | if (!switchOffBM && !switchOffLazyAttachment && |
duke@1 | 981 | (multiPart != null) && !attachmentsInitialized) { |
duke@1 | 982 | headerAndBody = new BMMimeMultipart(); |
duke@1 | 983 | headerAndBody.addBodyPart(mimeSoapPart); |
duke@1 | 984 | if (attachments != null) { |
duke@1 | 985 | for (Iterator eachAttachment = attachments.iterator(); |
duke@1 | 986 | eachAttachment.hasNext();) { |
duke@1 | 987 | headerAndBody.addBodyPart( |
duke@1 | 988 | ((AttachmentPartImpl) eachAttachment.next()) |
duke@1 | 989 | .getMimePart()); |
duke@1 | 990 | } |
duke@1 | 991 | } |
duke@1 | 992 | InputStream in = ((BMMimeMultipart)multiPart).getInputStream(); |
duke@1 | 993 | if (!((BMMimeMultipart)multiPart).lastBodyPartFound() && |
duke@1 | 994 | !((BMMimeMultipart)multiPart).isEndOfStream()) { |
duke@1 | 995 | ((BMMimeMultipart)headerAndBody).setInputStream(in); |
duke@1 | 996 | ((BMMimeMultipart)headerAndBody).setBoundary( |
duke@1 | 997 | ((BMMimeMultipart)multiPart).getBoundary()); |
duke@1 | 998 | ((BMMimeMultipart)headerAndBody). |
duke@1 | 999 | setLazyAttachments(lazyAttachments); |
duke@1 | 1000 | } |
duke@1 | 1001 | |
duke@1 | 1002 | } else { |
duke@1 | 1003 | headerAndBody = new MimeMultipart(); |
duke@1 | 1004 | headerAndBody.addBodyPart(mimeSoapPart); |
duke@1 | 1005 | |
duke@1 | 1006 | for (Iterator eachAttachement = getAttachments(); |
duke@1 | 1007 | eachAttachement.hasNext(); |
duke@1 | 1008 | ) { |
duke@1 | 1009 | headerAndBody.addBodyPart( |
duke@1 | 1010 | ((AttachmentPartImpl) eachAttachement.next()) |
duke@1 | 1011 | .getMimePart()); |
duke@1 | 1012 | } |
duke@1 | 1013 | } |
duke@1 | 1014 | |
duke@1 | 1015 | ContentType contentType = headerAndBody.getContentType(); |
duke@1 | 1016 | |
duke@1 | 1017 | ParameterList l = contentType.getParameterList(); |
duke@1 | 1018 | |
duke@1 | 1019 | // set content type depending on SOAP version |
duke@1 | 1020 | l.set("type", getExpectedContentType()); |
duke@1 | 1021 | l.set("boundary", contentType.getParameter("boundary")); |
duke@1 | 1022 | ContentType nct = new ContentType("multipart", "related", l); |
duke@1 | 1023 | |
duke@1 | 1024 | headers.setHeader( |
duke@1 | 1025 | "Content-Type", |
duke@1 | 1026 | convertToSingleLine(nct.toString())); |
duke@1 | 1027 | // TBD |
duke@1 | 1028 | // Set content length MIME header here. |
duke@1 | 1029 | |
duke@1 | 1030 | return headerAndBody; |
duke@1 | 1031 | } catch (SOAPException ex) { |
duke@1 | 1032 | throw ex; |
duke@1 | 1033 | } catch (Throwable ex) { |
duke@1 | 1034 | log.severe("SAAJ0538.soap.cannot.convert.msg.to.multipart.obj"); |
duke@1 | 1035 | throw new SOAPExceptionImpl( |
duke@1 | 1036 | "Unable to convert SOAP message into " |
duke@1 | 1037 | + "a MimeMultipart object", |
duke@1 | 1038 | ex); |
duke@1 | 1039 | } |
duke@1 | 1040 | } |
duke@1 | 1041 | |
duke@1 | 1042 | private String initCharset() { |
duke@1 | 1043 | |
duke@1 | 1044 | String charset = null; |
duke@1 | 1045 | |
duke@1 | 1046 | String[] cts = getMimeHeaders().getHeader("Content-Type"); |
duke@1 | 1047 | if ((cts != null) && (cts[0] != null)) { |
duke@1 | 1048 | charset = getCharsetString(cts[0]); |
duke@1 | 1049 | } |
duke@1 | 1050 | |
duke@1 | 1051 | if (charset == null) { |
duke@1 | 1052 | charset = (String) getProperty(CHARACTER_SET_ENCODING); |
duke@1 | 1053 | } |
duke@1 | 1054 | |
duke@1 | 1055 | if (charset != null) { |
duke@1 | 1056 | return charset; |
duke@1 | 1057 | } |
duke@1 | 1058 | |
duke@1 | 1059 | return "utf-8"; |
duke@1 | 1060 | } |
duke@1 | 1061 | |
duke@1 | 1062 | private String getCharsetString(String s) { |
duke@1 | 1063 | try { |
duke@1 | 1064 | int index = s.indexOf(";"); |
duke@1 | 1065 | if(index < 0) |
duke@1 | 1066 | return null; |
duke@1 | 1067 | ParameterList pl = new ParameterList(s.substring(index)); |
duke@1 | 1068 | return pl.get("charset"); |
duke@1 | 1069 | } catch(Exception e) { |
duke@1 | 1070 | return null; |
duke@1 | 1071 | } |
duke@1 | 1072 | } |
duke@1 | 1073 | |
duke@1 | 1074 | public void saveChanges() throws SOAPException { |
duke@1 | 1075 | |
duke@1 | 1076 | // suck in all the data from the attachments and have it |
duke@1 | 1077 | // ready for writing/sending etc. |
duke@1 | 1078 | |
duke@1 | 1079 | String charset = initCharset(); |
duke@1 | 1080 | |
duke@1 | 1081 | /*if (countAttachments() == 0) {*/ |
duke@1 | 1082 | int attachmentCount = (attachments == null) ? 0 : attachments.size(); |
duke@1 | 1083 | if (attachmentCount == 0) { |
duke@1 | 1084 | if (!switchOffBM && !switchOffLazyAttachment && |
duke@1 | 1085 | !attachmentsInitialized && (multiPart != null)) { |
duke@1 | 1086 | // so there might be attachments |
duke@1 | 1087 | attachmentCount = 1; |
duke@1 | 1088 | } |
duke@1 | 1089 | } |
duke@1 | 1090 | |
duke@1 | 1091 | try { |
duke@1 | 1092 | if ((attachmentCount == 0) && !hasXOPContent()) { |
duke@1 | 1093 | ByteInputStream in; |
duke@1 | 1094 | try{ |
duke@1 | 1095 | /* |
duke@1 | 1096 | * Not sure why this is called getHeaderBytes(), but it actually |
duke@1 | 1097 | * returns the whole message as a byte stream. This stream could |
duke@1 | 1098 | * be either XML of Fast depending on the mode. |
duke@1 | 1099 | */ |
duke@1 | 1100 | in = getHeaderBytes(); |
duke@1 | 1101 | // no attachments, hence this property can be false |
duke@1 | 1102 | this.optimizeAttachmentProcessing = false; |
duke@1 | 1103 | } catch (IOException ex) { |
duke@1 | 1104 | log.severe("SAAJ0539.soap.cannot.get.header.stream"); |
duke@1 | 1105 | throw new SOAPExceptionImpl( |
duke@1 | 1106 | "Unable to get header stream in saveChanges: ", |
duke@1 | 1107 | ex); |
duke@1 | 1108 | } |
duke@1 | 1109 | |
duke@1 | 1110 | messageBytes = in.getBytes(); |
duke@1 | 1111 | messageByteCount = in.getCount(); |
duke@1 | 1112 | |
duke@1 | 1113 | headers.setHeader( |
duke@1 | 1114 | "Content-Type", |
duke@1 | 1115 | getExpectedContentType() + |
duke@1 | 1116 | (isFastInfoset ? "" : "; charset=" + charset)); |
duke@1 | 1117 | headers.setHeader( |
duke@1 | 1118 | "Content-Length", |
duke@1 | 1119 | Integer.toString(messageByteCount)); |
duke@1 | 1120 | } else { |
duke@1 | 1121 | if(hasXOPContent()) |
duke@1 | 1122 | mmp = getXOPMessage(); |
duke@1 | 1123 | else |
duke@1 | 1124 | mmp = getMimeMessage(); |
duke@1 | 1125 | } |
duke@1 | 1126 | } catch (Throwable ex) { |
duke@1 | 1127 | log.severe("SAAJ0540.soap.err.saving.multipart.msg"); |
duke@1 | 1128 | throw new SOAPExceptionImpl( |
duke@1 | 1129 | "Error during saving a multipart message", |
duke@1 | 1130 | ex); |
duke@1 | 1131 | } |
duke@1 | 1132 | |
duke@1 | 1133 | // FIX ME -- SOAP Action replaced by Content-Type optional parameter action |
duke@1 | 1134 | /* |
duke@1 | 1135 | if(isCorrectSoapVersion(SOAP1_1_FLAG)) { |
duke@1 | 1136 | |
duke@1 | 1137 | String[] soapAction = headers.getHeader("SOAPAction"); |
duke@1 | 1138 | |
duke@1 | 1139 | if (soapAction == null || soapAction.length == 0) |
duke@1 | 1140 | headers.setHeader("SOAPAction", "\"\""); |
duke@1 | 1141 | |
duke@1 | 1142 | } |
duke@1 | 1143 | */ |
duke@1 | 1144 | |
duke@1 | 1145 | saved = true; |
duke@1 | 1146 | } |
duke@1 | 1147 | |
duke@1 | 1148 | private MimeMultipart getXOPMessage() throws SOAPException { |
duke@1 | 1149 | try { |
duke@1 | 1150 | MimeMultipart headerAndBody = new MimeMultipart(); |
duke@1 | 1151 | SOAPPartImpl soapPart = (SOAPPartImpl)getSOAPPart(); |
duke@1 | 1152 | MimeBodyPart mimeSoapPart = soapPart.getMimePart(); |
duke@1 | 1153 | ContentType soapPartCtype = |
duke@1 | 1154 | new ContentType("application/xop+xml"); |
duke@1 | 1155 | soapPartCtype.setParameter("type", getExpectedContentType()); |
duke@1 | 1156 | String charset = initCharset(); |
duke@1 | 1157 | soapPartCtype.setParameter("charset", charset); |
duke@1 | 1158 | mimeSoapPart.setHeader("Content-Type", soapPartCtype.toString()); |
duke@1 | 1159 | headerAndBody.addBodyPart(mimeSoapPart); |
duke@1 | 1160 | |
duke@1 | 1161 | for (Iterator eachAttachement = getAttachments(); |
duke@1 | 1162 | eachAttachement.hasNext(); |
duke@1 | 1163 | ) { |
duke@1 | 1164 | headerAndBody.addBodyPart( |
duke@1 | 1165 | ((AttachmentPartImpl) eachAttachement.next()) |
duke@1 | 1166 | .getMimePart()); |
duke@1 | 1167 | } |
duke@1 | 1168 | |
duke@1 | 1169 | ContentType contentType = headerAndBody.getContentType(); |
duke@1 | 1170 | |
duke@1 | 1171 | ParameterList l = contentType.getParameterList(); |
duke@1 | 1172 | |
duke@1 | 1173 | //lets not write start-info for now till we get servlet fix done |
duke@1 | 1174 | l.set("start-info", getExpectedContentType());//+";charset="+initCharset()); |
duke@1 | 1175 | |
duke@1 | 1176 | // set content type depending on SOAP version |
duke@1 | 1177 | l.set("type", "application/xop+xml"); |
duke@1 | 1178 | |
duke@1 | 1179 | if (isCorrectSoapVersion(SOAP1_2_FLAG)) { |
duke@1 | 1180 | String action = getAction(); |
duke@1 | 1181 | if(action != null) |
duke@1 | 1182 | l.set("action", action); |
duke@1 | 1183 | } |
duke@1 | 1184 | |
duke@1 | 1185 | l.set("boundary", contentType.getParameter("boundary")); |
duke@1 | 1186 | ContentType nct = new ContentType("Multipart", "Related", l); |
duke@1 | 1187 | headers.setHeader( |
duke@1 | 1188 | "Content-Type", |
duke@1 | 1189 | convertToSingleLine(nct.toString())); |
duke@1 | 1190 | // TBD |
duke@1 | 1191 | // Set content length MIME header here. |
duke@1 | 1192 | |
duke@1 | 1193 | return headerAndBody; |
duke@1 | 1194 | } catch (SOAPException ex) { |
duke@1 | 1195 | throw ex; |
duke@1 | 1196 | } catch (Throwable ex) { |
duke@1 | 1197 | log.severe("SAAJ0538.soap.cannot.convert.msg.to.multipart.obj"); |
duke@1 | 1198 | throw new SOAPExceptionImpl( |
duke@1 | 1199 | "Unable to convert SOAP message into " |
duke@1 | 1200 | + "a MimeMultipart object", |
duke@1 | 1201 | ex); |
duke@1 | 1202 | } |
duke@1 | 1203 | |
duke@1 | 1204 | } |
duke@1 | 1205 | |
duke@1 | 1206 | private boolean hasXOPContent() throws ParseException { |
duke@1 | 1207 | String type = getContentType(); |
duke@1 | 1208 | if(type == null) |
duke@1 | 1209 | return false; |
duke@1 | 1210 | ContentType ct = new ContentType(type); |
duke@1 | 1211 | return isMimeMultipartXOPPackage(ct) || isSOAPBodyXOPPackage(ct); |
duke@1 | 1212 | } |
duke@1 | 1213 | |
duke@1 | 1214 | public void writeTo(OutputStream out) throws SOAPException, IOException { |
duke@1 | 1215 | if (saveRequired()){ |
duke@1 | 1216 | this.optimizeAttachmentProcessing = true; |
duke@1 | 1217 | saveChanges(); |
duke@1 | 1218 | } |
duke@1 | 1219 | |
duke@1 | 1220 | if(!optimizeAttachmentProcessing){ |
duke@1 | 1221 | out.write(messageBytes, 0, messageByteCount); |
duke@1 | 1222 | } |
duke@1 | 1223 | else{ |
duke@1 | 1224 | try{ |
duke@1 | 1225 | if(hasXOPContent()){ |
duke@1 | 1226 | mmp.writeTo(out); |
duke@1 | 1227 | }else{ |
duke@1 | 1228 | mmp.writeTo(out); |
duke@1 | 1229 | if (!switchOffBM && !switchOffLazyAttachment && |
duke@1 | 1230 | (multiPart != null) && !attachmentsInitialized) { |
duke@1 | 1231 | ((BMMimeMultipart)multiPart).setInputStream( |
duke@1 | 1232 | ((BMMimeMultipart)mmp).getInputStream()); |
duke@1 | 1233 | } |
duke@1 | 1234 | } |
duke@1 | 1235 | } catch(Exception ex){ |
duke@1 | 1236 | log.severe("SAAJ0540.soap.err.saving.multipart.msg"); |
duke@1 | 1237 | throw new SOAPExceptionImpl( |
duke@1 | 1238 | "Error during saving a multipart message", |
duke@1 | 1239 | ex); |
duke@1 | 1240 | } |
duke@1 | 1241 | } |
duke@1 | 1242 | |
duke@1 | 1243 | if(isCorrectSoapVersion(SOAP1_1_FLAG)) { |
duke@1 | 1244 | |
duke@1 | 1245 | String[] soapAction = headers.getHeader("SOAPAction"); |
duke@1 | 1246 | |
duke@1 | 1247 | if (soapAction == null || soapAction.length == 0) |
duke@1 | 1248 | headers.setHeader("SOAPAction", "\"\""); |
duke@1 | 1249 | |
duke@1 | 1250 | } |
duke@1 | 1251 | |
duke@1 | 1252 | messageBytes = null; |
duke@1 | 1253 | needsSave(); |
duke@1 | 1254 | } |
duke@1 | 1255 | |
duke@1 | 1256 | public SOAPBody getSOAPBody() throws SOAPException { |
tbell@45 | 1257 | SOAPBody body = getSOAPPart().getEnvelope().getBody(); |
tbell@45 | 1258 | /*if (body == null) { |
tbell@45 | 1259 | throw new SOAPException("No SOAP Body was found in the SOAP Message"); |
tbell@45 | 1260 | }*/ |
tbell@45 | 1261 | return body; |
duke@1 | 1262 | } |
duke@1 | 1263 | |
duke@1 | 1264 | public SOAPHeader getSOAPHeader() throws SOAPException { |
tbell@45 | 1265 | SOAPHeader hdr = getSOAPPart().getEnvelope().getHeader(); |
tbell@45 | 1266 | /*if (hdr == null) { |
tbell@45 | 1267 | throw new SOAPException("No SOAP Header was found in the SOAP Message"); |
tbell@45 | 1268 | }*/ |
tbell@45 | 1269 | return hdr; |
duke@1 | 1270 | } |
duke@1 | 1271 | |
duke@1 | 1272 | private void initializeAllAttachments () |
duke@1 | 1273 | throws MessagingException, SOAPException { |
duke@1 | 1274 | if (switchOffBM || switchOffLazyAttachment) { |
duke@1 | 1275 | return; |
duke@1 | 1276 | } |
duke@1 | 1277 | |
duke@1 | 1278 | if (attachmentsInitialized || (multiPart == null)) { |
duke@1 | 1279 | return; |
duke@1 | 1280 | } |
duke@1 | 1281 | |
duke@1 | 1282 | if (attachments == null) |
duke@1 | 1283 | attachments = new FinalArrayList(); |
duke@1 | 1284 | |
duke@1 | 1285 | int count = multiPart.getCount(); |
duke@1 | 1286 | for (int i=0; i < count; i++ ) { |
duke@1 | 1287 | initializeAttachment(multiPart.getBodyPart(i)); |
duke@1 | 1288 | } |
duke@1 | 1289 | attachmentsInitialized = true; |
duke@1 | 1290 | //multiPart = null; |
duke@1 | 1291 | needsSave(); |
duke@1 | 1292 | } |
duke@1 | 1293 | |
duke@1 | 1294 | private void initializeAttachment(MimeBodyPart mbp) throws SOAPException { |
duke@1 | 1295 | AttachmentPartImpl attachmentPart = new AttachmentPartImpl(); |
duke@1 | 1296 | DataHandler attachmentHandler = mbp.getDataHandler(); |
duke@1 | 1297 | attachmentPart.setDataHandler(attachmentHandler); |
duke@1 | 1298 | |
duke@1 | 1299 | AttachmentPartImpl.copyMimeHeaders(mbp, attachmentPart); |
duke@1 | 1300 | attachments.add(attachmentPart); |
duke@1 | 1301 | } |
duke@1 | 1302 | |
duke@1 | 1303 | private void initializeAttachment(MimeMultipart multiPart, int i) |
duke@1 | 1304 | throws Exception { |
duke@1 | 1305 | MimeBodyPart currentBodyPart = multiPart.getBodyPart(i); |
duke@1 | 1306 | AttachmentPartImpl attachmentPart = new AttachmentPartImpl(); |
duke@1 | 1307 | |
duke@1 | 1308 | DataHandler attachmentHandler = currentBodyPart.getDataHandler(); |
duke@1 | 1309 | attachmentPart.setDataHandler(attachmentHandler); |
duke@1 | 1310 | |
duke@1 | 1311 | AttachmentPartImpl.copyMimeHeaders(currentBodyPart, attachmentPart); |
duke@1 | 1312 | addAttachmentPart(attachmentPart); |
duke@1 | 1313 | } |
duke@1 | 1314 | |
duke@1 | 1315 | private void setMimeHeaders(SOAPPart soapPart, |
duke@1 | 1316 | MimeBodyPart soapMessagePart) throws Exception { |
duke@1 | 1317 | |
duke@1 | 1318 | // first remove the existing content-type |
duke@1 | 1319 | soapPart.removeAllMimeHeaders(); |
duke@1 | 1320 | // add everything present in soapMessagePart |
duke@1 | 1321 | List headers = soapMessagePart.getAllHeaders(); |
duke@1 | 1322 | int sz = headers.size(); |
duke@1 | 1323 | for( int i=0; i<sz; i++ ) { |
duke@1 | 1324 | Header h = (Header) headers.get(i); |
duke@1 | 1325 | soapPart.addMimeHeader(h.getName(), h.getValue()); |
duke@1 | 1326 | } |
duke@1 | 1327 | } |
duke@1 | 1328 | |
duke@1 | 1329 | private void initCharsetProperty(ContentType contentType) { |
duke@1 | 1330 | String charset = contentType.getParameter("charset"); |
duke@1 | 1331 | if (charset != null) { |
duke@1 | 1332 | ((SOAPPartImpl) getSOAPPart()).setSourceCharsetEncoding(charset); |
duke@1 | 1333 | if(!charset.equalsIgnoreCase("utf-8")) |
duke@1 | 1334 | setProperty(CHARACTER_SET_ENCODING, charset); |
duke@1 | 1335 | } |
duke@1 | 1336 | } |
duke@1 | 1337 | |
duke@1 | 1338 | public void setLazyAttachments(boolean flag) { |
duke@1 | 1339 | lazyAttachments = flag; |
duke@1 | 1340 | } |
duke@1 | 1341 | |
duke@1 | 1342 | } |