001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  You may obtain a copy of the License at
009     *
010     *  http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing,
013     * software distributed under the License is distributed on an
014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     * KIND, either express or implied.  See the License for the
016     * specific language governing permissions and limitations
017     * under the License.
018     */
019    
020    package javax.xml.soap;
021    
022    import javax.activation.DataHandler;
023    import java.io.IOException;
024    import java.io.OutputStream;
025    import java.util.Iterator;
026    
027    /**
028     * <P>The root class for all SOAP messages. As transmitted on the
029     * "wire", a SOAP message is an XML document or a MIME message
030     * whose first body part is an XML/SOAP document.</P>
031     *
032     * <P>A <CODE>SOAPMessage</CODE> object consists of a SOAP part
033     * and optionally one or more attachment parts. The SOAP part for
034     * a <CODE>SOAPMessage</CODE> object is a <CODE>SOAPPart</CODE>
035     * object, which contains information used for message routing and
036     * identification, and which can contain application-specific
037     * content. All data in the SOAP Part of a message must be in XML
038     * format.</P>
039     *
040     * <P>A new <CODE>SOAPMessage</CODE> object contains the following
041     * by default:</P>
042     *
043     * <UL>
044     *  <LI>A <CODE>SOAPPart</CODE> object</LI>
045     *
046     *  <LI>A <CODE>SOAPEnvelope</CODE> object</LI>
047     *
048     *  <LI>A <CODE>SOAPBody</CODE> object</LI>
049     *
050     *  <LI>A <CODE>SOAPHeader</CODE> object</LI>
051     * </UL>
052     * The SOAP part of a message can be retrieved by calling the
053     * method <CODE>SOAPMessage.getSOAPPart()</CODE>. The <CODE>
054     * SOAPEnvelope</CODE> object is retrieved from the <CODE>
055     * SOAPPart</CODE> object, and the <CODE>SOAPEnvelope</CODE>
056     * object is used to retrieve the <CODE>SOAPBody</CODE> and <CODE>
057     * SOAPHeader</CODE> objects.
058     * <PRE>
059     * SOAPPart sp = message.getSOAPPart();
060     * SOAPEnvelope se = sp.getEnvelope();
061     * SOAPBody sb = se.getBody();
062     * SOAPHeader sh = se.getHeader();
063     * </PRE>
064     *
065     * <P>In addition to the mandatory <CODE>SOAPPart</CODE> object, a
066     * <CODE>SOAPMessage</CODE> object may contain zero or more <CODE>
067     * AttachmentPart</CODE> objects, each of which contains
068     * application-specific data. The <CODE>SOAPMessage</CODE>
069     * interface provides methods for creating <CODE>
070     * AttachmentPart</CODE> objects and also for adding them to a
071     * <CODE>SOAPMessage</CODE> object. A party that has received a
072     * <CODE>SOAPMessage</CODE> object can examine its contents by
073     * retrieving individual attachment parts.</P>
074     *
075     * <P>Unlike the rest of a SOAP message, an attachment is not
076     * required to be in XML format and can therefore be anything from
077     * simple text to an image file. Consequently, any message content
078     * that is not in XML format must be in an <CODE>
079     * AttachmentPart</CODE> object.</P>
080     *
081     * <P>A <CODE>MessageFactory</CODE> object creates new <CODE>
082     * SOAPMessage</CODE> objects. If the <CODE>MessageFactory</CODE>
083     * object was initialized with a messaging Profile, it produces
084     * <CODE>SOAPMessage</CODE> objects that conform to that Profile.
085     * For example, a <CODE>SOAPMessage</CODE> object created by a
086     * <CODE>MessageFactory</CODE> object initialized with the ebXML
087     * Profile will have the appropriate ebXML headers.</P>
088     * @see MessageFactory MessageFactory
089     * @see AttachmentPart AttachmentPart
090     */
091    public abstract class SOAPMessage {
092    
093        public SOAPMessage() {}
094    
095        /**
096         * Retrieves a description of this <CODE>SOAPMessage</CODE>
097         * object's content.
098         * @return  a <CODE>String</CODE> describing the content of this
099         *     message or <CODE>null</CODE> if no description has been
100         *     set
101         * @see #setContentDescription(java.lang.String) setContentDescription(java.lang.String)
102         */
103        public abstract String getContentDescription();
104    
105        /**
106         * Sets the description of this <CODE>SOAPMessage</CODE>
107         * object's content with the given description.
108         * @param  description a <CODE>String</CODE>
109         *     describing the content of this message
110         * @see #getContentDescription() getContentDescription()
111         */
112        public abstract void setContentDescription(String description);
113    
114        /**
115         * Gets the SOAP part of this <CODE>SOAPMessage</CODE> object.
116         *
117         *
118         *   <P>If a <CODE>SOAPMessage</CODE> object contains one or
119         *   more attachments, the SOAP Part must be the first MIME body
120         *   part in the message.</P>
121         * @return the <CODE>SOAPPart</CODE> object for this <CODE>
122         *     SOAPMessage</CODE> object
123         */
124        public abstract SOAPPart getSOAPPart();
125    
126        /**
127         * Removes all <CODE>AttachmentPart</CODE> objects that have
128         *   been added to this <CODE>SOAPMessage</CODE> object.
129         *
130         *   <P>This method does not touch the SOAP part.</P>
131         */
132        public abstract void removeAllAttachments();
133    
134        /**
135         * Gets a count of the number of attachments in this
136         * message. This count does not include the SOAP part.
137         * @return  the number of <CODE>AttachmentPart</CODE> objects
138         *     that are part of this <CODE>SOAPMessage</CODE>
139         *     object
140         */
141        public abstract int countAttachments();
142    
143        /**
144         * Retrieves all the <CODE>AttachmentPart</CODE> objects
145         * that are part of this <CODE>SOAPMessage</CODE> object.
146         * @return  an iterator over all the attachments in this
147         *     message
148         */
149        public abstract Iterator getAttachments();
150    
151        /**
152         * Retrieves all the <CODE>AttachmentPart</CODE> objects
153         * that have header entries that match the specified headers.
154         * Note that a returned attachment could have headers in
155         * addition to those specified.
156         * @param   headers a <CODE>MimeHeaders</CODE>
157         *     object containing the MIME headers for which to
158         *     search
159         * @return an iterator over all attachments that have a header
160         *     that matches one of the given headers
161         */
162        public abstract Iterator getAttachments(MimeHeaders headers);
163    
164        /**
165         * Adds the given <CODE>AttachmentPart</CODE> object to this
166         * <CODE>SOAPMessage</CODE> object. An <CODE>
167         * AttachmentPart</CODE> object must be created before it can be
168         * added to a message.
169         * @param  attachmentpart an <CODE>
170         *     AttachmentPart</CODE> object that is to become part of
171         *     this <CODE>SOAPMessage</CODE> object
172         * @throws java.lang.IllegalArgumentException
173         */
174        public abstract void addAttachmentPart(AttachmentPart attachmentpart);
175    
176        /**
177         * Creates a new empty <CODE>AttachmentPart</CODE> object.
178         * Note that the method <CODE>addAttachmentPart</CODE> must be
179         * called with this new <CODE>AttachmentPart</CODE> object as
180         * the parameter in order for it to become an attachment to this
181         * <CODE>SOAPMessage</CODE> object.
182         * @return  a new <CODE>AttachmentPart</CODE> object that can be
183         *     populated and added to this <CODE>SOAPMessage</CODE>
184         *     object
185         */
186        public abstract AttachmentPart createAttachmentPart();
187    
188        /**
189         * Creates an <CODE>AttachmentPart</CODE> object and
190         * populates it using the given <CODE>DataHandler</CODE>
191         * object.
192         * @param   datahandler  the <CODE>
193         *     javax.activation.DataHandler</CODE> object that will
194         *     generate the content for this <CODE>SOAPMessage</CODE>
195         *     object
196         * @return a new <CODE>AttachmentPart</CODE> object that
197         *     contains data generated by the given <CODE>
198         *     DataHandler</CODE> object
199         * @throws java.lang.IllegalArgumentException if
200         *     there was a problem with the specified <CODE>
201         *     DataHandler</CODE> object
202         * @see DataHandler DataHandler
203         * @see javax.activation.DataContentHandler DataContentHandler
204         */
205        public AttachmentPart createAttachmentPart(DataHandler datahandler) {
206    
207            AttachmentPart attachmentpart = createAttachmentPart();
208    
209            attachmentpart.setDataHandler(datahandler);
210    
211            return attachmentpart;
212        }
213    
214        /**
215         * Returns all the transport-specific MIME headers for this
216         * <CODE>SOAPMessage</CODE> object in a transport-independent
217         * fashion.
218         * @return a <CODE>MimeHeaders</CODE> object containing the
219         *     <CODE>MimeHeader</CODE> objects
220         */
221        public abstract MimeHeaders getMimeHeaders();
222    
223        /**
224         * Creates an <CODE>AttachmentPart</CODE> object and
225         * populates it with the specified data of the specified content
226         * type.
227         * @param   content  an <CODE>Object</CODE>
228         *     containing the content for this <CODE>SOAPMessage</CODE>
229         *     object
230         * @param   contentType a <CODE>String</CODE>
231         *     object giving the type of content; examples are
232         *     "text/xml", "text/plain", and "image/jpeg"
233         * @return a new <CODE>AttachmentPart</CODE> object that
234         *     contains the given data
235         * @throws java.lang.IllegalArgumentException if the contentType does not match the type of the content
236         *     object, or if there was no <CODE>
237         *     DataContentHandler</CODE> object for the given content
238         *     object
239         * @see DataHandler DataHandler
240         * @see javax.activation.DataContentHandler DataContentHandler
241         */
242        public AttachmentPart createAttachmentPart(Object content,
243                                                   String contentType) {
244    
245            AttachmentPart attachmentpart = createAttachmentPart();
246    
247            attachmentpart.setContent(content, contentType);
248    
249            return attachmentpart;
250        }
251    
252        /**
253         * Updates this <CODE>SOAPMessage</CODE> object with all the
254         *   changes that have been made to it. This method is called
255         *   automatically when a message is sent or written to by the
256         *   methods <CODE>ProviderConnection.send</CODE>, <CODE>
257         *   SOAPConnection.call</CODE>, or <CODE>
258         *   SOAPMessage.writeTo</CODE>. However, if changes are made to
259         *   a message that was received or to one that has already been
260         *   sent, the method <CODE>saveChanges</CODE> needs to be
261         *   called explicitly in order to save the changes. The method
262         *   <CODE>saveChanges</CODE> also generates any changes that
263         *   can be read back (for example, a MessageId in profiles that
264         *   support a message id). All MIME headers in a message that
265         *   is created for sending purposes are guaranteed to have
266         *   valid values only after <CODE>saveChanges</CODE> has been
267         *   called.
268         *
269         *   <P>In addition, this method marks the point at which the
270         *   data from all constituent <CODE>AttachmentPart</CODE>
271         *   objects are pulled into the message.</P>
272         * @throws  SOAPException if there
273         *     was a problem saving changes to this message.
274         */
275        public abstract void saveChanges() throws SOAPException;
276    
277        /**
278         * Indicates whether this <CODE>SOAPMessage</CODE> object
279         * has had the method <CODE>saveChanges</CODE> called on
280         * it.
281         * @return <CODE>true</CODE> if <CODE>saveChanges</CODE> has
282         *     been called on this message at least once; <CODE>
283         *     false</CODE> otherwise.
284         */
285        public abstract boolean saveRequired();
286    
287        /**
288         * Writes this <CODE>SOAPMessage</CODE> object to the given
289         *   output stream. The externalization format is as defined by
290         *   the SOAP 1.1 with Attachments specification.
291         *
292         *   <P>If there are no attachments, just an XML stream is
293         *   written out. For those messages that have attachments,
294         *   <CODE>writeTo</CODE> writes a MIME-encoded byte stream.</P>
295         * @param   out the <CODE>OutputStream</CODE>
296         *     object to which this <CODE>SOAPMessage</CODE> object will
297         *     be written
298         * @throws  SOAPException  if there was a problem in
299         *     externalizing this SOAP message
300         * @throws  IOException  if an I/O error
301         *     occurs
302         */
303        public abstract void writeTo(OutputStream out)
304            throws SOAPException, IOException;
305    
306        /**
307         * Gets the SOAP Body contained in this <code>SOAPMessage</code> object.
308         *
309         * @return the <code>SOAPBody</code> object contained by this
310         *              <code>SOAPMessage</code> object
311         * @throws SOAPException if the SOAP Body does not exist or cannot be
312         *              retrieved
313         */
314        public SOAPBody getSOAPBody() throws SOAPException {
315            throw new UnsupportedOperationException("getSOAPBody must be overridden in subclasses of SOAPMessage");        
316        }
317    
318        /**
319         * Gets the SOAP Header contained in this <code>SOAPMessage</code> object.
320         *
321         * @return the <code>SOAPHeader</code> object contained by this
322         *              <code>SOAPMessage</code> object
323         * @throws SOAPException  if the SOAP Header does not exist or cannot be
324         *              retrieved
325         */
326        public SOAPHeader getSOAPHeader() throws SOAPException {
327            throw new UnsupportedOperationException("getSOAPHeader must be overridden in subclasses of SOAPMessage");        
328        }
329    
330        /**
331         * Associates the specified value with the specified property. If there was
332         * already a value associated with this property, the old value is replaced.
333         * <p>
334         * The valid property names include <code>WRITE_XML_DECLARATION</code> and
335         * <code>CHARACTER_SET_ENCODING</code>. All of these standard SAAJ
336         * properties are prefixed by "javax.xml.soap". Vendors may also add
337         * implementation specific properties. These properties must be prefixed
338         * with package names that are unique to the vendor.
339         * <p>
340         * Setting the property <code>WRITE_XML_DECLARATION</code> to
341         * <code>"true"</code> will cause an XML Declaration to be written out at
342         * the start of the SOAP message. The default value of "false" suppresses
343         * this declaration.
344         * <p>
345         * The property <code>CHARACTER_SET_ENCODING</code> defaults to the value
346         * <code>"utf-8"</code> which causes the SOAP message to be encoded using
347         * UTF-8. Setting <code>CHARACTER_SET_ENCODING</code> to
348         * <code>"utf-16"</code> causes the SOAP message to be encoded using UTF-16.
349         * <p>
350         * Some implementations may allow encodings in addition to UTF-8 and UTF-16.
351         * Refer to your vendor's documentation for details.
352         *
353         * @param property the property with which the specified value is to be
354         *              associated
355         * @param value the value to be associated with the specified property
356         * @throws SOAPException if the property name is not recognized
357         */
358        public void setProperty(String property, Object value)
359                throws SOAPException  {
360            throw new UnsupportedOperationException("setProperty must be overridden in subclasses of SOAPMessage");        
361        }
362    
363        /**
364         * Retrieves value of the specified property.
365         *
366         * @param property the name of the property to retrieve
367         * @return the value of the property or <code>null</code> if no such
368         *              property exists
369         * @throws SOAPException  if the property name is not recognized
370         */
371        public Object getProperty(String property) throws SOAPException {
372            throw new UnsupportedOperationException("getProperty must be overridden in subclasses of SOAPMessage");        
373        }
374    
375        /** Specifies the character type encoding for the SOAP Message. */
376        public static final String CHARACTER_SET_ENCODING
377                = "javax.xml.soap.character-set-encoding";
378    
379        /** Specifies whether the SOAP Message should contain an XML declaration. */
380        public static final String WRITE_XML_DECLARATION
381                = "javax.xml.soap.write-xml-declaration";
382    }