1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/MessageImpl.java Tue Mar 06 16:09:35 2012 -0800 1.3 @@ -0,0 +1,1436 @@ 1.4 +/* 1.5 + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Oracle designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Oracle in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.25 + * or visit www.oracle.com if you need additional information or have any 1.26 + * questions. 1.27 + */ 1.28 + 1.29 +package com.sun.xml.internal.messaging.saaj.soap; 1.30 + 1.31 +import java.io.*; 1.32 +import java.util.*; 1.33 +import java.util.logging.Level; 1.34 +import java.util.logging.Logger; 1.35 + 1.36 +import javax.activation.DataHandler; 1.37 +import javax.activation.DataSource; 1.38 +import javax.xml.soap.*; 1.39 +import javax.xml.transform.Source; 1.40 +import javax.xml.transform.stream.StreamSource; 1.41 + 1.42 +import com.sun.xml.internal.messaging.saaj.packaging.mime.Header; 1.43 +import com.sun.xml.internal.messaging.saaj.packaging.mime.internet.*; 1.44 +import com.sun.xml.internal.messaging.saaj.packaging.mime.util.*; 1.45 +import com.sun.xml.internal.messaging.saaj.packaging.mime.MessagingException; 1.46 + 1.47 +import com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl; 1.48 +import com.sun.xml.internal.messaging.saaj.soap.impl.EnvelopeImpl; 1.49 +import com.sun.xml.internal.messaging.saaj.util.*; 1.50 +import com.sun.xml.internal.org.jvnet.mimepull.MIMEPart; 1.51 + 1.52 +/** 1.53 + * The message implementation for SOAP messages with 1.54 + * attachments. Messages for specific profiles will likely extend this 1.55 + * MessageImpl class and add more value for that particular profile. 1.56 + * 1.57 + * @author Anil Vijendran (akv@eng.sun.com) 1.58 + * @author Rajiv Mordani (rajiv.mordani@sun.com) 1.59 + * @author Manveen Kaur (manveen.kaur@sun.com) 1.60 + */ 1.61 + 1.62 +public abstract class MessageImpl 1.63 + extends SOAPMessage 1.64 + implements SOAPConstants { 1.65 + 1.66 + 1.67 + public static final String CONTENT_ID = "Content-ID"; 1.68 + public static final String CONTENT_LOCATION = "Content-Location"; 1.69 + 1.70 + protected static final Logger log = 1.71 + Logger.getLogger(LogDomainConstants.SOAP_DOMAIN, 1.72 + "com.sun.xml.internal.messaging.saaj.soap.LocalStrings"); 1.73 + 1.74 + protected static final int PLAIN_XML_FLAG = 1; // 00001 1.75 + protected static final int MIME_MULTIPART_FLAG = 2; // 00010 1.76 + protected static final int SOAP1_1_FLAG = 4; // 00100 1.77 + protected static final int SOAP1_2_FLAG = 8; // 01000 1.78 + //protected static final int MIME_MULTIPART_XOP_FLAG = 14; // 01110 1.79 + protected static final int MIME_MULTIPART_XOP_SOAP1_1_FLAG = 6; // 00110 1.80 + protected static final int MIME_MULTIPART_XOP_SOAP1_2_FLAG = 10; // 01010 1.81 + protected static final int XOP_FLAG = 13; // 01101 1.82 + protected static final int FI_ENCODED_FLAG = 16; // 10000 1.83 + 1.84 + protected MimeHeaders headers; 1.85 + protected ContentType contentType; 1.86 + protected SOAPPartImpl soapPartImpl; 1.87 + protected FinalArrayList attachments; 1.88 + protected boolean saved = false; 1.89 + protected byte[] messageBytes; 1.90 + protected int messageByteCount; 1.91 + protected HashMap properties = new HashMap(); 1.92 + 1.93 + // used for lazy attachment initialization 1.94 + protected MimeMultipart multiPart = null; 1.95 + protected boolean attachmentsInitialized = false; 1.96 + 1.97 + /** 1.98 + * True if this part is encoded using Fast Infoset. 1.99 + * MIME -> application/fastinfoset 1.100 + */ 1.101 + protected boolean isFastInfoset = false; 1.102 + 1.103 + /** 1.104 + * True if the Accept header of this message includes 1.105 + * application/fastinfoset 1.106 + */ 1.107 + protected boolean acceptFastInfoset = false; 1.108 + 1.109 + protected MimeMultipart mmp = null; 1.110 + 1.111 + // if attachments are present, don't read the entire message in byte stream in saveTo() 1.112 + private boolean optimizeAttachmentProcessing = true; 1.113 + 1.114 + private InputStream inputStreamAfterSaveChanges = null; 1.115 + 1.116 + // switch back to old MimeMultipart incase of problem 1.117 + private static boolean switchOffBM = false; 1.118 + private static boolean switchOffLazyAttachment = false; 1.119 + private static boolean useMimePull = false; 1.120 + 1.121 + static { 1.122 + String s = SAAJUtil.getSystemProperty("saaj.mime.optimization"); 1.123 + if ((s != null) && s.equals("false")) { 1.124 + switchOffBM = true; 1.125 + } 1.126 + s = SAAJUtil.getSystemProperty("saaj.lazy.mime.optimization"); 1.127 + if ((s != null) && s.equals("false")) { 1.128 + switchOffLazyAttachment = true; 1.129 + } 1.130 + useMimePull = SAAJUtil.getSystemBoolean("saaj.use.mimepull"); 1.131 + 1.132 + } 1.133 + 1.134 + //property to indicate optimized serialization for lazy attachments 1.135 + private boolean lazyAttachments = false; 1.136 + 1.137 + // most of the times, Content-Types are already all lower cased. 1.138 + // String.toLowerCase() works faster in this case, so even if you 1.139 + // are only doing one comparison, it pays off to use String.toLowerCase() 1.140 + // than String.equalsIgnoreCase(). When you do more than one comparison, 1.141 + // the benefits of String.toLowerCase() dominates. 1.142 + // 1.143 + // 1.144 + // for FI, 1.145 + // use application/fastinfoset for SOAP 1.1 1.146 + // use application/soap+fastinfoset for SOAP 1.2 1.147 + // to speed up comparisons, test methods always use lower cases. 1.148 + 1.149 + /** 1.150 + * @param primary 1.151 + * must be all lower case 1.152 + * @param sub 1.153 + * must be all lower case 1.154 + */ 1.155 + private static boolean isSoap1_1Type(String primary, String sub) { 1.156 + return primary.equalsIgnoreCase("text") && sub.equalsIgnoreCase("xml") 1.157 + || primary.equalsIgnoreCase("text") && sub.equalsIgnoreCase("xml-soap") 1.158 + || primary.equals("application") 1.159 + && sub.equals("fastinfoset"); 1.160 + } 1.161 + 1.162 + /** 1.163 + * @param type 1.164 + * must be all lower case 1.165 + */ 1.166 + private static boolean isEqualToSoap1_1Type(String type) { 1.167 + return type.startsWith("text/xml") || 1.168 + type.startsWith("application/fastinfoset"); 1.169 + } 1.170 + 1.171 + /** 1.172 + * @param primary 1.173 + * must be all lower case 1.174 + * @param sub 1.175 + * must be all lower case 1.176 + */ 1.177 + private static boolean isSoap1_2Type(String primary, String sub) { 1.178 + return primary.equals("application") 1.179 + && (sub.equals("soap+xml") 1.180 + || sub.equals("soap+fastinfoset")); 1.181 + } 1.182 + 1.183 + /** 1.184 + * @param type 1.185 + * must be all lower case 1.186 + */ 1.187 + private static boolean isEqualToSoap1_2Type(String type) { 1.188 + return type.startsWith("application/soap+xml") || 1.189 + type.startsWith("application/soap+fastinfoset"); 1.190 + } 1.191 + 1.192 + /** 1.193 + * Construct a new message. This will be invoked before message 1.194 + * sends. 1.195 + */ 1.196 + protected MessageImpl() { 1.197 + this(false, false); 1.198 + attachmentsInitialized = true; 1.199 + } 1.200 + 1.201 + /** 1.202 + * Construct a new message. This will be invoked before message 1.203 + * sends. 1.204 + */ 1.205 + protected MessageImpl(boolean isFastInfoset, boolean acceptFastInfoset) { 1.206 + this.isFastInfoset = isFastInfoset; 1.207 + this.acceptFastInfoset = acceptFastInfoset; 1.208 + 1.209 + headers = new MimeHeaders(); 1.210 + headers.setHeader("Accept", getExpectedAcceptHeader()); 1.211 + contentType = new ContentType(); 1.212 + } 1.213 + 1.214 + /** 1.215 + * Shallow copy. 1.216 + */ 1.217 + protected MessageImpl(SOAPMessage msg) { 1.218 + if (!(msg instanceof MessageImpl)) { 1.219 + // don't know how to handle this. 1.220 + } 1.221 + MessageImpl src = (MessageImpl) msg; 1.222 + this.headers = src.headers; 1.223 + this.soapPartImpl = src.soapPartImpl; 1.224 + this.attachments = src.attachments; 1.225 + this.saved = src.saved; 1.226 + this.messageBytes = src.messageBytes; 1.227 + this.messageByteCount = src.messageByteCount; 1.228 + this.properties = src.properties; 1.229 + this.contentType = src.contentType; 1.230 + } 1.231 + 1.232 + /** 1.233 + * @param stat 1.234 + * the mask value obtained from {@link #identifyContentType(ContentType)} 1.235 + */ 1.236 + protected static boolean isSoap1_1Content(int stat) { 1.237 + return (stat & SOAP1_1_FLAG) != 0; 1.238 + } 1.239 + 1.240 + /** 1.241 + * @param stat 1.242 + * the mask value obtained from {@link #identifyContentType(ContentType)} 1.243 + */ 1.244 + protected static boolean isSoap1_2Content(int stat) { 1.245 + return (stat & SOAP1_2_FLAG) != 0; 1.246 + } 1.247 + 1.248 + private static boolean isMimeMultipartXOPSoap1_2Package(ContentType contentType) { 1.249 + String type = contentType.getParameter("type"); 1.250 + if (type == null) { 1.251 + return false; 1.252 + } 1.253 + type = type.toLowerCase(); 1.254 + if (!type.startsWith("application/xop+xml")) { 1.255 + return false; 1.256 + } 1.257 + String startinfo = contentType.getParameter("start-info"); 1.258 + if (startinfo == null) { 1.259 + return false; 1.260 + } 1.261 + startinfo = startinfo.toLowerCase(); 1.262 + return isEqualToSoap1_2Type(startinfo); 1.263 + } 1.264 + 1.265 + 1.266 + //private static boolean isMimeMultipartXOPPackage(ContentType contentType) { 1.267 + private static boolean isMimeMultipartXOPSoap1_1Package(ContentType contentType) { 1.268 + String type = contentType.getParameter("type"); 1.269 + if(type==null) 1.270 + return false; 1.271 + 1.272 + type = type.toLowerCase(); 1.273 + if(!type.startsWith("application/xop+xml")) 1.274 + return false; 1.275 + 1.276 + String startinfo = contentType.getParameter("start-info"); 1.277 + if(startinfo == null) 1.278 + return false; 1.279 + startinfo = startinfo.toLowerCase(); 1.280 + return isEqualToSoap1_1Type(startinfo); 1.281 + } 1.282 + 1.283 + private static boolean isSOAPBodyXOPPackage(ContentType contentType){ 1.284 + String primary = contentType.getPrimaryType(); 1.285 + String sub = contentType.getSubType(); 1.286 + 1.287 + if (primary.equalsIgnoreCase("application")) { 1.288 + if (sub.equalsIgnoreCase("xop+xml")) { 1.289 + String type = getTypeParameter(contentType); 1.290 + return isEqualToSoap1_2Type(type) || isEqualToSoap1_1Type(type); 1.291 + } 1.292 + } 1.293 + return false; 1.294 + } 1.295 + 1.296 + /** 1.297 + * Construct a message from an input stream. When messages are 1.298 + * received, there's two parts -- the transport headers and the 1.299 + * message content in a transport specific stream. 1.300 + */ 1.301 + protected MessageImpl(MimeHeaders headers, final InputStream in) 1.302 + throws SOAPExceptionImpl { 1.303 + contentType = parseContentType(headers); 1.304 + init(headers,identifyContentType(contentType),contentType,in); 1.305 + } 1.306 + 1.307 + private static ContentType parseContentType(MimeHeaders headers) throws SOAPExceptionImpl { 1.308 + final String ct; 1.309 + if (headers != null) 1.310 + ct = getContentType(headers); 1.311 + else { 1.312 + log.severe("SAAJ0550.soap.null.headers"); 1.313 + throw new SOAPExceptionImpl("Cannot create message: " + 1.314 + "Headers can't be null"); 1.315 + } 1.316 + 1.317 + if (ct == null) { 1.318 + log.severe("SAAJ0532.soap.no.Content-Type"); 1.319 + throw new SOAPExceptionImpl("Absent Content-Type"); 1.320 + } 1.321 + try { 1.322 + return new ContentType(ct); 1.323 + } catch (Throwable ex) { 1.324 + log.severe("SAAJ0535.soap.cannot.internalize.message"); 1.325 + throw new SOAPExceptionImpl("Unable to internalize message", ex); 1.326 + } 1.327 + } 1.328 + 1.329 + /** 1.330 + * Construct a message from an input stream. When messages are 1.331 + * received, there's two parts -- the transport headers and the 1.332 + * message content in a transport specific stream. 1.333 + * 1.334 + * @param contentType 1.335 + * The parsed content type header from the headers variable. 1.336 + * This is redundant parameter, but it avoids reparsing this header again. 1.337 + * @param stat 1.338 + * The result of {@link #identifyContentType(ContentType)} over 1.339 + * the contentType parameter. This redundant parameter, but it avoids 1.340 + * recomputing this information again. 1.341 + */ 1.342 + protected MessageImpl(MimeHeaders headers, final ContentType contentType, int stat, final InputStream in) throws SOAPExceptionImpl { 1.343 + init(headers, stat, contentType, in); 1.344 + 1.345 + } 1.346 + 1.347 + private void init(MimeHeaders headers, int stat, final ContentType contentType, final InputStream in) throws SOAPExceptionImpl { 1.348 + this.headers = headers; 1.349 + 1.350 + try { 1.351 + 1.352 + // Set isFastInfoset/acceptFastInfoset flag based on MIME type 1.353 + if ((stat & FI_ENCODED_FLAG) > 0) { 1.354 + isFastInfoset = acceptFastInfoset = true; 1.355 + } 1.356 + 1.357 + // If necessary, inspect Accept header to set acceptFastInfoset 1.358 + if (!isFastInfoset) { 1.359 + String[] values = headers.getHeader("Accept"); 1.360 + if (values != null) { 1.361 + for (int i = 0; i < values.length; i++) { 1.362 + StringTokenizer st = new StringTokenizer(values[i], ","); 1.363 + while (st.hasMoreTokens()) { 1.364 + final String token = st.nextToken().trim(); 1.365 + if (token.equalsIgnoreCase("application/fastinfoset") || 1.366 + token.equalsIgnoreCase("application/soap+fastinfoset")) { 1.367 + acceptFastInfoset = true; 1.368 + break; 1.369 + } 1.370 + } 1.371 + } 1.372 + } 1.373 + } 1.374 + 1.375 + if (!isCorrectSoapVersion(stat)) { 1.376 + log.log( 1.377 + Level.SEVERE, 1.378 + "SAAJ0533.soap.incorrect.Content-Type", 1.379 + new String[] { 1.380 + contentType.toString(), 1.381 + getExpectedContentType()}); 1.382 + throw new SOAPVersionMismatchException( 1.383 + "Cannot create message: incorrect content-type for SOAP version. Got: " 1.384 + + contentType 1.385 + + " Expected: " 1.386 + + getExpectedContentType()); 1.387 + } 1.388 + 1.389 + if ((stat & PLAIN_XML_FLAG) != 0) { 1.390 + if (isFastInfoset) { 1.391 + getSOAPPart().setContent( 1.392 + FastInfosetReflection.FastInfosetSource_new(in)); 1.393 + } else { 1.394 + initCharsetProperty(contentType); 1.395 + getSOAPPart().setContent(new StreamSource(in)); 1.396 + } 1.397 + } 1.398 + else if ((stat & MIME_MULTIPART_FLAG) != 0) { 1.399 + DataSource ds = new DataSource() { 1.400 + public InputStream getInputStream() { 1.401 + return in; 1.402 + } 1.403 + 1.404 + public OutputStream getOutputStream() { 1.405 + return null; 1.406 + } 1.407 + 1.408 + public String getContentType() { 1.409 + return contentType.toString(); 1.410 + } 1.411 + 1.412 + public String getName() { 1.413 + return ""; 1.414 + } 1.415 + }; 1.416 + 1.417 + multiPart = null; 1.418 + if (useMimePull) { 1.419 + multiPart = new MimePullMultipart(ds,contentType); 1.420 + } else if (switchOffBM) { 1.421 + multiPart = new MimeMultipart(ds,contentType); 1.422 + } else { 1.423 + multiPart = new BMMimeMultipart(ds,contentType); 1.424 + } 1.425 + 1.426 + String startParam = contentType.getParameter("start"); 1.427 + MimeBodyPart soapMessagePart = null; 1.428 + InputStream soapPartInputStream = null; 1.429 + String contentID = null; 1.430 + String contentIDNoAngle = null; 1.431 + if (switchOffBM || switchOffLazyAttachment) { 1.432 + if(startParam == null) { 1.433 + soapMessagePart = multiPart.getBodyPart(0); 1.434 + for (int i = 1; i < multiPart.getCount(); i++) { 1.435 + initializeAttachment(multiPart, i); 1.436 + } 1.437 + } else { 1.438 + soapMessagePart = multiPart.getBodyPart(startParam); 1.439 + for (int i = 0; i < multiPart.getCount(); i++) { 1.440 + contentID = multiPart.getBodyPart(i).getContentID(); 1.441 + // Old versions of AXIS2 put angle brackets around the content 1.442 + // id but not the start param 1.443 + contentIDNoAngle = (contentID != null) ? 1.444 + contentID.replaceFirst("^<", "").replaceFirst(">$", "") : null; 1.445 + if(!startParam.equals(contentID) && !startParam.equals(contentIDNoAngle)) 1.446 + initializeAttachment(multiPart, i); 1.447 + } 1.448 + } 1.449 + } else { 1.450 + if (useMimePull) { 1.451 + MimePullMultipart mpMultipart = (MimePullMultipart)multiPart; 1.452 + MIMEPart sp = mpMultipart.readAndReturnSOAPPart(); 1.453 + soapMessagePart = new MimeBodyPart(sp); 1.454 + soapPartInputStream = sp.readOnce(); 1.455 + } else { 1.456 + BMMimeMultipart bmMultipart = 1.457 + (BMMimeMultipart) multiPart; 1.458 + InputStream stream = bmMultipart.initStream(); 1.459 + 1.460 + SharedInputStream sin = null; 1.461 + if (stream instanceof SharedInputStream) { 1.462 + sin = (SharedInputStream) stream; 1.463 + } 1.464 + 1.465 + String boundary = "--" + 1.466 + contentType.getParameter("boundary"); 1.467 + byte[] bndbytes = ASCIIUtility.getBytes(boundary); 1.468 + if (startParam == null) { 1.469 + soapMessagePart = 1.470 + bmMultipart.getNextPart(stream, bndbytes, sin); 1.471 + bmMultipart.removeBodyPart(soapMessagePart); 1.472 + } else { 1.473 + MimeBodyPart bp = null; 1.474 + try { 1.475 + while (!startParam.equals(contentID) && !startParam.equals(contentIDNoAngle)) { 1.476 + bp = bmMultipart.getNextPart( 1.477 + stream, bndbytes, sin); 1.478 + contentID = bp.getContentID(); 1.479 + // Old versions of AXIS2 put angle brackets around the content 1.480 + // id but not the start param 1.481 + contentIDNoAngle = (contentID != null) ? 1.482 + contentID.replaceFirst("^<", "").replaceFirst(">$", "") : null; 1.483 + } 1.484 + soapMessagePart = bp; 1.485 + bmMultipart.removeBodyPart(bp); 1.486 + } catch (Exception e) { 1.487 + throw new SOAPExceptionImpl(e); 1.488 + } 1.489 + } 1.490 + } 1.491 + } 1.492 + 1.493 + if (soapPartInputStream == null && soapMessagePart != null) { 1.494 + soapPartInputStream = soapMessagePart.getInputStream(); 1.495 + } 1.496 + 1.497 + ContentType soapPartCType = new ContentType( 1.498 + soapMessagePart.getContentType()); 1.499 + initCharsetProperty(soapPartCType); 1.500 + String baseType = soapPartCType.getBaseType().toLowerCase(); 1.501 + if(!(isEqualToSoap1_1Type(baseType) 1.502 + || isEqualToSoap1_2Type(baseType) 1.503 + || isSOAPBodyXOPPackage(soapPartCType))) { 1.504 + log.log(Level.SEVERE, 1.505 + "SAAJ0549.soap.part.invalid.Content-Type", 1.506 + new Object[] {baseType}); 1.507 + throw new SOAPExceptionImpl( 1.508 + "Bad Content-Type for SOAP Part : " + 1.509 + baseType); 1.510 + } 1.511 + 1.512 + SOAPPart soapPart = getSOAPPart(); 1.513 + setMimeHeaders(soapPart, soapMessagePart); 1.514 + soapPart.setContent(isFastInfoset ? 1.515 + (Source) FastInfosetReflection.FastInfosetSource_new( 1.516 + soapPartInputStream) : 1.517 + (Source) new StreamSource(soapPartInputStream)); 1.518 + } else { 1.519 + log.severe("SAAJ0534.soap.unknown.Content-Type"); 1.520 + throw new SOAPExceptionImpl("Unrecognized Content-Type"); 1.521 + } 1.522 + } catch (Throwable ex) { 1.523 + log.severe("SAAJ0535.soap.cannot.internalize.message"); 1.524 + throw new SOAPExceptionImpl("Unable to internalize message", ex); 1.525 + } 1.526 + needsSave(); 1.527 + } 1.528 + 1.529 + public boolean isFastInfoset() { 1.530 + return isFastInfoset; 1.531 + } 1.532 + 1.533 + public boolean acceptFastInfoset() { 1.534 + return acceptFastInfoset; 1.535 + } 1.536 + 1.537 + public void setIsFastInfoset(boolean value) { 1.538 + if (value != isFastInfoset) { 1.539 + isFastInfoset = value; 1.540 + if (isFastInfoset) { 1.541 + acceptFastInfoset = true; 1.542 + } 1.543 + saved = false; // ensure transcoding if necessary 1.544 + } 1.545 + } 1.546 + 1.547 + public Object getProperty(String property) { 1.548 + return (String) properties.get(property); 1.549 + } 1.550 + 1.551 + public void setProperty(String property, Object value) { 1.552 + verify(property, value); 1.553 + properties.put(property, value); 1.554 + } 1.555 + 1.556 + private void verify(String property, Object value) { 1.557 + if (property.equalsIgnoreCase(SOAPMessage.WRITE_XML_DECLARATION)) { 1.558 + if (!("true".equals(value) || "false".equals(value))) 1.559 + throw new RuntimeException( 1.560 + property + " must have value false or true"); 1.561 + 1.562 + try { 1.563 + EnvelopeImpl env = (EnvelopeImpl) getSOAPPart().getEnvelope(); 1.564 + if ("true".equalsIgnoreCase((String)value)) { 1.565 + env.setOmitXmlDecl("no"); 1.566 + } else if ("false".equalsIgnoreCase((String)value)) { 1.567 + env.setOmitXmlDecl("yes"); 1.568 + } 1.569 + } catch (Exception e) { 1.570 + log.log(Level.SEVERE, "SAAJ0591.soap.exception.in.set.property", 1.571 + new Object[] {e.getMessage(), "javax.xml.soap.write-xml-declaration"}); 1.572 + throw new RuntimeException(e); 1.573 + } 1.574 + return; 1.575 + } 1.576 + 1.577 + if (property.equalsIgnoreCase(SOAPMessage.CHARACTER_SET_ENCODING)) { 1.578 + try { 1.579 + ((EnvelopeImpl) getSOAPPart().getEnvelope()).setCharsetEncoding((String)value); 1.580 + } catch (Exception e) { 1.581 + log.log(Level.SEVERE, "SAAJ0591.soap.exception.in.set.property", 1.582 + new Object[] {e.getMessage(), "javax.xml.soap.character-set-encoding"}); 1.583 + throw new RuntimeException(e); 1.584 + } 1.585 + } 1.586 + } 1.587 + 1.588 + protected abstract boolean isCorrectSoapVersion(int contentTypeId); 1.589 + 1.590 + protected abstract String getExpectedContentType(); 1.591 + protected abstract String getExpectedAcceptHeader(); 1.592 + 1.593 + /** 1.594 + * Sniffs the Content-Type header so that we can determine how to process. 1.595 + * 1.596 + * <p> 1.597 + * In the absence of type attribute we assume it to be text/xml. 1.598 + * That would mean we're easy on accepting the message and 1.599 + * generate the correct thing (as the SWA spec also specifies 1.600 + * that the type parameter should always be text/xml) 1.601 + * 1.602 + * @return 1.603 + * combination of flags, such as PLAIN_XML_CODE and MIME_MULTIPART_CODE. 1.604 + */ 1.605 + // SOAP1.2 allow SOAP1.2 content type 1.606 + static int identifyContentType(ContentType ct) 1.607 + throws SOAPExceptionImpl { 1.608 + // TBD 1.609 + // Is there anything else we need to verify here? 1.610 + 1.611 + String primary = ct.getPrimaryType().toLowerCase(); 1.612 + String sub = ct.getSubType().toLowerCase(); 1.613 + 1.614 + if (primary.equals("multipart")) { 1.615 + if (sub.equals("related")) { 1.616 + String type = getTypeParameter(ct); 1.617 + if (isEqualToSoap1_1Type(type)) { 1.618 + return (type.equals("application/fastinfoset") ? 1.619 + FI_ENCODED_FLAG : 0) | MIME_MULTIPART_FLAG | SOAP1_1_FLAG; 1.620 + } 1.621 + else if (isEqualToSoap1_2Type(type)) { 1.622 + return (type.equals("application/soap+fastinfoset") ? 1.623 + FI_ENCODED_FLAG : 0) | MIME_MULTIPART_FLAG | SOAP1_2_FLAG; 1.624 + /*} else if (isMimeMultipartXOPPackage(ct)) { 1.625 + return MIME_MULTIPART_XOP_FLAG;*/ 1.626 + } else if (isMimeMultipartXOPSoap1_1Package(ct)) { 1.627 + return MIME_MULTIPART_XOP_SOAP1_1_FLAG; 1.628 + } else if (isMimeMultipartXOPSoap1_2Package(ct)) { 1.629 + return MIME_MULTIPART_XOP_SOAP1_2_FLAG; 1.630 + } else { 1.631 + log.severe("SAAJ0536.soap.content-type.mustbe.multipart"); 1.632 + throw new SOAPExceptionImpl( 1.633 + "Content-Type needs to be Multipart/Related " 1.634 + + "and with \"type=text/xml\" " 1.635 + + "or \"type=application/soap+xml\""); 1.636 + } 1.637 + } else { 1.638 + log.severe("SAAJ0537.soap.invalid.content-type"); 1.639 + throw new SOAPExceptionImpl( 1.640 + "Invalid Content-Type: " + primary + '/' + sub); 1.641 + } 1.642 + } 1.643 + else if (isSoap1_1Type(primary, sub)) { 1.644 + return (primary.equalsIgnoreCase("application") 1.645 + && sub.equalsIgnoreCase("fastinfoset") ? 1.646 + FI_ENCODED_FLAG : 0) 1.647 + | PLAIN_XML_FLAG | SOAP1_1_FLAG; 1.648 + } 1.649 + else if (isSoap1_2Type(primary, sub)) { 1.650 + return (primary.equalsIgnoreCase("application") 1.651 + && sub.equalsIgnoreCase("soap+fastinfoset") ? 1.652 + FI_ENCODED_FLAG : 0) 1.653 + | PLAIN_XML_FLAG | SOAP1_2_FLAG; 1.654 + } else if(isSOAPBodyXOPPackage(ct)){ 1.655 + return XOP_FLAG; 1.656 + } else { 1.657 + log.severe("SAAJ0537.soap.invalid.content-type"); 1.658 + throw new SOAPExceptionImpl( 1.659 + "Invalid Content-Type:" 1.660 + + primary 1.661 + + '/' 1.662 + + sub 1.663 + + ". Is this an error message instead of a SOAP response?"); 1.664 + } 1.665 + } 1.666 + 1.667 + /** 1.668 + * Obtains the type parameter of the Content-Type header. Defaults to "text/xml". 1.669 + */ 1.670 + private static String getTypeParameter(ContentType contentType) { 1.671 + String p = contentType.getParameter("type"); 1.672 + if(p!=null) 1.673 + return p.toLowerCase(); 1.674 + else 1.675 + return "text/xml"; 1.676 + } 1.677 + 1.678 + public MimeHeaders getMimeHeaders() { 1.679 + return this.headers; 1.680 + } 1.681 + 1.682 + final static String getContentType(MimeHeaders headers) { 1.683 + String[] values = headers.getHeader("Content-Type"); 1.684 + if (values == null) 1.685 + return null; 1.686 + else 1.687 + return values[0]; 1.688 + } 1.689 + 1.690 + /* 1.691 + * Get the complete ContentType value along with optional parameters. 1.692 + */ 1.693 + public String getContentType() { 1.694 + return getContentType(this.headers); 1.695 + } 1.696 + 1.697 + public void setContentType(String type) { 1.698 + headers.setHeader("Content-Type", type); 1.699 + needsSave(); 1.700 + } 1.701 + 1.702 + private ContentType contentType() { 1.703 + ContentType ct = null; 1.704 + try { 1.705 + String currentContent = getContentType(); 1.706 + if (currentContent == null) { 1.707 + return this.contentType; 1.708 + } 1.709 + ct = new ContentType(currentContent); 1.710 + } catch (Exception e) { 1.711 + // what to do here? 1.712 + } 1.713 + return ct; 1.714 + } 1.715 + 1.716 + /* 1.717 + * Return the MIME type string, without the parameters. 1.718 + */ 1.719 + public String getBaseType() { 1.720 + return contentType().getBaseType(); 1.721 + } 1.722 + 1.723 + public void setBaseType(String type) { 1.724 + ContentType ct = contentType(); 1.725 + ct.setParameter("type", type); 1.726 + headers.setHeader("Content-Type", ct.toString()); 1.727 + needsSave(); 1.728 + } 1.729 + 1.730 + public String getAction() { 1.731 + return contentType().getParameter("action"); 1.732 + } 1.733 + 1.734 + public void setAction(String action) { 1.735 + ContentType ct = contentType(); 1.736 + ct.setParameter("action", action); 1.737 + headers.setHeader("Content-Type", ct.toString()); 1.738 + needsSave(); 1.739 + } 1.740 + 1.741 + public String getCharset() { 1.742 + return contentType().getParameter("charset"); 1.743 + } 1.744 + 1.745 + public void setCharset(String charset) { 1.746 + ContentType ct = contentType(); 1.747 + ct.setParameter("charset", charset); 1.748 + headers.setHeader("Content-Type", ct.toString()); 1.749 + needsSave(); 1.750 + } 1.751 + 1.752 + /** 1.753 + * All write methods (i.e setters) should call this method in 1.754 + * order to make sure that a save is necessary since the state 1.755 + * has been modified. 1.756 + */ 1.757 + private final void needsSave() { 1.758 + saved = false; 1.759 + } 1.760 + 1.761 + public boolean saveRequired() { 1.762 + return saved != true; 1.763 + } 1.764 + 1.765 + public String getContentDescription() { 1.766 + String[] values = headers.getHeader("Content-Description"); 1.767 + if (values != null && values.length > 0) 1.768 + return values[0]; 1.769 + return null; 1.770 + } 1.771 + 1.772 + public void setContentDescription(String description) { 1.773 + headers.setHeader("Content-Description", description); 1.774 + needsSave(); 1.775 + } 1.776 + 1.777 + public abstract SOAPPart getSOAPPart(); 1.778 + 1.779 + public void removeAllAttachments() { 1.780 + try { 1.781 + initializeAllAttachments(); 1.782 + } catch (Exception e) { 1.783 + throw new RuntimeException(e); 1.784 + } 1.785 + 1.786 + if (attachments != null) { 1.787 + attachments.clear(); 1.788 + needsSave(); 1.789 + } 1.790 + } 1.791 + 1.792 + public int countAttachments() { 1.793 + try { 1.794 + initializeAllAttachments(); 1.795 + } catch (Exception e) { 1.796 + throw new RuntimeException(e); 1.797 + } 1.798 + if (attachments != null) 1.799 + return attachments.size(); 1.800 + return 0; 1.801 + } 1.802 + 1.803 + public void addAttachmentPart(AttachmentPart attachment) { 1.804 + try { 1.805 + initializeAllAttachments(); 1.806 + this.optimizeAttachmentProcessing = true; 1.807 + } catch (Exception e) { 1.808 + throw new RuntimeException(e); 1.809 + } 1.810 + if (attachments == null) 1.811 + attachments = new FinalArrayList(); 1.812 + 1.813 + attachments.add(attachment); 1.814 + 1.815 + needsSave(); 1.816 + } 1.817 + 1.818 + static private final Iterator nullIter = Collections.EMPTY_LIST.iterator(); 1.819 + 1.820 + public Iterator getAttachments() { 1.821 + try { 1.822 + initializeAllAttachments(); 1.823 + } catch (Exception e) { 1.824 + throw new RuntimeException(e); 1.825 + } 1.826 + if (attachments == null) 1.827 + return nullIter; 1.828 + return attachments.iterator(); 1.829 + } 1.830 + 1.831 + private void setFinalContentType(String charset) { 1.832 + ContentType ct = contentType(); 1.833 + if (ct == null) { 1.834 + ct = new ContentType(); 1.835 + } 1.836 + String[] split = getExpectedContentType().split("/"); 1.837 + ct.setPrimaryType(split[0]); 1.838 + ct.setSubType(split[1]); 1.839 + ct.setParameter("charset", charset); 1.840 + headers.setHeader("Content-Type", ct.toString()); 1.841 + } 1.842 + 1.843 + private class MimeMatchingIterator implements Iterator { 1.844 + public MimeMatchingIterator(MimeHeaders headers) { 1.845 + this.headers = headers; 1.846 + this.iter = attachments.iterator(); 1.847 + } 1.848 + 1.849 + private Iterator iter; 1.850 + private MimeHeaders headers; 1.851 + private Object nextAttachment; 1.852 + 1.853 + public boolean hasNext() { 1.854 + if (nextAttachment == null) 1.855 + nextAttachment = nextMatch(); 1.856 + return nextAttachment != null; 1.857 + } 1.858 + 1.859 + public Object next() { 1.860 + if (nextAttachment != null) { 1.861 + Object ret = nextAttachment; 1.862 + nextAttachment = null; 1.863 + return ret; 1.864 + } 1.865 + 1.866 + if (hasNext()) 1.867 + return nextAttachment; 1.868 + 1.869 + return null; 1.870 + } 1.871 + 1.872 + Object nextMatch() { 1.873 + while (iter.hasNext()) { 1.874 + AttachmentPartImpl ap = (AttachmentPartImpl) iter.next(); 1.875 + if (ap.hasAllHeaders(headers)) 1.876 + return ap; 1.877 + } 1.878 + return null; 1.879 + } 1.880 + 1.881 + public void remove() { 1.882 + iter.remove(); 1.883 + } 1.884 + } 1.885 + 1.886 + public Iterator getAttachments(MimeHeaders headers) { 1.887 + try { 1.888 + initializeAllAttachments(); 1.889 + } catch (Exception e) { 1.890 + throw new RuntimeException(e); 1.891 + } 1.892 + if (attachments == null) 1.893 + return nullIter; 1.894 + 1.895 + return new MimeMatchingIterator(headers); 1.896 + } 1.897 + 1.898 + public void removeAttachments(MimeHeaders headers) { 1.899 + try { 1.900 + initializeAllAttachments(); 1.901 + } catch (Exception e) { 1.902 + throw new RuntimeException(e); 1.903 + } 1.904 + if (attachments == null) 1.905 + return ; 1.906 + 1.907 + Iterator it = new MimeMatchingIterator(headers); 1.908 + while (it.hasNext()) { 1.909 + int index = attachments.indexOf(it.next()); 1.910 + attachments.set(index, null); 1.911 + } 1.912 + FinalArrayList f = new FinalArrayList(); 1.913 + for (int i = 0; i < attachments.size(); i++) { 1.914 + if (attachments.get(i) != null) { 1.915 + f.add(attachments.get(i)); 1.916 + } 1.917 + } 1.918 + attachments = f; 1.919 + // needsSave(); 1.920 + } 1.921 + 1.922 + public AttachmentPart createAttachmentPart() { 1.923 + return new AttachmentPartImpl(); 1.924 + } 1.925 + 1.926 + public AttachmentPart getAttachment(SOAPElement element) 1.927 + throws SOAPException { 1.928 + try { 1.929 + initializeAllAttachments(); 1.930 + } catch (Exception e) { 1.931 + throw new RuntimeException(e); 1.932 + } 1.933 + String uri; 1.934 + String hrefAttr = element.getAttribute("href"); 1.935 + if ("".equals(hrefAttr)) { 1.936 + Node node = getValueNodeStrict(element); 1.937 + String swaRef = null; 1.938 + if (node != null) { 1.939 + swaRef = node.getValue(); 1.940 + } 1.941 + if (swaRef == null || "".equals(swaRef)) { 1.942 + return null; 1.943 + } else { 1.944 + uri = swaRef; 1.945 + } 1.946 + } else { 1.947 + uri = hrefAttr; 1.948 + } 1.949 + return getAttachmentPart(uri); 1.950 + } 1.951 + 1.952 + private Node getValueNodeStrict(SOAPElement element) { 1.953 + Node node = (Node)element.getFirstChild(); 1.954 + if (node != null) { 1.955 + if (node.getNextSibling() == null 1.956 + && node.getNodeType() == org.w3c.dom.Node.TEXT_NODE) { 1.957 + return node; 1.958 + } else { 1.959 + return null; 1.960 + } 1.961 + } 1.962 + return null; 1.963 + } 1.964 + 1.965 + 1.966 + private AttachmentPart getAttachmentPart(String uri) throws SOAPException { 1.967 + AttachmentPart _part; 1.968 + try { 1.969 + if (uri.startsWith("cid:")) { 1.970 + // rfc2392 1.971 + uri = '<'+uri.substring("cid:".length())+'>'; 1.972 + 1.973 + MimeHeaders headersToMatch = new MimeHeaders(); 1.974 + headersToMatch.addHeader(CONTENT_ID, uri); 1.975 + 1.976 + Iterator i = this.getAttachments(headersToMatch); 1.977 + _part = (i == null) ? null : (AttachmentPart)i.next(); 1.978 + } else { 1.979 + // try content-location 1.980 + MimeHeaders headersToMatch = new MimeHeaders(); 1.981 + headersToMatch.addHeader(CONTENT_LOCATION, uri); 1.982 + 1.983 + Iterator i = this.getAttachments(headersToMatch); 1.984 + _part = (i == null) ? null : (AttachmentPart)i.next(); 1.985 + } 1.986 + 1.987 + // try auto-generated JAXRPC CID 1.988 + if (_part == null) { 1.989 + Iterator j = this.getAttachments(); 1.990 + 1.991 + while (j.hasNext()) { 1.992 + AttachmentPart p = (AttachmentPart)j.next(); 1.993 + String cl = p.getContentId(); 1.994 + if (cl != null) { 1.995 + // obtain the partname 1.996 + int eqIndex = cl.indexOf("="); 1.997 + if (eqIndex > -1) { 1.998 + cl = cl.substring(1, eqIndex); 1.999 + if (cl.equalsIgnoreCase(uri)) { 1.1000 + _part = p; 1.1001 + break; 1.1002 + } 1.1003 + } 1.1004 + } 1.1005 + } 1.1006 + } 1.1007 + 1.1008 + } catch (Exception se) { 1.1009 + log.log(Level.SEVERE, "SAAJ0590.soap.unable.to.locate.attachment", new Object[] {uri}); 1.1010 + throw new SOAPExceptionImpl(se); 1.1011 + } 1.1012 + return _part; 1.1013 + } 1.1014 + 1.1015 + private final InputStream getHeaderBytes() 1.1016 + throws IOException { 1.1017 + SOAPPartImpl sp = (SOAPPartImpl) getSOAPPart(); 1.1018 + return sp.getContentAsStream(); 1.1019 + } 1.1020 + 1.1021 + private String convertToSingleLine(String contentType) { 1.1022 + StringBuffer buffer = new StringBuffer(); 1.1023 + for (int i = 0; i < contentType.length(); i ++) { 1.1024 + char c = contentType.charAt(i); 1.1025 + if (c != '\r' && c != '\n' && c != '\t') 1.1026 + buffer.append(c); 1.1027 + } 1.1028 + return buffer.toString(); 1.1029 + } 1.1030 + 1.1031 + private MimeMultipart getMimeMessage() throws SOAPException { 1.1032 + try { 1.1033 + SOAPPartImpl soapPart = (SOAPPartImpl) getSOAPPart(); 1.1034 + MimeBodyPart mimeSoapPart = soapPart.getMimePart(); 1.1035 + 1.1036 + /* 1.1037 + * Get content type from this message instead of soapPart 1.1038 + * to ensure agreement if soapPart is transcoded (XML <-> FI) 1.1039 + */ 1.1040 + ContentType soapPartCtype = new ContentType(getExpectedContentType()); 1.1041 + 1.1042 + if (!isFastInfoset) { 1.1043 + soapPartCtype.setParameter("charset", initCharset()); 1.1044 + } 1.1045 + mimeSoapPart.setHeader("Content-Type", soapPartCtype.toString()); 1.1046 + 1.1047 + MimeMultipart headerAndBody = null; 1.1048 + 1.1049 + if (!switchOffBM && !switchOffLazyAttachment && 1.1050 + (multiPart != null) && !attachmentsInitialized) { 1.1051 + headerAndBody = new BMMimeMultipart(); 1.1052 + headerAndBody.addBodyPart(mimeSoapPart); 1.1053 + if (attachments != null) { 1.1054 + for (Iterator eachAttachment = attachments.iterator(); 1.1055 + eachAttachment.hasNext();) { 1.1056 + headerAndBody.addBodyPart( 1.1057 + ((AttachmentPartImpl) eachAttachment.next()) 1.1058 + .getMimePart()); 1.1059 + } 1.1060 + } 1.1061 + InputStream in = ((BMMimeMultipart)multiPart).getInputStream(); 1.1062 + if (!((BMMimeMultipart)multiPart).lastBodyPartFound() && 1.1063 + !((BMMimeMultipart)multiPart).isEndOfStream()) { 1.1064 + ((BMMimeMultipart)headerAndBody).setInputStream(in); 1.1065 + ((BMMimeMultipart)headerAndBody).setBoundary( 1.1066 + ((BMMimeMultipart)multiPart).getBoundary()); 1.1067 + ((BMMimeMultipart)headerAndBody). 1.1068 + setLazyAttachments(lazyAttachments); 1.1069 + } 1.1070 + 1.1071 + } else { 1.1072 + headerAndBody = new MimeMultipart(); 1.1073 + headerAndBody.addBodyPart(mimeSoapPart); 1.1074 + 1.1075 + for (Iterator eachAttachement = getAttachments(); 1.1076 + eachAttachement.hasNext(); 1.1077 + ) { 1.1078 + headerAndBody.addBodyPart( 1.1079 + ((AttachmentPartImpl) eachAttachement.next()) 1.1080 + .getMimePart()); 1.1081 + } 1.1082 + } 1.1083 + 1.1084 + ContentType contentType = headerAndBody.getContentType(); 1.1085 + 1.1086 + ParameterList l = contentType.getParameterList(); 1.1087 + 1.1088 + // set content type depending on SOAP version 1.1089 + l.set("type", getExpectedContentType()); 1.1090 + l.set("boundary", contentType.getParameter("boundary")); 1.1091 + ContentType nct = new ContentType("multipart", "related", l); 1.1092 + 1.1093 + headers.setHeader( 1.1094 + "Content-Type", 1.1095 + convertToSingleLine(nct.toString())); 1.1096 + // TBD 1.1097 + // Set content length MIME header here. 1.1098 + 1.1099 + return headerAndBody; 1.1100 + } catch (SOAPException ex) { 1.1101 + throw ex; 1.1102 + } catch (Throwable ex) { 1.1103 + log.severe("SAAJ0538.soap.cannot.convert.msg.to.multipart.obj"); 1.1104 + throw new SOAPExceptionImpl( 1.1105 + "Unable to convert SOAP message into " 1.1106 + + "a MimeMultipart object", 1.1107 + ex); 1.1108 + } 1.1109 + } 1.1110 + 1.1111 + private String initCharset() { 1.1112 + 1.1113 + String charset = null; 1.1114 + 1.1115 + String[] cts = getMimeHeaders().getHeader("Content-Type"); 1.1116 + if ((cts != null) && (cts[0] != null)) { 1.1117 + charset = getCharsetString(cts[0]); 1.1118 + } 1.1119 + 1.1120 + if (charset == null) { 1.1121 + charset = (String) getProperty(CHARACTER_SET_ENCODING); 1.1122 + } 1.1123 + 1.1124 + if (charset != null) { 1.1125 + return charset; 1.1126 + } 1.1127 + 1.1128 + return "utf-8"; 1.1129 + } 1.1130 + 1.1131 + private String getCharsetString(String s) { 1.1132 + try { 1.1133 + int index = s.indexOf(";"); 1.1134 + if(index < 0) 1.1135 + return null; 1.1136 + ParameterList pl = new ParameterList(s.substring(index)); 1.1137 + return pl.get("charset"); 1.1138 + } catch(Exception e) { 1.1139 + return null; 1.1140 + } 1.1141 + } 1.1142 + 1.1143 + public void saveChanges() throws SOAPException { 1.1144 + 1.1145 + // suck in all the data from the attachments and have it 1.1146 + // ready for writing/sending etc. 1.1147 + 1.1148 + String charset = initCharset(); 1.1149 + 1.1150 + /*if (countAttachments() == 0) {*/ 1.1151 + int attachmentCount = (attachments == null) ? 0 : attachments.size(); 1.1152 + if (attachmentCount == 0) { 1.1153 + if (!switchOffBM && !switchOffLazyAttachment && 1.1154 + !attachmentsInitialized && (multiPart != null)) { 1.1155 + // so there might be attachments 1.1156 + attachmentCount = 1; 1.1157 + } 1.1158 + } 1.1159 + 1.1160 + try { 1.1161 + if ((attachmentCount == 0) && !hasXOPContent()) { 1.1162 + InputStream in; 1.1163 + try{ 1.1164 + /* 1.1165 + * Not sure why this is called getHeaderBytes(), but it actually 1.1166 + * returns the whole message as a byte stream. This stream could 1.1167 + * be either XML of Fast depending on the mode. 1.1168 + */ 1.1169 + in = getHeaderBytes(); 1.1170 + // no attachments, hence this property can be false 1.1171 + this.optimizeAttachmentProcessing = false; 1.1172 + if (SOAPPartImpl.lazyContentLength) { 1.1173 + inputStreamAfterSaveChanges = in; 1.1174 + } 1.1175 + } catch (IOException ex) { 1.1176 + log.severe("SAAJ0539.soap.cannot.get.header.stream"); 1.1177 + throw new SOAPExceptionImpl( 1.1178 + "Unable to get header stream in saveChanges: ", 1.1179 + ex); 1.1180 + } 1.1181 + 1.1182 + if (in instanceof ByteInputStream) { 1.1183 + ByteInputStream bIn = (ByteInputStream)in; 1.1184 + messageBytes = bIn.getBytes(); 1.1185 + messageByteCount = bIn.getCount(); 1.1186 + } 1.1187 + 1.1188 + setFinalContentType(charset); 1.1189 + /* 1.1190 + headers.setHeader( 1.1191 + "Content-Type", 1.1192 + getExpectedContentType() + 1.1193 + (isFastInfoset ? "" : "; charset=" + charset));*/ 1.1194 + if (messageByteCount > 0) { 1.1195 + headers.setHeader( 1.1196 + "Content-Length", 1.1197 + Integer.toString(messageByteCount)); 1.1198 + } 1.1199 + } else { 1.1200 + if(hasXOPContent()) 1.1201 + mmp = getXOPMessage(); 1.1202 + else 1.1203 + mmp = getMimeMessage(); 1.1204 + } 1.1205 + } catch (Throwable ex) { 1.1206 + log.severe("SAAJ0540.soap.err.saving.multipart.msg"); 1.1207 + throw new SOAPExceptionImpl( 1.1208 + "Error during saving a multipart message", 1.1209 + ex); 1.1210 + } 1.1211 + 1.1212 + // FIX ME -- SOAP Action replaced by Content-Type optional parameter action 1.1213 + /* 1.1214 + if(isCorrectSoapVersion(SOAP1_1_FLAG)) { 1.1215 + 1.1216 + String[] soapAction = headers.getHeader("SOAPAction"); 1.1217 + 1.1218 + if (soapAction == null || soapAction.length == 0) 1.1219 + headers.setHeader("SOAPAction", "\"\""); 1.1220 + 1.1221 + } 1.1222 + */ 1.1223 + 1.1224 + saved = true; 1.1225 + } 1.1226 + 1.1227 + private MimeMultipart getXOPMessage() throws SOAPException { 1.1228 + try { 1.1229 + MimeMultipart headerAndBody = new MimeMultipart(); 1.1230 + SOAPPartImpl soapPart = (SOAPPartImpl)getSOAPPart(); 1.1231 + MimeBodyPart mimeSoapPart = soapPart.getMimePart(); 1.1232 + ContentType soapPartCtype = 1.1233 + new ContentType("application/xop+xml"); 1.1234 + soapPartCtype.setParameter("type", getExpectedContentType()); 1.1235 + String charset = initCharset(); 1.1236 + soapPartCtype.setParameter("charset", charset); 1.1237 + mimeSoapPart.setHeader("Content-Type", soapPartCtype.toString()); 1.1238 + headerAndBody.addBodyPart(mimeSoapPart); 1.1239 + 1.1240 + for (Iterator eachAttachement = getAttachments(); 1.1241 + eachAttachement.hasNext(); 1.1242 + ) { 1.1243 + headerAndBody.addBodyPart( 1.1244 + ((AttachmentPartImpl) eachAttachement.next()) 1.1245 + .getMimePart()); 1.1246 + } 1.1247 + 1.1248 + ContentType contentType = headerAndBody.getContentType(); 1.1249 + 1.1250 + ParameterList l = contentType.getParameterList(); 1.1251 + 1.1252 + //lets not write start-info for now till we get servlet fix done 1.1253 + l.set("start-info", getExpectedContentType());//+";charset="+initCharset()); 1.1254 + 1.1255 + // set content type depending on SOAP version 1.1256 + l.set("type", "application/xop+xml"); 1.1257 + 1.1258 + if (isCorrectSoapVersion(SOAP1_2_FLAG)) { 1.1259 + String action = getAction(); 1.1260 + if(action != null) 1.1261 + l.set("action", action); 1.1262 + } 1.1263 + 1.1264 + l.set("boundary", contentType.getParameter("boundary")); 1.1265 + ContentType nct = new ContentType("Multipart", "Related", l); 1.1266 + headers.setHeader( 1.1267 + "Content-Type", 1.1268 + convertToSingleLine(nct.toString())); 1.1269 + // TBD 1.1270 + // Set content length MIME header here. 1.1271 + 1.1272 + return headerAndBody; 1.1273 + } catch (SOAPException ex) { 1.1274 + throw ex; 1.1275 + } catch (Throwable ex) { 1.1276 + log.severe("SAAJ0538.soap.cannot.convert.msg.to.multipart.obj"); 1.1277 + throw new SOAPExceptionImpl( 1.1278 + "Unable to convert SOAP message into " 1.1279 + + "a MimeMultipart object", 1.1280 + ex); 1.1281 + } 1.1282 + 1.1283 + } 1.1284 + 1.1285 + private boolean hasXOPContent() throws ParseException { 1.1286 + String type = getContentType(); 1.1287 + if(type == null) 1.1288 + return false; 1.1289 + ContentType ct = new ContentType(type); 1.1290 + //return isMimeMultipartXOPPackage(ct) || isSOAPBodyXOPPackage(ct); 1.1291 + return isMimeMultipartXOPSoap1_1Package(ct) || 1.1292 + isMimeMultipartXOPSoap1_2Package(ct) || isSOAPBodyXOPPackage(ct); 1.1293 + 1.1294 + } 1.1295 + 1.1296 + public void writeTo(OutputStream out) throws SOAPException, IOException { 1.1297 + if (saveRequired()){ 1.1298 + this.optimizeAttachmentProcessing = true; 1.1299 + saveChanges(); 1.1300 + } 1.1301 + 1.1302 + if(!optimizeAttachmentProcessing){ 1.1303 + if (SOAPPartImpl.lazyContentLength && messageByteCount <= 0) { 1.1304 + byte[] buf = new byte[1024]; 1.1305 + 1.1306 + int length = 0; 1.1307 + while( (length = inputStreamAfterSaveChanges.read(buf)) != -1) { 1.1308 + out.write(buf,0, length); 1.1309 + messageByteCount += length; 1.1310 + } 1.1311 + if (messageByteCount > 0) { 1.1312 + headers.setHeader( 1.1313 + "Content-Length", 1.1314 + Integer.toString(messageByteCount)); 1.1315 + } 1.1316 + } else { 1.1317 + out.write(messageBytes, 0, messageByteCount); 1.1318 + } 1.1319 + } 1.1320 + else{ 1.1321 + try{ 1.1322 + if(hasXOPContent()){ 1.1323 + mmp.writeTo(out); 1.1324 + }else{ 1.1325 + mmp.writeTo(out); 1.1326 + if (!switchOffBM && !switchOffLazyAttachment && 1.1327 + (multiPart != null) && !attachmentsInitialized) { 1.1328 + ((BMMimeMultipart)multiPart).setInputStream( 1.1329 + ((BMMimeMultipart)mmp).getInputStream()); 1.1330 + } 1.1331 + } 1.1332 + } catch(Exception ex){ 1.1333 + log.severe("SAAJ0540.soap.err.saving.multipart.msg"); 1.1334 + throw new SOAPExceptionImpl( 1.1335 + "Error during saving a multipart message", 1.1336 + ex); 1.1337 + } 1.1338 + } 1.1339 + 1.1340 + if(isCorrectSoapVersion(SOAP1_1_FLAG)) { 1.1341 + 1.1342 + String[] soapAction = headers.getHeader("SOAPAction"); 1.1343 + 1.1344 + if (soapAction == null || soapAction.length == 0) 1.1345 + headers.setHeader("SOAPAction", "\"\""); 1.1346 + 1.1347 + } 1.1348 + 1.1349 + messageBytes = null; 1.1350 + needsSave(); 1.1351 + } 1.1352 + 1.1353 + public SOAPBody getSOAPBody() throws SOAPException { 1.1354 + SOAPBody body = getSOAPPart().getEnvelope().getBody(); 1.1355 + /*if (body == null) { 1.1356 + throw new SOAPException("No SOAP Body was found in the SOAP Message"); 1.1357 + }*/ 1.1358 + return body; 1.1359 + } 1.1360 + 1.1361 + public SOAPHeader getSOAPHeader() throws SOAPException { 1.1362 + SOAPHeader hdr = getSOAPPart().getEnvelope().getHeader(); 1.1363 + /*if (hdr == null) { 1.1364 + throw new SOAPException("No SOAP Header was found in the SOAP Message"); 1.1365 + }*/ 1.1366 + return hdr; 1.1367 + } 1.1368 + 1.1369 + private void initializeAllAttachments () 1.1370 + throws MessagingException, SOAPException { 1.1371 + if (switchOffBM || switchOffLazyAttachment) { 1.1372 + return; 1.1373 + } 1.1374 + 1.1375 + if (attachmentsInitialized || (multiPart == null)) { 1.1376 + return; 1.1377 + } 1.1378 + 1.1379 + if (attachments == null) 1.1380 + attachments = new FinalArrayList(); 1.1381 + 1.1382 + int count = multiPart.getCount(); 1.1383 + for (int i=0; i < count; i++ ) { 1.1384 + initializeAttachment(multiPart.getBodyPart(i)); 1.1385 + } 1.1386 + attachmentsInitialized = true; 1.1387 + //multiPart = null; 1.1388 + needsSave(); 1.1389 + } 1.1390 + 1.1391 + private void initializeAttachment(MimeBodyPart mbp) throws SOAPException { 1.1392 + AttachmentPartImpl attachmentPart = new AttachmentPartImpl(); 1.1393 + DataHandler attachmentHandler = mbp.getDataHandler(); 1.1394 + attachmentPart.setDataHandler(attachmentHandler); 1.1395 + 1.1396 + AttachmentPartImpl.copyMimeHeaders(mbp, attachmentPart); 1.1397 + attachments.add(attachmentPart); 1.1398 + } 1.1399 + 1.1400 + private void initializeAttachment(MimeMultipart multiPart, int i) 1.1401 + throws Exception { 1.1402 + MimeBodyPart currentBodyPart = multiPart.getBodyPart(i); 1.1403 + AttachmentPartImpl attachmentPart = new AttachmentPartImpl(); 1.1404 + 1.1405 + DataHandler attachmentHandler = currentBodyPart.getDataHandler(); 1.1406 + attachmentPart.setDataHandler(attachmentHandler); 1.1407 + 1.1408 + AttachmentPartImpl.copyMimeHeaders(currentBodyPart, attachmentPart); 1.1409 + addAttachmentPart(attachmentPart); 1.1410 + } 1.1411 + 1.1412 + private void setMimeHeaders(SOAPPart soapPart, 1.1413 + MimeBodyPart soapMessagePart) throws Exception { 1.1414 + 1.1415 + // first remove the existing content-type 1.1416 + soapPart.removeAllMimeHeaders(); 1.1417 + // add everything present in soapMessagePart 1.1418 + List headers = soapMessagePart.getAllHeaders(); 1.1419 + int sz = headers.size(); 1.1420 + for( int i=0; i<sz; i++ ) { 1.1421 + Header h = (Header) headers.get(i); 1.1422 + soapPart.addMimeHeader(h.getName(), h.getValue()); 1.1423 + } 1.1424 + } 1.1425 + 1.1426 + private void initCharsetProperty(ContentType contentType) { 1.1427 + String charset = contentType.getParameter("charset"); 1.1428 + if (charset != null) { 1.1429 + ((SOAPPartImpl) getSOAPPart()).setSourceCharsetEncoding(charset); 1.1430 + if(!charset.equalsIgnoreCase("utf-8")) 1.1431 + setProperty(CHARACTER_SET_ENCODING, charset); 1.1432 + } 1.1433 + } 1.1434 + 1.1435 + public void setLazyAttachments(boolean flag) { 1.1436 + lazyAttachments = flag; 1.1437 + } 1.1438 + 1.1439 +}