mirror of
				https://github.com/Alfresco/alfresco-community-repo.git
				synced 2025-10-29 15:21:53 +00:00 
			
		
		
		
	99981: Merged 5.0.N (5.0.2) to HEAD-BUG-FIX (5.1/Cloud) (PARTIAL MERGE)
      99482: Merged DEV to 5.0.N (5.0.1)
         99198 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc typo in project alfresco-jlan
         99413 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc parameters inconsistence in project alfresco-jlan
         99205 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc parameters inconsistence in project core
         99415 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc parameters inconsistence in project data-model
         99227 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc parameters inconsistence in project file-transfer-receiver
         99416 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc parameters inconsistence in project legacy-lucene
         99417 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc parameters inconsistence in project qa-share
         99418 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc parameters inconsistence in project remote-api
         99427 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc in project Repository, letters S..Z
         99433 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc in project Repository, letters A..R
         99421 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc parameters inconsistence in project share-po
         99247 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc typo in project slingshot
         99248 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc parameters inconsistence in project slingshot
         99424 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc parameters inconsistence in project solr
         99426 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc parameters inconsistence in project solr4
         99253 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc parameters inconsistence in project solr-client
         99259 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc parameters inconsistence in project web-client
         99260 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc parameters inconsistence in project web-framework-commons
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@100501 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
		
	
		
			
				
	
	
		
			501 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			501 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| /*
 | |
|  * Copyright (C) 2005-2010 Alfresco Software Limited.
 | |
|  *
 | |
|  * This file is part of Alfresco
 | |
|  *
 | |
|  * Alfresco is free software: you can redistribute it and/or modify
 | |
|  * it under the terms of the GNU Lesser General Public License as published by
 | |
|  * the Free Software Foundation, either version 3 of the License, or
 | |
|  * (at your option) any later version.
 | |
|  *
 | |
|  * Alfresco is distributed in the hope that it will be useful,
 | |
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
|  * GNU Lesser General Public License for more details.
 | |
|  *
 | |
|  * You should have received a copy of the GNU Lesser General Public License
 | |
|  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 | |
|  */
 | |
| package org.alfresco.repo.imap;
 | |
| 
 | |
| import java.util.Date;
 | |
| import java.util.LinkedList;
 | |
| import java.util.List;
 | |
| 
 | |
| import javax.mail.Flags;
 | |
| import javax.mail.internet.MimeMessage;
 | |
| import javax.mail.search.SearchTerm;
 | |
| 
 | |
| import org.alfresco.repo.imap.exception.AlfrescoImapFolderException;
 | |
| import org.alfresco.repo.transaction.RetryingTransactionHelper;
 | |
| import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
 | |
| import org.alfresco.service.ServiceRegistry;
 | |
| import org.apache.commons.logging.Log;
 | |
| import org.apache.commons.logging.LogFactory;
 | |
| 
 | |
| import com.icegreen.greenmail.foedus.util.MsgRangeFilter;
 | |
| import com.icegreen.greenmail.mail.MovingMessage;
 | |
| import com.icegreen.greenmail.store.FolderException;
 | |
| import com.icegreen.greenmail.store.FolderListener;
 | |
| import com.icegreen.greenmail.store.MailFolder;
 | |
| import com.icegreen.greenmail.store.SimpleStoredMessage;
 | |
| 
 | |
| /**
 | |
|  * Implementation of greenmail MailFolder. It represents an Alfresco content folder and handles
 | |
|  * appendMessage, copyMessage, expunge (delete), getMessages, getMessage and so requests.
 | |
|  * 
 | |
|  * @author Ivan Rybnikov
 | |
|  */
 | |
| public abstract class AbstractImapFolder implements MailFolder
 | |
