src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/MessageImpl.java

Tue, 06 Mar 2012 16:09:35 -0800

author
ohair
date
Tue, 06 Mar 2012 16:09:35 -0800
changeset 286
f50545b5e2f1
child 368
0989ad8c0860
permissions
-rw-r--r--

7150322: Stop using drop source bundles in jaxws
Reviewed-by: darcy, ohrstrom

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

mercurial