001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.mail;
018:
019: import java.io.IOException; //import java.io.InputStream;
020: import java.text.SimpleDateFormat;
021: import java.util.Date;
022: import java.util.Enumeration;
023: import javax.mail.Address;
024: import javax.mail.Flags;
025: import javax.mail.Folder;
026: import javax.mail.Header;
027: import javax.mail.Message;
028: import javax.mail.MessagingException;
029: import javax.mail.Multipart;
030: import javax.mail.Part;
031: import javax.mail.internet.ContentType;
032: import javax.mail.internet.InternetAddress;
033: import javax.mail.internet.MimeMultipart;
034: import javax.mail.internet.MimePart;
035: import javax.mail.internet.ParameterList;
036: import javax.mail.internet.ParseException;
037: import org.apache.avalon.framework.logger.AbstractLogEnabled;
038: import org.apache.excalibur.xml.sax.XMLizable;
039: import org.xml.sax.Attributes;
040: import org.xml.sax.ContentHandler;
041: import org.xml.sax.SAXException;
042: import org.xml.sax.helpers.AttributesImpl;
043:
044: /**
045: * Marshal javamail objects
046: * <p>
047: * Having one or more javamail objects, like Message, Folder, et al. emit SAX events
048: * </p>
049: *
050: * @author Bernhard Huber
051: * @since 24 October 2002
052: * @version $Id: MailContentHandlerDelegate.java 468424 2006-10-27 15:44:53Z vgritsenko $
053: */
054:
055: /*
056: * Generated SAX events conforming to following folder sample xml:
057: *
058: * <mail:mail xmlns:mail="http://apache.org/cocoon/mail/1.0">
059: *
060: * <mail:folder name="INBOX" full-name="INBOX" url-name="imap://user-name@host-name/INBOX"
061: * is-subscribed="yes"
062: * is-direcory="no"
063: * has-new-messages="no"
064: * total-messages="3"
065: * new-messages="0"
066: * deleted-messages="-1"
067: * unread-messages="0"
068: * >
069: * </mail:mail>
070: *
071: * Generated SAX events conforming to following message sample xml:
072: *
073: * <mail:mail xmlns:mail="http://apache.org/cocoon/mail/1.0">
074: *
075: * <mail:message-envelope>
076: * <mail:from email-address="name@a1.net">name@xxx.net</mail:from>
077: * <mail:to email-address="test@xxx.net">test@xxx.net</mail:to>
078: * <mail:reply-to email-address="xxx@test.net">test@xxx.net</mail:reply-to>
079: * <mail:subject>TEST</mail:subject>
080: * <mail:sent-date>Thu Oct 10 14:40:43 CEST 2002</mail:sent-date>
081: * <mail:received-date>Thu Oct 10 14:43:29 CEST 2002</mail:received-date>
082: * <mail:size>4440</mail:size>
083: * <mail:message-number>1</mail:message-number> <mail:flags seen="yes"/>
084: * <mail:header name="Return-path" value="<test@a1.xxx>"/>
085: * <mail:header name="Received" value="from x1"/>
086: * <mail:header name="Received" value="from x2"/>
087: * <mail:header name="Date" value="Thu, 10 Oct 2002 14:40:43 +0200 (CEST)"/>
088: * <mail:header name="From" value="test@xxx.net"/>
089: * <mail:header name="Subject" value="TEST"/>
090: * <mail:header name="To" value="test@xxx.net"/>
091: * <mail:header name="Message-id" value="<4630087.1034253643941.JavaMail.root@test>"/>
092: * <mail:header name="MIME-version" value="1.0"/>
093: * <mail:header name="Content-type" value="multipart/mixed; boundary="18119425.1034253643876.JavaMail.root@test""/>
094: * </mail:message-envelope>
095: *
096: * <mail:part content-type="multipart/MIXED; boundary="18119425.1034253643876.JavaMail.root@test"">
097: * <mail:content>
098: * <mail:part content-type="TEXT/PLAIN; charset=us-ascii">
099: * <mail:content>TEST CONTENT MESSSAGE TEST.</mail:content>
100: * </mail:part>
101: * <mail:part content-type="MESSAGE/RFC822">
102: * <mail:content>
103: * <mail:part content-type="multipart/MIXED; boundary=--1f735d241edf3a1">
104: * <mail:content>
105: * <mail:part content-type="TEXT/PLAIN; charset=us-ascii">
106: * <mail:content>Test </mail:content>
107: * </mail:part>
108: * <mail:part content-type="TEXT/X-VCARD; name=xxx.vcf; charset=windows-1252" description="Card for <xxx@a1.xxx>" disposition="ATTACHMENT" file-name="xxx.vcf">
109: * <mail:content>begin:vcard n:Name;Name title:Dr email;internet:xxx@xxx.net url:www.xxx.net fn:xXxXx end:vcard </mail:content>
110: * </mail:part>
111: * </mail:content>
112: * </mail:part>
113: * </mail:content>
114: * </mail:part>
115: * </mail:content>
116: * </mail:part>
117: *
118: * </mail:mail>
119: *
120: */
121: public class MailContentHandlerDelegate extends AbstractLogEnabled {
122:
123: /**
124: * URI of the generated XML elements
125: */
126: public final static String URI = "http://apache.org/cocoon/mail/1.0";
127:
128: /**
129: * PREFIX of the generated XML elements
130: */
131: public final static String PREFIX = "mail";
132:
133: /**
134: * Destination content handler receiving SAX events generated by
135: * this class
136: */
137: private ContentHandler contentHandler;
138:
139: /**
140: * use this attributes for startElement attributes invocation, reusing
141: * attributes object for all elements
142: */
143: private AttributesImpl attributes = null;
144:
145: private SimpleDateFormat sdf;
146:
147: private ContentTypePreference alternativeMailCtPref = new MailCtPref();
148:
149: /**
150: * Constructor for the MailContentHandler object
151: *
152: * @param contentHandler Description of Parameter
153: */
154: public MailContentHandlerDelegate(ContentHandler contentHandler) {
155: this .contentHandler = contentHandler;
156: }
157:
158: /**
159: * Sets the simpleDateFormatter attribute of the MailContentHandlerDelegate object
160: *
161: * @param sdf The new simpleDateFormat value
162: */
163: public void setSimpleDateFormat(SimpleDateFormat sdf) {
164: this .sdf = sdf;
165: }
166:
167: /**
168: * Gets the simpleDateFormat attribute of the MailContentHandlerDelegate object
169: *
170: * @return The simpleDateFormat value
171: */
172: public SimpleDateFormat getSimpleDateFormat() {
173: return sdf;
174: }
175:
176: /**
177: * Emit starting SAX events sequence, including SAX startDocument event
178: *
179: * @exception SAXException thrown iff generating SAX events fails
180: */
181: public void startDocument() throws SAXException {
182: startDocumentInternal(true);
183: }
184:
185: /**
186: * Emit starting SAX events sequence, excluding SAX startDocument event
187: *
188: * @exception SAXException thrown iff generating SAX events fails
189: */
190: public void startDocumentXMLizer() throws SAXException {
191: startDocumentInternal(false);
192: }
193:
194: /**
195: * Emit starting SAX events sequence, including SAX endDocument event
196: *
197: * @exception SAXException thrown iff generating SAX events fails
198: */
199: public void endDocument() throws SAXException {
200: endDocumentInternal(true);
201: }
202:
203: /**
204: * Emit starting SAX events sequence, excluding SAX endDocument event
205: *
206: * @exception SAXException thrown iff generating SAX events fails
207: */
208: public void endDocumentXMLizer() throws SAXException {
209: endDocumentInternal(false);
210: }
211:
212: /**
213: * Emit a folder as a sequence of SAX events
214: *
215: * @param folder emit this folder
216: */
217: public void marshalFolderToSAX(Folder folder) {
218: try {
219: folderToSAX(this .contentHandler, folder);
220: } catch (Exception e) {
221: getLogger().error("Cannot generate SAX events from folder",
222: e);
223: }
224: }
225:
226: /**
227: * Emit folders as a sequence of SAX events
228: *
229: * @param folders emit these folders
230: */
231: public void marshalFolderToSAX(Folder[] folders) {
232: try {
233: for (int i = 0; i < folders.length; i++) {
234: folderToSAX(this .contentHandler, folders[i]);
235: }
236: } catch (Exception e) {
237: getLogger().error(
238: "Cannot generate SAX events from folders", e);
239: }
240: }
241:
242: /**
243: * Emit a message envelope as a sequence of SAX events
244: *
245: * @param message emit envelope of this message
246: */
247: public void marshalMessageEnvelopeToSAX(Message message) {
248: try {
249: messageEnvelopeToSAX(this .contentHandler, message);
250: } catch (Exception e) {
251: getLogger()
252: .error(
253: "Cannot generate SAX events from message envelope ",
254: e);
255: }
256: }
257:
258: /**
259: * Emit a message envelope, and message content as a sequence of SAX events
260: *
261: * @param message emit envelope, and content of this message
262: */
263: public void marshalMessageToSAX(Message message) {
264: try {
265: messageEnvelopeToSAX(this .contentHandler, message);
266: partToSAX(this .contentHandler, message, 0);
267: } catch (Exception e) {
268: getLogger().error(
269: "Cannot generate SAX events from message ", e);
270: }
271: }
272:
273: /**
274: * Emit a message content as a sequence of SAX events
275: *
276: * @param part Description of the Parameter
277: */
278: public void marshalPartToSAX(Part part) {
279: try {
280: partToSAX(this .contentHandler, part, 0);
281: } catch (Exception e) {
282: getLogger().error("Cannot generate SAX events part", e);
283: }
284: }
285:
286: /**
287: * Emit start document sequence
288: *
289: * @param emitStartDocument flag controlling invocation of SAX startDocument
290: * @exception SAXException thrown iff generating SAX events fails
291: */
292: protected void startDocumentInternal(boolean emitStartDocument)
293: throws SAXException {
294: if (emitStartDocument) {
295: this .contentHandler.startDocument();
296: }
297: this .contentHandler.startPrefixMapping(PREFIX, URI);
298:
299: attributes = new AttributesImpl();
300: attributes.addAttribute("", PREFIX, "xmlns:" + PREFIX, "CDATA",
301: URI);
302: startElement("mail", attributes);
303: }
304:
305: /**
306: * Emit end document sequence
307: *
308: * @param emitEndDocument flag controlling invocation of SAX endDocument
309: * @exception SAXException thrown iff generating SAX events fails
310: */
311: protected void endDocumentInternal(boolean emitEndDocument)
312: throws SAXException {
313: endElement("mail");
314:
315: this .contentHandler.endPrefixMapping(PREFIX);
316: if (emitEndDocument) {
317: this .contentHandler.endDocument();
318: }
319: }
320:
321: /**
322: * Emit folder as sequence of SAX events
323: *
324: * @param folder emit this folder
325: * @param contentHandler specifies sink of SAX events
326: * @exception MessagingException thrown iff accessing javamail data fails
327: * @exception SAXException thrown iff generating SAX events fails
328: */
329: protected void folderToSAX(ContentHandler contentHandler,
330: Folder folder) throws MessagingException, SAXException {
331: attributes.clear();
332: addAttribute("name", folder.getName());
333: addAttribute("full-name", folder.getFullName());
334: addAttribute("url-name", folder.getURLName().toString());
335: addAttribute("is-subscribed", folder.isSubscribed() ? "yes"
336: : "no");
337: addAttribute("is-directory",
338: (folder.getType() & Folder.HOLDS_FOLDERS) != 0 ? "yes"
339: : "no");
340:
341: if ((folder.getType() & Folder.HOLDS_MESSAGES) != 0) {
342: addAttribute("holds-messages", "yes");
343: addAttribute("has-new-messages",
344: folder.hasNewMessages() ? "yes" : "no");
345: addAttribute("total-messages", String.valueOf(folder
346: .getMessageCount()));
347: addAttribute("new-messages", String.valueOf(folder
348: .getNewMessageCount()));
349: addAttribute("deleted-messages", String.valueOf(folder
350: .getDeletedMessageCount()));
351: addAttribute("unread-messages", String.valueOf(folder
352: .getUnreadMessageCount()));
353: }
354:
355: startElement("folder", attributes);
356: endElement("folder");
357: }
358:
359: /**
360: * Emit message envelope as sequence of SAX events
361: *
362: * @param message emit envelope of this message
363: * @param contentHandler specifies sink of SAX events
364: * @exception MessagingException thrown iff accessing javamail data fails
365: * @exception SAXException thrown iff generating SAX events fails
366: */
367: protected void messageEnvelopeToSAX(ContentHandler contentHandler,
368: Message message) throws MessagingException, SAXException {
369: attributes.clear();
370: startElement("message-envelope", attributes);
371:
372: Address[] a;
373: // FROM
374: if ((a = message.getFrom()) != null) {
375: for (int j = 0; j < a.length; j++) {
376: emitAddress("from", a[j]);
377: }
378: }
379:
380: // TO
381: if ((a = message.getRecipients(Message.RecipientType.TO)) != null) {
382: for (int j = 0; j < a.length; j++) {
383: emitAddress("to", a[j]);
384: }
385: }
386:
387: // CC
388: if ((a = message.getRecipients(Message.RecipientType.CC)) != null) {
389: for (int j = 0; j < a.length; j++) {
390: emitAddress("cc", a[j]);
391: }
392: }
393: // BCC
394: if ((a = message.getRecipients(Message.RecipientType.BCC)) != null) {
395: for (int j = 0; j < a.length; j++) {
396: emitAddress("bcc", a[j]);
397: }
398: }
399:
400: // REPLY-TO
401: if ((a = message.getReplyTo()) != null) {
402: for (int j = 0; j < a.length; j++) {
403: emitAddress("reply-to", a[j]);
404: }
405: }
406:
407: // SUBJECT
408: attributes.clear();
409: startElement("subject", attributes);
410: characters(message.getSubject());
411: endElement("subject");
412:
413: // SENT-DATE
414: Date d;
415: d = message.getSentDate();
416: emitDate("sent-date", d);
417:
418: // RECEIVED-DATE
419: d = message.getReceivedDate();
420: emitDate("received-date", d);
421:
422: // SIZE
423: attributes.clear();
424: startElement("size", attributes);
425: characters(String.valueOf(message.getSize()));
426: endElement("size");
427:
428: // MESSAGE NUMBER
429: attributes.clear();
430: startElement("message-number", attributes);
431: characters(String.valueOf(message.getMessageNumber()));
432: endElement("message-number");
433:
434: // FLAGS:
435: Flags flags = message.getFlags();
436: Flags.Flag[] sf = flags.getSystemFlags();
437: // get the system flags
438:
439: attributes.clear();
440: for (int i = 0; i < sf.length; i++) {
441: Flags.Flag flag = sf[i];
442: if (flag == Flags.Flag.ANSWERED) {
443: addAttribute("answered", "yes");
444: } else if (flag == Flags.Flag.DELETED) {
445: addAttribute("deleted", "yes");
446: } else if (flag == Flags.Flag.DRAFT) {
447: addAttribute("draft", "yes");
448: } else if (flag == Flags.Flag.FLAGGED) {
449: addAttribute("flagged", "yes");
450: } else if (flag == Flags.Flag.RECENT) {
451: addAttribute("recent", "yes");
452: } else if (flag == Flags.Flag.SEEN) {
453: addAttribute("seen", "yes");
454: }
455: }
456: startElement("flags", attributes);
457: endElement("flags");
458:
459: String[] uf = flags.getUserFlags();
460: // get the user flag strings
461: for (int i = 0; i < uf.length; i++) {
462: attributes.clear();
463: startElement("user-flags", attributes);
464: characters(uf[i]);
465: endElement("user-flags");
466: }
467:
468: // X-MAILER
469: //String[] hdrs = message.getHeader("X-Mailer");
470: //logger.info("X-Mailer " + (hdrs != null ? hdrs[0] : "NOT available"));
471:
472: Enumeration allHeaders = message.getAllHeaders();
473: if (allHeaders != null) {
474: while (allHeaders.hasMoreElements()) {
475: Header header = (Header) allHeaders.nextElement();
476: attributes.clear();
477: addAttribute("name", header.getName());
478: addAttribute("value", header.getValue());
479: startElement("header", attributes);
480:
481: endElement("header");
482: }
483: }
484:
485: endElement("message-envelope");
486: }
487:
488: /**
489: * Emit part as sequence of SAX events
490: *
491: * @param part Description of the Parameter
492: * @param contentHandler specifies sink of SAX events
493: * @param i Description of the Parameter
494: * @exception MessagingException thrown iff accessing javamail data fails
495: * @exception IOException thrown iff accessing content fails
496: * @exception SAXException thrown iff generating SAX events fails
497: */
498: protected void partToSAX(ContentHandler contentHandler, Part part,
499: int i) throws MessagingException, IOException, SAXException {
500: attributes.clear();
501: String v;
502: if ((v = part.getContentType()) != null) {
503: // content type as-is
504: addAttribute("content-type", v);
505: try {
506: ContentType ct = new ContentType(v);
507: String s;
508:
509: // primary part only
510: s = ct.getPrimaryType();
511: if (s != null) {
512: addAttribute("primary-type", s.toLowerCase());
513: }
514:
515: // secondary part only
516: s = ct.getSubType();
517: if (s != null) {
518: addAttribute("secondary-type", s.toLowerCase());
519: }
520:
521: // primary part '/' secondary part
522: s = ct.getBaseType();
523: if (s != null) {
524: addAttribute("base-type", s.toLowerCase());
525: }
526:
527: // list of parameters : parameter-name parameter-value
528: ParameterList pl = ct.getParameterList();
529: Enumeration names = pl.getNames();
530: while (names.hasMoreElements()) {
531: String key = (String) names.nextElement();
532: String value = pl.get(key);
533: addAttribute(key, value);
534: }
535: } catch (ParseException pe) {
536: String message = "Cannot parse content-type "
537: + String.valueOf(v);
538: getLogger().error(message, pe);
539: }
540: }
541:
542: if (i > 0) {
543: addAttribute("part-num", String.valueOf(i));
544:
545: if (part.getDescription() != null) {
546: addAttribute("description", part.getDescription());
547: }
548: if (part.getDisposition() != null) {
549: addAttribute("disposition", part.getDisposition());
550: addAttribute("disposition-inline", String.valueOf(part
551: .getDisposition().equals(Part.INLINE)));
552: }
553: if (part.getFileName() != null) {
554: addAttribute("file-name", part.getFileName());
555: }
556: } else {
557: boolean hasAttachments = false;
558: if (part.isMimeType("multipart/*")) {
559: Multipart mp = (Multipart) part.getContent();
560: if (mp.getCount() > 1) {
561: hasAttachments = true;
562: addAttribute("num-parts", String.valueOf(mp
563: .getCount()));
564: }
565: }
566: addAttribute("has-attachments", String
567: .valueOf(hasAttachments));
568: }
569:
570: startElement("part", attributes);
571: contentToSAX(contentHandler, part);
572: endElement("part");
573: }
574:
575: /**
576: * Emit content of message part as sequence of SAX events
577: *
578: * @param contentHandler specifies sink of SAX events
579: * @param part emit this part as sequence of SAX events
580: * @exception SAXException thrown iff generating SAX events fails
581: * @exception MessagingException thrown iff accessing javamail data fails
582: * @exception IOException thrown iff accessing content fails
583: */
584: protected void contentToSAX(ContentHandler contentHandler, Part part)
585: throws MessagingException, IOException, SAXException {
586: attributes.clear();
587: startElement("content", attributes);
588:
589: /*
590: * Using isMimeType to determine the content type avoids
591: * fetching the actual content data until we need it.
592: *
593: * todo: recheck this code for all circumstances.........
594: */
595: if (part.getContent() instanceof String
596: && (part.isMimeType("text/plain"))) {
597: characters((String) part.getContent());
598: } else if (part.isMimeType("multipart/alternative")) {
599: MimeMultipart mp = (MimeMultipart) part.getContent();
600: MimePart bestPart = null;
601: int ctMax = 0;
602: for (int i = 0; i < mp.getCount(); i++) {
603: MimePart p = (MimePart) mp.getBodyPart(i);
604: int ctPrefN = alternativeMailCtPref.preference(p);
605: if (ctPrefN > ctMax) {
606: ctMax = ctPrefN;
607: bestPart = p;
608: }
609: }
610: if (bestPart != null) {
611: partToSAX(contentHandler, bestPart, 0);
612: }
613: } else if (part.isMimeType("multipart/*")) {
614: Multipart mp = (Multipart) part.getContent();
615:
616: int count = mp.getCount();
617: for (int i = 0; i < count; i++) {
618: partToSAX(contentHandler, mp.getBodyPart(i), i);
619: }
620: } else if (part.isMimeType("message/rfc822")) {
621: partToSAX(contentHandler, (Part) part.getContent(), 0);
622: } else {
623: /*
624: * If we actually want to see the data, and it's not a
625: * MIME type we know, fetch it and check its Java type.
626: Object o = part.getContent();
627: if (o instanceof String) {
628: characters((String) o);
629: } else if (o instanceof InputStream) {
630: encodeInputStreamForXML((InputStream) o);
631: } else {
632: // unknown type
633: InputStream is = part.getInputStream();
634: encodeInputStreamForXML(is);
635: }
636: */
637: }
638: endElement("content");
639: }
640:
641: /**
642: * Helper method emitting SAX events representing an internet address
643: *
644: * @param nodeName emitted element node name
645: * @param address emitted address data
646: * @exception SAXException thrown iff generating SAX events fails
647: */
648: protected void emitAddress(String nodeName, Address address)
649: throws SAXException {
650:
651: attributes.clear();
652:
653: if (address instanceof InternetAddress) {
654: InternetAddress internetAddress = (InternetAddress) address;
655: String personal = internetAddress.getPersonal();
656: if (personal != null) {
657: addAttribute("personal", personal);
658: }
659: String emailAddress = internetAddress.getAddress();
660: if (emailAddress != null) {
661: addAttribute("email-address", emailAddress);
662: }
663: }
664:
665: startElement(nodeName, attributes);
666: String addressAsString = address.toString();
667: characters(addressAsString);
668: endElement(nodeName);
669: }
670:
671: /**
672: * Helper method emitting SAX events representing a date
673: *
674: * @param nodeName emitted element node name
675: * @param d Description of the Parameter
676: * @exception SAXException thrown iff generating SAX events fails
677: */
678: protected void emitDate(String nodeName, Date d)
679: throws SAXException {
680: attributes.clear();
681: startElement(nodeName, attributes);
682: if (d != null) {
683: if (sdf != null) {
684: String formattedDate = sdf.format(d);
685: characters(formattedDate);
686: } else {
687: characters(d.toString());
688: }
689: }
690: endElement(nodeName);
691: }
692:
693: /**
694: * Helper method emitting SAX startElement event
695: *
696: * @param nodeName Description of the Parameter
697: * @param attributes Description of the Parameter
698: * @exception SAXException thrown iff generating SAX events fails
699: */
700: private void startElement(String nodeName, Attributes attributes)
701: throws SAXException {
702: this .contentHandler.startElement(URI, nodeName, PREFIX + ":"
703: + nodeName, attributes);
704: }
705:
706: /**
707: * Helper method emitting SAX characters event
708: *
709: * @param s Description of the Parameter
710: * @exception SAXException thrown iff generating SAX events fails
711: */
712: private void characters(String s) throws SAXException {
713: if (s != null) {
714: // replace 0d0a by 0a
715: // any better idea ?
716: StringBuffer sb = new StringBuffer();
717: char[] stringCharacters = s.toCharArray();
718: for (int i = 0; i < stringCharacters.length; i++) {
719: if (stringCharacters[i] != 0x0d) {
720: sb.append(stringCharacters[i]);
721: }
722: }
723: stringCharacters = sb.toString().toCharArray();
724:
725: this .contentHandler.characters(stringCharacters, 0,
726: stringCharacters.length);
727: }
728: }
729:
730: /**
731: * Helper method emitting SAX endElement event
732: *
733: * @param nodeName Description of the Parameter
734: * @exception SAXException thrown iff generating SAX events fails
735: */
736: private void endElement(String nodeName) throws SAXException {
737: this .contentHandler.endElement(URI, nodeName, PREFIX + ":"
738: + nodeName);
739: }
740:
741: /**
742: * Helper method adding an attribute name-value pair
743: *
744: * @param nodeName The feature to be added to the Attribute attribute
745: * @param nodeValue The feature to be added to the Attribute attribute
746: */
747: private void addAttribute(String nodeName, String nodeValue) {
748: attributes.addAttribute("", nodeName, nodeName, "CDATA",
749: nodeValue);
750: }
751:
752: /*
753: * Description of the Method
754: *
755: * @param is Description of Parameter
756: * @exception IOException Description of Exception
757: * @exception SAXException thrown iff generating SAX events fails
758: */
759: /* FIXME (SM) This method doesn't appear to be used
760: private void encodeInputStreamForXML(InputStream is) throws IOException, SAXException {
761: int contentLength = is.available();
762: if (contentLength < 16) {
763: contentLength = 2048;
764: }
765: attributes.clear();
766: addAttribute("type", "hex");
767: startElement("encoding", attributes);
768: byte content[] = new byte[contentLength];
769: int readLength;
770: while ((readLength = is.read(content, 0, content.length)) != -1) {
771: String strContent = encodeBytes(content, 0, readLength);
772: characters(strContent);
773: }
774: endElement("encoding");
775: } */
776:
777: /*
778: * A simple byte as hex encodeing
779: *
780: * @param bytes Description of Parameter
781: * @param offset Description of Parameter
782: * @param length Description of Parameter
783: * @return Description of the Returned Value
784: */
785: /* FIXME (SM) This method doesn't appear to be used
786: private String encodeBytes(final byte[] bytes, final int offset, final int length) {
787: StringBuffer sb = new StringBuffer();
788: final String ENCODE_TABLE[] = {
789: "0", "1", "2", "3", "4", "5", "6", "7", "8",
790: "9", "a", "b", "c", "d", "e", "f"};
791: final int l = offset + length;
792: for (int i = offset; i < l; i++) {
793: byte b = bytes[i];
794: int upperNibble = ((b >> 4) & 0x0f);
795: int lowerNibble = (b & 0x0f);
796:
797: sb.append(ENCODE_TABLE[upperNibble]);
798: sb.append(ENCODE_TABLE[lowerNibble]);
799: sb.append(" ");
800: }
801: return sb.toString();
802: } */
803:
804: /**
805: * XMLizable Wrapper for one or more folders, saxing folders.
806: *
807: */
808: static class FolderXMLizer extends AbstractLogEnabled implements
809: XMLizable {
810: //private Folder folder;
811: private Folder[] folders;
812:
813: /**
814: *Constructor for the FolderSAX object
815: *
816: * @param folder Description of the Parameter
817: */
818: FolderXMLizer(Folder folder) {
819: this .folders = new Folder[] { folder };
820: }
821:
822: /**
823: *Constructor for the FolderXMLizer object
824: *
825: * @param folders Description of the Parameter
826: */
827: FolderXMLizer(Folder[] folders) {
828: this .folders = folders;
829: }
830:
831: /**
832: * Generate SAX events from one or more folders
833: *
834: * @param handler Description of the Parameter
835: * @exception SAXException thrown iff generating SAX events fails
836: */
837: public void toSAX(ContentHandler handler) throws SAXException {
838: MailContentHandlerDelegate mailContentHandlerDelegate = new MailContentHandlerDelegate(
839: handler);
840: mailContentHandlerDelegate.enableLogging(getLogger());
841: mailContentHandlerDelegate.startDocumentXMLizer();
842: for (int i = 0; i < folders.length; i++) {
843: mailContentHandlerDelegate
844: .marshalFolderToSAX(folders[i]);
845: }
846: mailContentHandlerDelegate.endDocumentXMLizer();
847: }
848: }
849:
850: /**
851: * XMLizable Wrapper for one or more messages, saxing envelope only of messages.
852: */
853: static class MessageEnvelopeXMLizer extends AbstractLogEnabled
854: implements XMLizable {
855: private Message[] messages;
856:
857: private SimpleDateFormat sdf;
858:
859: /**
860: *Constructor for the MessageEnvelopeXMLizer object
861: *
862: * @param message Description of the Parameter
863: */
864: public MessageEnvelopeXMLizer(Message message) {
865: this .messages = new Message[1];
866: this .messages[0] = message;
867: }
868:
869: /**
870: *Constructor for the MessageEnvelopeXMLize object
871: *
872: * @param messages Description of the Parameter
873: */
874: public MessageEnvelopeXMLizer(Message[] messages) {
875: this .messages = messages;
876: }
877:
878: /**
879: * Sets the simpleDateFormat attribute of the MessageEnvelopeXMLizer object
880: *
881: * @param sdf The new simpleDateFormat value
882: */
883: public void setSimpleDateFormat(SimpleDateFormat sdf) {
884: this .sdf = sdf;
885: }
886:
887: /**
888: * Gets the simpleDateFormat attribute of the MessageEnvelopeXMLizer object
889: *
890: * @param sdf Description of the Parameter
891: */
892: public void getSimpleDateFormat(SimpleDateFormat sdf) {
893: this .sdf = sdf;
894: }
895:
896: /**
897: * Generate SAX events from one or more messages
898: *
899: * @param handler Description of the Parameter
900: * @exception SAXException thrown iff generating SAX events fails
901: */
902: public void toSAX(ContentHandler handler) throws SAXException {
903: MailContentHandlerDelegate mailContentHandlerDelegate = new MailContentHandlerDelegate(
904: handler);
905: mailContentHandlerDelegate.enableLogging(getLogger());
906: mailContentHandlerDelegate.setSimpleDateFormat(sdf);
907: mailContentHandlerDelegate.startDocumentXMLizer();
908:
909: for (int i = 0; i < messages.length; i++) {
910: mailContentHandlerDelegate
911: .marshalMessageEnvelopeToSAX(messages[i]);
912: }
913:
914: mailContentHandlerDelegate.endDocumentXMLizer();
915: }
916: }
917:
918: /**
919: * XMLizable Wrapper for a message, saxing a message envelope, plus content.
920: */
921: static class MessageXMLizer extends AbstractLogEnabled implements
922: XMLizable {
923: private Message message;
924:
925: private SimpleDateFormat sdf;
926:
927: /**
928: *Constructor for the MessageXMLizer object
929: *
930: * @param message Description of the Parameter
931: */
932: public MessageXMLizer(Message message) {
933: this .message = message;
934: }
935:
936: /**
937: * Sets the simpleDateFormat attribute of the MessageXMLizer object
938: *
939: * @param sdf The new simpleDateFormat value
940: */
941: public void setSimpleDateFormat(SimpleDateFormat sdf) {
942: this .sdf = sdf;
943: }
944:
945: /**
946: * Gets the simpleDateFormat attribute of the MessageXMLizer object
947: *
948: * @param sdf Description of the Parameter
949: */
950: public void getSimpleDateFormat(SimpleDateFormat sdf) {
951: this .sdf = sdf;
952: }
953:
954: /**
955: * Generate SAX events from a message
956: *
957: * @param handler Description of the Parameter
958: * @exception SAXException thrown iff generating SAX events fails
959: */
960: public void toSAX(ContentHandler handler) throws SAXException {
961: MailContentHandlerDelegate mailContentHandlerDelegate = new MailContentHandlerDelegate(
962: handler);
963: mailContentHandlerDelegate.enableLogging(getLogger());
964: mailContentHandlerDelegate.setSimpleDateFormat(sdf);
965: mailContentHandlerDelegate.startDocumentXMLizer();
966: mailContentHandlerDelegate.marshalMessageToSAX(message);
967: mailContentHandlerDelegate.endDocumentXMLizer();
968: }
969: }
970: }
|