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

Binary file not shown.

View File

@@ -651,11 +651,11 @@
<prop key="messages">alfresco/messages/bootstrap-spaces</prop> <prop key="messages">alfresco/messages/bootstrap-spaces</prop>
</props> </props>
<!-- imapSpacesLocales.acp depends on the above imapSpaces.acp being bootstrapped as it imports <!-- imapSpacesTemplates.acp depends on the above imapSpaces.acp being bootstrapped as it imports
into folders defined in that acp. --> into folders defined in that acp. -->
<props> <props>
<prop key="path">/${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.imapConfig.childname}/${spaces.imap_templates.childname}</prop> <prop key="path">/${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.imapConfig.childname}/${spaces.imap_templates.childname}</prop>
<prop key="location">alfresco/bootstrap/imapSpacesLocales.acp</prop> <prop key="location">alfresco/bootstrap/imapSpacesTemplates.acp</prop>
<prop key="messages">alfresco/messages/bootstrap-spaces</prop> <prop key="messages">alfresco/messages/bootstrap-spaces</prop>
</props> </props>

View File

@@ -185,6 +185,9 @@ patch.webscripts.description=Adds Web Scripts to Data Dictionary.
patch.webscripts2.description=Adds Web Scripts (second set) to Data Dictionary. patch.webscripts2.description=Adds Web Scripts (second set) to Data Dictionary.
patch.webscripts3.description=Update Web Scripts ReadMe. patch.webscripts3.description=Update Web Scripts ReadMe.
patch.webscriptsExtension.description=Adds Web Scripts Extension to Data Dictionary. patch.webscriptsExtension.description=Adds Web Scripts Extension to Data Dictionary.
patch.imap.messages.share.description=Adds email template for txt files to the Imap Configs/Templates
patch.imap.clear.old.messages.description=Remove old IMAP message templates
patch.imap.clear.old.messages.description.cleared=Old IMAP message templates no more exists in repo
patch.AVMLayeredSnapshot.description=Set indirectionVersion on Layered Nodes. patch.AVMLayeredSnapshot.description=Set indirectionVersion on Layered Nodes.
patch.AVMLayeredSnapshot.result=Layered Node indirectionVersions set. patch.AVMLayeredSnapshot.result=Layered Node indirectionVersions set.

View File

@@ -2798,4 +2798,62 @@
</property> </property>
</bean> </bean>
<bean id="patch.imap.messages.share" class="org.alfresco.repo.admin.patch.impl.GenericBootstrapPatch" parent="basePatch" >
<property name="id"><value>patch.imap.messages.share</value></property>
<property name="description"><value>patch.imap.messages.share.description</value></property>
<property name="fixesFromSchema"><value>0</value></property>
<property name="fixesToSchema"><value>4202</value></property>
<property name="targetSchema"><value>4203</value></property>
<!-- bootstrap view -->
<property name="importerBootstrap">
<ref bean="spacesBootstrap" />
</property>
<property name="bootstrapView">
<props>
<prop key="path">/${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.imapConfig.childname}/${spaces.imap_templates.childname}</prop>
<prop key="location">alfresco/templates/imap/share_messages.xml</prop>
</props>
</property>
</bean>
<bean id="patch.imap.clear.old.messages" class="org.alfresco.repo.admin.patch.impl.ClearOldImapMessgesPatch" parent="basePatch" >
<property name="id"><value>patch.imap.clear.old.messages</value></property>
<property name="description"><value>patch.imap.clear.old.messages.description</value></property>
<property name="fixesFromSchema"><value>0</value></property>
<property name="fixesToSchema"><value>4202</value></property>
<property name="targetSchema"><value>4203</value></property>
<property name="importerBootstrap">
<ref bean="spacesBootstrap" />
</property>
</bean>
<bean id="patch.imap.clear.old.templates2" class="org.alfresco.repo.admin.patch.impl.ClearOldImapTemplatesPatch2" parent="basePatch" >
<property name="id"><value>patch.imap.clear.old.messages</value></property>
<property name="description"><value>patch.imap.clear.old.messages.description</value></property>
<property name="fixesFromSchema"><value>0</value></property>
<property name="fixesToSchema"><value>5000</value></property>
<property name="targetSchema"><value>5001</value></property>
<property name="importerBootstrap">
<ref bean="spacesBootstrap" />
</property>
</bean>
<bean id="patch.imapSpacesTemplates2" class="org.alfresco.repo.admin.patch.impl.GenericBootstrapPatch" parent="basePatch" >
<property name="id"><value>patch.imapSpacesLocaleTemplates</value></property>
<property name="description"><value>patch.imapSpacesLocaleTemplates.description</value></property>
<property name="fixesFromSchema"><value>0</value></property>
<property name="fixesToSchema"><value>5000</value></property>
<property name="targetSchema"><value>5001</value></property>
<property name="importerBootstrap">
<ref bean="spacesBootstrap" />
</property>
<property name="bootstrapView">
<props>
<prop key="path">/${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.imapConfig.childname}/${spaces.imap_templates.childname}</prop>
<prop key="location">alfresco/bootstrap/imapSpacesTemplates.acp</prop>
<prop key="messages">alfresco/messages/bootstrap-spaces</prop>
</props>
</property>
</bean>
</beans> </beans>

