com.atlassian.jira.service.util.handler
Class AbstractMessageHandler

java.lang.Object
  extended by com.atlassian.jira.service.util.handler.AbstractMessageHandler
All Implemented Interfaces:
MessageHandler
Direct Known Subclasses:
AbstractCommentHandler, CreateIssueHandler, CreateOrCommentHandler, CVSLogHandler

public abstract class AbstractMessageHandler
extends java.lang.Object
implements MessageHandler

An AbstractMessageHandler that stores the parameter map.

TODO Insert summary about other responsibilities/ features of this class.

Attachment processing

This class does a number of things including the processing of parts that need to be saved as attachments within the saveAttachmentIfNecessary(javax.mail.Part, javax.mail.Message, com.opensymphony.user.User, org.ofbiz.core.entity.GenericValue) method.

This method eventually calls others which attempt to locate all parts that are possible candidates and should be kept after it is categorised a part as a particular type. These types are

A few protected methods within this class that are intended for overriding if behaviour needs to be customised. These methods of interest are

The two abstract attachXXX methods are implemented by sub classes.

Numerous helper methods are available upon the MailUtils class to assit with simple tests.


Field Summary
protected  ApplicationProperties applicationProperties
           
 java.lang.String bulk
          How to handle emails with header: "Precedence: bulk"
 java.lang.String catchEmail
          New issues without this receipient are ignored.
protected  CommentManager commentManager
           
protected static java.lang.String CONTENT_TYPE_TEXT
           
 boolean createUsers
          Whether to create users if they do not exist
protected  boolean deleteEmail
          This is a silly protected field that indicates whether the email should be deleted BUT only after the canHandleMessage() method is called.
protected static java.lang.String HEADER_IN_REPLY_TO
           
protected static java.lang.String HEADER_MESSAGE_ID
           
protected  IssueFactory issueFactory
           
protected static java.lang.String KEY_BULK
           
protected static java.lang.String KEY_CATCHEMAIL
           
protected static java.lang.String KEY_CREATEUSERS
           
protected static java.lang.String KEY_FINGER_PRINT
           
protected static java.lang.String KEY_NOTIFYUSERS
           
protected static java.lang.String KEY_REPORTER
           
 boolean notifyUsers
           
protected  java.util.Map params
           
 java.lang.String reporteruserName
          Username of default reporter, if sender not recognized.
 
Constructor Summary
protected AbstractMessageHandler()
           
protected AbstractMessageHandler(CommentManager commentManager, IssueFactory issueFactory, ApplicationProperties applicationProperties, JiraApplicationContext jiraApplicationContext)
           
 
Method Summary
 void addError(java.lang.String error)
           
 void addError(java.lang.String error, java.lang.Exception e)
           
 boolean addErrorAndReturnFalse(java.lang.String error)
          Deprecated. Please use addError(String) and return your own false :-) TODO: remove in 4.1
 boolean addErrorAndReturnFalse(java.lang.String error, java.lang.Exception e)
          Deprecated. Please use addError(String, Exception) and return your own false :-) TODO: remove in 4.1
protected  boolean attachAttachmentsParts(javax.mail.Part part)
          Only attach an attachment part if it's content is not empty and if it is not a signature part.
protected abstract  boolean attachHtmlParts(javax.mail.Part part)
          This method determines whether or not HTML parts should be attached.
protected  boolean attachInlineParts(javax.mail.Part part)
          Only attach an inline part if it's content is not empty and if it is not a signature part.
protected  boolean attachMessagePart(javax.mail.Part messagePart, javax.mail.Message containingMessage)
          JRA-15133: if this part is an attached message, skip it if: the option to ignore attached messages is set to true, OR this message is in reply to the attached one (redundant info), OR if the message is not in reply to the attached one, skip if the content is empty

