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

Wed, 27 Apr 2016 01:27:09 +0800

author
aoqi
date
Wed, 27 Apr 2016 01:27:09 +0800
changeset 0
373ffda63c9a
child 637
9c07ef4934dd
permissions
-rw-r--r--

Initial load
http://hg.openjdk.java.net/jdk8u/jdk8u/jaxws/
changeset: 657:d47a47f961ee
tag: jdk8u25-b17

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

mercurial