Skip to content

Package: MessageImpl$1

MessageImpl$1

nameinstructionbranchcomplexitylinemethod
getContentType()
M: 4 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
getInputStream()
M: 0 C: 3
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
getName()
M: 2 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
getOutputStream()
M: 2 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
{...}
M: 0 C: 12
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%

Coverage

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