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.util.Iterator;
024    
025    /**
026     * <P>A single attachment to a <CODE>SOAPMessage</CODE> object. A
027     *   <CODE>SOAPMessage</CODE> object may contain zero, one, or many
028     *   <CODE>AttachmentPart</CODE> objects. Each <CODE>
029     *   AttachmentPart</CODE> object consists of two parts,
030     *   application-specific content and associated MIME headers. The
031     *   MIME headers consists of name/value pairs that can be used to
032     *   identify and describe the content.</P>
033     *
034     *   <P>An <CODE>AttachmentPart</CODE> object must conform to
035     *   certain standards.</P>
036     *
037     *   <OL>
038     *     <LI>It must conform to <A href=
039     *     "http://www.ietf.org/rfc/rfc2045.txt">MIME [RFC2045]
040     *     standards</A></LI>
041     *
042     *     <LI>It MUST contain content</LI>
043     *
044     *     <LI>
045     *       The header portion MUST include the following header:
046     *
047     *       <UL>
048     *         <LI>
049     *           <CODE>Content-Type</CODE><BR>
050     *            This header identifies the type of data in the content
051     *           of an <CODE>AttachmentPart</CODE> object and MUST
052     *           conform to [RFC2045]. The following is an example of a
053     *           Content-Type header:
054     * <PRE>
055     *      Content-Type:  application/xml
056     *
057     * </PRE>
058     *           The following line of code, in which <CODE>ap</CODE> is
059     *           an <CODE>AttachmentPart</CODE> object, sets the header
060     *           shown in the previous example.
061     * <PRE>
062     *      ap.setMimeHeader("Content-Type", "application/xml");
063     *
064     * </PRE>
065     *
066     *           <P></P>
067     *         </LI>
068     *       </UL>
069     *     </LI>
070     *   </OL>
071     *
072     *   <P>There are no restrictions on the content portion of an
073     *   <CODE>AttachmentPart</CODE> object. The content may be anything
074     *   from a simple plain text object to a complex XML document or
075     *   image file.</P>
076     *
077     *   <P>An <CODE>AttachmentPart</CODE> object is created with the
078     *   method <CODE>SOAPMessage.createAttachmentPart</CODE>. After
079     *   setting its MIME headers, the <CODE>AttachmentPart</CODE>
080     *   object is added to the message that created it with the method
081     *   <CODE>SOAPMessage.addAttachmentPart</CODE>.</P>
082     *
083     *   <P>The following code fragment, in which <CODE>m</CODE> is a
084     *   <CODE>SOAPMessage</CODE> object and <CODE>contentStringl</CODE>
085     *   is a <CODE>String</CODE>, creates an instance of <CODE>
086     *   AttachmentPart</CODE>, sets the <CODE>AttachmentPart</CODE>
087     *   object with some content and header information, and adds the
088     *   <CODE>AttachmentPart</CODE> object to the <CODE>
089     *   SOAPMessage</CODE> object.</P>
090     * <PRE>
091     *    AttachmentPart ap1 = m.createAttachmentPart();
092     *    ap1.setContent(contentString1, "text/plain");
093     *    m.addAttachmentPart(ap1);
094     * </PRE>
095     *
096     *   <P>The following code fragment creates and adds a second <CODE>
097     *   AttachmentPart</CODE> instance to the same message. <CODE>
098     *   jpegData</CODE> is a binary byte buffer representing the jpeg
099     *   file.</P>
100     * <PRE>
101     *    AttachmentPart ap2 = m.createAttachmentPart();
102     *    byte[] jpegData =  ...;
103     *    ap2.setContent(new ByteArrayInputStream(jpegData), "image/jpeg");
104     *    m.addAttachmentPart(ap2);
105     * </PRE>
106     *
107     *   <P>The <CODE>getContent</CODE> method retrieves the contents
108     *   and header from an <CODE>AttachmentPart</CODE> object.
109     *   Depending on the <CODE>DataContentHandler</CODE> objects
110     *   present, the returned <CODE>Object</CODE> can either be a typed
111     *   Java object corresponding to the MIME type or an <CODE>
112     *   InputStream</CODE> object that contains the content as
113     *   bytes.</P>
114     * <PRE>
115     *    String content1 = ap1.getContent();
116     *    java.io.InputStream content2 = ap2.getContent();
117     * </PRE>
118     *   The method <CODE>clearContent</CODE> removes all the content
119     *   from an <CODE>AttachmentPart</CODE> object but does not affect
120     *   its header information.
121     * <PRE>
122     *    ap1.clearContent();
123     * </PRE>
124     */
125    public abstract class AttachmentPart {
126    
127        // fixme: should this constructor be protected?
128        /** Create a new AttachmentPart. */
129        public AttachmentPart() {}
130    
131        /**
132         * Returns the number of bytes in this <CODE>
133         * AttachmentPart</CODE> object.
134         * @return the size of this <CODE>AttachmentPart</CODE> object
135         *     in bytes or -1 if the size cannot be determined
136         * @throws  SOAPException  if the content of this
137         *     attachment is corrupted of if there was an exception
138         *     while trying to determine the size.
139         */
140        public abstract int getSize() throws SOAPException;
141    
142        /**
143         * Clears out the content of this <CODE>
144         * AttachmentPart</CODE> object. The MIME header portion is left
145         * untouched.
146         */
147        public abstract void clearContent();
148    
149        /**
150         * Gets the content of this <code>AttachmentPart</code> object as a Java
151         * object. The type of the returned Java object depends on (1) the
152         * <code>DataContentHandler</code> object that is used to interpret the bytes
153         * and (2) the <code>Content-Type</code> given in the header.
154         * <p>
155         * For the MIME content types "text/plain", "text/html" and "text/xml", the
156         * <code>DataContentHandler</code> object does the conversions to and
157         * from the Java types corresponding to the MIME types.
158         * For other MIME types,the <code>DataContentHandler</code> object
159         * can return an <code>InputStream</code> object that contains the content data
160         * as raw bytes.
161         * <p>
162         * A JAXM-compliant implementation must, as a minimum, return a
163         * <code>java.lang.String</code> object corresponding to any content
164         * stream with a <code>Content-Type</code> value of
165         * <code>text/plain</code>, a
166         * <code>javax.xml.transform.StreamSource</code> object corresponding to a
167         * content stream with a <code>Content-Type</code> value of
168         * <code>text/xml</code>, a <code>java.awt.Image</code> object
169         * corresponding to a content stream with a
170         * <code>Content-Type</code> value of <code>image/gif</code> or
171         * <code>image/jpeg</code>.  For those content types that an
172         * installed <code>DataContentHandler</code> object does not understand, the
173         * <code>DataContentHandler</code> object is required to return a
174         * <code>java.io.InputStream</code> object with the raw bytes.
175         *
176         * @return a Java object with the content of this <CODE>
177         *     AttachmentPart</CODE> object
178         * @throws  SOAPException  if there is no content set
179         *     into this <CODE>AttachmentPart</CODE> object or if there
180         *     was a data transformation error
181         */
182        public abstract Object getContent() throws SOAPException;
183    
184        /**
185         * Sets the content of this attachment part to that of the
186         * given <CODE>Object</CODE> and sets the value of the <CODE>
187         * Content-Type</CODE> header to the given type. The type of the
188         * <CODE>Object</CODE> should correspond to the value given for
189         * the <CODE>Content-Type</CODE>. This depends on the particular
190         * set of <CODE>DataContentHandler</CODE> objects in use.
191         * @param  object  the Java object that makes up
192         * the content for this attachment part
193         * @param  contentType the MIME string that
194         * specifies the type of the content
195         * @throws java.lang.IllegalArgumentException if
196         *     the contentType does not match the type of the content
197         *     object, or if there was no <CODE>
198         *     DataContentHandler</CODE> object for this content
199         *     object
200         * @see #getContent() getContent()
201         */
202        public abstract void setContent(Object object, String contentType);
203    
204        /**
205         * Gets the <CODE>DataHandler</CODE> object for this <CODE>
206         * AttachmentPart</CODE> object.
207         * @return the <CODE>DataHandler</CODE> object associated with
208         *     this <CODE>AttachmentPart</CODE> object
209         * @throws  SOAPException  if there is
210         *     no data in this <CODE>AttachmentPart</CODE> object
211         */
212        public abstract DataHandler getDataHandler() throws SOAPException;
213    
214        /**
215         * Sets the given <CODE>DataHandler</CODE> object as the
216         * data handler for this <CODE>AttachmentPart</CODE> object.
217         * Typically, on an incoming message, the data handler is
218         * automatically set. When a message is being created and
219         * populated with content, the <CODE>setDataHandler</CODE>
220         * method can be used to get data from various data sources into
221         * the message.
222         * @param  datahandler  <CODE>DataHandler</CODE> object to
223         *     be set
224         * @throws java.lang.IllegalArgumentException if
225         *     there was a problem with the specified <CODE>
226         *     DataHandler</CODE> object
227         */
228        public abstract void setDataHandler(DataHandler datahandler);
229    
230        /**
231         * Gets the value of the MIME header whose name is
232         * "Content-Id".
233         * @return  a <CODE>String</CODE> giving the value of the
234         *     "Content-Id" header or <CODE>null</CODE> if there is
235         *     none
236         * @see #setContentId(java.lang.String) setContentId(java.lang.String)
237         */
238        public String getContentId() {
239    
240            String as[] = getMimeHeader("Content-Id");
241    
242            if (as != null && as.length > 0) {
243                return as[0];
244            } else {
245                return null;
246            }
247        }
248    
249        /**
250         * Gets the value of the MIME header
251         * "Content-Location".
252         * @return  a <CODE>String</CODE> giving the value of the
253         *     "Content-Location" header or <CODE>null</CODE> if there
254         *     is none
255         */
256        public String getContentLocation() {
257    
258            String as[] = getMimeHeader("Content-Location");
259    
260            if (as != null && as.length > 0) {
261                return as[0];
262            } else {
263                return null;
264            }
265        }
266    
267        /**
268         * Gets the value of the MIME header "Content-Type".
269         * @return  a <CODE>String</CODE> giving the value of the
270         *     "Content-Type" header or <CODE>null</CODE> if there is
271         *     none
272         */
273        public String getContentType() {
274    
275            String as[] = getMimeHeader("Content-Type");
276    
277            if (as != null && as.length > 0) {
278                return as[0];
279            } else {
280                return null;
281            }
282        }
283    
284        /**
285         * Sets the MIME header "Content-Id" with the given
286         * value.
287         * @param  contentId a <CODE>String</CODE> giving
288         *     the value of the "Content-Id" header
289         * @throws java.lang.IllegalArgumentException if
290         *     there was a problem with the specified <CODE>
291         *     contentId</CODE> value
292         * @see #getContentId() getContentId()
293         */
294        public void setContentId(String contentId) {
295            setMimeHeader("Content-Id", contentId);
296        }
297    
298        /**
299         * Sets the MIME header "Content-Location" with the given
300         * value.
301         * @param  contentLocation a <CODE>String</CODE>
302         *     giving the value of the "Content-Location" header
303         * @throws java.lang.IllegalArgumentException if
304         *     there was a problem with the specified content
305         *     location
306         */
307        public void setContentLocation(String contentLocation) {
308            setMimeHeader("Content-Location", contentLocation);
309        }
310    
311        /**
312         * Sets the MIME header "Content-Type" with the given
313         * value.
314         * @param  contentType  a <CODE>String</CODE>
315         *     giving the value of the "Content-Type" header
316         * @throws java.lang.IllegalArgumentException if
317         * there was a problem with the specified content type
318         */
319        public void setContentType(String contentType) {
320            setMimeHeader("Content-Type", contentType);
321        }
322    
323        /**
324         * Removes all MIME headers that match the given name.
325         * @param  header - the string name of the MIME
326         *     header/s to be removed
327         */
328        public abstract void removeMimeHeader(String header);
329    
330        /** Removes all the MIME header entries. */
331        public abstract void removeAllMimeHeaders();
332    
333        /**
334         * Gets all the values of the header identified by the given
335         * <CODE>String</CODE>.
336         * @param   name  the name of the header; example:
337         *     "Content-Type"
338         * @return a <CODE>String</CODE> array giving the value for the
339         *     specified header
340         * @see #setMimeHeader(java.lang.String, java.lang.String) setMimeHeader(java.lang.String, java.lang.String)
341         */
342        public abstract String[] getMimeHeader(String name);
343    
344        /**
345         * Changes the first header entry that matches the given name
346         *   to the given value, adding a new header if no existing
347         *   header matches. This method also removes all matching
348         *   headers but the first.
349         *
350         *   <P>Note that RFC822 headers can only contain US-ASCII
351         *   characters.</P>
352         * @param  name   a <CODE>String</CODE> giving the
353         *     name of the header for which to search
354         * @param  value  a <CODE>String</CODE> giving the
355         *     value to be set for the header whose name matches the
356         *     given name
357         * @throws java.lang.IllegalArgumentException if
358         *     there was a problem with the specified mime header name
359         *     or value
360         */
361        public abstract void setMimeHeader(String name, String value);
362    
363        /**
364         * Adds a MIME header with the specified name and value to
365         *   this <CODE>AttachmentPart</CODE> object.
366         *
367         *   <P>Note that RFC822 headers can contain only US-ASCII
368         *   characters.</P>
369         * @param  name   a <CODE>String</CODE> giving the
370         *     name of the header to be added
371         * @param  value  a <CODE>String</CODE> giving the
372         *     value of the header to be added
373         * @throws java.lang.IllegalArgumentException if
374         *     there was a problem with the specified mime header name
375         *     or value
376         */
377        public abstract void addMimeHeader(String name, String value);
378    
379        /**
380         * Retrieves all the headers for this <CODE>
381         * AttachmentPart</CODE> object as an iterator over the <CODE>
382         * MimeHeader</CODE> objects.
383         * @return  an <CODE>Iterator</CODE> object with all of the Mime
384         *     headers for this <CODE>AttachmentPart</CODE> object
385         */
386        public abstract Iterator getAllMimeHeaders();
387    
388        /**
389         * Retrieves all <CODE>MimeHeader</CODE> objects that match
390         * a name in the given array.
391         * @param   names a <CODE>String</CODE> array with
392         *     the name(s) of the MIME headers to be returned
393         * @return all of the MIME headers that match one of the names
394         *     in the given array as an <CODE>Iterator</CODE>
395         *     object
396         */
397        public abstract Iterator getMatchingMimeHeaders(String names[]);
398    
399        /**
400         * Retrieves all <CODE>MimeHeader</CODE> objects whose name
401         * does not match a name in the given array.
402         * @param   names  a <CODE>String</CODE> array with
403         *     the name(s) of the MIME headers not to be returned
404         * @return all of the MIME headers in this <CODE>
405         *     AttachmentPart</CODE> object except those that match one
406         *     of the names in the given array. The nonmatching MIME
407         *     headers are returned as an <CODE>Iterator</CODE>
408         *     object.
409         */
410        public abstract Iterator getNonMatchingMimeHeaders(String names[]);
411    }