| {
 | |
|     private List<FolderListener> listeners = new LinkedList<FolderListener>();
 | |
| 
 | |
|     protected Log logger = LogFactory.getLog(getClass());
 | |
| 
 | |
|     protected ServiceRegistry serviceRegistry;
 | |
|     protected static int MAX_RETRIES = 20;
 | |
| 
 | |
|     
 | |
|     public AbstractImapFolder(ServiceRegistry serviceRegistry)
 | |
|     {
 | |
|         this.serviceRegistry = serviceRegistry;
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Method that checks mandatory parameter.
 | |
|      * @param parameter The parameter instance to check.
 | |
|      * @param name The name of the parameter.
 | |
|      */
 | |
|     protected void checkParameter(Object parameter, String name)
 | |
|     {
 | |
|         if (parameter == null)
 | |
|         {
 | |
|             throw new IllegalArgumentException(name + " parameter is null.");
 | |
|         }
 | |
|     }
 | |
| 
 | |
| 
 | |
|     /**
 | |
|      * Appends message to the folder.
 | |
|      * 
 | |
|      * @param message - message.
 | |
|      * @param flags - message flags.
 | |
|      * @param internalDate - not used. Current date used instead.
 | |
|      * @return
 | |
|      */
 | |
|     public long appendMessage(final MimeMessage message, final Flags flags, final Date internalDate) throws FolderException
 | |
|     {
 | |
|         if (isReadOnly())
 | |
|         {
 | |
|             throw new FolderException("Can't append message - Permission denied");
 | |
|         }
 | |
| 
 | |
|         CommandCallback<Long> command = new CommandCallback<Long>()
 | |
|         {
 | |
|             public Long command() throws Throwable
 | |
|             {
 | |
|                 return appendMessageInternal(message, flags, internalDate);
 | |
|             }
 | |
|         };
 | |
|         return command.runFeedback();
 | |
|      }
 | |
| 
 | |
| 
 | |
|     /**
 | |
|      * Copies message with the given UID to the specified {@link MailFolder}.
 | |
|      * 
 | |
|      * @param uid - UID of the message
 | |
|      * @param toFolder - reference to the destination folder.
 | |
|      */
 | |
|     public long copyMessage(final long uid, final MailFolder toFolder) throws FolderException
 | |
|     {
 | |
|         AbstractImapFolder toImapMailFolder = (AbstractImapFolder) toFolder;
 | |
| 
 | |
|         if (toImapMailFolder.isReadOnly())
 | |
|         {
 | |
|             throw new FolderException(AlfrescoImapFolderException.PERMISSION_DENIED);
 | |
|         }
 | |
| 
 | |
|         CommandCallback<Long> command = new CommandCallback<Long>()
 | |
|         {
 | |
|             public Long command() throws Throwable
 | |
|             {
 | |
|                 return copyMessageInternal(uid, toFolder);
 | |
|             }
 | |
|         };
 | |
|         return command.runFeedback();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Marks all messages in the folder as deleted using {@link Flags.Flag#DELETED} flag.
 | |
|      */
 | |
|     public void deleteAllMessages() throws FolderException
 | |
|     {
 | |
|         CommandCallback<Object> command = new CommandCallback<Object>()
 | |
|         {
 | |
|             public Object command() throws Throwable
 | |
|             {
 | |
|                 deleteAllMessagesInternal();
 | |
|                 return null;
 | |
|             }
 | |
|         };
 | |
|         command.runFeedback();
 | |
|     }
 | |
| 
 | |
|     
 | |
| 
 | |
|     /**
 | |
|      * Deletes messages marked with {@link Flags.Flag#DELETED}. Note that this message deletes all messages with this flag.
 | |
|      */
 | |
|     public void expunge() throws FolderException
 | |
|     {
 | |
|         if (isReadOnly())
 | |
|         {
 | |
|             throw new FolderException("Can't expunge - Permission denied");
 | |
|         }
 | |
|         CommandCallback<Object> command = new CommandCallback<Object>()
 | |
|         {
 | |
|             public Object command() throws Throwable
 | |
|             {
 | |
|                 expungeInternal();
 | |
|                 return null;
 | |
|             }
 | |
|         };
 | |
|         command.runFeedback();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Deletes messages marked with {@link Flags.Flag#DELETED}. Note that this message deletes the messages with current uid
 | |
|      */
 | |
|     public void expunge(final long uid) throws FolderException
 | |
|     {
 | |
|         if (isReadOnly())
 | |
|         {
 | |
|             throw new FolderException("Can't expunge - Permission denied");
 | |
|         }
 | |
|         CommandCallback<Object> command = new CommandCallback<Object>()
 | |
|         {
 | |
|             public Object command() throws Throwable
 | |
|             {
 | |
|                 expungeInternal(uid);
 | |
|                 return null;
 | |
|             }
 | |
|         };
 | |
|         command.runFeedback();
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Returns message by its UID.
 | |
|      * 
 | |
|      * @param uid - UID of the message.
 | |
|      * @return message.
 | |
|      */
 | |
|     public SimpleStoredMessage getMessage(final long uid)
 | |
|     {
 | |
|         CommandCallback<SimpleStoredMessage> command = new CommandCallback<SimpleStoredMessage>()
 | |
|         {
 | |
|             public SimpleStoredMessage command() throws Throwable
 | |
|             {
 | |
|                 return getMessageInternal(uid);
 | |
|             }
 | |
|         };
 | |
|         return command.run();
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Returns list of all messages in the folder.
 | |
|      * 
 | |
|      * @return list of {@link SimpleStoredMessage} objects.
 | |
|      */
 | |
|     public List<SimpleStoredMessage> getMessages()
 | |
|     {
 | |
|         CommandCallback<List<SimpleStoredMessage>> command = new CommandCallback<List<SimpleStoredMessage>>()
 | |
|         {
 | |
|             public List<SimpleStoredMessage> command() throws Throwable
 | |
|             {
 | |
|                 return getMessagesInternal();
 | |
|             }
 | |
|         };
 | |
|         return command.run();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns list of messages by filter.
 | |
|      * 
 | |
|      * @param msgRangeFilter - {@link MsgRangeFilter} object representing filter.
 | |
|      * @return list of filtered messages.
 | |
|      */
 | |
|     public List<SimpleStoredMessage> getMessages(final MsgRangeFilter msgRangeFilter)
 | |
|     {
 | |
|         CommandCallback <List<SimpleStoredMessage>> command = new CommandCallback <List<SimpleStoredMessage>>()
 | |
|         {
 | |
|             public List<SimpleStoredMessage> command() throws Throwable
 | |
|             {
 | |
|                 return getMessagesInternal(msgRangeFilter);
 | |
|             }
 | |
|         };
 | |
|         return command.run();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns the list of messages that have no {@link Flags.Flag#DELETED} flag set for current user.
 | |
|      * 
 | |
|      * @return the list of non-deleted messages.
 | |
|      */
 | |
|     public List<SimpleStoredMessage> getNonDeletedMessages()
 | |
|     {
 | |
|         CommandCallback <List<SimpleStoredMessage>> command = new CommandCallback<List<SimpleStoredMessage>>()
 | |
|         {
 | |
|             public List<SimpleStoredMessage> command() throws Throwable
 | |
|             {
 | |
|                 return getNonDeletedMessagesInternal();
 | |
|             }
 | |
|         };
 | |
|         List<SimpleStoredMessage> result = (List<SimpleStoredMessage>)command.run();
 | |
|         return result;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Replaces flags for the message with the given UID. If {@code addUid} is set to
 | |
|      * {@code true} {@link FolderListener} objects defined for this folder will be notified.
 | |
|      * {@code silentListener} can be provided - this listener wouldn't be notified.
 | |
|      * 
 | |
|      * @param flags - new flags.
 | |
|      * @param uid - message UID.
 | |
|      * @param silentListener - listener that shouldn't be notified.
 | |
|      * @param addUid - defines whether or not listeners be notified.
 | |
|      */
 | |
|     public void replaceFlags(final Flags flags, final long uid, final FolderListener silentListener, final boolean addUid) throws FolderException
 | |
|     {
 | |
|         CommandCallback<Object> command = new CommandCallback<Object>()
 | |
|         {
 | |
|             public Object command() throws Throwable
 | |
|             {
 | |
|                 replaceFlagsInternal(flags, uid, silentListener, addUid);
 | |
|                 return null;
 | |
|             }
 | |
|         };
 | |
|         command.runFeedback();
 | |
|     }
 | |
| 
 | |
|     
 | |
|     /**
 | |
|      * Searches the mailbox for messages that match the given searching criteria
 | |
|      * 
 | |
|      * @param searchTerm - search term that contains search criteria.
 | |
|      * @return UIDs of the messages
 | |
|      */
 | |
|     public long[] search(final SearchTerm searchTerm)
 | |
|     {
 | |
|         CommandCallback<long[]> command = new CommandCallback<long[]>()
 | |
|         {
 | |
|             public long[] command() throws Throwable
 | |
|             {
 | |
|                 return searchInternal(searchTerm);
 | |
|             }
 | |
|         };
 | |
|         return command.run();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Sets flags for the message with the given UID. If {@code addUid} is set to {@code true}
 | |
|      * {@link FolderListener} objects defined for this folder will be notified.
 | |
|      * {@code silentListener} can be provided - this listener wouldn't be notified.
 | |
|      * 
 | |
|      * @param flags - new flags.
 | |
|      * @param value - flags value.
 | |
|      * @param uid - message UID.
 | |
|      * @param silentListener - listener that shouldn't be notified.
 | |
|      * @param addUid - defines whether or not listeners be notified.
 | |
|      */
 | |
|     public void setFlags(
 | |
|             final Flags flags,
 | |
|             final boolean value,
 | |
|             final long uid,
 | |
|             final FolderListener silentListener,
 | |
|             final boolean addUid)
 | |
|             throws FolderException
 | |
|     {
 | |
|         CommandCallback<Object> command = new CommandCallback<Object>()
 | |
|         {
 | |
|             public Object command() throws Throwable
 | |
|             {
 | |
|                 setFlagsInternal(flags, value, uid, silentListener, addUid);
 | |
|                 return null;
 | |
|             }
 | |
|         };
 | |
|         command.runFeedback();
 | |
|     }
 | |
| 
 | |
| 
 | |
|     
 | |
|     /**
 | |
|      * Not supported. Added to implement {@link MailFolder#store(MovingMessage)}.
 | |
|      */
 | |
|     public void store(MovingMessage mail) throws Exception
 | |
|     {
 | |
|         throw new UnsupportedOperationException("Method store(MovingMessage) is not suppoted.");
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Not supported. Added to implement {@link MailFolder#store(MimeMessage)}.
 | |
|      */
 | |
|     public void store(MimeMessage message) throws Exception
 | |
|     {
 | |
|         throw new UnsupportedOperationException("Method store(MimeMessage) is not suppoted.");
 | |
|     }
 | |
| 
 | |
|     
 | |
|     /**
 | |
|      * Adds {@link FolderListener} to the folder.
 | |
|      * 
 | |
|      * @param listener - new listener.
 | |
|      */
 | |
|     public void addListener(FolderListener listener)
 | |
|     {
 | |
|         listeners.add(listener);
 | |
|     }
 | |
| 
 | |
|     
 | |
|     
 | |
|     /**
 | |
|      * Removes {@link FolderListener} from the folder.
 | |
|      * 
 | |
|      * @param listener - Listener to remove.
 | |
|      */
 | |
|     public void removeListener(FolderListener listener)
 | |
|     {
 | |
|         listeners.remove(listener);
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Method is called before the deletion of the folder. Notifies {@link FolderListener} objects with
 | |
|      * {@link FolderListener#mailboxDeleted()} method calls.
 | |
|      */
 | |
|     public void signalDeletion()
 | |
|     {
 | |
|         synchronized (listeners)
 | |
|         {
 | |
|             for (int i = 0; i < listeners.size(); i++)
 | |
|             {
 | |
|                 FolderListener listener = (FolderListener) listeners.get(i);
 | |
|                 listener.mailboxDeleted();
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     
 | |
|     protected void notifyFlagUpdate(int msn, Flags flags, Long uidNotification, FolderListener silentListener)
 | |
|     {
 | |
|         synchronized (listeners)
 | |
|         {
 | |
|             for (FolderListener listener : listeners)
 | |
|             {
 | |
|                 if (listener == silentListener)
 | |
|                 {
 | |
|                     continue;
 | |
|                 }
 | |
| 
 | |
|                 listener.flagsUpdated(msn, flags, uidNotification);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     
 | |
|     protected abstract boolean isReadOnly();
 | |
| 
 | |
|     protected abstract long appendMessageInternal(MimeMessage message, Flags flags, Date internalDate) throws Exception;
 | |
| 
 | |
|     protected abstract long copyMessageInternal(long uid, MailFolder toFolder) throws Exception;
 | |
|     
 | |
|     protected abstract void deleteAllMessagesInternal() throws Exception;
 | |
| 
 | |
|     protected abstract void expungeInternal() throws Exception;
 | |
| 
 | |
|     protected abstract void expungeInternal(long uid) throws Exception;
 | |
| 
 | |
|     protected abstract SimpleStoredMessage getMessageInternal(long uid) throws Exception;
 | |
| 
 | |
|     protected abstract List<SimpleStoredMessage> getMessagesInternal();
 | |
|     
 | |
|     protected abstract List<SimpleStoredMessage> getMessagesInternal(MsgRangeFilter msgRangeFilter);
 | |
| 
 | |
|     protected abstract List<SimpleStoredMessage> getNonDeletedMessagesInternal();
 | |
| 
 | |
|     protected abstract void replaceFlagsInternal(Flags flags, long uid, FolderListener silentListener, boolean addUid) throws Exception;
 | |
| 
 | |
|     protected abstract long[] searchInternal(SearchTerm searchTerm);
 | |
| 
 | |
|     protected abstract void setFlagsInternal(Flags flags, boolean value, long uid, FolderListener silentListener, boolean addUid) throws Exception;
 | |
| 
 | |
|     protected abstract class CommandCallback<T>
 | |
|     {
 | |
|         public abstract T command() throws Throwable;
 | |
| 
 | |
|         public T runFeedback() throws FolderException
 | |
|         {
 | |
|             return this.runFeedback(false);
 | |
|         }
 | |
| 
 | |
|         public T runFeedback(boolean readOnly) throws FolderException
 | |
|         {
 | |
|             try
 | |
|             {
 | |
|                 RetryingTransactionHelper txHelper = serviceRegistry.getTransactionService().getRetryingTransactionHelper();
 | |
|                 txHelper.setMaxRetries(MAX_RETRIES);
 | |
|                 txHelper.setReadOnly(readOnly);
 | |
|                 T result = txHelper.doInTransaction(
 | |
|                         new RetryingTransactionCallback<T>()
 | |
|                         {
 | |
|                             public T execute() throws Throwable
 | |
|                             {
 | |
|                                 return command();
 | |
|                             }
 | |
|                         }, readOnly);
 | |
|                 return result;
 | |
|             }
 | |
|             catch (Exception e)
 | |
|             {
 | |
|                 Throwable cause = e.getCause();
 | |
|                 
 | |
|                 if (logger.isDebugEnabled())
 | |
|                 {
 | |
|                     logger.debug("Exception is thrown : " + e + "\nCause : " + cause);
 | |
|                 }
 | |
|                 
 | |
|                 String message;
 | |
|                 if (cause != null)
 | |
|                 {
 | |
|                     message = cause.getMessage();
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     message = e.getMessage();
 | |
|                 }
 | |
|                 throw new FolderException(message);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public T run()
 | |
|         {
 | |
|             return this.run(false);
 | |
|         }
 | |
|         
 | |
|         public T run(boolean readOnly)
 | |
|         {
 | |
|             RetryingTransactionHelper txHelper = serviceRegistry.getTransactionService().getRetryingTransactionHelper();
 | |
|             txHelper.setMaxRetries(MAX_RETRIES);
 | |
|             txHelper.setReadOnly(readOnly);
 | |
|             T result = txHelper.doInTransaction(
 | |
|                     new RetryingTransactionCallback<T>()
 | |
|                     {
 | |
|                         public T execute() throws Throwable
 | |
|                         {
 | |
|                             return command();
 | |
|                         }
 | |
|                     }, readOnly);
 | |
|             return result;
 | |
|         }
 | |
|     }
 | |
| }
 |