KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > axis > attachments > AttachmentPart


1 /*
2  * Copyright 2001-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.axis.attachments;
17
18 import org.apache.axis.Part;
19 import org.apache.axis.components.logger.LogFactory;
20 import org.apache.axis.components.image.ImageIOFactory;
21 import org.apache.axis.transport.http.HTTPConstants;
22 import org.apache.axis.utils.Messages;
23 import org.apache.axis.utils.SessionUtils;
24 import org.apache.axis.utils.IOUtils;
25 import org.apache.commons.logging.Log;
26
27 import javax.activation.DataHandler JavaDoc;
28 import javax.xml.soap.SOAPException JavaDoc;
29 import javax.xml.transform.stream.StreamSource JavaDoc;
30 import java.util.Iterator JavaDoc;
31 import java.io.ByteArrayOutputStream JavaDoc;
32 import java.io.File JavaDoc;
33 import java.io.InputStream JavaDoc;
34
35 /**
36  * An attachment part.
37  *
38  *
39  */

40 public class AttachmentPart extends javax.xml.soap.AttachmentPart JavaDoc
41         implements Part {
42
43     /** Field log */
44     protected static Log log =
45             LogFactory.getLog(AttachmentPart.class.getName());
46
47     /**
48      * The data handler.
49      * <p>
50      * TODO: make private?
51      * */

52     javax.activation.DataHandler JavaDoc datahandler = null;
53
54     /** Field mimeHeaders. */
55     private javax.xml.soap.MimeHeaders JavaDoc mimeHeaders =
56             new javax.xml.soap.MimeHeaders JavaDoc();
57
58     private Object JavaDoc contentObject;
59
60     /**
61      * The name of a file used to store the data.
62      */

63     private String JavaDoc attachmentFile;
64
65     /**
66      * Bulds a new <code>AttachmentPart</code>.
67      */

68     public AttachmentPart() {
69         setMimeHeader(HTTPConstants.HEADER_CONTENT_ID, SessionUtils.generateSessionId());
70     }
71
72     /**
73      * Bulds a new <code>AttachmentPart</code> with a <code>DataHandler</code>.
74      *
75      * @param dh the <code>DataHandler</code>
76      */

77     public AttachmentPart(javax.activation.DataHandler JavaDoc dh) {
78         setMimeHeader(HTTPConstants.HEADER_CONTENT_ID,
79                 SessionUtils.generateSessionId());
80         datahandler = dh;
81         if(dh != null) {
82             setMimeHeader(HTTPConstants.HEADER_CONTENT_TYPE, dh.getContentType());
83         javax.activation.DataSource JavaDoc ds = dh.getDataSource();
84         if (ds instanceof ManagedMemoryDataSource) {
85         extractFilename((ManagedMemoryDataSource)ds); //and get the filename if appropriate
86

87         }
88         }
89     }
90
91     // fixme: be aware, this may never be called
92
/**
93      * On death, we clean up our file.
94      *
95      * @throws Throwable if anything went wrong during finalization
96      */

97     protected void finalize() throws Throwable JavaDoc {
98         dispose();
99     }
100
101     /**
102      * Get the data handler.
103      *
104      * @return the activation <code>DataHandler</code>
105      */

106     public javax.activation.DataHandler JavaDoc getActivationDataHandler() {
107         return datahandler;
108     }
109
110     /**
111      * getContentType
112      *
113      * @return content type
114      */

115     public String JavaDoc getContentType() {
116         return getFirstMimeHeader(HTTPConstants.HEADER_CONTENT_TYPE);
117     }
118
119     /**
120      * Add the specified MIME header, as per JAXM.
121      *
122      * @param header
123      * @param value
124      */

125     public void addMimeHeader(String JavaDoc header, String JavaDoc value) {
126         mimeHeaders.addHeader(header, value);
127     }
128
129     /**
130      * Get the specified MIME header.
131      *
132      * @param header
133      *
134      * @return
135      */

136     public String JavaDoc getFirstMimeHeader(String JavaDoc header) {
137         String JavaDoc[] values = mimeHeaders.getHeader(header.toLowerCase());
138         if ((values != null) && (values.length > 0)) {
139             return values[0];
140         }
141         return null;
142     }
143
144     /**
145      * check if this Part's mimeheaders matches the one passed in.
146      * TODO: Am not sure about the logic.
147      *
148      * @param headers the <code>MimeHeaders</code> to check
149      * @return true if all header name, values in <code>headers</code> are
150      * found, false otherwise
151      */

152     public boolean matches(javax.xml.soap.MimeHeaders JavaDoc headers) {
153         for (Iterator JavaDoc i = headers.getAllHeaders(); i.hasNext();) {
154             javax.xml.soap.MimeHeader JavaDoc hdr = (javax.xml.soap.MimeHeader JavaDoc) i.next();
155             String JavaDoc values[] = mimeHeaders.getHeader(hdr.getName());
156             boolean found = false;
157             if (values != null) {
158                 for (int j = 0; j < values.length; j++) {
159                     if (!hdr.getValue().equalsIgnoreCase(values[j])) {
160                         continue;
161                     }
162                     found = true;
163                     break;
164                 }
165             }
166             if (!found) {
167                 return false;
168             }
169         }
170         return true;
171     }
172
173     public String JavaDoc getContentLocation() {
174         return getFirstMimeHeader(HTTPConstants.HEADER_CONTENT_LOCATION);
175     }
176
177     public void setContentLocation(String JavaDoc loc) {
178         setMimeHeader(HTTPConstants.HEADER_CONTENT_LOCATION, loc);
179     }
180
181     public void setContentId(String JavaDoc newCid) {
182         setMimeHeader(HTTPConstants.HEADER_CONTENT_ID, newCid);
183     }
184
185     public String JavaDoc getContentId() {
186         return getFirstMimeHeader(HTTPConstants.HEADER_CONTENT_ID);
187     }
188
189     public java.util.Iterator JavaDoc getMatchingMimeHeaders(final String JavaDoc[] match) {
190         return mimeHeaders.getMatchingHeaders(match);
191     }
192
193     public java.util.Iterator JavaDoc getNonMatchingMimeHeaders(final String JavaDoc[] match) {
194         return mimeHeaders.getNonMatchingHeaders(match);
195     }
196
197     public Iterator JavaDoc getAllMimeHeaders() {
198         return mimeHeaders.getAllHeaders();
199     }
200
201     /**
202      * Changes the first header entry that matches the given name
203      * to the given value, adding a new header if no existing
204      * header matches. This method also removes all matching
205      * headers but the first.
206      *
207      * <P>Note that RFC822 headers can only contain US-ASCII
208      * characters.</P>
209      * @param name a <CODE>String</CODE> giving the
210      * name of the header for which to search
211      * @param value a <CODE>String</CODE> giving the
212      * value to be set for the header whose name matches the
213      * given name
214      * @throws java.lang.IllegalArgumentException if
215      * there was a problem with the specified mime header name
216      * or value
217      */

218     public void setMimeHeader(String JavaDoc name, String JavaDoc value) {
219         mimeHeaders.setHeader(name, value);
220     }
221
222     /** Removes all the MIME header entries. */
223     public void removeAllMimeHeaders() {
224         mimeHeaders.removeAllHeaders();
225     }
226
227     /**
228      * Removes all MIME headers that match the given name.
229      * @param header - the string name of the MIME
230      * header/s to be removed
231      */

232     public void removeMimeHeader(String JavaDoc header) {
233         mimeHeaders.removeHeader(header);
234     }
235
236     /**
237      * Gets the <CODE>DataHandler</CODE> object for this <CODE>
238      * AttachmentPart</CODE> object.
239      * @return the <CODE>DataHandler</CODE> object associated with
240      * this <CODE>AttachmentPart</CODE> object
241      * @throws SOAPException if there is
242      * no data in this <CODE>AttachmentPart</CODE> object
243      */

244     public DataHandler JavaDoc getDataHandler() throws SOAPException JavaDoc {
245         if(datahandler == null) {
246             throw new SOAPException JavaDoc(Messages.getMessage("noContent"));
247         }
248         return datahandler;
249     }
250
251     /**
252      * Sets the given <CODE>DataHandler</CODE> object as the
253      * data handler for this <CODE>AttachmentPart</CODE> object.
254      * Typically, on an incoming message, the data handler is
255      * automatically set. When a message is being created and
256      * populated with content, the <CODE>setDataHandler</CODE>
257      * method can be used to get data from various data sources into
258      * the message.
259      * @param datahandler <CODE>DataHandler</CODE> object to
260      * be set
261      * @throws java.lang.IllegalArgumentException if
262      * there was a problem with the specified <CODE>
263      * DataHandler</CODE> object
264      */

265     public void setDataHandler(DataHandler JavaDoc datahandler) {
266         if(datahandler == null) {
267             throw new java.lang.IllegalArgumentException JavaDoc(
268                 Messages.getMessage("illegalArgumentException00"));
269         }
270         this.datahandler = datahandler;
271         setMimeHeader(HTTPConstants.HEADER_CONTENT_TYPE, datahandler.getContentType());
272         //now look at the source of the data
273
javax.activation.DataSource JavaDoc ds = datahandler.getDataSource();
274         if (ds instanceof ManagedMemoryDataSource) {
275             //and get the filename if appropriate
276
extractFilename((ManagedMemoryDataSource)ds);
277         }
278
279
280     }
281
282     /**
283      * Gets the content of this <CODE>AttachmentPart</CODE> object
284      * as a Java object. The type of the returned Java object
285      * depends on (1) the <CODE>DataContentHandler</CODE> object
286      * that is used to interpret the bytes and (2) the <CODE>
287      * Content-Type</CODE> given in the header.
288      *
289      * <P>For the MIME content types "text/plain", "text/html" and
290      * "text/xml", the <CODE>DataContentHandler</CODE> object does
291      * the conversions to and from the Java types corresponding to
292      * the MIME types. For other MIME types,the <CODE>
293      * DataContentHandler</CODE> object can return an <CODE>
294      * InputStream</CODE> object that contains the content data as
295      * raw bytes.</P>
296      *
297      * <P>A JAXM-compliant implementation must, as a minimum,
298      * return a <CODE>java.lang.String</CODE> object corresponding
299      * to any content stream with a <CODE>Content-Type</CODE>
300      * value of <CODE>text/plain</CODE> and a <CODE>
301      * javax.xml.transform.StreamSource</CODE> object
302      * corresponding to a content stream with a <CODE>
303      * Content-Type</CODE> value of <CODE>text/xml</CODE>. For
304      * those content types that an installed <CODE>
305      * DataContentHandler</CODE> object does not understand, the
306      * <CODE>DataContentHandler</CODE> object is required to
307      * return a <CODE>java.io.InputStream</CODE> object with the
308      * raw bytes.</P>
309      * @return a Java object with the content of this <CODE>
310      * AttachmentPart</CODE> object
311      * @throws SOAPException if there is no content set
312      * into this <CODE>AttachmentPart</CODE> object or if there
313      * was a data transformation error
314      */

315     public Object JavaDoc getContent() throws SOAPException JavaDoc {
316         if(contentObject != null) {
317             return contentObject;
318         }
319
320         if(datahandler == null) {
321             throw new SOAPException JavaDoc(Messages.getMessage("noContent"));
322         }
323
324         javax.activation.DataSource JavaDoc ds = datahandler.getDataSource();
325         InputStream JavaDoc is = null;
326         try {
327             is = ds.getInputStream();;
328         } catch (java.io.IOException JavaDoc io) {
329             log.error(Messages.getMessage("javaIOException00"), io);
330             throw new SOAPException JavaDoc(io);
331         }
332         if (ds.getContentType().equals("text/plain")) {
333             try {
334                 byte[] bytes = new byte[is.available()];
335                 IOUtils.readFully(is, bytes);
336                 return new String JavaDoc(bytes);
337             } catch (java.io.IOException JavaDoc io) {
338                 log.error(Messages.getMessage("javaIOException00"), io);
339                 throw new SOAPException JavaDoc(io);
340             }
341         } else if (ds.getContentType().equals("text/xml")) {
342             return new StreamSource JavaDoc(is);
343         } else if (ds.getContentType().equals("image/gif") ||
344                    ds.getContentType().equals("image/jpeg")) {
345             try {
346                 return ImageIOFactory.getImageIO().loadImage(is);
347             } catch (Exception JavaDoc ex) {
348                 log.error(Messages.getMessage("javaIOException00"), ex);
349                 throw new SOAPException JavaDoc(ex);
350             }
351         }
352         return is;
353     }
354
355
356     /**
357      * Sets the content of this attachment part to that of the
358      * given <CODE>Object</CODE> and sets the value of the <CODE>
359      * Content-Type</CODE> header to the given type. The type of the
360      * <CODE>Object</CODE> should correspond to the value given for
361      * the <CODE>Content-Type</CODE>. This depends on the particular
362      * set of <CODE>DataContentHandler</CODE> objects in use.
363      * @param object the Java object that makes up
364      * the content for this attachment part
365      * @param contentType the MIME string that
366      * specifies the type of the content
367      * @throws java.lang.IllegalArgumentException if
368      * the contentType does not match the type of the content
369      * object, or if there was no <CODE>
370      * DataContentHandler</CODE> object for this content
371      * object
372      * @see #getContent() getContent()
373      */

374     public void setContent(Object JavaDoc object, String JavaDoc contentType) {
375         ManagedMemoryDataSource source = null;
376         setMimeHeader(HTTPConstants.HEADER_CONTENT_TYPE, contentType);
377         if (object instanceof String JavaDoc) {
378             try {
379                 String JavaDoc s = (String JavaDoc) object;
380                 java.io.ByteArrayInputStream JavaDoc bais =
381                         new java.io.ByteArrayInputStream JavaDoc(s.getBytes());
382                 source = new ManagedMemoryDataSource(bais,
383                         ManagedMemoryDataSource.MAX_MEMORY_DISK_CACHED,
384                         contentType, true);
385                 extractFilename(source);
386                 datahandler = new DataHandler JavaDoc(source);
387                 contentObject = object;
388                 return;
389             } catch (java.io.IOException JavaDoc io) {
390                 log.error(Messages.getMessage("javaIOException00"), io);
391                 throw new java.lang.IllegalArgumentException JavaDoc(
392                         Messages.getMessage("illegalArgumentException00"));
393             }
394         } else if (object instanceof java.io.InputStream JavaDoc) {
395             try {
396                 source = new ManagedMemoryDataSource((java.io.InputStream JavaDoc) object,
397                         ManagedMemoryDataSource.MAX_MEMORY_DISK_CACHED,
398                         contentType, true);
399                 extractFilename(source);
400                 datahandler = new DataHandler JavaDoc(source);
401                 contentObject = null; // the stream has been consumed
402
return;
403             } catch (java.io.IOException JavaDoc io) {
404                 log.error(Messages.getMessage("javaIOException00"), io);
405                 throw new java.lang.IllegalArgumentException JavaDoc(Messages.getMessage
406                         ("illegalArgumentException00"));
407             }
408         } else if (object instanceof StreamSource JavaDoc) {
409             try {
410                 source = new ManagedMemoryDataSource(((StreamSource JavaDoc)object).getInputStream(),
411                         ManagedMemoryDataSource.MAX_MEMORY_DISK_CACHED,
412                         contentType, true);
413                 extractFilename(source);
414                 datahandler = new DataHandler JavaDoc(source);
415                 contentObject = null; // the stream has been consumed
416
return;
417             } catch (java.io.IOException JavaDoc io) {
418                 log.error(Messages.getMessage("javaIOException00"), io);
419                 throw new java.lang.IllegalArgumentException JavaDoc(Messages.getMessage
420                         ("illegalArgumentException00"));
421             }
422         } else {
423             throw new java.lang.IllegalArgumentException JavaDoc(
424                     Messages.getMessage("illegalArgumentException00"));
425         }
426     }
427
428     /**
429      * Clears out the content of this <CODE>
430      * AttachmentPart</CODE> object. The MIME header portion is left
431      * untouched.
432      */

433     public void clearContent() {
434         datahandler = null;
435         contentObject = null;
436     }
437
438     /**
439      * Returns the number of bytes in this <CODE>
440      * AttachmentPart</CODE> object.
441      * @return the size of this <CODE>AttachmentPart</CODE> object
442      * in bytes or -1 if the size cannot be determined
443      * @throws SOAPException if the content of this
444      * attachment is corrupted of if there was an exception
445      * while trying to determine the size.
446      */

447     public int getSize() throws SOAPException JavaDoc {
448         if (datahandler == null) {
449             return 0;
450         }
451         ByteArrayOutputStream JavaDoc bout = new ByteArrayOutputStream JavaDoc();
452         try {
453             datahandler.writeTo(bout);
454         } catch (java.io.IOException JavaDoc ex) {
455             log.error(Messages.getMessage("javaIOException00"), ex);
456             throw new SOAPException JavaDoc(Messages.getMessage("javaIOException01", ex.getMessage()), ex);
457         }
458         return bout.size();
459     }
460
461     /**
462      * Gets all the values of the header identified by the given
463      * <CODE>String</CODE>.
464      * @param name the name of the header; example:
465      * "Content-Type"
466      * @return a <CODE>String</CODE> array giving the value for the
467      * specified header
468      * @see #setMimeHeader(java.lang.String, java.lang.String) setMimeHeader(java.lang.String, java.lang.String)
469      */

470     public String JavaDoc[] getMimeHeader(String JavaDoc name) {
471         return mimeHeaders.getHeader(name);
472     }
473
474     /**
475      * Content ID.
476      *
477      * @return the contentId reference value that should be used directly
478      * as an href in a SOAP element to reference this attachment.
479      * <B>Not part of JAX-RPC, JAX-M, SAAJ, etc. </B>
480      */

481     public String JavaDoc getContentIdRef() {
482       return Attachments.CIDprefix + getContentId();
483     }
484
485     /**
486      * Maybe add file name to the attachment.
487      *
488      * @param source the source of the data
489      */

490
491     private void extractFilename(ManagedMemoryDataSource source) {
492         //check for there being a file
493
if(source.getDiskCacheFile()!=null) {
494             String JavaDoc path = source.getDiskCacheFile().getAbsolutePath();
495             setAttachmentFile(path);
496         }
497     }
498
499     /**
500      * Set the filename of this attachment part.
501      *
502      * @param path the new file path
503      */

504     protected void setAttachmentFile(String JavaDoc path) {
505         attachmentFile=path;
506     }
507
508     /**
509      * Detach the attachment file from this class, so it is not cleaned up.
510      * This has the side-effect of making subsequent calls to
511      * getAttachmentFile() return <code>null</code>.
512      */

513     public void detachAttachmentFile() {
514         attachmentFile=null;
515     }
516     
517     /**
518      * Get the filename of this attachment.
519      *
520      * @return the filename or null for an uncached file
521      */

522     public String JavaDoc getAttachmentFile() {
523         return attachmentFile;
524     }
525
526     /**
527      * when an attachment part is disposed, any associated files
528      * are deleted, and the datahandler itself nulled. The object
529      * is no longer completely usable, at this point
530      */

531     public synchronized void dispose() {
532         if (attachmentFile != null) {
533             javax.activation.DataSource JavaDoc ds = datahandler.getDataSource();
534             if (ds instanceof ManagedMemoryDataSource) {
535                 ((ManagedMemoryDataSource) ds).delete(); //and delete the file
536
} else {
537                 File JavaDoc f = new File JavaDoc(attachmentFile);
538                 //no need to check for existence here.
539
f.delete();
540             }
541             //set the filename to null to stop repeated use
542
setAttachmentFile(null);
543         }
544         //clean up the datahandler, as it will have been
545
//invalidated if it was bound to a file; if it wasnt
546
//we get to release memory anyway
547
datahandler = null;
548     }
549 }
550
Popular Tags