001: package net.suberic.pooka;
002:
003: import javax.mail.*;
004: import javax.mail.internet.*;
005: import javax.activation.DataHandler;
006: import java.io.*;
007: import java.util.*;
008: import javax.mail.internet.InternetHeaders;
009:
010: public class Attachment {
011: DataHandler handler;
012: String name;
013: ContentType mimeType;
014: int size;
015: String encoding;
016: InternetHeaders headers = null;
017: Vector headerLines = null;
018:
019: /**
020: * Creates an Attachment out of a MimeBodyPart.
021: */
022: public Attachment(MimePart mp) throws MessagingException {
023: handler = mp.getDataHandler();
024: name = mp.getFileName();
025: String type = mp.getContentType();
026: try {
027: mimeType = new ContentType(type);
028: } catch (ParseException pe) {
029: if (type.equalsIgnoreCase("text"))
030: mimeType = new ContentType("text/plain");
031: else if (type.length() > 0 && type.indexOf('/') == -1) {
032: try {
033: mimeType = new ContentType(type + "/plain");
034: } catch (ParseException petwo) {
035: // fall back to text/plain.
036: mimeType = new ContentType("text/plain");
037: }
038:
039: } else {
040: // fall back to text/plain.
041: mimeType = new ContentType("text/plain");
042: }
043:
044: }
045: size = mp.getSize();
046: encoding = mp.getEncoding();
047: }
048:
049: /**
050: * Creates an Attachment with the given MimeBodyPart, but with
051: * the attached MimePart as the source for the Headers.
052: */
053: public Attachment(MimePart mp, MimePart headerSource)
054: throws MessagingException {
055: handler = mp.getDataHandler();
056: if (mp instanceof MimeBodyPart)
057: name = mp.getFileName();
058: else
059: name = Pooka.getProperty("message.unknownMessage",
060: "Message Text");
061:
062: String type = mp.getContentType();
063: try {
064: mimeType = new ContentType(type);
065: } catch (ParseException pe) {
066: if (type.equalsIgnoreCase("text"))
067: mimeType = new ContentType("text/plain");
068: else if (type.length() > 0 && type.indexOf('/') == -1) {
069: try {
070: mimeType = new ContentType(type + "/plain");
071: } catch (ParseException petwo) {
072: // fall back to text/plain.
073: mimeType = new ContentType("text/plain");
074: }
075: } else {
076: // fall back to text/plain.
077: mimeType = new ContentType("text/plain");
078:
079: }
080: }
081: size = mp.getSize();
082: encoding = mp.getEncoding();
083: headers = parseHeaders(headerSource.getAllHeaders());
084: headerLines = parseHeaderLines(headerSource.getAllHeaderLines());
085: }
086:
087: /**
088: * Creates an Attachment out of a MimeMessage. This is typically
089: * used when the content of a Message is too large to display, and
090: * therefore it needs to be treated as an attachment rather than
091: * as the text of the Message.
092: */
093: /*
094: public Attachment(MimeMessage msg) throws MessagingException {
095: handler = msg.getDataHandler();
096: name = Pooka.getProperty("message.unknownMessage", "Message Text");
097: String type = msg.getContentType();
098: try {
099: mimeType = new ContentType(type);
100: } catch (ParseException pe) {
101: if (type.equalsIgnoreCase("text"))
102: mimeType = new ContentType("text/plain");
103: else if (type.length() > 0 && type.indexOf('/') == -1) {
104: try {
105: mimeType = new ContentType(type + "/plain");
106: } catch (ParseException petwo) {
107: // fall back to text/plain.
108: mimeType = new ContentType("text/plain");
109: }
110: } else {
111: // fall back to text/plain.
112: mimeType = new ContentType("text/plain");
113: }
114: }
115: size = msg.getSize();
116: encoding = msg.getEncoding();
117: }
118: */
119:
120: public void setHeaderSource(MimePart headerSource)
121: throws MessagingException {
122: headers = parseHeaders(headerSource.getAllHeaders());
123: headerLines = parseHeaderLines(headerSource.getAllHeaderLines());
124: }
125:
126: public void setHeaderSource(AttachmentBundle bundle) {
127: headers = bundle.headers;
128: headerLines = bundle.headerLines;
129: }
130:
131: // accessor methods.
132:
133: /**
134: * Returns the decoded InputStream of this Attachment.
135: */
136: public InputStream getInputStream() throws java.io.IOException {
137: return handler.getInputStream();
138: }
139:
140: /**
141: * Returns the DataHandler for this Attachment.
142: */
143: public DataHandler getDataHandler() {
144: return handler;
145: }
146:
147: /**
148: * Returns the content of this attachment as an Object.
149: */
150: public Object getContent() throws java.io.IOException {
151: try {
152: return getDataHandler().getContent();
153: } catch (UnsupportedEncodingException uee) {
154: if (isText()) {
155: /**
156: * Just read the InputStream directly into a byte array and
157: * hope for the best. :)
158: */
159: InputStream is = getDataHandler().getInputStream();
160: ByteArrayOutputStream bos = new ByteArrayOutputStream();
161: int b;
162: while ((b = is.read()) != -1)
163: bos.write(b);
164: byte[] barray = bos.toByteArray();
165: return new String(barray, Pooka.getProperty(
166: "Pooka.defaultCharset", "iso-8859-1"));
167: } else {
168: throw uee;
169: }
170: }
171: }
172:
173: public int getSize() {
174: return size;
175: }
176:
177: public String getName() {
178: return name;
179: }
180:
181: public String getEncoding() {
182: return encoding;
183: }
184:
185: public ContentType getMimeType() {
186: return mimeType;
187: }
188:
189: public boolean isText() {
190: return getMimeType().match("text/");
191: }
192:
193: public boolean isPlainText() {
194: return getMimeType().match("text/plain");
195: }
196:
197: public boolean isHtml() {
198: return getMimeType().match("text/html");
199: }
200:
201: /**
202: * Returns the text of the Attachment, up to maxLength bytes. If
203: * the content is truncated, then append the truncationMessage at the
204: * end of the content displayed.
205: *
206: * If withHeaders is set, then show the Headers to go with this message.
207: * If showFullHeaders is also set, then show all the headers.
208: */
209: public String getText(boolean withHeaders, boolean showFullHeaders,
210: int maxLength, String truncationMessage)
211: throws java.io.IOException {
212: if (isPlainText()) {
213: StringBuffer retVal = new StringBuffer();
214: if (withHeaders)
215: retVal.append(getHeaderInformation(showFullHeaders));
216:
217: retVal.append(getText(maxLength, truncationMessage));
218:
219: return retVal.toString();
220: } else
221: return null;
222: }
223:
224: /**
225: * Returns the String content of this message, up to maxLength
226: * bytes.
227: */
228: String getText(int maxLength, String truncationMessage)
229: throws IOException {
230: if (maxLength > 0 && maxLength >= size) {
231: try {
232: Object o = getDataHandler().getContent();
233: if (o instanceof String)
234: return (String) o;
235: else
236: throw new UnsupportedEncodingException();
237: } catch (UnsupportedEncodingException uee) {
238: /**
239: * Just read the InputStream directly into a byte array and
240: * hope for the best. :)
241: */
242:
243: InputStream is = getDataHandler().getInputStream();
244: ByteArrayOutputStream bos = new ByteArrayOutputStream();
245: int b;
246: while ((b = is.read()) != -1)
247: bos.write(b);
248: byte[] barray = bos.toByteArray();
249: return new String(barray, Pooka.getProperty(
250: "Pooka.defaultCharset", "iso-8859-1"));
251: }
252: } else {
253: int written = 0;
254: InputStream decodedIS = null;
255: ByteArrayOutputStream outStream = new ByteArrayOutputStream();
256:
257: decodedIS = getInputStream();
258:
259: int b = 0;
260: byte[] buf = new byte[16384];
261:
262: b = decodedIS.read(buf);
263: while (b != -1 && written < maxLength) {
264: if (b <= (maxLength - written)) {
265: outStream.write(buf, 0, b);
266: written = written + b;
267: } else {
268: outStream.write(buf, 0, (maxLength - written));
269: written = maxLength;
270: }
271: b = decodedIS.read(buf);
272: }
273:
274: byte[] barray = outStream.toByteArray();
275: String content;
276: try {
277: content = new String(barray, Pooka.getProperty(
278: "Pooka.defaultCharset", "iso-8859-1"));
279: } catch (UnsupportedEncodingException uee) {
280: content = new String(barray, Pooka.getProperty(
281: "Pooka.defaultCharset", "iso-8859-1"));
282: }
283:
284: return content + "\n" + truncationMessage + "\n";
285: }
286:
287: }
288:
289: /**
290: * Returns the html of the Attachment, up to maxLength bytes. If
291: * the content is truncated, then append the truncationMessage at the
292: * end of the content displayed.
293: *
294: * If withHeaders is set, then show the Headers to go with this message.
295: * If showFullHeaders is also set, then show all the headers.
296: */
297: public String getHtml(boolean withHeaders, boolean showFullHeaders,
298: int maxLength, String truncationMessage)
299: throws java.io.IOException {
300: if (isHtml()) {
301: StringBuffer retVal = new StringBuffer();
302: if (withHeaders)
303: retVal.append(getHeaderInformation(showFullHeaders));
304:
305: retVal.append(getText(maxLength, truncationMessage));
306:
307: return retVal.toString();
308: } else
309: return null;
310: }
311:
312: /**
313: * Parses the Enumeration of Header objects into a HashMap.
314: */
315: private InternetHeaders parseHeaders(Enumeration pHeaders) {
316: InternetHeaders retVal = new InternetHeaders();
317: while (pHeaders.hasMoreElements()) {
318: Header hdr = (Header) pHeaders.nextElement();
319: retVal.addHeader(hdr.getName(), hdr.getValue());
320: }
321:
322: return retVal;
323: }
324:
325: /**
326: * Parses the Enumeration of header lines into a Vector.
327: */
328: private Vector parseHeaderLines(Enumeration pHeaderLines) {
329: Vector retVal = new Vector();
330: while (pHeaderLines.hasMoreElements())
331: retVal.add(pHeaderLines.nextElement());
332: return retVal;
333: }
334:
335: /**
336: * This returns the formatted header information for a message.
337: */
338: public StringBuffer getHeaderInformation(boolean showFullHeaders) {
339: if (headers != null) {
340: StringBuffer headerText = new StringBuffer();
341:
342: if (showFullHeaders) {
343: Enumeration allHdrs = headers.getAllHeaderLines();
344: while (allHdrs.hasMoreElements()) {
345: headerText
346: .append(MailUtilities
347: .decodeText((String) allHdrs
348: .nextElement()));
349: }
350: } else {
351: StringTokenizer tokens = new StringTokenizer(Pooka
352: .getProperty(
353: "MessageWindow.Header.DefaultHeaders",
354: "From:To:CC:Date:Subject"), ":");
355: String hdrLabel, currentHeader = null;
356: String hdrValue = null;
357:
358: while (tokens.hasMoreTokens()) {
359: currentHeader = tokens.nextToken();
360: hdrLabel = Pooka.getProperty(
361: "MessageWindow.Header." + currentHeader
362: + ".label", currentHeader);
363: hdrValue = MailUtilities
364: .decodeText((String) headers.getHeader(
365: Pooka.getProperty(
366: "MessageWindow.Header."
367: + currentHeader
368: + ".MIMEHeader",
369: currentHeader), ":"));
370: if (hdrValue != null) {
371: headerText.append(hdrLabel + ": ");
372: headerText.append(hdrValue);
373:
374: headerText.append("\n");
375: }
376: }
377: }
378: String separator = Pooka.getProperty(
379: "MessageWindow.separator", "");
380: if (separator.equals(""))
381: headerText.append("\n\n");
382: else
383: headerText.append(separator);
384:
385: return headerText;
386: } else {
387: return new StringBuffer();
388: }
389: }
390:
391: /**
392: * Returns the Headers for this Attachment.
393: */
394: public InternetHeaders getHeaders() {
395: return headers;
396: }
397: }
|