KickJava   Java API By Example, From Geeks To Geeks.

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


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
17 /* @author Rob Jellinghaus (robj@unrealities.com) */
18 /* @author Rick Rineholt */
19 package org.apache.axis.attachments;
20
21 import org.apache.axis.AxisFault;
22 import org.apache.axis.Part;
23 import org.apache.axis.SOAPPart;
24 import org.apache.axis.components.logger.LogFactory;
25 import org.apache.axis.utils.Messages;
26 import org.apache.commons.logging.Log;
27
28 import javax.activation.DataHandler JavaDoc;
29 import javax.activation.DataSource JavaDoc;
30 import java.util.Collection JavaDoc;
31 import java.util.HashMap JavaDoc;
32 import java.util.LinkedList JavaDoc;
33
34 /**
35  * Implements the Attachment interface, via an actual Hashmap of actual
36  * AttachmentParts.
37  */

38 public class AttachmentsImpl implements Attachments {
39     protected static Log log =
40             LogFactory.getLog(AttachmentsImpl.class.getName());
41
42     /** Field attachments. */
43     private HashMap JavaDoc attachments = new java.util.HashMap JavaDoc();
44
45     /** Field orderedAttachments. */
46     private LinkedList JavaDoc orderedAttachments = new LinkedList JavaDoc();
47
48     /** Field soapPart. */
49     protected SOAPPart soapPart = null;
50
51     /**
52      * The actual stream to manage the multi-related input stream.
53      */

54     protected MultiPartInputStream mpartStream =
55             null;
56     /**
57      * The form of the attachments, whether MIME or DIME.
58      */

59     protected int sendtype= Attachments.SEND_TYPE_NOTSET;
60
61     /**
62      * This is the content location as specified in SOAP with Attachments.
63      * This maybe null if the message had no Content-Location specifed.
64      */

65     protected String JavaDoc contentLocation = null;
66
67     /**
68      * The HashMap for DataHandler Managements.
69      */

70     private HashMap JavaDoc stackDataHandler = new HashMap JavaDoc();
71
72     /**
73      * Construct one of these on a parent Message.
74      * Should only ever be called by Message constructor!
75      *
76      * @param intialContents should be anything but today only a stream is
77      * supported.
78      * @param contentType The mime content type of the stream for transports
79      * that provide it.
80      * @param contentLocation
81      *
82      * @throws org.apache.axis.AxisFault
83      */

84     public AttachmentsImpl(
85             Object JavaDoc intialContents, String JavaDoc contentType, String JavaDoc contentLocation)
86             throws org.apache.axis.AxisFault {
87
88         if (contentLocation != null) {
89             contentLocation = contentLocation.trim();
90
91             if (contentLocation.length() == 0) {
92                 contentLocation = null;
93             }
94         }
95
96         this.contentLocation = contentLocation;
97
98         if (contentType != null) {
99             if (contentType.equals(org.apache.axis.Message.MIME_UNKNOWN)) {
100
101             } else {
102                 java.util.StringTokenizer JavaDoc st =
103                         new java.util.StringTokenizer JavaDoc(contentType, " \t;");
104
105                 if (st.hasMoreTokens()) {
106                     String JavaDoc mimetype = st.nextToken();
107
108                     if (mimetype.equalsIgnoreCase(
109                             org.apache.axis.Message.MIME_MULTIPART_RELATED)) {
110                         sendtype= SEND_TYPE_MIME;
111                         mpartStream =
112                                 new org.apache.axis.attachments.MultiPartRelatedInputStream(
113                                         contentType,
114                                         (java.io.InputStream JavaDoc) intialContents);
115
116                         if (null == contentLocation) {
117
118                             // If the content location is not specified as
119
// of the main message use the SOAP content location.
120
contentLocation = mpartStream.getContentLocation();
121
122                             if (contentLocation != null) {
123                                 contentLocation = contentLocation.trim();
124
125                                 if (contentLocation.length() == 0) {
126                                     contentLocation = null;
127                                 }
128                             }
129                         }
130
131                         soapPart = new org.apache.axis.SOAPPart(null,
132                                 mpartStream,
133                                 false);
134                      } else if (mimetype.equalsIgnoreCase(org.apache.axis.Message.MIME_APPLICATION_DIME)) {
135                          try{
136                             mpartStream=
137                              new MultiPartDimeInputStream( (java.io.InputStream JavaDoc) intialContents);
138                              soapPart = new org.apache.axis.SOAPPart(null, mpartStream, false);
139                          }catch(Exception JavaDoc e){ throw org.apache.axis.AxisFault.makeFault(e);}
140                          sendtype= SEND_TYPE_DIME;
141                     }
142                 }
143             }
144         }
145     }
146
147     /**
148      * Copies attachment references from the multipartStream to local list.
149      * Done only once per object creation.
150      *
151      * @throws AxisFault
152      */

153     private void mergeinAttachments() throws AxisFault {
154
155         if (mpartStream != null) {
156             Collection JavaDoc atts = mpartStream.getAttachments();
157
158             if(contentLocation == null)
159                 contentLocation= mpartStream.getContentLocation();
160
161             mpartStream = null;
162
163             setAttachmentParts(atts);
164         }
165     }
166
167     /**
168      * This method uses getAttacmentByReference() to look for attachment.
169      * If attachment has been found, it will be removed from the list, and
170      * returned to the user.
171      * @param reference The reference that referers to an attachment.
172      *
173      * @return The part associated with the removed attachment, or null.
174      *
175      * @throws org.apache.axis.AxisFault
176      */

177     public Part removeAttachmentPart(String JavaDoc reference)
178             throws org.apache.axis.AxisFault {
179
180         multipart = null;
181
182         dimemultipart = null;
183
184         mergeinAttachments();
185
186         Part removedPart = getAttachmentByReference(reference);
187
188         if (removedPart != null) {
189             attachments.remove(removedPart.getContentId());
190             attachments.remove(removedPart.getContentLocation());
191             orderedAttachments.remove(removedPart);
192         }
193
194         return removedPart;
195     }
196
197     /**
198      * Adds an existing attachment to this list.
199      * Note: Passed part will be bound to this message.
200      * @param newPart new part to add
201      * @return Part old attachment with the same Content-ID, or null.
202      *
203      * @throws org.apache.axis.AxisFault
204      */

205     public Part addAttachmentPart(Part newPart)
206             throws org.apache.axis.AxisFault {
207
208
209         multipart = null;
210         dimemultipart = null;
211
212         mergeinAttachments();
213
214         Part oldPart = (Part) attachments.put(newPart.getContentId(), newPart);
215
216         if (oldPart != null) {
217             orderedAttachments.remove(oldPart);
218             attachments.remove(oldPart.getContentLocation());
219         }
220
221         orderedAttachments.add(newPart);
222
223         if (newPart.getContentLocation() != null) {
224             attachments.put(newPart.getContentLocation(), newPart);
225         }
226
227         return oldPart;
228     }
229
230     public Part createAttachmentPart(Object JavaDoc datahandler)
231             throws org.apache.axis.AxisFault {
232
233         // Searching for the same attachements
234
Integer JavaDoc key = new Integer JavaDoc(datahandler.hashCode());
235         if (stackDataHandler.containsKey(key)) {
236             return (Part)stackDataHandler.get(key);
237         }
238
239         multipart = null;
240
241         dimemultipart = null;
242
243         mergeinAttachments();
244
245         if (!(datahandler instanceof javax.activation.DataHandler JavaDoc)) {
246             throw new org.apache.axis.AxisFault(
247                     Messages.getMessage(
248                             "unsupportedAttach", datahandler.getClass().getName(),
249                             javax.activation.DataHandler JavaDoc.class.getName()));
250         }
251
252         Part ret =
253                 new AttachmentPart((javax.activation.DataHandler JavaDoc) datahandler);
254
255         addAttachmentPart(ret);
256
257         // Store the current DataHandler with its key
258
stackDataHandler.put(key, ret);
259
260         return ret;
261     }
262
263     /**
264      * Add the collection of parts.
265      *
266      * @param parts
267      *
268      * @throws org.apache.axis.AxisFault
269      */

270     public void setAttachmentParts(java.util.Collection JavaDoc parts)
271             throws org.apache.axis.AxisFault {
272
273         removeAllAttachments();
274
275         if ((parts != null) && !parts.isEmpty()) {
276             for (java.util.Iterator JavaDoc i = parts.iterator(); i.hasNext();) {
277                 Object JavaDoc part = i.next();
278
279                 if (null != part) {
280                     if(part instanceof Part)
281                         addAttachmentPart((Part)part);
282                     else
283                         createAttachmentPart(part);
284                 }
285             }
286         }
287     }
288
289     /**
290      * This method should look at a refernce and determine if it is a CID: or
291      * url to look for attachment.
292      * <br>
293      * Note: if Content-Id or Content-Location headers have changed by outside
294      * code, lookup will not return proper values. In order to change these
295      * values attachment should be removed, then added again.
296      * @param reference The reference in the xml that referers to an attachment.
297      *
298      * @return The part associated with the attachment.
299      *
300      * @throws org.apache.axis.AxisFault
301      */

302     public Part getAttachmentByReference(String JavaDoc reference)
303             throws org.apache.axis.AxisFault {
304
305         if (null == reference) {
306             return null;
307         }
308
309         reference = reference.trim();
310
311         if (0 == reference.length()) {
312             return null;
313         }
314
315         mergeinAttachments();
316
317         //This search will pickit up if its fully qualified location or if it's a content-id
318
// that is not prefixed by the cid.
319

320         Part ret = (Part) attachments.get(reference);
321         if( null != ret) return ret;
322
323
324         if (!reference.startsWith(Attachments.CIDprefix) && (null != contentLocation)) {
325             //Not a content-id check to see if its a relative location id.
326

327                 String JavaDoc fqreference = contentLocation;
328
329                 if (!fqreference.endsWith("/")) {
330                     fqreference += "/";
331                 }
332
333                 if (reference.startsWith("/")) {
334                     fqreference += reference.substring(1);
335                 } else {
336                     fqreference += reference;
337                 }
338
339                 // lets see if we can get it as Content-Location
340
ret = (AttachmentPart) attachments.get(fqreference);
341         }
342
343         if( null == ret && reference.startsWith(Attachments.CIDprefix)){
344              //This is a content-id lets see if we have it.
345
ret = (Part) attachments.get( reference.substring(4));
346         }
347
348         return ret;
349     }
350
351     /**
352      * This method will return all attachments as a collection.
353      *
354      * @return A collection of attachments.
355      *
356      * @throws org.apache.axis.AxisFault
357      */

358     public java.util.Collection JavaDoc getAttachments()
359             throws org.apache.axis.AxisFault {
360
361         mergeinAttachments();
362
363         return new LinkedList JavaDoc(orderedAttachments);
364     }
365
366     /**
367      * From the complex stream return the root part.
368      * Today this is SOAP.
369      *
370      * @return the root <code>Part</code>
371      */

372     public Part getRootPart() {
373         return soapPart;
374     }
375
376     public void setRootPart(Part newRoot) {
377
378         try {
379             this.soapPart = (SOAPPart) newRoot;
380             multipart = null;
381             dimemultipart = null;
382         } catch (ClassCastException JavaDoc e) {
383             throw new ClassCastException JavaDoc(Messages.getMessage("onlySOAPParts"));
384         }
385     }
386
387     /** multipart , cached entries for the stream of attachment that are going to be sent. */
388     javax.mail.internet.MimeMultipart JavaDoc multipart = null;
389     DimeMultiPart dimemultipart = null;
390
391     /**
392      * Get the content length of the stream.
393      *
394      * @return the content length of the stream
395      *
396      * @throws org.apache.axis.AxisFault
397      */

398     public long getContentLength() throws org.apache.axis.AxisFault {
399
400         mergeinAttachments();
401
402         int sendtype= this.sendtype == SEND_TYPE_NOTSET ? SEND_TYPE_DEFAULT : this.sendtype;
403
404         try {
405               if(sendtype == SEND_TYPE_MIME)
406                  return org.apache.axis.attachments.MimeUtils.getContentLength(
407                                 multipart != null ? multipart : (multipart = org.apache.axis.attachments.MimeUtils.createMP(soapPart.getAsString(), orderedAttachments)));
408               else if (sendtype == SEND_TYPE_DIME)return createDimeMessage().getTransmissionSize();
409         } catch (Exception JavaDoc e) {
410             throw AxisFault.makeFault(e);
411         }
412         return 0;
413     }
414
415     /**
416      * Creates the DIME message
417      *
418      * @return a DIME part
419      *
420      * @throws org.apache.axis.AxisFault if the part could not be built
421      */

422     protected DimeMultiPart createDimeMessage() throws org.apache.axis.AxisFault{
423         int sendtype= this.sendtype == SEND_TYPE_NOTSET ? SEND_TYPE_DEFAULT : this.sendtype;
424         if (sendtype == SEND_TYPE_DIME){
425            if(dimemultipart== null){
426
427               dimemultipart= new DimeMultiPart();
428               dimemultipart.addBodyPart(new DimeBodyPart(
429                 soapPart.getAsBytes(), DimeTypeNameFormat.URI,
430                 "http://schemas.xmlsoap.org/soap/envelope/",
431                   "uuid:714C6C40-4531-442E-A498-3AC614200295"));
432
433               for( java.util.Iterator JavaDoc i= orderedAttachments.iterator();
434                 i.hasNext(); ){
435                 AttachmentPart part= (AttachmentPart)i.next();
436                     DataHandler JavaDoc dh= AttachmentUtils.
437                       getActivationDataHandler(part);
438                     dimemultipart.addBodyPart(new
439                       DimeBodyPart(dh,part.getContentId()));
440               }
441             }
442         }
443         return dimemultipart;
444       }
445
446     /**
447      * Write the content to the stream.
448      *
449      * @param os
450      *
451      * @throws org.apache.axis.AxisFault
452      */

453     public void writeContentToStream(java.io.OutputStream JavaDoc os)
454             throws org.apache.axis.AxisFault {
455         int sendtype= this.sendtype == SEND_TYPE_NOTSET ?
456                           SEND_TYPE_DEFAULT : this.sendtype;
457         try{
458
459         mergeinAttachments();
460         if(sendtype == SEND_TYPE_MIME){
461         org.apache.axis.attachments.MimeUtils.writeToMultiPartStream(os,
462                 (multipart != null)
463                 ? multipart
464                 : (multipart =
465                    org.apache.axis.attachments.MimeUtils.createMP(
466                         soapPart.getAsString(), orderedAttachments)));
467
468         for (java.util.Iterator JavaDoc i = orderedAttachments.iterator();
469              i.hasNext();) {
470             AttachmentPart part = (AttachmentPart) i.next();
471             DataHandler JavaDoc dh =
472                     AttachmentUtils.getActivationDataHandler(part);
473             DataSource JavaDoc ds = dh.getDataSource();
474
475             if ((ds != null) && (ds instanceof ManagedMemoryDataSource)) {
476                 ((ManagedMemoryDataSource) ds).delete();
477             }
478         }
479         }else if (sendtype == SEND_TYPE_DIME)createDimeMessage().write(os);
480        }catch(Exception JavaDoc e){ throw org.apache.axis.AxisFault.makeFault(e);}
481     }
482
483     /**
484      * Gets the content type for the whole stream.
485      *
486      * @return the content type for the whole stream
487      *
488      * @throws org.apache.axis.AxisFault
489      */

490     public String JavaDoc getContentType() throws org.apache.axis.AxisFault {
491
492         mergeinAttachments();
493
494         int sendtype= this.sendtype == SEND_TYPE_NOTSET ? SEND_TYPE_DEFAULT :
495                this.sendtype;
496         if(sendtype == SEND_TYPE_MIME)
497           return org.apache.axis.attachments.MimeUtils.getContentType((multipart
498                   != null)
499                   ? multipart
500                   : (multipart =
501                   org.apache.axis.attachments.MimeUtils.createMP(
502                           soapPart.getAsString(),
503                           orderedAttachments)));
504         else return org.apache.axis.Message.MIME_APPLICATION_DIME;
505     }
506
507     /**
508      * This is the number of attachments.
509      *
510      * @return the number of attachments
511      */

512     public int getAttachmentCount() {
513
514         try {
515             mergeinAttachments();
516
517             // force a serialization of the message so that
518
// any attachments will be added
519
soapPart.saveChanges();
520             
521             return orderedAttachments.size();
522         } catch (AxisFault e) {
523             log.warn(Messages.getMessage("exception00"),e);
524         }
525
526         return 0;
527     }
528
529     /**
530      * Determine if an object is to be treated as an attchment.
531      *
532      * @param value the value that is to be determined if
533      * its an attachment.
534      *
535      * @return True if value should be treated as an attchment.
536      */

537     public boolean isAttachment(Object JavaDoc value) {
538         return AttachmentUtils.isAttachment(value);
539     }
540
541     /**
542      * Removes all <CODE>AttachmentPart</CODE> objects that have
543      * been added to this <CODE>SOAPMessage</CODE> object.
544      *
545      * <P>This method does not touch the SOAP part.</P>
546      */

547     public void removeAllAttachments() {
548         try {
549             multipart = null;
550             dimemultipart = null;
551             mergeinAttachments();
552             attachments.clear();
553             orderedAttachments.clear();
554             stackDataHandler.clear();
555         } catch (AxisFault af){
556             log.warn(Messages.getMessage("exception00"),af);
557         }
558     }
559
560     /**
561      * Retrieves all the <CODE>AttachmentPart</CODE> objects
562      * that have header entries that match the specified headers.
563      * Note that a returned attachment could have headers in
564      * addition to those specified.
565      * @param headers a <CODE>MimeHeaders</CODE>
566      * object containing the MIME headers for which to
567      * search
568      * @return an iterator over all attachments that have a header
569      * that matches one of the given headers
570      */

571     public java.util.Iterator JavaDoc getAttachments(
572             javax.xml.soap.MimeHeaders JavaDoc headers) {
573         java.util.Vector JavaDoc vecParts = new java.util.Vector JavaDoc();
574         java.util.Iterator JavaDoc iterator = GetAttachmentsIterator();
575         while(iterator.hasNext()){
576             Part part = (Part) iterator.next();
577             if(part instanceof AttachmentPart){
578                 if(((AttachmentPart)part).matches(headers)){
579                     vecParts.add(part);
580                 }
581             }
582         }
583         return vecParts.iterator();
584     }
585
586     /**
587      * get an iterator over all attachments. This
588      * @return iterator of Part Objects; some of which may be
589      * AttachmentPart instances
590      * @see org.apache.axis.Part
591      * @see AttachmentPart
592      */

593     private java.util.Iterator JavaDoc GetAttachmentsIterator() {
594         java.util.Iterator JavaDoc iterator = attachments.values().iterator();
595         return iterator;
596     }
597
598     /**
599      * Create a new attachment Part in this Message.
600      * Will actually, and always, return an AttachmentPart.
601      *
602      * @return a new attachment Part
603      *
604      * @throws org.apache.axis.AxisFault
605      */

606     public Part createAttachmentPart() throws org.apache.axis.AxisFault {
607         return new AttachmentPart();
608     }
609
610     public void setSendType( int sendtype){
611       if( sendtype < 1)
612         throw new IllegalArgumentException JavaDoc("");
613       if( sendtype > SEND_TYPE_MAX )
614         throw new IllegalArgumentException JavaDoc("");
615       this.sendtype= sendtype;
616     }
617
618     public int getSendType(){
619       return sendtype;
620     }
621
622     /**
623      * dispose of the attachments and their files; do not use the object
624      * after making this call.
625      */

626
627     public void dispose() {
628         java.util.Iterator JavaDoc iterator = GetAttachmentsIterator();
629         while (iterator.hasNext()) {
630             Part part = (Part) iterator.next();
631             if (part instanceof AttachmentPart) {
632                 AttachmentPart apart=(AttachmentPart)part;
633                 apart.dispose();
634             }
635         }
636
637     }
638
639     // consider type-safe e-num here?
640
/**
641      * Determine how an object typically sent as attachments are to
642      * be represented. Currently, MIME DIME and NONE are reccognised.
643      *
644      * @param value a String representing a sending type, treated in a
645      * case-insensetive manner
646      * @return an <code>int</code> send type code
647      */

648     public static int getSendType(String JavaDoc value) {
649         if (value.equalsIgnoreCase("MIME")) return SEND_TYPE_MIME;
650         if (value.equalsIgnoreCase("DIME")) return SEND_TYPE_DIME;
651         if (value.equalsIgnoreCase("NONE")) return SEND_TYPE_NONE;
652         return SEND_TYPE_NOTSET;
653     }
654
655     /**
656      * For a given sendType value, return a string representation.
657      *
658      * @param value a type code integer
659      * @return a <code>String</code> representation of <code>value</code>
660      */

661     public static String JavaDoc getSendTypeString(int value) {
662         if (value == SEND_TYPE_MIME) {
663             return "MIME";
664         }
665         if (value == SEND_TYPE_DIME) {
666             return "DIME";
667         }
668         if (value == SEND_TYPE_NONE) {
669             return "NONE";
670         }
671         return null;
672     }
673 }
674
Popular Tags