This is required to handle the behaviour of some mail clients (e.g.

protected abstract  boolean attachPlainTextParts(javax.mail.Part part)
          This method determines whether or not plain text parts should be attached.
protected  boolean attachRelatedPart(javax.mail.Part part)
          JRA-15670: if this part is contained within a multipart/related message, keep it, as it may be a legitimate attachment, but without the content disposition set to a sensible value (e.g.
protected  boolean canHandleMessage(javax.mail.Message message)
          Validation call to be made at the start of handleMessage().
It sets a global boolean deleteEmail, whether the email should be deleted if it cannot be handled.
protected  java.util.Collection<ChangeItemBean> createAttachmentsForMessage(javax.mail.Message message, org.ofbiz.core.entity.GenericValue issue)
          Loops through all the Parts, and for each one of type Part.ATTACHMENT, call createAttachmentWithPart(Part,User,GenericValue).
protected  ChangeItemBean createAttachmentWithPart(javax.mail.Part part, com.opensymphony.user.User reporter, org.ofbiz.core.entity.GenericValue issue)
          Create an attachment for a particular mime-part.
protected  com.opensymphony.user.User createUserForReporter(javax.mail.Message message)
          Tries to create a user using the details provided by the reporter.
protected  com.opensymphony.user.User findUserByEmail(java.lang.String emailAddress)
          Returns the first User found with an email address that equals the given emailAddress case insensitively.
protected  com.opensymphony.user.User findUserByUsername(java.lang.String username)
          Finds the user with the given username or returns null if there is no such User.
protected  org.ofbiz.core.entity.GenericValue getAssociatedIssue(javax.mail.Message message)
           
protected  MessageErrorHandler getErrorHandler()
           
protected  java.io.File getFileFromPart(javax.mail.Part part, java.lang.String issueKey)
           
protected  java.lang.String getFilenameForAttachment(javax.mail.Part part)
          Handy method which takes a number of strategies when attempting to give a filename for a particular part.
protected  I18nHelper getI18nBean()
           
protected  java.lang.String getPrecedenceHeader(javax.mail.Message message)
          Extract the 'Precedence' header value from the message
protected  com.opensymphony.user.User getReporter(javax.mail.Message message)
          Get the reporter from the email address who sent the message, or else create a new user if creating users is set to true, or use the default reporter if one is specified.
abstract  boolean handleMessage(javax.mail.Message message)
          Perform the specific work of this handler for the given message.
 void init(java.util.Map params)
          Will be called before any messages are to be handled.
protected  boolean isAutoSubmitted(javax.mail.Message message)
           
protected  boolean isDeliveryStatus(javax.mail.Message message)
           
protected  void recordMessageId(java.lang.String type, javax.mail.Message message, java.lang.Long issueId)
           
protected  java.lang.String renameFileIfInvalid(java.lang.String filename, org.ofbiz.core.entity.GenericValue issue, com.opensymphony.user.User reporter)
          Replaces all invalid characters in the filename using FileNameCharacterCheckerUtil.replaceInvalidChars(String, char) with INVALID_CHAR_REPLACEMENT as the replacement character.
 void setErrorHandler(MessageErrorHandler errorHandler)
           
protected  boolean shouldAttach(javax.mail.Part part, javax.mail.Message containingMessage)
          This method determines if a particular part should be included added as an attachment to an issue.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

KEY_REPORTER

protected static final java.lang.String KEY_REPORTER
See Also:
Constant Field Values

KEY_CATCHEMAIL

protected static final java.lang.String KEY_CATCHEMAIL
See Also:
Constant Field Values

KEY_CREATEUSERS

protected static final java.lang.String KEY_CREATEUSERS
See Also:
Constant Field Values

KEY_NOTIFYUSERS

protected static final java.lang.String KEY_NOTIFYUSERS
See Also:
Constant Field Values

KEY_FINGER_PRINT

protected static final java.lang.String KEY_FINGER_PRINT
See Also:
Constant Field Values

KEY_BULK

protected static final java.lang.String KEY_BULK
See Also:
Constant Field Values

CONTENT_TYPE_TEXT

protected static final java.lang.String CONTENT_TYPE_TEXT
See Also:
Constant Field Values

HEADER_MESSAGE_ID

protected static final java.lang.String HEADER_MESSAGE_ID
See Also:
Constant Field Values

HEADER_IN_REPLY_TO

protected static final java.lang.String HEADER_IN_REPLY_TO
See Also:
Constant Field Values

deleteEmail

protected boolean deleteEmail
This is a silly protected field that indicates whether the email should be deleted BUT only after the canHandleMessage() method is called. It is used as a mechanism to indicate two values from from a single method call.

One say it should be lined up against the wall and shot, with a 2 value object returned instead. But in the interests of binary compatibility its left as is for the moment.


params

protected java.util.Map params

reporteruserName

public java.lang.String reporteruserName
Username of default reporter, if sender not recognized.


catchEmail

public java.lang.String catchEmail
New issues without this receipient are ignored.


bulk

public java.lang.String bulk
How to handle emails with header: "Precedence: bulk"


createUsers

public boolean createUsers
Whether to create users if they do not exist


notifyUsers

public boolean notifyUsers

commentManager

protected final CommentManager commentManager

issueFactory

protected final IssueFactory issueFactory

applicationProperties

protected final ApplicationProperties applicationProperties
Constructor Detail

AbstractMessageHandler

protected AbstractMessageHandler()

AbstractMessageHandler

protected AbstractMessageHandler(CommentManager commentManager,
                                 IssueFactory issueFactory,
                                 ApplicationProperties applicationProperties,
                                 JiraApplicationContext jiraApplicationContext)
Method Detail

init

public void init(java.util.Map params)
Description copied from interface: MessageHandler
Will be called before any messages are to be handled.

Specified by:
init in interface MessageHandler
Parameters:
params - configuration.

handleMessage

public abstract boolean handleMessage(javax.mail.Message message)
                               throws javax.mail.MessagingException
Perform the specific work of this handler for the given message.

Specified by:
handleMessage in interface MessageHandler
Parameters:
message - the message to check for handling.
Returns:
true if the message is to be deleted from the source.
Throws:
javax.mail.MessagingException - if anything went wrong.

canHandleMessage

protected boolean canHandleMessage(javax.mail.Message message)
Validation call to be made at the start of handleMessage().
It sets a global boolean deleteEmail, whether the email should be deleted if it cannot be handled. ie. return deleteEmail if canHandleMessage() is false

Parameters:
message - message to check if it can be handled
Returns:
whether the message should be handled

createAttachmentsForMessage

protected java.util.Collection<ChangeItemBean> createAttachmentsForMessage(javax.mail.Message message,
                                                                           org.ofbiz.core.entity.GenericValue issue)
                                                                    throws java.io.IOException,
                                                                           javax.mail.MessagingException
Loops through all the Parts, and for each one of type Part.ATTACHMENT, call createAttachmentWithPart(Part,User,GenericValue).

Parameters:
message - The multipart message to search for attachments in
issue - The issue to create attachments in
Returns:
a collection of change items, one for each attachment added. If no attachments are added, returns and empty collection.
Throws:
java.io.IOException - If there is a problem creating the attachment
javax.mail.MessagingException - If there is a problem reading the message

shouldAttach

protected final boolean shouldAttach(javax.mail.Part part,
                                     javax.mail.Message containingMessage)
                              throws javax.mail.MessagingException,
                                     java.io.IOException
This method determines if a particular part should be included added as an attachment to an issue.

Parameters:
part - the part to potentially attach
containingMessage - the message which contained the part - may be null
Returns:
true if the part should be attached; false otherwise
Throws:
java.io.IOException - if javamail complains
javax.mail.MessagingException - if javamail complains

attachPlainTextParts

protected abstract boolean attachPlainTextParts(javax.mail.Part part)
                                         throws javax.mail.MessagingException,
                                                java.io.IOException
This method determines whether or not plain text parts should be attached.

Parameters:
part - the part to be attached - already determined to be type text/plain.
Returns:
true if the part should be attached; false otherwise
Throws:
java.io.IOException - if javamail complains
javax.mail.MessagingException - if javamail complains

attachHtmlParts

protected abstract boolean attachHtmlParts(javax.mail.Part part)
                                    throws javax.mail.MessagingException,
                                           java.io.IOException
This method determines whether or not HTML parts should be attached.

Parameters:
part - the part to be attached - already determined to be type text/html.
Returns:
true if the part should be attached; false otherwise
Throws:
java.io.IOException - if javamail complains
javax.mail.MessagingException - if javamail complains

attachInlineParts

protected boolean attachInlineParts(javax.mail.Part part)
                             throws javax.mail.MessagingException,
                                    java.io.IOException
Only attach an inline part if it's content is not empty and if it is not a signature part.

Parameters:
part - a mail part - assumed to have inline disposition
Returns:
whether or not this inline part should be attached.
Throws:
javax.mail.MessagingException - if Content-Type checks fail
java.io.IOException - if content checks fail

attachAttachmentsParts

protected boolean attachAttachmentsParts(javax.mail.Part part)
                                  throws javax.mail.MessagingException,
                                         java.io.IOException
Only attach an attachment part if it's content is not empty and if it is not a signature part.

Parameters:
part - a mail part - assumed to have attachment disposition
Returns:
whether or not this inline part should be attached.
Throws:
javax.mail.MessagingException - if Content-Type checks fail
java.io.IOException - if content checks fail

attachMessagePart

protected boolean attachMessagePart(javax.mail.Part messagePart,
                                    javax.mail.Message containingMessage)
                             throws java.io.IOException,
                                    javax.mail.MessagingException
JRA-15133: if this part is an attached message, skip it if:

This is required to handle the behaviour of some mail clients (e.g. Outlook) who, when replying to a message, include the entire original message as an attachment with content type "message/rfc822". In these cases, the attached message is redundant information, so we skip it.

Parameters:
messagePart - the Message part (already known to be of message content type)
containingMessage - the original message which contains messagePart
Returns:
true if the part should be attached, false otherwise
Throws:
java.io.IOException - if javamail complains
javax.mail.MessagingException - if javamail complains

attachRelatedPart

protected boolean attachRelatedPart(javax.mail.Part part)
                             throws java.io.IOException,
                                    javax.mail.MessagingException
JRA-15670: if this part is contained within a multipart/related message, keep it, as it may be a legitimate attachment, but without the content disposition set to a sensible value (e.g. when using Outlook 2007 and Rich Text format).

Parameters:
part - the part contained within the related message
Returns:
true if the part should be attached, false otherwise
Throws:
java.io.IOException - if javamail complains
javax.mail.MessagingException - if javamail complains

createAttachmentWithPart

protected ChangeItemBean createAttachmentWithPart(javax.mail.Part part,
                                                  com.opensymphony.user.User reporter,
                                                  org.ofbiz.core.entity.GenericValue issue)
                                           throws java.io.IOException
Create an attachment for a particular mime-part. The BodyPart must be of type Part.ATTACHMENT.

Parameters:
part - part of disposition Part.ATTACHMENT to create the attachment from
reporter - issue reporter
issue - issue to create attachments in
Returns:
A ChangeItemBean representing the added attachment, or null if no attachment was created
Throws:
java.io.IOException - If there is a problem creating the attachment in the filesystem

getFilenameForAttachment

protected java.lang.String getFilenameForAttachment(javax.mail.Part part)
                                             throws javax.mail.MessagingException,
                                                    java.io.IOException
Handy method which takes a number of strategies when attempting to give a filename for a particular part. The filename may already be present in the part or may need to be formulated or composed from other identifies within the part (such as a subject, content type etc).

Parameters:
part - The part being tested.
Returns:
The filename for the attachment or null if one was not present.
Throws:
javax.mail.MessagingException - relays any MessagingException thrown by a lower layer such as java mail
java.io.IOException - relays any IOExceptions

renameFileIfInvalid

protected java.lang.String renameFileIfInvalid(java.lang.String filename,
                                               org.ofbiz.core.entity.GenericValue issue,
                                               com.opensymphony.user.User reporter)
Replaces all invalid characters in the filename using FileNameCharacterCheckerUtil.replaceInvalidChars(String, char) with INVALID_CHAR_REPLACEMENT as the replacement character.

Parameters:
filename - filename to check if its valid
issue - issue the file is to be attached
reporter - the author of the comment to add to the issue if the filename is invalid
Returns:
  • if filename is null, returns null
  • if its valid, returns filename
  • if its invalid, returns filename with all invalid characters replaced with INVALID_CHAR_REPLACEMENT

  • getFileFromPart

    protected java.io.File getFileFromPart(javax.mail.Part part,
                                           java.lang.String issueKey)
                                    throws java.io.IOException,
                                           javax.mail.MessagingException,
                                           org.ofbiz.core.entity.GenericEntityException
    Throws:
    java.io.IOException
    javax.mail.MessagingException
    org.ofbiz.core.entity.GenericEntityException

    getReporter

    protected com.opensymphony.user.User getReporter(javax.mail.Message message)
                                              throws javax.mail.MessagingException
    Get the reporter from the email address who sent the message, or else create a new user if creating users is set to true, or use the default reporter if one is specified.

    If neither of these are found, return null.

    Parameters:
    message - The email message to search through.
    Returns:
    The user who sent the email, or the default reporter, or null.
    Throws:
    javax.mail.MessagingException - If there is a problem getting the user who created the message.

    findUserByUsername

    protected com.opensymphony.user.User findUserByUsername(java.lang.String username)
    Finds the user with the given username or returns null if there is no such User. Convenience method which doesn't throw up.

    Parameters:
    username - the username.
    Returns:
    the User or null.

    findUserByEmail

    protected com.opensymphony.user.User findUserByEmail(java.lang.String emailAddress)
    Returns the first User found with an email address that equals the given emailAddress case insensitively.

    Parameters:
    emailAddress - the email address to match.
    Returns:
    the User.

    createUserForReporter

    protected com.opensymphony.user.User createUserForReporter(javax.mail.Message message)
    Tries to create a user using the details provided by the reporter. Fails if external user managment is turned on or, if no valid from email address was specified.

    Parameters:
    message - The original e-mail message.
    Returns:
    A new user or null.

    getPrecedenceHeader

    protected java.lang.String getPrecedenceHeader(javax.mail.Message message)
                                            throws javax.mail.MessagingException
    Extract the 'Precedence' header value from the message

    Throws:
    javax.mail.MessagingException

    isDeliveryStatus

    protected boolean isDeliveryStatus(javax.mail.Message message)
                                throws javax.mail.MessagingException
    Throws:
    javax.mail.MessagingException

    isAutoSubmitted

    protected boolean isAutoSubmitted(javax.mail.Message message)
                               throws javax.mail.MessagingException
    Throws:
    javax.mail.MessagingException

    recordMessageId

    protected void recordMessageId(java.lang.String type,
                                   javax.mail.Message message,
                                   java.lang.Long issueId)
                            throws javax.mail.MessagingException
    Throws:
    javax.mail.MessagingException

    getAssociatedIssue

    protected org.ofbiz.core.entity.GenericValue getAssociatedIssue(javax.mail.Message message)

    setErrorHandler

    public void setErrorHandler(MessageErrorHandler errorHandler)
    Specified by:
    setErrorHandler in interface MessageHandler

    addError

    public void addError(java.lang.String error)

    addError

    public void addError(java.lang.String error,
                         java.lang.Exception e)

    addErrorAndReturnFalse

    public boolean addErrorAndReturnFalse(java.lang.String error)
    Deprecated. Please use addError(String) and return your own false :-) TODO: remove in 4.1


    addErrorAndReturnFalse

    public boolean addErrorAndReturnFalse(java.lang.String error,
                                          java.lang.Exception e)
    Deprecated. Please use addError(String, Exception) and return your own false :-) TODO: remove in 4.1


    getErrorHandler

    protected MessageErrorHandler getErrorHandler()

    getI18nBean

    protected I18nHelper getI18nBean()


    Copyright © 2002-2010 Atlassian. All Rights Reserved.