You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by do...@apache.org on 2013/08/21 18:35:18 UTC
svn commit: r1516205 [5/9] - in /james/hupa/trunk: ./
client/src/main/java/org/apache/hupa/
client/src/main/java/org/apache/hupa/client/
client/src/main/java/org/apache/hupa/client/gin/
client/src/main/java/org/apache/hupa/client/mvp/ client/src/main/j...
Added: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/AbstractDeleteMessageHandler.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/AbstractDeleteMessageHandler.java?rev=1516205&view=auto
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/AbstractDeleteMessageHandler.java (added)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/AbstractDeleteMessageHandler.java Wed Aug 21 16:35:16 2013
@@ -0,0 +1,123 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.hupa.server.handler;
+
+import javax.mail.Flags;
+import javax.mail.Message;
+import javax.mail.MessagingException;
+import javax.servlet.http.HttpSession;
+
+import net.customware.gwt.dispatch.server.ExecutionContext;
+import net.customware.gwt.dispatch.shared.ActionException;
+
+import org.apache.commons.logging.Log;
+import org.apache.hupa.server.IMAPStoreCache;
+import org.apache.hupa.shared.data.User;
+import org.apache.hupa.shared.rpc.DeleteMessage;
+import org.apache.hupa.shared.rpc.DeleteMessageResult;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.sun.mail.imap.IMAPStore;
+
+/**
+ * Abstract class which should get extended by all handlers which needs to handle message deletion
+ *
+ * @param <Action>
+ */
+public abstract class AbstractDeleteMessageHandler<Action extends DeleteMessage>
+ extends AbstractSessionHandler<Action, DeleteMessageResult> {
+
+ @Inject
+ public AbstractDeleteMessageHandler(IMAPStoreCache cache, Log logger,
+ Provider<HttpSession> sessionProvider) {
+ super(cache, logger, sessionProvider);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.apache.hupa.server.handler.AbstractSessionHandler#executeInternal(org.apache.hupa.shared.rpc.Session, net.customware.gwt.dispatch.server.ExecutionContext)
+ */
+ public DeleteMessageResult executeInternal(Action action,
+ ExecutionContext context) throws ActionException {
+ org.apache.hupa.shared.data.IMAPFolder folder = action.getFolder();
+ User user = getUser();
+ try {
+ IMAPStore store = cache.get(user);
+ com.sun.mail.imap.IMAPFolder f = (com.sun.mail.imap.IMAPFolder) store
+ .getFolder(folder.getFullName());
+ // check if the folder is open, if not open it "rw"
+ if (f.isOpen() == false) {
+ f.open(com.sun.mail.imap.IMAPFolder.READ_WRITE);
+ }
+
+ Message[] mArray = getMessagesToDelete(action);
+
+ // check if the delete was triggered not in the trash folder
+ if (folder.getFullName().equalsIgnoreCase(
+ user.getSettings().getTrashFolderName()) == false) {
+ com.sun.mail.imap.IMAPFolder trashFolder = (com.sun.mail.imap.IMAPFolder) store
+ .getFolder(user.getSettings().getTrashFolderName());
+
+ boolean trashFound = false;
+ // if the trash folder does not exist we create it
+ if (trashFolder.exists() == false) {
+ trashFound = trashFolder
+ .create(com.sun.mail.imap.IMAPFolder.READ_WRITE);
+ } else {
+ trashFound = true;
+ }
+
+ // Check if we are able to copy the messages to the trash folder
+ if (trashFound) {
+ // copy the messages to the trashfolder
+ f.copyMessages(mArray, trashFolder);
+ }
+ }
+
+
+ // delete the messages from the folder
+ f.setFlags(mArray, new Flags(Flags.Flag.DELETED), true);
+
+ try {
+ f.expunge(mArray);
+ f.close(false);
+ } catch (MessagingException e) {
+ // prolly UID expunge is not supported
+ f.close(true);
+ }
+ return new DeleteMessageResult(user, folder, mArray.length);
+
+ } catch (MessagingException e) {
+ logger.error("Error while deleting messages for user " + user
+ + " in folder" + action.getFolder(), e);
+ throw new ActionException("Error while deleting messages");
+ }
+ }
+
+ /**
+ * Return an array holding all messages which should get deleted by the given action
+ *
+ * @param action
+ * @return messages
+ * @throws ActionException
+ */
+ protected abstract Message[] getMessagesToDelete(Action action) throws ActionException;
+}
Added: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/AbstractFetchMessagesHandler.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/AbstractFetchMessagesHandler.java?rev=1516205&view=auto
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/AbstractFetchMessagesHandler.java (added)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/AbstractFetchMessagesHandler.java Wed Aug 21 16:35:16 2013
@@ -0,0 +1,272 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.hupa.server.handler;
+
+import com.google.inject.Provider;
+
+import com.sun.mail.imap.IMAPStore;
+
+import net.customware.gwt.dispatch.server.ExecutionContext;
+import net.customware.gwt.dispatch.shared.ActionException;
+
+import org.apache.commons.logging.Log;
+import org.apache.hupa.server.IMAPStoreCache;
+import org.apache.hupa.server.preferences.UserPreferencesStorage;
+import org.apache.hupa.shared.data.IMAPFolder;
+import org.apache.hupa.shared.data.Tag;
+import org.apache.hupa.shared.data.User;
+import org.apache.hupa.shared.data.Message.IMAPFlag;
+import org.apache.hupa.shared.rpc.FetchMessages;
+import org.apache.hupa.shared.rpc.FetchMessagesResult;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+
+import javax.mail.Address;
+import javax.mail.FetchProfile;
+import javax.mail.Message;
+import javax.mail.MessagingException;
+import javax.mail.Multipart;
+import javax.mail.Part;
+import javax.mail.internet.MimeUtility;
+import javax.mail.internet.MimeMessage.RecipientType;
+import javax.servlet.http.HttpSession;
+
+public abstract class AbstractFetchMessagesHandler <A extends FetchMessages> extends AbstractSessionHandler<A, FetchMessagesResult>{
+
+ UserPreferencesStorage userPreferences;
+
+ public AbstractFetchMessagesHandler(IMAPStoreCache cache, Log logger, Provider<HttpSession> sessionProvider, UserPreferencesStorage preferences) {
+ super(cache, logger, sessionProvider);
+ this.userPreferences = preferences;
+ }
+
+ @Override
+ protected FetchMessagesResult executeInternal(A action,
+ ExecutionContext context) throws ActionException {
+ User user = getUser();
+ IMAPFolder folder = action.getFolder();
+ if (folder == null) {
+ folder = new IMAPFolder(user.getSettings().getInboxFolderName());
+ }
+ com.sun.mail.imap.IMAPFolder f = null;
+ int start = action.getStart();
+ int offset = action.getOffset();
+ try {
+ IMAPStore store = cache.get(user);
+
+ f = (com.sun.mail.imap.IMAPFolder)store.getFolder(folder.getFullName());
+
+ // check if the folder is open, if not open it read only
+ if (f.isOpen() == false) {
+ f.open(com.sun.mail.imap.IMAPFolder.READ_ONLY);
+ }
+
+ // if the folder is empty we have no need to process
+ int exists = f.getMessageCount();
+ if (exists == 0) {
+ return new FetchMessagesResult(new ArrayList<org.apache.hupa.shared.data.Message>(), start, offset, 0, 0);
+ }
+
+ MessageConvertArray convArray = getMessagesToConvert(f,action);
+ return new FetchMessagesResult(convert(offset, f, convArray.getMesssages()),start, offset,convArray.getRealCount(),f.getUnreadMessageCount());
+ } catch (MessagingException e) {
+ logger.info("Error fetching messages in folder: " + folder.getFullName() + " " + e.getMessage());
+ // Folder can not contain messages
+ return new FetchMessagesResult(new ArrayList<org.apache.hupa.shared.data.Message>(), start, offset, 0, 0);
+ } catch (Exception e) {
+ e.printStackTrace();
+ logger.error("Error while fetching headers for user " + user.getName() + " in folder " + folder,e);
+ throw new ActionException(
+ "Error while fetching headers for user " + user.getName() + " in folder " + folder);
+
+ } finally {
+ if (f != null && f.isOpen()) {
+ try {
+ f.close(false);
+ } catch (MessagingException e) {
+ // we don't care to much about an exception on close here...
+ }
+ }
+ }
+ }
+
+ protected abstract MessageConvertArray getMessagesToConvert(com.sun.mail.imap.IMAPFolder f, A action) throws MessagingException, ActionException;
+
+ protected ArrayList<org.apache.hupa.shared.data.Message> convert(int offset, com.sun.mail.imap.IMAPFolder folder, Message[] messages) throws MessagingException {
+ ArrayList<org.apache.hupa.shared.data.Message> mList = new ArrayList<org.apache.hupa.shared.data.Message>();
+ // Setup fetchprofile to limit the stuff which is fetched
+ FetchProfile fp = new FetchProfile();
+ fp.add(FetchProfile.Item.ENVELOPE);
+ fp.add(FetchProfile.Item.FLAGS);
+ fp.add(FetchProfile.Item.CONTENT_INFO);
+ folder.fetch(messages, fp);
+
+ // loop over the fetched messages
+ for (int i = 0; i < messages.length && i < offset; i++) {
+ org.apache.hupa.shared.data.Message msg = new org.apache.hupa.shared.data.Message();
+ Message m = messages[i];
+ String from = null;
+ if (m.getFrom() != null && m.getFrom().length >0 ) {
+ from = m.getFrom()[0].toString().trim();
+ try {
+ from = MimeUtility.decodeText(from);
+ userPreferences.addContact(from);
+ } catch (UnsupportedEncodingException e) {
+ logger.debug("Unable to decode from " + from + " " + e.getMessage());
+ }
+ }
+ msg.setFrom(from);
+
+ String replyto = null;
+ if (m.getReplyTo() != null && m.getReplyTo().length >0 ) {
+ replyto = m.getReplyTo()[0].toString().trim();
+ try {
+ replyto = MimeUtility.decodeText(replyto);
+ userPreferences.addContact(replyto);
+ } catch (UnsupportedEncodingException e) {
+ logger.debug("Unable to decode replyto " + replyto + " " + e.getMessage());
+ }
+ }
+ msg.setReplyto(replyto);
+
+ ArrayList<String> to = new ArrayList<String>();
+ // Add to addresses
+ Address[] toArray = m.getRecipients(RecipientType.TO);
+ if (toArray != null) {
+ for (Address addr : toArray) {
+ String mailTo = null;
+ try {
+ mailTo = MimeUtility.decodeText(addr.toString());
+ userPreferences.addContact(mailTo);
+ } catch (UnsupportedEncodingException e) {
+ logger.debug("Unable to decode mailTo " + mailTo + " " + e.getMessage());
+ }
+ if (mailTo != null)
+ to.add(mailTo);
+ }
+ }
+ msg.setTo(to);
+
+ // Check if a subject exist and if so decode it
+ String subject = m.getSubject();
+ if (subject != null) {
+ try {
+ subject = MimeUtility.decodeText(subject);
+ } catch (UnsupportedEncodingException e) {
+ logger.debug("Unable to decode subject " + subject + " " + e.getMessage());
+ }
+ }
+ msg.setSubject(subject);
+
+ // Add cc addresses
+ Address[] ccArray = m.getRecipients(RecipientType.CC);
+ ArrayList<String> cc = new ArrayList<String>();
+ if (ccArray != null) {
+ for (Address addr : ccArray) {
+ String mailCc = null;
+ try {
+ mailCc = MimeUtility.decodeText(addr.toString());
+ userPreferences.addContact(mailCc);
+ } catch (UnsupportedEncodingException e) {
+ logger.debug("Unable to decode mailTo " + mailCc + " " + e.getMessage());
+ }
+ if (mailCc != null)
+ cc.add(mailCc);
+ }
+ }
+ msg.setCc(cc);
+
+ // Using sentDate since received date is not useful in the view when using fetchmail
+ msg.setReceivedDate(m.getSentDate());
+
+ // Add flags
+ ArrayList<IMAPFlag> iFlags = JavamailUtil.convert(m.getFlags());
+
+ ArrayList<Tag> tags = new ArrayList<Tag>();
+ for (String flag : m.getFlags().getUserFlags()) {
+ if (flag.startsWith(Tag.PREFIX)) {
+ tags.add(new Tag(flag.substring(Tag.PREFIX.length())));
+ }
+ }
+
+ msg.setUid(folder.getUID(m));
+ msg.setFlags(iFlags);
+ msg.setTags(tags);
+ try {
+ msg.setHasAttachments(hasAttachment(m));
+ } catch (MessagingException e) {
+ logger.debug("Unable to identify attachments in message UID:" + msg.getUid() + " subject:" + msg.getSubject() + " cause:" + e.getMessage());
+ logger.info("");
+ }
+ mList.add(0, msg);
+
+ }
+ return mList;
+ }
+
+ private boolean hasAttachment(Message message) throws MessagingException {
+ if (message.getContentType().startsWith("multipart/")) {
+ try {
+ Object content;
+
+ content = message.getContent();
+
+ if (content instanceof Multipart) {
+ Multipart mp = (Multipart) content;
+ if (mp.getCount() > 1) {
+ for (int i = 0; i < mp.getCount(); i++) {
+ String disp = mp.getBodyPart(i).getDisposition();
+ if (disp != null
+ && disp.equalsIgnoreCase(Part.ATTACHMENT)) {
+ return true;
+ }
+ }
+ }
+
+ }
+ } catch (IOException e) {
+ logger.error("Error while get content of message " + message.getMessageNumber());
+ }
+
+ }
+ return false;
+ }
+
+
+ protected final class MessageConvertArray {
+ private Message[] messages;
+ private int realCount;
+
+ public MessageConvertArray(int realCount, Message[] messages) {
+ this.messages = messages;
+ this.realCount = realCount;
+ }
+
+ public int getRealCount() {
+ return realCount;
+ }
+
+ public Message[] getMesssages() {
+ return messages;
+ }
+ }
+}
Added: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/AbstractSendMessageHandler.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/AbstractSendMessageHandler.java?rev=1516205&view=auto
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/AbstractSendMessageHandler.java (added)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/AbstractSendMessageHandler.java Wed Aug 21 16:35:16 2013
@@ -0,0 +1,427 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.hupa.server.handler;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.activation.DataSource;
+import javax.mail.Address;
+import javax.mail.AuthenticationFailedException;
+import javax.mail.BodyPart;
+import javax.mail.Flags.Flag;
+import javax.mail.Folder;
+import javax.mail.Message;
+import javax.mail.MessagingException;
+import javax.mail.Multipart;
+import javax.mail.Session;
+import javax.mail.Transport;
+import javax.mail.internet.AddressException;
+import javax.mail.internet.InternetAddress;
+import javax.mail.internet.MimeBodyPart;
+import javax.mail.internet.MimeMessage;
+import javax.mail.internet.MimeMessage.RecipientType;
+import javax.mail.internet.MimeMultipart;
+import javax.servlet.http.HttpSession;
+
+import net.customware.gwt.dispatch.server.ExecutionContext;
+import net.customware.gwt.dispatch.shared.ActionException;
+
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.logging.Log;
+import org.apache.hupa.server.FileItemRegistry;
+import org.apache.hupa.server.IMAPStoreCache;
+import org.apache.hupa.server.preferences.UserPreferencesStorage;
+import org.apache.hupa.server.utils.MessageUtils;
+import org.apache.hupa.server.utils.RegexPatterns;
+import org.apache.hupa.server.utils.SessionUtils;
+import org.apache.hupa.shared.data.MessageAttachment;
+import org.apache.hupa.shared.data.SMTPMessage;
+import org.apache.hupa.shared.data.User;
+import org.apache.hupa.shared.rpc.GenericResult;
+import org.apache.hupa.shared.rpc.SendMessage;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.name.Named;
+import com.sun.mail.imap.IMAPFolder;
+import com.sun.mail.imap.IMAPStore;
+
+/**
+ * Handle sending of email messages
+ *
+ */
+public abstract class AbstractSendMessageHandler<A extends SendMessage> extends AbstractSessionHandler<A,GenericResult> {
+
+ private final boolean auth;
+ private final String address;
+ private final int port;
+ private boolean useSSL = false;
+ UserPreferencesStorage userPreferences;
+ Session session;
+
+ @Inject
+ public AbstractSendMessageHandler(Log logger, IMAPStoreCache store, Provider<HttpSession> provider, UserPreferencesStorage preferences, @Named("SMTPServerAddress") String address, @Named("SMTPServerPort") int port, @Named("SMTPAuth") boolean auth, @Named("SMTPS") boolean useSSL) {
+ super(store,logger,provider);
+ this.auth = auth;
+ this.address = address;
+ this.port = port;
+ this.useSSL = useSSL;
+ this.userPreferences = preferences;
+ this.session = store.getMailSession();
+ session.getProperties().put("mail.smtp.auth", auth);
+ }
+
+ @Override
+ protected GenericResult executeInternal(A action, ExecutionContext context)
+ throws ActionException {
+ GenericResult result = new GenericResult();
+ try {
+
+ Message message = createMessage(session, action);
+ message = fillBody(message,action);
+
+ sendMessage(getUser(), message);
+ saveSentMessage(getUser(), message);
+
+ resetAttachments(action);
+
+ // TODO: notify the user more accurately where the error is
+ // if the message was sent and the storage in the sent folder failed, etc.
+ } catch (AddressException e) {
+ result.setError("Error while parsing recipient: " + e.getMessage());
+ logger.error("Error while parsing recipient", e);
+ } catch (AuthenticationFailedException e) {
+ result.setError("Error while sending message: SMTP Authentication error.");
+ logger.error("SMTP Authentication error", e);
+ } catch (MessagingException e) {
+ result.setError("Error while sending message: " + e.getMessage());
+ logger.error("Error while sending message", e);
+ } catch (Exception e) {
+ result.setError("Unexpected exception while sendig message: " + e.getMessage());
+ logger.error("Unexpected exception while sendig message: ", e);
+ }
+ return result;
+ }
+
+ /**
+ * Create basic Message which contains all headers. No body is filled
+ *
+ * @param session the Session
+ * @param action the action
+ * @return message
+ * @throws AddressException
+ * @throws MessagingException
+ * @throws ActionException
+ */
+ protected Message createMessage(Session session, A action) throws AddressException, MessagingException {
+ MimeMessage message = new MimeMessage(session);
+ SMTPMessage m = action.getMessage();
+ message.setFrom(new InternetAddress(m.getFrom()));
+
+ userPreferences.addContact(m.getTo());
+ userPreferences.addContact(m.getCc());
+ userPreferences.addContact(m.getBcc());
+
+ message.setRecipients(RecipientType.TO, MessageUtils.getRecipients(m.getTo()));
+ message.setRecipients(RecipientType.CC, MessageUtils.getRecipients(m.getCc()));
+ message.setRecipients(RecipientType.BCC, MessageUtils.getRecipients(m.getBcc()));
+ message.setSubject(m.getSubject());
+ message.saveChanges();
+ return message;
+ }
+ /**
+ * Fill the body of the given message with data which the given action contain
+ *
+ * @param message the message
+ * @param action the action
+ * @return filledMessage
+ * @throws MessagingException
+ * @throws ActionException
+ * @throws IOException
+ */
+ protected Message fillBody(Message message, A action) throws MessagingException, ActionException, IOException {
+
+ String html = restoreInlineLinks(action.getMessage().getText());
+
+ // TODO: client sends the message as a html document right now,
+ // the idea is that it should be sent in both formats because
+ // it is easier to handle html in the browser.
+ String text = htmlToText(html);
+
+ @SuppressWarnings("rawtypes")
+ List items = getAttachments(action);
+
+ return composeMessage(message, text, html, items);
+ }
+
+ protected String restoreInlineLinks(String s) {
+ return RegexPatterns.replaceAll(s, RegexPatterns.regex_revertInlineImg, RegexPatterns.repl_revertInlineImg);
+ }
+
+ // TODO: just temporary stuff because it has to be done in the client side
+ protected String htmlToText(String s){
+ s=s.replaceAll("\n", " ");
+ s=s.replaceAll("(?si)<br\\s*?/?>", "\n");
+ s=s.replaceAll("(?si)</div\\s*?>", "\n");
+ s=s.replaceAll("(\\w)<.*?>(\\w)", "$1 $2");
+ s=s.replaceAll("<.*?>", "");
+ s=s.replaceAll("[ \t]+", " ");
+ return s;
+ }
+
+ /**
+ * Get the attachments stored in the registry.
+ *
+ * @param action
+ * @return A list of stored attachments
+ */
+ @SuppressWarnings("rawtypes")
+ protected List getAttachments(A action) throws MessagingException, ActionException {
+ FileItemRegistry registry = SessionUtils.getSessionRegistry(logger, httpSessionProvider.get());
+ List<MessageAttachment> attachments = action.getMessage().getMessageAttachments();
+
+ ArrayList<FileItem> items = new ArrayList<FileItem>();
+ if (attachments != null && attachments.size() > 0) {
+ for (MessageAttachment attachment: attachments) {
+ FileItem fItem = registry.get(attachment.getName());
+ if (fItem != null)
+ items.add(fItem);
+ }
+ logger.debug("Found " + items.size() + " attachmets in the registry.");
+ }
+ return items;
+ }
+
+ /**
+ * Remove attachments from the registry
+ *
+ * @param action
+ * @throws MessagingException
+ * @throws ActionException
+ */
+ protected void resetAttachments(A action) throws MessagingException, ActionException {
+ SMTPMessage msg = action.getMessage();
+ ArrayList<MessageAttachment> attachments = msg.getMessageAttachments();
+ if (attachments != null && ! attachments.isEmpty()) {
+ for(MessageAttachment attach : attachments)
+ SessionUtils.getSessionRegistry(logger, httpSessionProvider.get()).remove(attach.getName());
+ }
+ }
+
+ /**
+ * Send the message using SMTP, if the configuration uses authenticated SMTP, it uses
+ * the user stored in session to get the given login and password.
+ *
+ * @param user
+ * @param session
+ * @param message
+ * @throws MessagingException
+ */
+ protected void sendMessage(User user, Message message) throws MessagingException {
+
+ Transport transport = cache.getMailTransport(useSSL);
+
+ if (auth) {
+ logger.debug("Use auth for smtp connection");
+ transport.connect(address,port,user.getName(), user.getPassword());
+ } else {
+ transport.connect(address, port, null,null);
+ }
+
+ Address[] recips = message.getAllRecipients();
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < recips.length; i++) {
+ sb.append(recips[i]);
+ if (i != recips.length -1) {
+ sb.append(", ");
+ }
+ }
+ logger.info("Send message from " + message.getFrom()[0].toString()+ " to " + sb.toString());
+ transport.sendMessage(message, recips);
+ }
+
+ /**
+ * Save the message in the sent folder
+ *
+ * @param user
+ * @param message
+ * @throws MessagingException
+ * @throws IOException
+ */
+ protected void saveSentMessage(User user, Message message) throws MessagingException, IOException {
+ IMAPStore iStore = cache.get(user);
+ IMAPFolder folder = (IMAPFolder) iStore.getFolder(user.getSettings().getSentFolderName());
+
+ if (folder.exists() || folder.create(IMAPFolder.READ_WRITE)) {
+ if (folder.isOpen() == false) {
+ folder.open(Folder.READ_WRITE);
+ }
+
+ // It is necessary to copy the message, before putting it
+ // in the sent folder. If not, it is not guaranteed that it is
+ // stored in ascii and is not possible to get the attachments
+ // size. message.saveChanges() doesn't fix the problem.
+ // There are tests which demonstrate this.
+ message = new MimeMessage((MimeMessage)message);
+
+ message.setFlag(Flag.SEEN, true);
+ folder.appendMessages(new Message[] {message});
+
+ try {
+ folder.close(false);
+ } catch (MessagingException e) {
+ // we don't care on close
+ }
+ }
+ }
+
+ /**
+ * Fill the body of a message already created.
+ * The result message depends on the information given.
+ *
+ * @param message
+ * @param text
+ * @param html
+ * @param parts
+ * @return The composed message
+ * @throws MessagingException
+ * @throws IOException
+ */
+ @SuppressWarnings("rawtypes")
+ public static Message composeMessage (Message message, String text, String html, List parts) throws MessagingException, IOException {
+
+ MimeBodyPart txtPart = null;
+ MimeBodyPart htmlPart = null;
+ MimeMultipart mimeMultipart = null;
+
+ if (text == null && html == null) {
+ text = "";
+ }
+ if (text != null) {
+ txtPart = new MimeBodyPart();
+ txtPart.setContent(text, "text/plain");
+ }
+ if (html != null) {
+ htmlPart = new MimeBodyPart();
+ htmlPart.setContent(html, "text/html");
+ }
+ if (html != null && text != null) {
+ mimeMultipart = new MimeMultipart();
+ mimeMultipart.setSubType("alternative");
+ mimeMultipart.addBodyPart(txtPart);
+ mimeMultipart.addBodyPart(htmlPart);
+ }
+
+ if (parts == null || parts.isEmpty()) {
+ if (mimeMultipart != null) {
+ message.setContent(mimeMultipart);
+ } else if (html != null) {
+ message.setText(html);
+ message.setHeader("Content-type", "text/html");
+ } else if (text != null) {
+ message.setText(text);
+ }
+ } else {
+ MimeBodyPart bodyPart = new MimeBodyPart();
+ if (mimeMultipart != null) {
+ bodyPart.setContent(mimeMultipart);
+ } else if (html != null) {
+ bodyPart.setText(html);
+ bodyPart.setHeader("Content-type", "text/html");
+ } else if (text != null) {
+ bodyPart.setText(text);
+ }
+ Multipart multipart = new MimeMultipart();
+ multipart.addBodyPart(bodyPart);
+ for (Object attachment: parts) {
+ if (attachment instanceof FileItem) {
+ multipart.addBodyPart(MessageUtils.fileitemToBodypart((FileItem)attachment));
+ } else {
+ multipart.addBodyPart((BodyPart)attachment);
+ }
+ }
+ message.setContent(multipart);
+ }
+
+ message.saveChanges();
+ return message;
+
+ }
+
+ /**
+ * DataStore which wrap a FileItem
+ *
+ */
+ public static class FileItemDataStore implements DataSource {
+
+ private FileItem item;
+
+ public FileItemDataStore(FileItem item) {
+ this.item = item;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.activation.DataSource#getContentType()
+ */
+ public String getContentType() {
+ return item.getContentType();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.activation.DataSource#getInputStream()
+ */
+ public InputStream getInputStream() throws IOException {
+ return item.getInputStream();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.activation.DataSource#getName()
+ */
+ public String getName() {
+ String fullName = item.getName();
+
+ // Strip path from file
+ int index = fullName.lastIndexOf(File.separator);
+ if (index == -1) {
+ return fullName;
+ } else {
+ return fullName.substring(index +1 ,fullName.length());
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.activation.DataSource#getOutputStream()
+ */
+ public OutputStream getOutputStream() throws IOException {
+ return null;
+ }
+
+ }
+
+}
Added: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/AbstractSessionHandler.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/AbstractSessionHandler.java?rev=1516205&view=auto
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/AbstractSessionHandler.java (added)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/AbstractSessionHandler.java Wed Aug 21 16:35:16 2013
@@ -0,0 +1,92 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+
+package org.apache.hupa.server.handler;
+
+import javax.servlet.http.HttpSession;
+
+import net.customware.gwt.dispatch.server.ActionHandler;
+import net.customware.gwt.dispatch.server.ExecutionContext;
+import net.customware.gwt.dispatch.shared.Action;
+import net.customware.gwt.dispatch.shared.ActionException;
+import net.customware.gwt.dispatch.shared.Result;
+
+import org.apache.commons.logging.Log;
+import org.apache.hupa.server.IMAPStoreCache;
+import org.apache.hupa.shared.SConsts;
+import org.apache.hupa.shared.data.User;
+import org.apache.hupa.shared.exception.InvalidSessionException;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+/**
+ * Abstract class which take care of checking if the session is still valid before
+ * executing the handler
+ *
+ */
+public abstract class AbstractSessionHandler<A extends Action<R>,R extends Result> implements ActionHandler<A, R> {
+
+ protected final Provider<HttpSession> httpSessionProvider;
+ protected final IMAPStoreCache cache;
+ protected final Log logger;
+
+ @Inject
+ public AbstractSessionHandler(IMAPStoreCache cache, Log logger, Provider<HttpSession> httpSessionProvider) {
+ this.httpSessionProvider = httpSessionProvider;
+ this.cache = cache;
+ this.logger = logger;
+ }
+
+ /**
+ * Execute executeInternal method
+ */
+ public R execute(A action, ExecutionContext context) throws ActionException {
+ return executeInternal(action, context);
+ }
+
+ /**
+ * Not implemented. Should get overridden if needed
+ */
+ public void rollback(A action, R result,
+ ExecutionContext context) throws ActionException {
+ // Not implemented
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see net.customware.gwt.dispatch.server.ActionHandler#execute(net.customware.gwt.dispatch.shared.Action, net.customware.gwt.dispatch.server.ExecutionContext)
+ */
+ protected abstract R executeInternal(A action, ExecutionContext context) throws ActionException;
+
+ /**
+ * Return the User stored in session with the given id
+ *
+ * @return user
+ * @throws ActionException
+ */
+ protected User getUser() throws ActionException{
+ User user = (User) httpSessionProvider.get().getAttribute(SConsts.USER_SESS_ATTR);
+ if (user == null) {
+ throw new InvalidSessionException("User not found in session with id " + httpSessionProvider.get().getId());
+ } else {
+ return user;
+ }
+ }
+}
Added: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/CheckSessionHandler.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/CheckSessionHandler.java?rev=1516205&view=auto
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/CheckSessionHandler.java (added)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/CheckSessionHandler.java Wed Aug 21 16:35:16 2013
@@ -0,0 +1,72 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+
+package org.apache.hupa.server.handler;
+
+import javax.servlet.http.HttpSession;
+
+import net.customware.gwt.dispatch.server.ActionHandler;
+import net.customware.gwt.dispatch.server.ExecutionContext;
+import net.customware.gwt.dispatch.shared.ActionException;
+
+import org.apache.commons.logging.Log;
+import org.apache.hupa.shared.data.User;
+import org.apache.hupa.shared.rpc.CheckSession;
+import org.apache.hupa.shared.rpc.CheckSessionResult;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+/**
+ * Handler for asking the server if the session is valid
+ */
+public class CheckSessionHandler implements ActionHandler<CheckSession, CheckSessionResult> {
+
+ protected final Provider<HttpSession> sessionProvider;
+ protected final Log logger;
+
+ @Inject
+ public CheckSessionHandler(Log logger, Provider<HttpSession> provider) {
+ this.sessionProvider = provider;
+ this.logger = logger;
+ }
+
+ public CheckSessionResult execute(CheckSession arg0, ExecutionContext arg1) throws ActionException {
+ CheckSessionResult ret = new CheckSessionResult();
+ try {
+ User user = (User) sessionProvider.get().getAttribute("user");
+ if (user != null && user.getAuthenticated())
+ ret.setUser(user);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ logger.debug("CheckSession returns: " + ret.isValid());
+ return ret;
+ }
+
+ public Class<CheckSession> getActionType() {
+ return CheckSession.class;
+ }
+
+ public void rollback(CheckSession arg0, CheckSessionResult arg1, ExecutionContext arg2) throws ActionException {
+ }
+
+
+}
Added: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/ContactsHandler.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/ContactsHandler.java?rev=1516205&view=auto
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/ContactsHandler.java (added)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/ContactsHandler.java Wed Aug 21 16:35:16 2013
@@ -0,0 +1,60 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.hupa.server.handler;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+import net.customware.gwt.dispatch.server.ActionHandler;
+import net.customware.gwt.dispatch.server.ExecutionContext;
+import net.customware.gwt.dispatch.shared.ActionException;
+
+import org.apache.commons.logging.Log;
+import org.apache.hupa.server.IMAPStoreCache;
+import org.apache.hupa.server.preferences.UserPreferencesStorage;
+import org.apache.hupa.shared.rpc.Contacts;
+import org.apache.hupa.shared.rpc.ContactsResult;
+
+import javax.servlet.http.HttpSession;
+
+/**
+ * Handler for getting the list of contacts
+ */
+public class ContactsHandler implements ActionHandler<Contacts, ContactsResult> {
+
+ UserPreferencesStorage userPreferences;
+
+ @Inject
+ public ContactsHandler(IMAPStoreCache cache, Log logger, Provider<HttpSession> sessionProvider, UserPreferencesStorage preferences) {
+ this.userPreferences = preferences;
+ }
+
+ public ContactsResult execute(Contacts action, ExecutionContext context) throws ActionException {
+ return new ContactsResult(userPreferences.getContacts());
+ }
+
+ public Class<Contacts> getActionType() {
+ return Contacts.class;
+ }
+
+ public void rollback(Contacts action, ContactsResult result, ExecutionContext context) throws ActionException {
+ }
+
+}
Added: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/CreateFolderHandler.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/CreateFolderHandler.java?rev=1516205&view=auto
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/CreateFolderHandler.java (added)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/CreateFolderHandler.java Wed Aug 21 16:35:16 2013
@@ -0,0 +1,83 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.hupa.server.handler;
+
+import javax.mail.Folder;
+import javax.servlet.http.HttpSession;
+
+import net.customware.gwt.dispatch.server.ExecutionContext;
+import net.customware.gwt.dispatch.shared.ActionException;
+
+import org.apache.commons.logging.Log;
+import org.apache.hupa.server.IMAPStoreCache;
+import org.apache.hupa.shared.data.IMAPFolder;
+import org.apache.hupa.shared.data.User;
+import org.apache.hupa.shared.rpc.CreateFolder;
+import org.apache.hupa.shared.rpc.GenericResult;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.sun.mail.imap.IMAPStore;
+
+/**
+ * Handle creation of folders
+ *
+ *
+ */
+public class CreateFolderHandler extends AbstractSessionHandler<CreateFolder, GenericResult>{
+
+ @Inject
+ public CreateFolderHandler(IMAPStoreCache cache, Log logger,
+ Provider<HttpSession> sessionProvider) {
+ super(cache, logger, sessionProvider);
+ }
+
+ @Override
+ protected GenericResult executeInternal(CreateFolder action,
+ ExecutionContext context) throws ActionException {
+ User user = getUser();
+ IMAPFolder folder = action.getFolder();
+
+ try {
+ IMAPStore store = cache.get(user);
+ Folder f = store.getFolder(folder.getFullName());
+ if (f.create(Folder.HOLDS_MESSAGES)) {
+ logger.info("Successfully create folder " + folder + " for user " + user);
+ return new GenericResult();
+ } else {
+ logger.info("Unable to create folder " + folder + " for user " + user);
+ throw new ActionException("Unable to create folder " + folder + " for user " + user);
+
+ }
+ } catch (Exception e) {
+ logger.error("Error while creating folder " + folder + " for user " + user, e);
+ throw new ActionException("Error while creating folder " + folder + " for user " + user, e);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see net.customware.gwt.dispatch.server.ActionHandler#getActionType()
+ */
+ public Class<CreateFolder> getActionType() {
+ return CreateFolder.class;
+ }
+
+}
Added: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/DeleteAllMessagesHandler.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/DeleteAllMessagesHandler.java?rev=1516205&view=auto
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/DeleteAllMessagesHandler.java (added)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/DeleteAllMessagesHandler.java Wed Aug 21 16:35:16 2013
@@ -0,0 +1,79 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.hupa.server.handler;
+
+import javax.mail.Folder;
+import javax.mail.Message;
+import javax.mail.MessagingException;
+import javax.servlet.http.HttpSession;
+
+import net.customware.gwt.dispatch.shared.ActionException;
+
+import org.apache.commons.logging.Log;
+import org.apache.hupa.server.IMAPStoreCache;
+import org.apache.hupa.shared.data.User;
+import org.apache.hupa.shared.rpc.DeleteAllMessages;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.sun.mail.imap.IMAPFolder;
+import com.sun.mail.imap.IMAPStore;
+
+public class DeleteAllMessagesHandler extends AbstractDeleteMessageHandler<DeleteAllMessages>{
+
+ @Inject
+ public DeleteAllMessagesHandler(IMAPStoreCache cache, Log logger,
+ Provider<HttpSession> sessionProvider) {
+ super(cache, logger, sessionProvider);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.apache.hupa.server.handler.AbstractDeleteMessageHandler#getMessagesToDelete(org.apache.hupa.shared.rpc.DeleteMessage)
+ */
+ protected Message[] getMessagesToDelete(DeleteAllMessages action)
+ throws ActionException {
+ User user = getUser();
+ try {
+ logger.info("Delete all messages in folder " + action.getFolder() + " for user " + user);
+ IMAPStore store =cache.get(user);
+ IMAPFolder folder = (IMAPFolder) store.getFolder(action.getFolder().getFullName());
+ if (folder.isOpen() == false) {
+ folder.open(Folder.READ_WRITE);
+ }
+ return folder.getMessages();
+ } catch (MessagingException e) {
+ String errorMsg = "Error while deleting all messages in folder " + action.getFolder() + " for user " + user;
+ logger.error(errorMsg, e);
+ throw new ActionException(errorMsg);
+
+ }
+
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see net.customware.gwt.dispatch.server.ActionHandler#getActionType()
+ */
+ public Class<DeleteAllMessages> getActionType() {
+ return DeleteAllMessages.class;
+ }
+
+}
Added: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/DeleteFolderHandler.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/DeleteFolderHandler.java?rev=1516205&view=auto
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/DeleteFolderHandler.java (added)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/DeleteFolderHandler.java Wed Aug 21 16:35:16 2013
@@ -0,0 +1,88 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.hupa.server.handler;
+
+import javax.mail.Folder;
+import javax.servlet.http.HttpSession;
+
+import net.customware.gwt.dispatch.server.ExecutionContext;
+import net.customware.gwt.dispatch.shared.ActionException;
+
+import org.apache.commons.logging.Log;
+import org.apache.hupa.server.IMAPStoreCache;
+import org.apache.hupa.shared.data.IMAPFolder;
+import org.apache.hupa.shared.data.User;
+import org.apache.hupa.shared.rpc.DeleteFolder;
+import org.apache.hupa.shared.rpc.GenericResult;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.sun.mail.imap.IMAPStore;
+
+/**
+ * Handle delete requests for a folder
+ *
+ *
+ */
+public class DeleteFolderHandler extends AbstractSessionHandler<DeleteFolder, GenericResult>{
+
+ @Inject
+ public DeleteFolderHandler(IMAPStoreCache cache, Log logger,
+ Provider<HttpSession> sessionProvider) {
+ super(cache, logger, sessionProvider);
+ }
+
+ @Override
+ protected GenericResult executeInternal(DeleteFolder action,
+ ExecutionContext context) throws ActionException {
+ User user = getUser();
+ IMAPFolder folder = action.getFolder();
+ try {
+ IMAPStore store = cache.get(user);
+
+ Folder f = store.getFolder(folder.getFullName());
+
+ // close the folder if its open
+ if (f.isOpen()) {
+ f.close(false);
+ }
+
+ // recursive delete the folder
+ if (f.delete(true)) {
+ logger.info("Successfully delete folder " + folder + " for user " + user);
+ return new GenericResult();
+ } else {
+ throw new ActionException("Unable to delete folder " + folder + " for user " + user);
+ }
+ } catch (Exception e) {
+ logger.error("Error while deleting folder " + folder + " for user " + user,e);
+ throw new ActionException("Error while deleting folder " + folder + " for user " + user,e);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see net.customware.gwt.dispatch.server.ActionHandler#getActionType()
+ */
+ public Class<DeleteFolder> getActionType() {
+ return DeleteFolder.class;
+ }
+
+}
Added: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/DeleteMessageByUidHandler.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/DeleteMessageByUidHandler.java?rev=1516205&view=auto
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/DeleteMessageByUidHandler.java (added)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/DeleteMessageByUidHandler.java Wed Aug 21 16:35:16 2013
@@ -0,0 +1,96 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.hupa.server.handler;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.mail.Message;
+import javax.mail.MessagingException;
+import javax.servlet.http.HttpSession;
+
+import net.customware.gwt.dispatch.shared.ActionException;
+
+import org.apache.commons.logging.Log;
+import org.apache.hupa.server.IMAPStoreCache;
+import org.apache.hupa.shared.data.IMAPFolder;
+import org.apache.hupa.shared.data.User;
+import org.apache.hupa.shared.rpc.DeleteMessageByUid;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.sun.mail.imap.IMAPStore;
+
+/**
+ * Handler which take care of deleting messages
+ *
+ */
+public class DeleteMessageByUidHandler extends
+ AbstractDeleteMessageHandler<DeleteMessageByUid> {
+
+ @Inject
+ public DeleteMessageByUidHandler(IMAPStoreCache cache, Log logger,
+ Provider<HttpSession> provider) {
+ super(cache, logger, provider);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see net.customware.gwt.dispatch.server.ActionHandler#getActionType()
+ */
+ public Class<DeleteMessageByUid> getActionType() {
+ return DeleteMessageByUid.class;
+ }
+
+ @Override
+ protected Message[] getMessagesToDelete(DeleteMessageByUid action)
+ throws ActionException {
+ IMAPFolder folder = action.getFolder();
+ ArrayList<Long> uids = action.getMessageUids();
+ User user = getUser();
+
+ logger.info("Deleting messages with uids " + action.getMessageUids()
+ + " for user " + user + " in folder " + action.getFolder());
+ try {
+ IMAPStore store = cache.get(user);
+ com.sun.mail.imap.IMAPFolder f = (com.sun.mail.imap.IMAPFolder) store
+ .getFolder(folder.getFullName());
+ // check if the folder is open, if not open it "rw"
+ if (f.isOpen() == false) {
+ f.open(com.sun.mail.imap.IMAPFolder.READ_WRITE);
+ }
+ // build up the list of messages to delete
+ List<Message> messages = new ArrayList<Message>();
+ for (Long uid : uids) {
+ messages.add(f.getMessageByUID(uid));
+ }
+ Message[] mArray = messages.toArray(new Message[messages.size()]);
+ return mArray;
+ } catch (MessagingException e) {
+ logger.error("Error while deleting messages with uids "
+ + action.getMessageUids() + " for user " + user
+ + " in folder" + action.getFolder(), e);
+ throw new ActionException("Error while deleting messages", e);
+ }
+
+ }
+
+}
Added: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/FetchFoldersHandler.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/FetchFoldersHandler.java?rev=1516205&view=auto
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/FetchFoldersHandler.java (added)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/FetchFoldersHandler.java Wed Aug 21 16:35:16 2013
@@ -0,0 +1,144 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.hupa.server.handler;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.mail.Folder;
+import javax.mail.MessagingException;
+import javax.servlet.http.HttpSession;
+
+import net.customware.gwt.dispatch.server.ExecutionContext;
+import net.customware.gwt.dispatch.shared.ActionException;
+
+import org.apache.commons.logging.Log;
+import org.apache.hupa.server.IMAPStoreCache;
+import org.apache.hupa.shared.data.IMAPFolder;
+import org.apache.hupa.shared.data.User;
+import org.apache.hupa.shared.rpc.FetchFolders;
+import org.apache.hupa.shared.rpc.FetchFoldersResult;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.sun.mail.imap.IMAPStore;
+
+/**
+ * Handler which fetch all Folders for an user
+ *
+ */
+public class FetchFoldersHandler extends AbstractSessionHandler<FetchFolders, FetchFoldersResult>{
+
+ @Inject
+ public FetchFoldersHandler(IMAPStoreCache cache, Log logger,Provider<HttpSession> provider) {
+ super(cache,logger,provider);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.apache.hupa.server.handler.AbstractSessionHandler#executeInternal(org.apache.hupa.shared.rpc.Session, net.customware.gwt.dispatch.server.ExecutionContext)
+ */
+ public FetchFoldersResult executeInternal(FetchFolders action, ExecutionContext arg1)
+ throws ActionException {
+ User user = getUser();
+ try {
+
+ // get the store for the user
+ IMAPStore store = cache.get(user);
+ com.sun.mail.imap.IMAPFolder folder = (com.sun.mail.imap.IMAPFolder) store.getDefaultFolder();
+
+ // List of mail 'root' imap folders
+ List<IMAPFolder> imapFolders = new ArrayList<IMAPFolder>();
+
+ // Create IMAPFolder tree list
+ for (Folder f : folder.list()) {
+ IMAPFolder imapFolder = createIMAPFolder(f);
+ imapFolders.add(imapFolder);
+ walkFolders(f, imapFolder);
+ }
+
+ // Create the tree and return the result
+ FetchFoldersResult fetchFolderResult = new FetchFoldersResult(imapFolders);
+ logger.debug("Fetching folders for user: " + user + " returns:\n" + fetchFolderResult.toString());
+
+ return fetchFolderResult;
+ } catch (Exception e) {
+ e.printStackTrace();
+ logger.error("Unable to get folders for User " + user,e);
+ throw new ActionException("Unable to get folders for User "
+ + user);
+ }
+ }
+
+ /**
+ * Walk through the folder's sub-folders and add sub-folders to current imapFolder
+ *
+ * @param folder Folder to walk
+ * @param imapFolder Current IMAPFolder
+ * @throws ActionException If an error occurs
+ * @throws MessagingException If an error occurs
+ */
+ private void walkFolders(Folder folder, IMAPFolder imapFolder) throws ActionException, MessagingException{
+ for (Folder f : folder.list()) {
+ IMAPFolder iFolder = createIMAPFolder(f);
+ imapFolder.getChildIMAPFolders().add(iFolder);
+ walkFolders(f, iFolder);
+ }
+ }
+ /*
+ * (non-Javadoc)
+ * @see net.customware.gwt.dispatch.server.ActionHandler#getActionType()
+ */
+ public Class<FetchFolders> getActionType() {
+ return FetchFolders.class;
+ }
+
+ /**
+ * Create a new IMAPFolder from the given Folder
+ *
+ * @param folder Current folder
+ * @return imapFolder Created IMAPFolder
+ * @throws ActionException If an error occurs
+ * @throws MessagingException If an error occurs
+ */
+ private IMAPFolder createIMAPFolder(Folder folder) throws ActionException {
+
+ String fullName = folder.getFullName();
+ String delimiter;
+ IMAPFolder iFolder = null;
+
+ try {
+ logger.debug("Creating folder: " + fullName + " for user: " + getUser());
+ delimiter = String.valueOf(folder.getSeparator());
+ iFolder = new IMAPFolder(fullName);
+ iFolder.setDelimiter(delimiter);
+ if("[Gmail]".equals(folder.getFullName()))
+ return iFolder;
+ iFolder.setMessageCount(folder.getMessageCount());
+ iFolder.setSubscribed(folder.isSubscribed());
+ iFolder.setUnseenMessageCount(folder.getUnreadMessageCount());
+ } catch (MessagingException e) {
+ logger.error("Unable to construct folder " + folder.getFullName(),e);
+ }
+
+ return iFolder;
+ }
+
+}
Added: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/FetchMessagesHandler.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/FetchMessagesHandler.java?rev=1516205&view=auto
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/FetchMessagesHandler.java (added)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/FetchMessagesHandler.java Wed Aug 21 16:35:16 2013
@@ -0,0 +1,122 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.hupa.server.handler;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.mail.Message;
+import javax.mail.MessagingException;
+import javax.mail.search.BodyTerm;
+import javax.mail.search.FromStringTerm;
+import javax.mail.search.OrTerm;
+import javax.mail.search.SearchTerm;
+import javax.mail.search.SubjectTerm;
+import javax.servlet.http.HttpSession;
+
+import org.apache.commons.logging.Log;
+import org.apache.hupa.server.IMAPStoreCache;
+import org.apache.hupa.server.preferences.UserPreferencesStorage;
+import org.apache.hupa.shared.rpc.FetchMessages;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+import net.customware.gwt.dispatch.shared.ActionException;
+
+/**
+ * Fetch Messages for a user. The Messages don't contain any body, just some
+ * fields of the headers are fetched for perfomance reasons
+ *
+ */
+public class FetchMessagesHandler extends
+ AbstractFetchMessagesHandler<FetchMessages> {
+
+
+ @Inject
+ public FetchMessagesHandler(IMAPStoreCache cache, Log logger,
+ Provider<HttpSession> provider, UserPreferencesStorage preferences) {
+ super(cache, logger, provider, preferences);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see net.customware.gwt.dispatch.server.ActionHandler#getActionType()
+ */
+ public Class<FetchMessages> getActionType() {
+ return FetchMessages.class;
+ }
+
+ @Override
+ protected MessageConvertArray getMessagesToConvert(com.sun.mail.imap.IMAPFolder f,
+ FetchMessages action) throws MessagingException, ActionException {
+ String searchString = action.getSearchString();
+ int start = action.getStart();
+ int offset = action.getOffset();
+ int end = start + offset;
+ Message[] messages;
+ int exists;
+ // check if a searchString was given, and if so use it
+ if (searchString == null) {
+ exists = f.getMessageCount();
+
+ if (end > exists) {
+ end = exists;
+ }
+
+ int firstIndex = exists - end + 1;
+ if (firstIndex < 1) {
+ firstIndex = 1;
+ }
+ int lastIndex = exists - start;
+
+ messages = f.getMessages(firstIndex, lastIndex);
+ } else {
+ SearchTerm subjectTerm = new SubjectTerm(searchString);
+ SearchTerm fromTerm = new FromStringTerm(searchString);
+ SearchTerm bodyTerm = new BodyTerm(searchString);
+ SearchTerm orTerm = new OrTerm(new SearchTerm[] { subjectTerm,
+ fromTerm, bodyTerm });
+ Message[] tmpMessages = f.search(orTerm);
+ if (end > tmpMessages.length) {
+ end = tmpMessages.length;
+ }
+ exists = tmpMessages.length;
+
+ int firstIndex = exists - end;
+
+ if (tmpMessages.length > firstIndex) {
+ List<Message> mList = new ArrayList<Message>();
+ for (int i = firstIndex; i < tmpMessages.length; i++) {
+ if (i == end) break;
+ mList.add(tmpMessages[i]);
+ }
+ messages = mList.toArray(new Message[mList.size()]);
+ } else {
+ messages = new Message[0];
+ }
+
+ }
+ logger.debug("Fetching messages for user: " + getUser() + " returns: " + messages.length + " messages in " + f.getFullName());
+
+ return new MessageConvertArray(exists, messages);
+ }
+}
Added: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/FetchRecentMessagesHandler.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/FetchRecentMessagesHandler.java?rev=1516205&view=auto
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/FetchRecentMessagesHandler.java (added)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/FetchRecentMessagesHandler.java Wed Aug 21 16:35:16 2013
@@ -0,0 +1,62 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+
+package org.apache.hupa.server.handler;
+
+import javax.mail.Flags;
+import javax.mail.Message;
+import javax.mail.MessagingException;
+import javax.mail.Flags.Flag;
+import javax.mail.search.FlagTerm;
+import javax.servlet.http.HttpSession;
+
+import org.apache.commons.logging.Log;
+import org.apache.hupa.server.IMAPStoreCache;
+import org.apache.hupa.server.preferences.UserPreferencesStorage;
+import org.apache.hupa.shared.rpc.FetchRecentMessages;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+public class FetchRecentMessagesHandler extends AbstractFetchMessagesHandler<FetchRecentMessages> {
+
+ @Inject
+ public FetchRecentMessagesHandler(IMAPStoreCache cache, Log logger,
+ Provider<HttpSession> provider, UserPreferencesStorage preferences) {
+ super(cache, logger, provider, preferences);
+ }
+
+
+ @Override
+ protected MessageConvertArray getMessagesToConvert(com.sun.mail.imap.IMAPFolder f,
+ FetchRecentMessages action) throws MessagingException {
+ Message[] messages = f.search(new FlagTerm(new Flags(Flag.RECENT), true));
+ return new MessageConvertArray(messages.length, messages);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see net.customware.gwt.dispatch.server.ActionHandler#getActionType()
+ */
+ public Class<FetchRecentMessages> getActionType() {
+ return FetchRecentMessages.class;
+ }
+
+}
Added: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/ForwardMessageHandler.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/ForwardMessageHandler.java?rev=1516205&view=auto
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/ForwardMessageHandler.java (added)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/ForwardMessageHandler.java Wed Aug 21 16:35:16 2013
@@ -0,0 +1,89 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.hupa.server.handler;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.mail.Folder;
+import javax.mail.Message;
+import javax.mail.MessagingException;
+import javax.servlet.http.HttpSession;
+
+import net.customware.gwt.dispatch.shared.ActionException;
+
+import org.apache.commons.logging.Log;
+import org.apache.hupa.server.IMAPStoreCache;
+import org.apache.hupa.server.preferences.UserPreferencesStorage;
+import org.apache.hupa.server.utils.MessageUtils;
+import org.apache.hupa.shared.rpc.ForwardMessage;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.name.Named;
+import com.sun.mail.imap.IMAPFolder;
+import com.sun.mail.imap.IMAPStore;
+
+/**
+ * Handler which handles the forwarding of a message
+ *
+ */
+public class ForwardMessageHandler extends AbstractSendMessageHandler<ForwardMessage> {
+
+ @Inject
+ public ForwardMessageHandler(Log logger, IMAPStoreCache store, Provider<HttpSession> provider, UserPreferencesStorage preferences, @Named("SMTPServerAddress") String address, @Named("SMTPServerPort") int port,
+ @Named("SMTPAuth") boolean auth, @Named("SMTPS") boolean useSSL) {
+ super(logger, store, provider, preferences, address, port, auth, useSSL);
+ }
+
+ @Override
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ protected List getAttachments(ForwardMessage action) throws MessagingException, ActionException {
+ List<?> items = new ArrayList();
+ IMAPStore store = cache.get(getUser());
+
+ IMAPFolder folder = (IMAPFolder) store.getFolder(action.getFolder().getFullName());
+ if (folder.isOpen() == false) {
+ folder.open(Folder.READ_ONLY);
+ }
+ // Put the original attachments in the list
+ Message msg = folder.getMessageByUID(action.getReplyMessageUid());
+ try {
+ items = MessageUtils.extractMessageAttachments(logger, msg.getContent());
+ logger.debug("Forwarding a message, extracted: " + items.size() + " from original.");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ // Put in the list the attachments uploaded by the user
+ items.addAll(super.getAttachments(action));
+ return items;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see net.customware.gwt.dispatch.server.ActionHandler#getActionType()
+ */
+ public Class<ForwardMessage> getActionType() {
+ return ForwardMessage.class;
+ }
+
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org