View File

@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<view:view xmlns:view="http://www.alfresco.org/view/repository/1.0">
<cm:content view:childName="cm:emailbody-share-textplain.ftl" xmlns:app="http://www.alfresco.org/model/application/1.0" xmlns:cm="http://www.alfresco.org/model/content/1.0">
<view:aspects>
<cm:titled></cm:titled>
<cm:author></cm:author>
<app:inlineeditable></app:inlineeditable>
</view:aspects>
<view:properties>
<app:editInline>true</app:editInline>
<cm:description>Email template used to generate the "multipart/alternative" IMAP message body ("text/plain" part) for documents in Sites.</cm:description>
<cm:content>contentUrl=classpath:alfresco/templates/imap/imap_message_text_plain_share.ftl|mimetype=text/plain|size=|encoding=UTF-8|locale=en_US_</cm:content>
<cm:title>emailbody-share-textplain.ftl</cm:title>
<cm:author></cm:author>
<cm:name>emailbody-share-textplain.ftl</cm:name>
</view:properties>
<view:associations></view:associations>
</cm:content>
<cm:content view:childName="cm:emailbody-share-texthtml.ftl" xmlns:app="http://www.alfresco.org/model/application/1.0" xmlns:cm="http://www.alfresco.org/model/content/1.0">
<view:aspects>
<cm:titled></cm:titled>
<cm:author></cm:author>
<app:inlineeditable></app:inlineeditable>
</view:aspects>
<view:properties>
<app:editInline>true</app:editInline>
<cm:description>Email template used to generate the "multipart/alternative" IMAP message body ("text/html" part) for documents in Sites</cm:description>
<cm:content>contentUrl=classpath:alfresco/templates/imap/imap_message_text_html_share.ftl|mimetype=text/plain|size=|encoding=UTF-8|locale=en_US_</cm:content>
<cm:title>emailbody-share-texthtml.ftl</cm:title>
<cm:author></cm:author>
<cm:name>emailbody-share-texthtml.ftl</cm:name>
</view:properties>
<view:associations></view:associations>
</cm:content>
<cm:content view:childName="cm:emailbody-alfresco-textplain.ftl" xmlns:app="http://www.alfresco.org/model/application/1.0" xmlns:cm="http://www.alfresco.org/model/content/1.0">
<view:aspects>
<cm:titled></cm:titled>
<cm:author></cm:author>
<app:inlineeditable></app:inlineeditable>
</view:aspects>
<view:properties>
<app:editInline>true</app:editInline>
<cm:description>Email template used to generate the "multipart/alternative" IMAP message body ("text/plain" part) for documents in Alfresco</cm:description>
<cm:content>contentUrl=classpath:alfresco/templates/imap/imap_message_text_plain_alfresco.ftl|mimetype=text/plain|size=|encoding=UTF-8|locale=en_US_</cm:content>
<cm:title>emailbody-alfresco-textplain.ftl</cm:title>
<cm:author></cm:author>
<cm:name>emailbody-alfresco-textplain.ftl</cm:name>
</view:properties>
<view:associations></view:associations>
</cm:content>
<cm:content view:childName="cm:emailbody-alfresco-texthtml.ftl" xmlns:app="http://www.alfresco.org/model/application/1.0" xmlns:cm="http://www.alfresco.org/model/content/1.0">
<view:aspects>
<cm:titled></cm:titled>
<cm:author></cm:author>
<app:inlineeditable></app:inlineeditable>
</view:aspects>
<view:properties>
<app:editInline>true</app:editInline>
<cm:description>Email template used to generate the "multipart/alternative" IMAP message body ("text/html" part) for documents in Alfresco</cm:description>
<cm:content>contentUrl=classpath:alfresco/templates/imap/imap_message_text_html_alfresco.ftl|mimetype=text/plain|size=|encoding=UTF-8|locale=en_US_</cm:content>
<cm:title>emailbody-alfresco-texthtml.ftl</cm:title>
<cm:author></cm:author>
<cm:name>emailbody-alfresco-texthtml.ftl</cm:name>
</view:properties>
<view:associations></view:associations>
</cm:content>
</view:view>

