MERGE V3.4-BUG-FIX to HEAD

26951 : ALF-8784 - IMAP emails point to explorer.

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@28214 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Mark Rogers
2011-06-06 12:59:26 +00:00
parent a8f0689c1c
commit 2397fa50a3
13 changed files with 565 additions and 32 deletions

View File

@@ -37,14 +37,16 @@ import javax.mail.internet.MimeMessage;
import org.springframework.extensions.surf.util.I18NUtil;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.imap.ImapService.EmailBodyType;
import org.alfresco.repo.imap.ImapService.EmailBodyFormat;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.site.SiteModel;
import org.alfresco.repo.template.TemplateNode;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -68,6 +70,7 @@ public abstract class AbstractMimeMessage extends MimeMessage
protected ImapService imapService;
protected FileInfo messageFileInfo;
protected MimeMessage wrappedMessage;
protected boolean isMessageInSitesLibrary;
protected AbstractMimeMessage(Session session)
{
@@ -88,6 +91,7 @@ public abstract class AbstractMimeMessage extends MimeMessage
this.serviceRegistry = serviceRegistry;
this.imapService = serviceRegistry.getImapService();
this.messageFileInfo = fileInfo;
this.isMessageInSitesLibrary = imapService.isNodeInSitesLibrary(messageFileInfo.getNodeRef());
RetryingTransactionHelper txHelper = serviceRegistry.getTransactionService().getRetryingTransactionHelper();
txHelper.setMaxRetries(MAX_RETRIES);
txHelper.setReadOnly(false);
@@ -214,10 +218,10 @@ public abstract class AbstractMimeMessage extends MimeMessage
* Returns the text representing email body for ContentModel node.
*
* @param nodeRef NodeRef of the target content.
* @param type The type of the returned body. May be the one of {@link EmailBodyType}.
* @param type The type of the returned body. May be the one of {@link EmailBodyFormat}.
* @return Text representing email body for ContentModel node.
*/
public String getEmailBodyText(EmailBodyType type)
public String getEmailBodyText(EmailBodyFormat type)
{
return serviceRegistry.getTemplateService().processTemplate(
imapService.getDefaultEmailBodyTemplate(type),
@@ -278,9 +282,46 @@ public abstract class AbstractMimeMessage extends MimeMessage
model.put("date", new Date());
model.put("contextUrl", new String(imapService.getWebApplicationContextUrl()));
model.put("alfTicket", new String(serviceRegistry.getAuthenticationService().getCurrentTicket()));
if (isMessageInSitesLibrary)
{
String pathFromSites = getPathFromSites(parent);
StringBuilder parsedPath = new StringBuilder();
String[] pathParts = pathFromSites.split("/");
if (pathParts.length > 2)
{
parsedPath.append(pathParts[0]).append("/").append(pathParts[1]);
parsedPath.append("?filter=path|");
for (int i = 2; i < pathParts.length; i++)
{
parsedPath.append("/").append(pathParts[i]);
}
}
else
{
parsedPath.append(pathFromSites);
}
model.put("shareContextUrl", new String(imapService.getShareApplicationContextUrl()));
model.put("parentPathFromSites", parsedPath.toString());
}
return model;
}
private String getPathFromSites(NodeRef ref)
{
NodeService nodeService = serviceRegistry.getNodeService();
String name = ((String) nodeService.getProperty(ref, ContentModel.PROP_NAME)).toLowerCase();
if (nodeService.getType(ref).equals(SiteModel.TYPE_SITE))
{
return name;
}
else
{
NodeRef parent = nodeService.getPrimaryParent(ref).getParentRef();
return getPathFromSites(parent) + "/" + name;
}
}
protected void updateMessageID() throws MessagingException
{
setHeader("Message-ID", this.messageFileInfo.getNodeRef().getId());

View File

@@ -58,8 +58,12 @@ public interface AlfrescoImapConst
public static final String USER_SEPARATOR = ";";
// Default content model email message templates
public static final String CLASSPATH_TEXT_PLAIN_TEMPLATE = "/alfresco/templates/imap/imap_message_text_plain.ftl";
public static final String CLASSPATH_TEXT_HTML_TEMPLATE = "/alfresco/templates/imap/imap_message_text_html.ftl";
public static final String CLASSPATH_ALFRESCO_TEXT_PLAIN_TEMPLATE = "/alfresco/templates/imap/emailbody_textplain_alfresco.ftl";
public static final String CLASSPATH_SHARE_TEXT_PLAIN_TEMPLATE = "/alfresco/templates/imap/emailbody_textplain_share.ftl";
public static final String CLASSPATH_ALFRESCO_TEXT_HTML_TEMPLATE = "/alfresco/templates/imap/emailbody_texthtml_alfresco.ftl";
public static final String CLASSPATH_SHARE_TEXT_HTML_TEMPLATE = "/alfresco/templates/imap/emailbody_texthtml_share.ftl";
public static final String DICTIONARY_TEMPLATE_PREFIX = "emailbody";
public static final String PREF_IMAP_FAVOURITE_SITES = "org.alfresco.share.sites.imapFavourites";

View File

@@ -32,7 +32,7 @@ import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.imap.ImapService.EmailBodyType;
import org.alfresco.repo.imap.ImapService.EmailBodyFormat;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.namespace.QName;
@@ -98,10 +98,20 @@ public class ContentModelMessage extends AbstractMimeMessage
// Cite MOB-395: "email agent will be used to select an appropriate template" - we are not able to
// detect an email agent so we use a default template for all messages.
// See AlfrescoImapConst to see the possible templates to use.
String bodyTxt = getEmailBodyText(EmailBodyType.TEXT_PLAIN);
rootMultipart.addBodyPart(getTextBodyPart(bodyTxt, EmailBodyType.TEXT_PLAIN.getSubtype(), EmailBodyType.TEXT_PLAIN.getMimeType()));
String bodyHtml = getEmailBodyText(EmailBodyType.TEXT_HTML);
rootMultipart.addBodyPart(getTextBodyPart(bodyHtml, EmailBodyType.TEXT_HTML.getSubtype(), EmailBodyType.TEXT_HTML.getMimeType()));
if (isMessageInSitesLibrary)
{
String bodyTxt = getEmailBodyText(EmailBodyFormat.SHARE_TEXT_PLAIN);
rootMultipart.addBodyPart(getTextBodyPart(bodyTxt, EmailBodyFormat.SHARE_TEXT_PLAIN.getSubtype(), EmailBodyFormat.SHARE_TEXT_PLAIN.getMimeType()));
String bodyHtml = getEmailBodyText(EmailBodyFormat.SHARE_TEXT_HTML);
rootMultipart.addBodyPart(getTextBodyPart(bodyHtml, EmailBodyFormat.SHARE_TEXT_HTML.getSubtype(), EmailBodyFormat.SHARE_TEXT_HTML.getMimeType()));
}
else
{
String bodyTxt = getEmailBodyText(EmailBodyFormat.ALFRESCO_TEXT_PLAIN);
rootMultipart.addBodyPart(getTextBodyPart(bodyTxt, EmailBodyFormat.ALFRESCO_TEXT_PLAIN.getSubtype(), EmailBodyFormat.ALFRESCO_TEXT_PLAIN.getMimeType()));
String bodyHtml = getEmailBodyText(EmailBodyFormat.ALFRESCO_TEXT_HTML);
rootMultipart.addBodyPart(getTextBodyPart(bodyHtml, EmailBodyFormat.ALFRESCO_TEXT_HTML.getSubtype(), EmailBodyFormat.ALFRESCO_TEXT_HTML.getMimeType()));
}
return rootMultipart;
}

View File

@@ -35,37 +35,45 @@ public interface ImapService
{
/**
* Helper enumeration to handle email body type text/html and text/plain
* Helper enumeration to handle email body format text/html and text/plain for Alfresco/Share webapp
*/
public static enum EmailBodyType
public static enum EmailBodyFormat
{
TEXT_PLAIN(AlfrescoImapConst.CLASSPATH_TEXT_PLAIN_TEMPLATE),
TEXT_HTML(AlfrescoImapConst.CLASSPATH_TEXT_HTML_TEMPLATE);
ALFRESCO_TEXT_PLAIN(AlfrescoImapConst.CLASSPATH_ALFRESCO_TEXT_PLAIN_TEMPLATE),
SHARE_TEXT_PLAIN(AlfrescoImapConst.CLASSPATH_SHARE_TEXT_PLAIN_TEMPLATE),
EmailBodyType(String templatePath)
ALFRESCO_TEXT_HTML(AlfrescoImapConst.CLASSPATH_ALFRESCO_TEXT_HTML_TEMPLATE),
SHARE_TEXT_HTML(AlfrescoImapConst.CLASSPATH_SHARE_TEXT_HTML_TEMPLATE);
EmailBodyFormat(String templatePath)
{
this.templatePath = templatePath;
}
public String getSubtype()
{
return name().toLowerCase().substring(5);
return name().toLowerCase().substring(name().indexOf("_") + 1 + "TEXT".length());
}
public String getTypeSubtype()
{
return name().toLowerCase().replaceAll("_", "");
return name().toLowerCase().substring(name().indexOf("_") + 1).replaceAll("_", "");
}
public String getMimeType()
{
return name().toLowerCase().replaceAll("_", "/");
return name().toLowerCase().substring(name().indexOf("_") + 1).replaceAll("_", "/");
}
public String getClasspathTempltePath()
public String getClasspathTemplatePath()
{
return this.templatePath;
}
public String getWebApp()
{
return name().toLowerCase().substring(0, name().indexOf("_"));
}
private String templatePath;
}
@@ -228,6 +236,11 @@ public interface ImapService
*/
public String getWebApplicationContextUrl();
/**
* @return Web application context url for share (e.g. http://localhost:8080/share)
*/
public String getShareApplicationContextUrl();
/**
* Returns a template for email body. It is either classpath path or NodeRef.toString().
* This method trying to find a template on the path in the repository first
@@ -238,5 +251,14 @@ public interface ImapService
* @param Type one of the possible body types text/html and text/plain
* @return
*/
public String getDefaultEmailBodyTemplate(EmailBodyType type);
public String getDefaultEmailBodyTemplate(EmailBodyFormat type);
/**
* Determine if provided node belongs to Sites.
*
* @param nodeRef nodeRef
* @return true if provided node belongs to sites.
*/
public boolean isNodeInSitesLibrary(NodeRef nodeRef);
}

View File

@@ -127,7 +127,7 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
private String repositoryTemplatePath;
private boolean extractAttachmentsEnabled = true;
private Map<EmailBodyType, String> defaultBodyTemplates;
private Map<EmailBodyFormat, String> defaultBodyTemplates;
private final static Map<QName, Flags.Flag> qNameToFlag;
private final static Map<Flags.Flag, QName> flagToQname;
@@ -271,6 +271,11 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
return sysAdminParams.getAlfrescoProtocol() + "://" + sysAdminParams.getAlfrescoHost() + ":" + sysAdminParams.getAlfrescoPort() + "/" + sysAdminParams.getAlfrescoContext();
}
public String getShareApplicationContextUrl()
{
return sysAdminParams.getShareProtocol() + "://" + sysAdminParams.getShareHost() + ":" + sysAdminParams.getSharePort() + "/" + sysAdminParams.getShareContext();
}
public String getRepositoryTemplatePath()
{
return repositoryTemplatePath;
@@ -1915,21 +1920,23 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
return extractAttachmentsEnabled && !ignoreExtractionFolders.contains(nodeRef);
}
public String getDefaultEmailBodyTemplate(EmailBodyType type)
public String getDefaultEmailBodyTemplate(EmailBodyFormat type)
{
if (defaultBodyTemplates == null)
{
defaultBodyTemplates = new HashMap<EmailBodyType, String>(2);
defaultBodyTemplates = new HashMap<EmailBodyFormat, String>(4);
for (EmailBodyType onetype : EmailBodyType.values())
for (EmailBodyFormat onetype : EmailBodyFormat.values())
{
String result = onetype.getClasspathTempltePath();
String result = onetype.getClasspathTemplatePath();
try
{
// This query uses cm:name to find the template node(s).
// For the case where the templates are renamed, it would be better to use a QName path-based query.
final StringBuilder templateName = new StringBuilder(DICTIONARY_TEMPLATE_PREFIX).append("-").append(onetype.getTypeSubtype()).append(".ftl");
final StringBuilder templateName = new StringBuilder(DICTIONARY_TEMPLATE_PREFIX).append("_").append(onetype.getTypeSubtype()).append("_").append(onetype.getWebApp()).append(".ftl");
final String repositoryTemplatePath = getRepositoryTemplatePath();
int indexOfStoreDelim = repositoryTemplatePath.indexOf(StoreRef.URI_FILLER);
if (indexOfStoreDelim == -1)
@@ -1953,7 +1960,11 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
ResultSet resultSet = serviceRegistry.getSearchService().query(storeRef, "xpath", query);
if (resultSet == null || resultSet.length() == 0)
{
throw new IllegalArgumentException(String.format("[getDefaultEmailBodyTemplate] IMAP message template '%1$s' does not exist in the path '%2$s'.", templateName, repositoryTemplatePath));
if(logger.isDebugEnabled())
{
logger.debug("template not found:" + templateName);
}
throw new AlfrescoRuntimeException(String.format("[getDefaultEmailBodyTemplate] IMAP message template '%1$s' does not exist in the path '%2$s'.", templateName, repositoryTemplatePath));
}
final NodeRef defaultLocaleTemplate = resultSet.getNodeRef(0);
@@ -1963,7 +1974,7 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
resultSet.close();
}
// We are catching all exceptions. E.g. search service can possibly trow an exceptions on malformed queries.
// We are catching all exceptions. E.g. search service can possibly throw an exceptions on malformed queries.
catch (Exception e)
{
logger.error("[getDefaultEmailBodyTemplate]", e);
@@ -2153,5 +2164,33 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
}
/**
* Return true if provided nodeRef is in Sites/.../documentlibrary
*/
public boolean isNodeInSitesLibrary(NodeRef nodeRef)
{
boolean isInDocLibrary = false;
NodeRef parent = nodeService.getPrimaryParent(nodeRef).getParentRef();
while (parent != null && !nodeService.getType(parent).equals(SiteModel.TYPE_SITE))
{
String parentName = (String) nodeService.getProperty(parent, ContentModel.PROP_NAME);
if (parentName.equalsIgnoreCase("documentlibrary"))
{
isInDocLibrary = true;
}
nodeRef = parent;
if (nodeService.getPrimaryParent(nodeRef) != null)
{
parent = nodeService.getPrimaryParent(nodeRef).getParentRef();
}
}
if (parent == null)
{
return false;
}
else
{
return nodeService.getType(parent).equals(SiteModel.TYPE_SITE) && isInDocLibrary;
}
}
}