KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > axis2 > attachments > MIMEHelper


1 /**
2  * Copyright 2001-2004 The Apache Software Foundation.
3  * <p/>
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  * <p/>
8  * http://www.apache.org/licenses/LICENSE-2.0
9  * <p/>
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  * <p/>
16  */

17 package org.apache.axis2.attachments;
18
19 import java.io.IOException JavaDoc;
20 import java.io.InputStream JavaDoc;
21 import java.io.PushbackInputStream JavaDoc;
22 import java.util.HashMap JavaDoc;
23
24 import javax.activation.DataHandler JavaDoc;
25 import javax.mail.MessagingException JavaDoc;
26 import javax.mail.Part JavaDoc;
27 import javax.mail.internet.ContentType JavaDoc;
28 import javax.mail.internet.MimeBodyPart JavaDoc;
29 import javax.mail.internet.ParseException JavaDoc;
30
31 import org.apache.axis2.om.OMException;
32
33 /**
34  * @author <a HREF="mailto:thilina@opensource.lk">Thilina Gunarathne </a>
35  */

36 public class MIMEHelper {
37     /**
38      * if the Message is MTOM optimised then <code>MTOM_TYPE</code>
39      */

40     public static final String JavaDoc MTOM_TYPE = "application/xop+xml";
41
42     /**
43      * If the message is Soap with Attachments <code>SwA_TYPE</code>
44      */

45     public static final String JavaDoc SWA_TYPE = "text/xml";
46
47     /**
48      * <code>rootPart</code> is used as the key for the root BodyPart in the
49      * Parts HashMap
50      */

51     public static final String JavaDoc ROOT_PART = "SoapPart";
52
53     /**
54      * <code>ContentType</code> of the MIME message
55      */

56     ContentType JavaDoc contentType;
57
58     /**
59      * Mime <code>boundary</code> which seperates mime parts
60      */

61     byte[] boundary;
62
63     /**
64      * <code>applicationType</code> used to distinguish between MTOM & SWA If
65      * the message is MTOM optimised type is application/xop+xml If the message
66      * is SWA, type is ??have to find out
67      */

68     String JavaDoc applicationType = null;
69
70     /**
71      * <code>pushbackInStream</code> stores the reference to the incoming
72      * stream A PushbackStream has the ability to "push back" or "unread" one
73      * byte.
74      */

75     PushbackInputStream JavaDoc pushbackInStream;
76
77     /**
78      * <code>mimeBodyPartsMap</code> stores the already parsed Mime Body
79      * Parts. This Map will be keyed using the content-ID's
80      */

81     HashMap JavaDoc bodyPartsMap;
82
83     /**
84      * <code>partIndex</code>- Number of Mime parts parsed
85      */

86     int partIndex = 0;
87     
88     String JavaDoc firstPartId=null;
89
90     boolean fileCacheEnable = false;
91
92     String JavaDoc attachmentRepoDir = null;
93
94     public MIMEHelper(InputStream JavaDoc inStream, String JavaDoc contentTypeString,
95             boolean fileCacheEnable, String JavaDoc attachmentRepoDir)
96             throws OMException {
97         this.attachmentRepoDir = attachmentRepoDir;
98         this.fileCacheEnable = fileCacheEnable;
99         bodyPartsMap = new HashMap JavaDoc();
100         try {
101             contentType = new ContentType JavaDoc(contentTypeString);
102         } catch (ParseException JavaDoc e) {
103             throw new OMException(
104                     "Invalid Content Type Field in the Mime Message"
105                             + e.toString());
106         }
107         // Boundary always have the prefix "--".
108
this.boundary = ("--" + contentType.getParameter("boundary"))
109                 .getBytes();
110
111         //TODO do we need to wrap InputStream from a BufferedInputStream before
112
// wrapping from PushbackStream
113
pushbackInStream = new PushbackInputStream JavaDoc(inStream,
114                 (this.boundary.length + 2));
115
116         // Move the read pointer to the begining of the first part
117
// read till the end of first boundary
118
while (true) {
119             int value;
120             try {
121                 value = pushbackInStream.read();
122                 if ((byte) value == boundary[0]) {
123                     int boundaryIndex = 0;
124                     while ((boundaryIndex < boundary.length)
125                             && ((byte) value == boundary[boundaryIndex])) {
126                         value = pushbackInStream.read();
127                         if (value == -1)
128                             throw new OMException(
129                                     "Unexpected End of Stream while searching for first Mime Boundary");
130                         boundaryIndex++;
131                     }
132                     if (boundaryIndex == boundary.length) { // boundary found
133
pushbackInStream.read();
134                         break;
135                     }
136                 } else if ((byte) value == -1) {
137                     throw new OMException(
138                             "Mime parts not found. Stream ended while searching for the boundary");
139                 }
140             } catch (IOException JavaDoc e1) {
141                 throw new OMException("Stream Error" + e1.toString());
142             }
143         }
144     }
145     
146     public MIMEHelper(InputStream JavaDoc inStream, String JavaDoc contentTypeString)
147             throws OMException {
148         this(inStream,contentTypeString,false,null);
149     }
150
151     /**
152      * @return whether Message Type is SOAP with Attachments or MTOM optimised
153      * by checking the application type parameter in the Contant Type
154      */

155     public String JavaDoc getAttachmentSpecType() {
156         if (this.applicationType == null) {
157             applicationType = contentType.getParameter("type");
158             if (applicationType.equalsIgnoreCase(MTOM_TYPE)) {
159                 this.applicationType = MTOM_TYPE;
160             } else if (applicationType.equalsIgnoreCase(SWA_TYPE)) {
161                 this.applicationType = SWA_TYPE;
162             } else {
163                 throw new OMException(
164                         "Invalid Application type. Support available for MTOM & SwA only.");
165             }
166         }
167         return this.applicationType;
168     }
169
170     /**
171      * @return the InputStream which includes the SOAP Envelope We assumes that
172      * the root mime part is always pointed by "start" parameter in
173      * content-type
174      */

175     public InputStream JavaDoc getSOAPPartInputStream() throws OMException {
176         String JavaDoc rootContentID = contentType.getParameter("start");
177         // to handle the Start parameter not mentioned situation
178
if (rootContentID==null)
179         {
180             if (partIndex==0)
181             {
182             getNextPart();
183             }
184             rootContentID=firstPartId;
185         }
186         else
187         {
188         rootContentID.trim();
189         rootContentID = rootContentID
190                 .substring(1, (rootContentID.length() - 1));
191         }
192         DataHandler JavaDoc dh;
193         try {
194             dh = getDataHandler(rootContentID);
195             if (dh == null) {
196                 throw new OMException(
197                         "Mandatory Root MIME part containing the SOAP Envelope is missing");
198             }
199             return dh.getInputStream();
200         } catch (IOException JavaDoc e) {
201             throw new OMException(
202                     "Problem with DataHandler of the Root Mime Part. " + e);
203         }
204     }
205
206     /**
207      * @param blobContentID
208      * @return The DataHandler of the mime part refered by the content-Id
209      * @throws OMException
210      * First checks whether the MIME part is already parsed by
211      * checking the parts HashMap. If it is not parsed yet then call
212      * the getNextPart() till we find the required part.
213      */

214     public DataHandler JavaDoc getDataHandler(String JavaDoc blobContentID) throws OMException {
215
216         Part JavaDoc bodyPart;
217         blobContentID = "<" + blobContentID + ">";
218         boolean attachmentFound = false;
219
220         // // without the following part a Null Pointer Exception is thrown
221
//
222
if (bodyPartsMap.containsKey(blobContentID)) {
223             bodyPart = (Part JavaDoc) bodyPartsMap.get(blobContentID);
224             attachmentFound = true;
225             DataHandler JavaDoc dh;
226             try {
227                 dh = bodyPart.getDataHandler();
228             } catch (MessagingException JavaDoc e) {
229                 throw new OMException("Problem with Mime Body Part No "
230                         + partIndex + ". " + e);
231             }
232             return dh;
233         } else {
234             try {
235                 while (true) {
236                     bodyPart = this.getNextPart();
237                     if (bodyPart == null) {
238                         return null;
239                     }
240                     if (bodyPartsMap.containsKey(blobContentID)) {
241                         bodyPart = (Part JavaDoc) bodyPartsMap.get(blobContentID);
242                         DataHandler JavaDoc dh = bodyPart.getDataHandler();
243                         return dh;
244                     }
245                 }
246             } catch (MessagingException JavaDoc e) {
247                 throw new OMException("Invalid Mime Message " + e.toString());
248             }
249         }
250
251     }
252
253     /**
254      * @return The next MIME Body part in the stream Uses the MimeBodyPartStream
255      * to obtain streams delimited by boundaries.
256      * @throws MessagingException
257      */

258     // TODO do we need Locking for this
259
private MimeBodyPart JavaDoc getMimeBodyPart() throws OMException {
260         MimeBodyPart JavaDoc mimeBodyPart = null;
261
262         MimeBodyPartInputStream partStream;
263                 partStream = new MimeBodyPartInputStream(pushbackInStream,
264                         boundary);
265         try {
266             mimeBodyPart = new MimeBodyPart JavaDoc(partStream);
267         } catch (MessagingException JavaDoc e) {
268             throw new OMException("Problem reading Mime Part No "
269                     + (partIndex + 1) + ". " + e);
270         }
271
272         partIndex++;
273         return mimeBodyPart;
274     }
275
276     /**
277      * @return The Mime body part which contains the SOAP Envelope In MTOM case
278      * it is the first part In SwA case we assumes it to be first
279      * part.Have to FIX This
280      * @throws MessagingException
281      */

282     private MimeBodyPart JavaDoc getRootMimeBodyPart() throws OMException {
283         MimeBodyPart JavaDoc rootMimeBodyPart;
284         if (bodyPartsMap.isEmpty()) {
285             rootMimeBodyPart = getMimeBodyPart();
286             bodyPartsMap.put(ROOT_PART, rootMimeBodyPart);
287         } else {
288             rootMimeBodyPart = (MimeBodyPart JavaDoc) bodyPartsMap.get(ROOT_PART);
289         }
290         return rootMimeBodyPart;
291     }
292
293     private Part JavaDoc getNextPart() throws OMException {
294         MimeBodyPart JavaDoc nextMimeBodyPart;
295         nextMimeBodyPart = getMimeBodyPart();
296         if (nextMimeBodyPart != null) {
297             String JavaDoc partContentID;
298             try {
299                 partContentID = nextMimeBodyPart.getContentID();
300                 if (partContentID==null & partIndex==1)
301                 {
302                     bodyPartsMap.put("firstPart", nextMimeBodyPart);
303                     firstPartId = "firstPart";
304                     return nextMimeBodyPart;
305                 }
306                 else if (partIndex==1)
307                 {
308                     firstPartId = partContentID;
309                 }
310                 if (fileCacheEnable)
311                 {
312                     PartOnFile part = new PartOnFile(nextMimeBodyPart,partContentID,attachmentRepoDir);
313                     return part;
314                 }
315                 else{
316                     bodyPartsMap.put(partContentID, nextMimeBodyPart);
317                     return nextMimeBodyPart;
318                 }
319             } catch (MessagingException JavaDoc e) {
320                 throw new OMException(
321                         "Error Reading Content-ID from Mime Part No "
322                                 + partIndex + ". " + e);
323             } catch (Exception JavaDoc e) {
324                 throw new OMException(
325                         "Error Creating File Storage Part"
326                                 + partIndex + ". " + e);
327             }
328         } else
329             return null;
330     }
331
332 }
Popular Tags