View File

@@ -19,4 +19,4 @@ version.build=@build-number@
# Schema number # Schema number
version.schema=5000 version.schema=5001

View File

@@ -0,0 +1,137 @@
/*
* 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.admin.patch.impl;
import java.util.List;
import java.util.Properties;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.admin.patch.AbstractPatch;
import org.alfresco.repo.importer.ImporterBootstrap;
import org.alfresco.service.cmr.admin.PatchException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.springframework.extensions.surf.util.I18NUtil;
public class ClearOldImapMessgesPatch extends AbstractPatch
{
private static final String MSG_REMOVED = "patch.imap.clear.old.messages.description.cleared";
private static final String PROPERTY_COMPANY_HOME_CHILDNAME = "spaces.company_home.childname";
private static final String PROPERTY_DICTIONARY_CHILDNAME = "spaces.dictionary.childname";
private static final String PROPERTY_SCRIPTS_CHILDNAME = "spaces.scripts.childname";
private static final String PROPERTY_IMAP_CONFIG_CHILDNAME = "spaces.imapConfig.childname";
private static final String PROPERTY_IMAP_TEMPLATES_CHILDNAME = "spaces.imap_templates.childname";
private ImporterBootstrap importerBootstrap;
protected Properties configuration;
private NodeRef imapTemplatesFolderNodeRef;
public void setImporterBootstrap(ImporterBootstrap importerBootstrap)
{
this.importerBootstrap = importerBootstrap;
}
protected void setUp() throws Exception
{
// get the node store that we must work against
StoreRef storeRef = importerBootstrap.getStoreRef();
if (storeRef == null)
{
throw new PatchException("Bootstrap store has not been set");
}
NodeRef storeRootNodeRef = nodeService.getRootNode(storeRef);
this.configuration = importerBootstrap.getConfiguration();
// get the association names that form the path
String companyHomeChildName = configuration.getProperty(PROPERTY_COMPANY_HOME_CHILDNAME);
if (companyHomeChildName == null || companyHomeChildName.length() == 0)
{
throw new PatchException("Bootstrap property '" + PROPERTY_COMPANY_HOME_CHILDNAME + "' is not present");
}
String dictionaryChildName = configuration.getProperty(PROPERTY_DICTIONARY_CHILDNAME);
if (dictionaryChildName == null || dictionaryChildName.length() == 0)
{
throw new PatchException("Bootstrap property '" + PROPERTY_DICTIONARY_CHILDNAME + "' is not present");
}
String scriptsChildName = configuration.getProperty(PROPERTY_SCRIPTS_CHILDNAME);
if (scriptsChildName == null || scriptsChildName.length() == 0)
{
throw new PatchException("Bootstrap property '" + PROPERTY_SCRIPTS_CHILDNAME + "' is not present");
}
String imapConfigChildName = configuration.getProperty(PROPERTY_IMAP_CONFIG_CHILDNAME);
if (imapConfigChildName == null || imapConfigChildName.length() == 0)
{
throw new PatchException("Bootstrap property '" + PROPERTY_IMAP_CONFIG_CHILDNAME + "' is not present");
}
String imapTemplatesChildName = configuration.getProperty(PROPERTY_IMAP_TEMPLATES_CHILDNAME);
if (imapConfigChildName == null || imapConfigChildName.length() == 0)
{
throw new PatchException("Bootstrap property '" + PROPERTY_IMAP_CONFIG_CHILDNAME + "' is not present");
}
// build the search string to get the company home node
StringBuilder sb = new StringBuilder(256);
sb.append("/").append(companyHomeChildName);
sb.append("/").append(dictionaryChildName);
sb.append("/").append(imapConfigChildName);
sb.append("/").append(imapTemplatesChildName);
String xpath = sb.toString();
List<NodeRef> nodeRefs = searchService.selectNodes(storeRootNodeRef, xpath, null, namespaceService, false);
if (nodeRefs.size() > 1)
{
throw new PatchException("XPath returned too many results: \n" + " root: " + storeRootNodeRef + "\n" + " xpath: " + xpath + "\n" + " results: " + nodeRefs);
}
else if (nodeRefs.size() == 0)
{
this.imapTemplatesFolderNodeRef = null;
}
else
{
this.imapTemplatesFolderNodeRef = nodeRefs.get(0);
}
}
@Override
protected String applyInternal() throws Exception
{
setUp();
if (imapTemplatesFolderNodeRef != null)
{
NodeRef oldTextPlain = nodeService.getChildByName(imapTemplatesFolderNodeRef, ContentModel.ASSOC_CONTAINS, "emailbody-textplain.ftl");
NodeRef oldTextHTML = nodeService.getChildByName(imapTemplatesFolderNodeRef, ContentModel.ASSOC_CONTAINS, "emailbody-texthtml.ftl");
if (oldTextPlain != null)
{
nodeService.deleteNode(oldTextPlain);
}
if (oldTextHTML != null)
{
nodeService.deleteNode(oldTextHTML);
}
}
return I18NUtil.getMessage(MSG_REMOVED);
}
}

View File

@@ -0,0 +1,152 @@
/*
* 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.admin.patch.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.admin.patch.AbstractPatch;
import org.alfresco.repo.importer.ImporterBootstrap;
import org.alfresco.service.cmr.admin.PatchException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.springframework.extensions.surf.util.I18NUtil;
public class ClearOldImapTemplatesPatch2 extends AbstractPatch
{
private static final String MSG_REMOVED = "patch.imap.clear.old.messages.description.cleared";
private static final String PROPERTY_COMPANY_HOME_CHILDNAME = "spaces.company_home.childname";
private static final String PROPERTY_DICTIONARY_CHILDNAME = "spaces.dictionary.childname";
private static final String PROPERTY_SCRIPTS_CHILDNAME = "spaces.scripts.childname";
private static final String PROPERTY_IMAP_CONFIG_CHILDNAME = "spaces.imapConfig.childname";
private static final String PROPERTY_IMAP_TEMPLATES_CHILDNAME = "spaces.imap_templates.childname";
private ImporterBootstrap importerBootstrap;
protected Properties configuration;
private NodeRef imapTemplatesFolderNodeRef;
public void setImporterBootstrap(ImporterBootstrap importerBootstrap)
{
this.importerBootstrap = importerBootstrap;
}
protected void setUp() throws Exception
{
// get the node store that we must work against
StoreRef storeRef = importerBootstrap.getStoreRef();
if (storeRef == null)
{
throw new PatchException("Bootstrap store has not been set");
}
NodeRef storeRootNodeRef = nodeService.getRootNode(storeRef);
this.configuration = importerBootstrap.getConfiguration();
// get the association names that form the path
String companyHomeChildName = configuration.getProperty(PROPERTY_COMPANY_HOME_CHILDNAME);
if (companyHomeChildName == null || companyHomeChildName.length() == 0)
{
throw new PatchException("Bootstrap property '" + PROPERTY_COMPANY_HOME_CHILDNAME + "' is not present");
}
String dictionaryChildName = configuration.getProperty(PROPERTY_DICTIONARY_CHILDNAME);
if (dictionaryChildName == null || dictionaryChildName.length() == 0)
{
throw new PatchException("Bootstrap property '" + PROPERTY_DICTIONARY_CHILDNAME + "' is not present");
}
String scriptsChildName = configuration.getProperty(PROPERTY_SCRIPTS_CHILDNAME);
if (scriptsChildName == null || scriptsChildName.length() == 0)
{
throw new PatchException("Bootstrap property '" + PROPERTY_SCRIPTS_CHILDNAME + "' is not present");
}
String imapConfigChildName = configuration.getProperty(PROPERTY_IMAP_CONFIG_CHILDNAME);
if (imapConfigChildName == null || imapConfigChildName.length() == 0)
{
throw new PatchException("Bootstrap property '" + PROPERTY_IMAP_CONFIG_CHILDNAME + "' is not present");
}
String imapTemplatesChildName = configuration.getProperty(PROPERTY_IMAP_TEMPLATES_CHILDNAME);
if (imapConfigChildName == null || imapConfigChildName.length() == 0)
{
throw new PatchException("Bootstrap property '" + PROPERTY_IMAP_CONFIG_CHILDNAME + "' is not present");
}
// build the search string to get the company home node
StringBuilder sb = new StringBuilder(256);
sb.append("/").append(companyHomeChildName);
sb.append("/").append(dictionaryChildName);
sb.append("/").append(imapConfigChildName);
sb.append("/").append(imapTemplatesChildName);
String xpath = sb.toString();
List<NodeRef> nodeRefs = searchService.selectNodes(storeRootNodeRef, xpath, null, namespaceService, false);
if (nodeRefs.size() > 1)
{
throw new PatchException("XPath returned too many results: \n" + " root: " + storeRootNodeRef + "\n" + " xpath: " + xpath + "\n" + " results: " + nodeRefs);
}
else if (nodeRefs.size() == 0)
{
this.imapTemplatesFolderNodeRef = null;
}
else
{
this.imapTemplatesFolderNodeRef = nodeRefs.get(0);
}
}
@Override
protected String applyInternal() throws Exception
{
setUp();
if (imapTemplatesFolderNodeRef != null)
{
List<String> templatesToDelete = new ArrayList<String>();
templatesToDelete.add("emailbody-textplain.ftl");
templatesToDelete.add("emailbody-textplain_de.ftl");
templatesToDelete.add("emailbody-textplain_it.ftl");
templatesToDelete.add("emailbody-textplain_fr.ftl");
templatesToDelete.add("emailbody-textplain_ja.ftl");
templatesToDelete.add("emailbody-textplain_es.ftl");
templatesToDelete.add("emailbody-texthtml.ftl");
templatesToDelete.add("emailbody-texthtml_de.ftl");
templatesToDelete.add("emailbody-texthtml_it.ftl");
templatesToDelete.add("emailbody-texthtml_fr.ftl");
templatesToDelete.add("emailbody-texthtml_ja.ftl");
templatesToDelete.add("emailbody-texthtml_es.ftl");
for(String template : templatesToDelete)
{
NodeRef nodeRef = nodeService.getChildByName(imapTemplatesFolderNodeRef, ContentModel.ASSOC_CONTAINS, template);
if(nodeRef != null)
{
nodeService.deleteNode(nodeRef);
}
}
}
return I18NUtil.getMessage(MSG_REMOVED);
}
}

View File

@@ -37,14 +37,16 @@ import javax.mail.internet.MimeMessage;
import org.springframework.extensions.surf.util.I18NUtil; import org.springframework.extensions.surf.util.I18NUtil;
import org.alfresco.model.ContentModel; 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.security.authentication.AuthenticationUtil;
import org.alfresco.repo.site.SiteModel;
import org.alfresco.repo.template.TemplateNode; import org.alfresco.repo.template.TemplateNode;
import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.ServiceRegistry; import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.model.FileInfo; import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@@ -68,6 +70,7 @@ public abstract class AbstractMimeMessage extends MimeMessage
protected ImapService imapService; protected ImapService imapService;
protected FileInfo messageFileInfo; protected FileInfo messageFileInfo;
protected MimeMessage wrappedMessage; protected MimeMessage wrappedMessage;
protected boolean isMessageInSitesLibrary;
protected AbstractMimeMessage(Session session) protected AbstractMimeMessage(Session session)
{ {
@@ -88,6 +91,7 @@ public abstract class AbstractMimeMessage extends MimeMessage
this.serviceRegistry = serviceRegistry; this.serviceRegistry = serviceRegistry;
this.imapService = serviceRegistry.getImapService(); this.imapService = serviceRegistry.getImapService();
this.messageFileInfo = fileInfo; this.messageFileInfo = fileInfo;
this.isMessageInSitesLibrary = imapService.isNodeInSitesLibrary(messageFileInfo.getNodeRef());
RetryingTransactionHelper txHelper = serviceRegistry.getTransactionService().getRetryingTransactionHelper(); RetryingTransactionHelper txHelper = serviceRegistry.getTransactionService().getRetryingTransactionHelper();
txHelper.setMaxRetries(MAX_RETRIES); txHelper.setMaxRetries(MAX_RETRIES);
txHelper.setReadOnly(false); txHelper.setReadOnly(false);
@@ -214,10 +218,10 @@ public abstract class AbstractMimeMessage extends MimeMessage
* Returns the text representing email body for ContentModel node. * Returns the text representing email body for ContentModel node.
* *
* @param nodeRef NodeRef of the target content. * @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. * @return Text representing email body for ContentModel node.
*/ */
public String getEmailBodyText(EmailBodyType type) public String getEmailBodyText(EmailBodyFormat type)
{ {
return serviceRegistry.getTemplateService().processTemplate( return serviceRegistry.getTemplateService().processTemplate(
imapService.getDefaultEmailBodyTemplate(type), imapService.getDefaultEmailBodyTemplate(type),
@@ -278,9 +282,46 @@ public abstract class AbstractMimeMessage extends MimeMessage
model.put("date", new Date()); model.put("date", new Date());
model.put("contextUrl", new String(imapService.getWebApplicationContextUrl())); model.put("contextUrl", new String(imapService.getWebApplicationContextUrl()));
model.put("alfTicket", new String(serviceRegistry.getAuthenticationService().getCurrentTicket())); 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; 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 protected void updateMessageID() throws MessagingException
{ {
setHeader("Message-ID", this.messageFileInfo.getNodeRef().getId()); setHeader("Message-ID", this.messageFileInfo.getNodeRef().getId());

View File

@@ -58,8 +58,12 @@ public interface AlfrescoImapConst
public static final String USER_SEPARATOR = ";"; public static final String USER_SEPARATOR = ";";
// Default content model email message templates // 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_ALFRESCO_TEXT_PLAIN_TEMPLATE = "/alfresco/templates/imap/emailbody_textplain_alfresco.ftl";
public static final String CLASSPATH_TEXT_HTML_TEMPLATE = "/alfresco/templates/imap/imap_message_text_html.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 DICTIONARY_TEMPLATE_PREFIX = "emailbody";
public static final String PREF_IMAP_FAVOURITE_SITES = "org.alfresco.share.sites.imapFavourites"; 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 javax.mail.internet.MimeUtility;
import org.alfresco.model.ContentModel; 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.ServiceRegistry;
import org.alfresco.service.cmr.model.FileInfo; import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.namespace.QName; 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 // 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. // detect an email agent so we use a default template for all messages.
// See AlfrescoImapConst to see the possible templates to use. // See AlfrescoImapConst to see the possible templates to use.
String bodyTxt = getEmailBodyText(EmailBodyType.TEXT_PLAIN); if (isMessageInSitesLibrary)
rootMultipart.addBodyPart(getTextBodyPart(bodyTxt, EmailBodyType.TEXT_PLAIN.getSubtype(), EmailBodyType.TEXT_PLAIN.getMimeType())); {
String bodyHtml = getEmailBodyText(EmailBodyType.TEXT_HTML); String bodyTxt = getEmailBodyText(EmailBodyFormat.SHARE_TEXT_PLAIN);
rootMultipart.addBodyPart(getTextBodyPart(bodyHtml, EmailBodyType.TEXT_HTML.getSubtype(), EmailBodyType.TEXT_HTML.getMimeType())); 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; 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), ALFRESCO_TEXT_PLAIN(AlfrescoImapConst.CLASSPATH_ALFRESCO_TEXT_PLAIN_TEMPLATE),
TEXT_HTML(AlfrescoImapConst.CLASSPATH_TEXT_HTML_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; this.templatePath = templatePath;
} }
public String getSubtype() public String getSubtype()
{ {
return name().toLowerCase().substring(5); return name().toLowerCase().substring(name().indexOf("_") + 1 + "TEXT".length());
} }
public String getTypeSubtype() public String getTypeSubtype()
{ {
return name().toLowerCase().replaceAll("_", ""); return name().toLowerCase().substring(name().indexOf("_") + 1).replaceAll("_", "");
} }
public String getMimeType() public String getMimeType()
{ {
return name().toLowerCase().replaceAll("_", "/"); return name().toLowerCase().substring(name().indexOf("_") + 1).replaceAll("_", "/");
} }
public String getClasspathTempltePath() public String getClasspathTemplatePath()
{ {
return this.templatePath; return this.templatePath;
} }
public String getWebApp()
{
return name().toLowerCase().substring(0, name().indexOf("_"));
}
private String templatePath; private String templatePath;
} }
@@ -228,6 +236,11 @@ public interface ImapService
*/ */
public String getWebApplicationContextUrl(); 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(). * 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 * 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 * @param Type one of the possible body types text/html and text/plain
* @return * @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 String repositoryTemplatePath;
private boolean extractAttachmentsEnabled = true; 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<QName, Flags.Flag> qNameToFlag;
private final static Map<Flags.Flag, QName> flagToQname; 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(); return sysAdminParams.getAlfrescoProtocol() + "://" + sysAdminParams.getAlfrescoHost() + ":" + sysAdminParams.getAlfrescoPort() + "/" + sysAdminParams.getAlfrescoContext();
} }
public String getShareApplicationContextUrl()
{
return sysAdminParams.getShareProtocol() + "://" + sysAdminParams.getShareHost() + ":" + sysAdminParams.getSharePort() + "/" + sysAdminParams.getShareContext();
}
public String getRepositoryTemplatePath() public String getRepositoryTemplatePath()
{ {
return repositoryTemplatePath; return repositoryTemplatePath;
@@ -1915,21 +1920,23 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
return extractAttachmentsEnabled && !ignoreExtractionFolders.contains(nodeRef); return extractAttachmentsEnabled && !ignoreExtractionFolders.contains(nodeRef);
} }
public String getDefaultEmailBodyTemplate(EmailBodyType type) public String getDefaultEmailBodyTemplate(EmailBodyFormat type)
{ {
if (defaultBodyTemplates == null) 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 try
{ {
// This query uses cm:name to find the template node(s). // 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. // 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(); final String repositoryTemplatePath = getRepositoryTemplatePath();
int indexOfStoreDelim = repositoryTemplatePath.indexOf(StoreRef.URI_FILLER); int indexOfStoreDelim = repositoryTemplatePath.indexOf(StoreRef.URI_FILLER);
if (indexOfStoreDelim == -1) if (indexOfStoreDelim == -1)
@@ -1953,7 +1960,11 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
ResultSet resultSet = serviceRegistry.getSearchService().query(storeRef, "xpath", query); ResultSet resultSet = serviceRegistry.getSearchService().query(storeRef, "xpath", query);
if (resultSet == null || resultSet.length() == 0) 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); final NodeRef defaultLocaleTemplate = resultSet.getNodeRef(0);
@@ -1963,7 +1974,7 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
resultSet.close(); 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) catch (Exception e)
{ {
logger.error("[getDefaultEmailBodyTemplate]", 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;
}
}
} }