001: /*
002: * $Id: RetrieveMessageRequester.java 10961 2008-02-22 19:01:02Z dfeist $
003: * --------------------------------------------------------------------------------------
004: * Copyright (c) MuleSource, Inc. All rights reserved. http://www.mulesource.com
005: *
006: * The software in this package is published under the terms of the CPAL v1.0
007: * license, a copy of which has been included with this distribution in the
008: * LICENSE.txt file.
009: */
010:
011: package org.mule.transport.email;
012:
013: import org.mule.DefaultMuleMessage;
014: import org.mule.api.MuleEvent;
015: import org.mule.api.MuleMessage;
016: import org.mule.api.endpoint.EndpointURI;
017: import org.mule.api.endpoint.InboundEndpoint;
018: import org.mule.transport.AbstractMessageRequester;
019:
020: import javax.mail.Flags;
021: import javax.mail.Folder;
022: import javax.mail.Message;
023: import javax.mail.MessagingException;
024: import javax.mail.Store;
025:
026: /**
027: * This dispatcher can only be used to receive message (as opposed to listening for them).
028: * Trying to send or dispatch will throw an UnsupportedOperationException.
029: *
030: * This contains a reference to a mail folder (and also the endpoint and connector, via superclasses)
031: */
032:
033: public class RetrieveMessageRequester extends AbstractMessageRequester {
034: private Folder folder;
035:
036: public RetrieveMessageRequester(InboundEndpoint endpoint) {
037: super (endpoint);
038: }
039:
040: private AbstractRetrieveMailConnector castConnector() {
041: return (AbstractRetrieveMailConnector) getConnector();
042: }
043:
044: protected void doConnect() throws Exception {
045: if (folder == null || !folder.isOpen()) {
046:
047: Store store = castConnector().getSessionDetails(endpoint)
048: .newStore();
049:
050: EndpointURI uri = endpoint.getEndpointURI();
051: store.connect(uri.getHost(), uri.getPort(), uri.getUser(),
052: uri.getPassword());
053:
054: folder = store
055: .getFolder(castConnector().getMailboxFolder());
056: if (!folder.isOpen()) {
057: try {
058: // Depending on Server implementation it's not always
059: // necessary to open the folder to check it
060: // Opening folders can be exprensive!
061: // folder.open(Folder.READ_ONLY);
062: folder.open(Folder.READ_WRITE);
063: } catch (MessagingException e) {
064: logger.warn("Failed to open folder: "
065: + folder.getFullName(), e);
066: }
067: }
068: }
069: }
070:
071: protected void doDisconnect() throws Exception {
072: // close and expunge deleted messages
073: try {
074: if (folder != null) {
075: try {
076: folder.expunge();
077: } catch (MessagingException e) {
078: if (logger.isDebugEnabled()) {
079: logger.debug("ignoring exception on expunge: "
080: + e.getMessage());
081: }
082: }
083: if (folder.isOpen()) {
084: folder.close(true);
085: }
086: }
087: } catch (Exception e) {
088: logger.error("Failed to close inbox: " + e.getMessage(), e);
089: }
090: }
091:
092: /**
093: * @param event
094: * @throws UnsupportedOperationException
095: */
096: protected void doDispatch(MuleEvent event) throws Exception {
097: throw new UnsupportedOperationException(
098: "Cannot dispatch from a Pop3 connection");
099: }
100:
101: /**
102: * @param event
103: * @return
104: * @throws UnsupportedOperationException
105: */
106: protected MuleMessage doSend(MuleEvent event) throws Exception {
107: throw new UnsupportedOperationException(
108: "Cannot send from a Pop3 connection");
109: }
110:
111: /**
112: * Make a specific request to the underlying transport. Endpoint can be in the
113: * form of pop3://username:password@pop3.lotsofmail.org
114: *
115: * @param timeout the maximum time the operation should block before returning.
116: * The call should return immediately if there is data available. If
117: * no data becomes available before the timeout elapses, null will be
118: * returned
119: * @return the result of the request wrapped in a MuleMessage object. Null will be
120: * returned if no data was avaialable
121: * @throws Exception if the call to the underlying protocal causes an exception
122: */
123: protected MuleMessage doRequest(long timeout) throws Exception {
124: long t0 = System.currentTimeMillis();
125: if (timeout < 0) {
126: timeout = Long.MAX_VALUE;
127: }
128:
129: do {
130: if (hasMessages(folder)) {
131: int count = getMessageCount(folder);
132: if (count > 0) {
133: Message message = getNextMessage(folder);
134: // so we don't get the same message again
135: flagMessage(folder, message);
136:
137: return new DefaultMuleMessage(castConnector()
138: .getMessageAdapter(message));
139: } else if (count == -1) {
140: throw new MessagingException(
141: "Cannot monitor folder: "
142: + folder.getFullName()
143: + " as folder is closed");
144: }
145: }
146:
147: long sleep = Math.min(castConnector().getCheckFrequency(),
148: timeout - (System.currentTimeMillis() - t0));
149:
150: if (sleep > 0) {
151: if (logger.isDebugEnabled()) {
152: logger.debug("No results, sleeping for " + sleep);
153: }
154: Thread.sleep(sleep);
155: } else {
156:
157: logger.debug("Timeout");
158: return null;
159: }
160:
161: } while (true);
162: }
163:
164: /**
165: * There seems to be som variation on pop3 implementation so it may be
166: * preferrable to mark messages as seen here and alos overload the getMessages
167: * method to grab only new messages
168: *
169: * @param message
170: * @throws javax.mail.MessagingException
171: */
172: protected void flagMessage(Folder folder, Message message)
173: throws MessagingException {
174: message.setFlag(Flags.Flag.DELETED, true);
175: }
176:
177: protected static Message getNextMessage(Folder folder)
178: throws MessagingException {
179: return folder.getMessage(1);
180: }
181:
182: protected static int getMessageCount(Folder folder)
183: throws MessagingException {
184: return folder.getMessageCount();
185: }
186:
187: /**
188: * Optimised check to se whether to return the message count and retrieve the
189: * messages. Some pop3 implementations differ so an optimised check such as
190: * folder.hasNewMessages() cannot be used
191: *
192: * @param folder
193: * @return
194: * @throws javax.mail.MessagingException
195: */
196: protected static boolean hasMessages(Folder folder)
197: throws MessagingException {
198: return getMessageCount(folder) > 0;
199: }
200:
201: protected void doDispose() {
202: if (null != folder && folder.isOpen()) {
203: try {
204:
205: folder.close(true);
206: } catch (Exception e) {
207: logger
208: .debug("ignoring exception: " + e.getMessage(),
209: e);
210: }
211: }
212: }
213:
214: }
|