KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > lucane > server > web > FormdataMultipart


1 /***
2 * jwma Java WebMail
3 * Copyright (c) 2001 Dieter Wimberger
4 *
5 * jwma is free software; you can distribute and use this source
6 * under the terms of the BSD-style license received along with
7 * the distribution.
8 ***/

9 package org.lucane.server.web;
10
11 import java.io.ByteArrayOutputStream JavaDoc;
12 import java.io.IOException JavaDoc;
13 import java.io.InputStream JavaDoc;
14 import java.io.OutputStream JavaDoc;
15 import java.util.Hashtable JavaDoc;
16
17 import javax.activation.DataHandler JavaDoc;
18 import javax.activation.DataSource JavaDoc;
19 import javax.mail.MessagingException JavaDoc;
20 import javax.mail.internet.MimeBodyPart JavaDoc;
21 import javax.mail.internet.MimeMultipart JavaDoc;
22 import javax.mail.internet.MimeUtility JavaDoc;
23
24 /**
25  * Class that implements a Multipart that handles
26  * the <code>multipart/form-data</code> content type.
27  *
28  * @author Dieter Wimberger
29  * @version 0.9.5 04/05/2001
30  */

31 public class FormdataMultipart extends MimeMultipart JavaDoc {
32
33     //instance attributes
34
private Hashtable JavaDoc m_Params=new Hashtable JavaDoc();
35     private boolean m_Removed=false;
36
37     /**
38      * Constructs a <code>FormdataMultipart</code> instance.<br>
39      * This implementation just calls the superclass constructor.
40      *
41      * @return the newly created <code>FormdataMultipart</code> instance.
42      */

43      public FormdataMultipart() {
44         super();
45      }//constructor
46

47     /**
48      * Constructs a <code>FormdataMultipart</code> instance.<br>
49      * Automatically processes the body parts to extract parameters,
50      * and attachments.
51      *
52      * @param DataSource to construct the Multipart from, will be a
53      * <code>MultipartInputStream</code>.
54      *
55      * @return the newly created <code>FormdataMultipart</code> instance.
56      */

57      public FormdataMultipart(DataSource JavaDoc ds)
58             throws MessagingException JavaDoc,IOException JavaDoc {
59         
60         super(ds);
61         processBodyParts();
62         updateHeaders();
63      }//constructor
64

65     /**
66      * Returns the extracted parameters (with the extrcted values)
67      * as <code>Hashtable</code>.
68      *
69      * @return the extracted parameter data as <code>Hashtable</code>
70      */

71      public Hashtable JavaDoc getParameters() {
72         return m_Params;
73      }//getParameters
74

75     /**
76      * Processes the body parts of the form-data.
77      * Extracts parameters and set values, and
78      * leaves over the attachments.
79      *
80      * @throws IOException if i/o operations fail.
81      * @throws MessagingException if parsing or part handling with
82      * Mail API classes fails.
83      */

84      private void processBodyParts()
85         throws IOException JavaDoc,MessagingException JavaDoc {
86         
87         //if write out to log for debug reasons!
88
//ByteArrayOutputStream bout=new ByteArrayOutputStream();
89
//writeTo(bout);
90
//JwmaKernel.getReference().debugLog().write(bout.toString());
91

92                 
93         for(int i=0; i<getCount(); i++){
94             MimeBodyPart JavaDoc mbp=(MimeBodyPart JavaDoc)getBodyPart(i);
95             processBodyPart(mbp);
96             if(m_Removed) {
97                 m_Removed=false;
98                 //decrease index i approbiately
99
i--;
100             }
101         }
102         setSubType("mixed");
103         //JwmaKernel.getReference().debugLog().write(
104
// "Processed multipart/form-data. Attachment parts:"+getCount()
105
//);
106
}//processParts
107

108     /**
109      * Processes a body part of the form-data.
110      * Extracts parameters and set values, and
111      * leaves over the attachments.
112      *
113      * @param mbp the <code>MimeBodyPart</code> to be processed.
114      *
115      * @throws IOException if i/o operations fail.
116      * @throws MessagingException if parsing or part handling with
117      * Mail API classes fails.
118      */

119      private void processBodyPart(MimeBodyPart JavaDoc mbp)
120         throws MessagingException JavaDoc,IOException JavaDoc {
121         
122         
123         String JavaDoc contenttype=new String JavaDoc(mbp.getContentType());
124         //JwmaKernel.getReference().debugLog().write("Processing "+contenttype);
125

126         //check if a content-type is given
127
String JavaDoc[] cts=mbp.getHeader("Content-Type");
128         if(cts==null || cts.length==0){
129             //this is a parameter, get it out and
130
//remove the part.
131
String JavaDoc controlname=extractName(
132                 (mbp.getHeader("Content-Disposition"))[0]);
133             
134             //JwmaKernel.getReference().debugLog().write("Processing control:"+controlname);
135
//retrieve value observing encoding
136
InputStream JavaDoc in=mbp.getInputStream();
137             String JavaDoc[] encoding=mbp.getHeader("Content-Transfer-Encoding");
138             if(encoding!=null && encoding.length>0){
139                 in=MimeUtility.decode(in,encoding[0]);
140             }
141             
142             String JavaDoc value=extractValue(in);
143             if(value!=null || !value.trim().equals("")) {
144                 addParameter(controlname,value);
145             }
146             //flag removal
147
m_Removed=true;
148             removeBodyPart(mbp);
149         } else {
150             String JavaDoc filename=extractFileName(
151                 (mbp.getHeader("Content-Disposition"))[0]);
152                 
153             //normally without file the control should be not successful.
154
//but neither netscape nor mircosoft iexploder care much.
155
//the only feature is an empty filename.
156
if(filename.equals("")) {
157                 //kick it out too
158
m_Removed=true;
159                 removeBodyPart(mbp);
160             } else {
161                 
162                 //JwmaKernel.getReference().debugLog().write("Incoming filename="+filename);
163

164                 //IExploder sends files with complete path.
165
//jwma doesnt want this.
166
int lastindex=filename.lastIndexOf("\\");
167                 if(lastindex!=-1) {
168                     filename=filename.substring(lastindex+1,filename.length());
169                 }
170                 
171                 //JwmaKernel.getReference().debugLog().write("Outgoing filename="+filename);
172

173                 //Observe a possible encoding
174
InputStream JavaDoc in=mbp.getInputStream();
175                 String JavaDoc[] encoding=mbp.getHeader("Content-Transfer-Encoding");
176                 if(encoding!=null && encoding.length>0){
177                     in=MimeUtility.decode(in,encoding[0]);
178                 }
179                 ByteArrayOutputStream JavaDoc bout=new ByteArrayOutputStream JavaDoc();
180                 OutputStream JavaDoc out=(OutputStream JavaDoc) bout;
181                     
182                 int i=0;
183                 while((i=in.read())!=-1) {
184                     //maybe more efficient in buffers, but well
185
out.write(i);
186                 }
187                 out.flush();
188                 out.close();
189                 
190                 //create the datasource
191
MimeBodyPartDataSource mbpds=
192                     new MimeBodyPartDataSource(
193                         contenttype,filename,bout.toByteArray()
194                     );
195                 
196                 
197                 //Re-set the Content-Disposition header, in case
198
//the file name was changed
199
mbp.removeHeader("Content-Disposition");
200                 mbp.addHeader(
201                     "Content-Disposition","attachment; filename=\""+
202                     filename+
203                     "\""
204                 );
205                 
206                 //set a base64 transferencoding und the data handler
207
mbp.addHeader("Content-Transfer-Encoding","base64");
208                 mbp.setDataHandler(new DataHandler JavaDoc(mbpds));
209             }
210         }
211      }//processBodyPart
212

213     /**
214      * Returns the name of a parameter by extracting it
215      * from the content-disposition header line.
216      *
217      * @param disposition the content-disposition header line as
218      * <code>String</code>.
219      *
220      * @return the name of the parameter as <code>String</code>.
221      *
222      * @throws IOException if the header line is malformed.
223      */

224      private String JavaDoc extractName(String JavaDoc disposition)
225         throws IOException JavaDoc {
226     
227         int end=0;
228         int start=-1;
229         
230         start=disposition.indexOf("name=\"");
231         end=disposition.indexOf("\"",start+7); //offset is to skip name=\"
232
if (start==-1 || end==-1) {
233             throw new IOException JavaDoc("Mime header malformed.");
234         }
235         return disposition.substring(start+6,end);
236     }//extractName
237

238     /**
239      * Returns the filename of an attachment by extracting it
240      * from the content-disposition header line.
241      *
242      * @param disposition the content-disposition header line as
243      * <code>String</code>.
244      *
245      * @return the filename of the attachment as <code>String</code>.
246      *
247      * @throws IOException if the header line is malformed.
248      */

249      private String JavaDoc extractFileName(String JavaDoc disposition)
250         throws IOException JavaDoc {
251     
252         int end=0;
253         int start=-1;
254         
255         start=disposition.indexOf("filename=\"");
256         end=disposition.indexOf("\"",start+10); //offset is to skip filename=\"
257
if (start==-1 || end==-1) {
258             throw new IOException JavaDoc("Mime header malformed.");
259         }
260         return disposition.substring(start+10,end);
261      }//extractFileName
262

263     /**
264      * Returns the value of a parameter by extracting it
265      * from the <code>InputStream</code> that represents the content
266      * of the (parameter) part.
267      *
268      * @param in <code>InputStream</code> that reads from the content
269      * of the (parameter) part.
270      *
271      * @return the value of the parameter as <code>String</code>.
272      *
273      * @throws IOException if reading from the stream fails.
274      */

275      private String JavaDoc extractValue(InputStream JavaDoc in)
276             throws IOException JavaDoc {
277         
278         ByteArrayOutputStream JavaDoc out=new ByteArrayOutputStream JavaDoc();
279         int i=0;
280         while ((i=in.read())!=-1) {
281             out.write(i);
282         }
283         out.flush();
284         out.close();
285         in.close();
286         
287         //JwmaKernel.getReference().debugLog().write("Retrieved value="+out.toString());
288
//apply a little bit of magic when returning
289
return out.toString("iso-8859-1");
290      }//extractValue
291

292     /**
293      * Adds a parameter and mapped value to the parameters collection.
294      * If the parameter already exists, it adds another value to
295      * an already existing parameter by extending the array of strings.
296      *
297      * @param name the name of the parameter as <code>String</code>.
298      * @param value the value of the parameter as <code>String</code>.
299      */

300      private void addParameter(String JavaDoc name, String JavaDoc value) {
301         String JavaDoc values[];
302     
303         //JwmaKernel.getReference().debugLog().write("Adding "+name+"="+value);
304

305         if (m_Params.containsKey(name)) {
306             String JavaDoc oldValues[]=(String JavaDoc[])m_Params.get(name);
307             values=new String JavaDoc[oldValues.length + 1];
308             for (int i = 0; i < oldValues.length; i++) {
309                 values[i] = oldValues[i];
310             }
311             values[oldValues.length]=value;
312         } else {
313             values=new String JavaDoc[1];
314             values[0]=value;
315         }
316         m_Params.put(name, values);
317      }//addParameter
318

319 }//FormdataMultipart
320
Popular Tags