001: package net.suberic.pooka;
002:
003: import java.util.*;
004: import java.io.IOException;
005: import javax.mail.internet.*;
006: import javax.mail.*;
007:
008: /**
009: * This class is here for my convenience so that I can have a single
010: * set of attachment parsers that will return any set of information
011: * that I want.
012: */
013: class AttachmentBundle {
014: private Attachment textPart = null;
015: private Vector allAttachments = new Vector();
016: Vector attachmentsAndTextPart = null;
017: InternetHeaders headers = null;
018: Vector headerLines = null;
019:
020: /**
021: * Creates an AttachmentBundle.
022: */
023: AttachmentBundle() {
024: }
025:
026: /**
027: * Creates an AttachmentBundle from the given MimePart.
028: */
029: AttachmentBundle(MimePart m) throws MessagingException {
030: setHeaderSource(m);
031: }
032:
033: /**
034: * Adds all of the entries in the <code>subBundle</code> to this
035: * AttachmentBundle. Also will update the <code>textPart</code>,
036: * if this Bundle doesn't have one yet.
037: */
038: synchronized void addAll(AttachmentBundle subBundle) {
039: if (subBundle.textPart != null)
040: subBundle.textPart.setHeaderSource(subBundle);
041:
042: if (textPart == null) {
043: textPart = subBundle.textPart;
044: } else if (textPart instanceof net.suberic.pooka.crypto.CryptoAttachment) {
045: if (subBundle.textPart != null) {
046: textPart = subBundle.textPart;
047: }
048: } else if (subBundle.textPart != null) {
049: allAttachments.add(subBundle.textPart);
050: }
051:
052: allAttachments.addAll(subBundle.allAttachments);
053: }
054:
055: /**
056: * Adds an Attachment to the AttachmentBundle. Automagically checks the
057: * type of the Attachment and sets it as the text part, if appropriate.
058: */
059: synchronized void addAttachment(Attachment newAttach) {
060: addAttachment(newAttach, newAttach.getMimeType(), true);
061: }
062:
063: /**
064: * Adds an Attachment to the AttachmentBundle.
065: *
066: * If allowTextPart is false, then forces the Attachment to
067: * be an attachment, rather than allowing it to be set as
068: * the content.
069: */
070: synchronized void addAttachment(Attachment newAttach,
071: boolean allowTextPart) {
072: addAttachment(newAttach, newAttach.getMimeType(), allowTextPart);
073: }
074:
075: /**
076: * Removes the given Attachment.
077: */
078: synchronized void removeAttachment(Attachment delAttach) {
079: if (textPart == delAttach) {
080: textPart = null;
081: Iterator it = allAttachments.iterator();
082: while (textPart == null && it.hasNext()) {
083: Attachment at = (Attachment) it.next();
084: if (at instanceof AlternativeAttachment
085: || at.getMimeType().match("text/")) {
086: textPart = at;
087: }
088: }
089: } else {
090: allAttachments.remove(delAttach);
091: }
092: }
093:
094: /**
095: * Adds an Attachment using the given ContentType.
096: */
097: synchronized void addAttachment(Attachment newAttach, ContentType ct) {
098: addAttachment(newAttach, ct, true);
099: }
100:
101: /**
102: * Adds an Attachment using the given ContentType.
103: *
104: * If allowTextPart is false, then forces the Attachment to
105: * be an attachment, rather than allowing it to be set as
106: * the content.
107: */
108: synchronized void addAttachment(Attachment newAttach,
109: ContentType ct, boolean allowTextPart) {
110: if (!allowTextPart) {
111: allAttachments.add(newAttach);
112: } else {
113: if ((textPart == null || textPart instanceof net.suberic.pooka.crypto.CryptoAttachment)
114: && (newAttach instanceof AlternativeAttachment || ct
115: .match("text/*"))) {
116: textPart = newAttach;
117: } else if (textPart == null
118: && newAttach instanceof net.suberic.pooka.crypto.CryptoAttachment) {
119: textPart = newAttach;
120: allAttachments.add(newAttach);
121: } else {
122: allAttachments.add(newAttach);
123: }
124: }
125:
126: }
127:
128: /**
129: * This gets the Text part of a message. This is useful if you want
130: * to display just the 'body' of the message without the attachments.
131: */
132: public String getTextPart(boolean withHeaders,
133: boolean showFullHeaders, int maxLength,
134: String truncationMessage) throws IOException {
135:
136: StringBuffer retVal = new StringBuffer();
137:
138: if (withHeaders)
139: retVal.append(getHeaderInformation(showFullHeaders, false));
140:
141: String text = null;
142: if (textPart != null) {
143: text = textPart.getText(withHeaders, showFullHeaders,
144: maxLength, truncationMessage);
145: }
146:
147: if (text != null) {
148: retVal.append(text);
149: return retVal.toString();
150: } else
151: return null;
152: }
153:
154: /**
155: * This gets the Html part of a message. This is useful if you want
156: * to display just the 'body' of the message without the attachments.
157: */
158: public String getHtmlPart(boolean withHeaders,
159: boolean showFullHeaders, int maxLength,
160: String truncationMessage) throws IOException {
161: StringBuffer retVal = new StringBuffer();
162:
163: retVal.append("<html><body>");
164:
165: if (withHeaders)
166: retVal.append(getHeaderInformation(showFullHeaders, true));
167:
168: if (textPart != null)
169: retVal.append(textPart.getHtml(withHeaders,
170: showFullHeaders, maxLength, truncationMessage));
171:
172: retVal.append("</body></html>");
173: return retVal.toString();
174: }
175:
176: /**
177: * This returns the Attachments (basically, all the Parts in a Multipart
178: * except for the main body of the message).
179: */
180: public Vector getAttachments() {
181: return new Vector(allAttachments);
182: }
183:
184: /**
185: * This returns the Attachments (basically, all the Parts in a Multipart
186: * except for the main body of the message) using the given
187: * messageLength to determine whether or not the main text part is an
188: * attachment or not.
189: */
190: public Vector getAttachments(int maxLength) {
191: if (textPart != null && textPart.getSize() >= maxLength) {
192: if (attachmentsAndTextPart != null)
193: return attachmentsAndTextPart;
194: else {
195: attachmentsAndTextPart = new Vector();
196: attachmentsAndTextPart.add(textPart);
197: attachmentsAndTextPart.addAll(allAttachments);
198: return new Vector(attachmentsAndTextPart);
199: }
200: } else
201: return new Vector(allAttachments);
202: }
203:
204: /**
205: * Returns all attachments, including the text part.
206: */
207: public Vector getAttachmentsAndTextPart() {
208: if (attachmentsAndTextPart != null)
209: return new Vector(attachmentsAndTextPart);
210: else {
211: attachmentsAndTextPart = new Vector();
212: attachmentsAndTextPart.add(textPart);
213: attachmentsAndTextPart.addAll(allAttachments);
214: return new Vector(attachmentsAndTextPart);
215: }
216: }
217:
218: /**
219: * This method returns the Message Text plus the text inline attachments.
220: * The attachments are separated by the separator flag.
221: */
222: public String getTextAndTextInlines(String separator,
223: boolean withHeaders, boolean showFullHeaders,
224: int maxLength, String truncationMessage) throws IOException {
225: StringBuffer returnValue = new StringBuffer();
226:
227: if (withHeaders)
228: returnValue.append(getHeaderInformation(showFullHeaders,
229: false));
230:
231: if (textPart != null)
232: returnValue.append(textPart.getText(withHeaders,
233: showFullHeaders, maxLength, truncationMessage));
234:
235: if (allAttachments != null && allAttachments.size() > 0) {
236: for (int i = 0; i < allAttachments.size(); i++) {
237: Attachment attach = (Attachment) allAttachments
238: .elementAt(i);
239: if (attach.isPlainText()) {
240: returnValue.append(separator);
241: returnValue.append(attach.getText(withHeaders,
242: showFullHeaders, maxLength,
243: truncationMessage));
244: }
245: }
246: }
247:
248: return returnValue.toString();
249: }
250:
251: /**
252: * This method returns the Message HTML plus the text inline attachments.
253: * The attachments are separated by the separator flag.
254: */
255: public String getHtmlAndTextInlines(String separator,
256: boolean withHeaders, boolean showFullHeaders,
257: int maxLength, String truncationMessage) throws IOException {
258: StringBuffer returnValue = new StringBuffer();
259:
260: returnValue.append("<html><body>");
261:
262: if (withHeaders)
263: returnValue.append(getHeaderInformation(showFullHeaders,
264: true));
265:
266: if (textPart != null)
267: returnValue.append(textPart.getHtml(withHeaders,
268: showFullHeaders, maxLength, truncationMessage));
269:
270: if (allAttachments != null && allAttachments.size() > 0) {
271: for (int i = 0; i < allAttachments.size(); i++) {
272: Attachment attach = (Attachment) allAttachments
273: .elementAt(i);
274: if (attach.isPlainText()) {
275: returnValue.append(separator);
276: returnValue.append(attach.getText(withHeaders,
277: showFullHeaders, maxLength,
278: truncationMessage));
279: }
280: }
281: }
282:
283: returnValue.append("</body></html>");
284: return returnValue.toString();
285: }
286:
287: /**
288: * Sets the header source for this AttachmentBundle. This is used when
289: * we print out headers for the Message.
290: */
291: public void setHeaderSource(MimePart headerSource)
292: throws MessagingException {
293: headers = parseHeaders(headerSource.getAllHeaders());
294: headerLines = parseHeaderLines(headerSource.getAllHeaderLines());
295: }
296:
297: /**
298: * This returns the formatted header information for a message.
299: */
300: public StringBuffer getHeaderInformation(boolean showFullHeaders,
301: boolean useHtml) {
302: if (headers != null) {
303: StringBuffer headerText = new StringBuffer();
304:
305: if (showFullHeaders) {
306: if (useHtml) {
307: Enumeration allHdrs = headers.getAllHeaders();
308: while (allHdrs.hasMoreElements()) {
309: Header nextHeader = (Header) allHdrs
310: .nextElement();
311: headerText.append("<b>" + nextHeader.getName()
312: + ":</b> ");
313: headerText.append(MailUtilities
314: .escapeHtml(nextHeader.getValue()));
315:
316: headerText.append("<br>\n");
317: }
318: } else {
319: Enumeration allHdrs = headers.getAllHeaderLines();
320: while (allHdrs.hasMoreElements()) {
321: headerText.append(MailUtilities
322: .decodeText((String) allHdrs
323: .nextElement()));
324: headerText.append('\n');
325: }
326: }
327: } else {
328: StringTokenizer tokens = new StringTokenizer(Pooka
329: .getProperty(
330: "MessageWindow.Header.DefaultHeaders",
331: "From:To:CC:Date:Subject"), ":");
332: String hdrLabel, currentHeader = null;
333: String hdrValue = null;
334:
335: while (tokens.hasMoreTokens()) {
336: currentHeader = tokens.nextToken();
337: hdrLabel = Pooka.getProperty(
338: "MessageWindow.Header." + currentHeader
339: + ".label", currentHeader);
340: hdrValue = MailUtilities
341: .decodeText((String) headers.getHeader(
342: Pooka.getProperty(
343: "MessageWindow.Header."
344: + currentHeader
345: + ".MIMEHeader",
346: currentHeader), ":"));
347: if (hdrValue != null) {
348: if (useHtml) {
349: headerText.append("<b>" + hdrLabel
350: + ":</b> ");
351: headerText.append(MailUtilities
352: .escapeHtml(hdrValue));
353:
354: headerText.append("<br>\n");
355: } else {
356: headerText.append(hdrLabel + ": ");
357: headerText.append(hdrValue);
358:
359: headerText.append("\n");
360: }
361: }
362: }
363: }
364: if (useHtml) {
365: String separator = Pooka.getProperty(
366: "MessageWindow.htmlSeparator", "<hr><br>");
367: headerText.append(separator);
368: } else {
369: String separator = Pooka.getProperty(
370: "MessageWindow.separator", "");
371: if (separator.equals(""))
372: headerText.append("\n\n");
373: else
374: headerText.append(separator);
375: }
376:
377: return headerText;
378: } else {
379: return new StringBuffer();
380: }
381: }
382:
383: /**
384: * Parses the Enumeration of Header objects into a HashMap.
385: */
386: private InternetHeaders parseHeaders(Enumeration pHeaders) {
387: InternetHeaders retVal = new InternetHeaders();
388: while (pHeaders.hasMoreElements()) {
389: Header hdr = (Header) pHeaders.nextElement();
390: retVal.addHeader(hdr.getName(), hdr.getValue());
391: }
392: return retVal;
393: }
394:
395: /**
396: * Parses the Enumeration of header lines into a Vector.
397: */
398: private Vector parseHeaderLines(Enumeration pHeaderLines) {
399: Vector retVal = new Vector();
400: while (pHeaderLines.hasMoreElements())
401: retVal.add(pHeaderLines.nextElement());
402: return retVal;
403: }
404:
405: /**
406: * Returns whether or not this attachment has an HTML version available.
407: */
408: public boolean containsHtml() {
409: if (textPart != null) {
410: if (textPart instanceof AlternativeAttachment) {
411: return true;
412: } else {
413: return textPart.getMimeType().match("text/html");
414: }
415: } else
416: return false;
417: }
418:
419: /**
420: * Returns true if the main content of this message exists only as
421: * HTML.
422: */
423: public boolean isHtml() {
424: if (textPart != null) {
425: if (textPart instanceof AlternativeAttachment)
426: return false;
427: else
428: return (textPart.getMimeType().match("text/html"));
429: } else
430: return false;
431: }
432: }
|