mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
Initial cut of IMAP support (disabled by default, to enable move imap sample files into extension folder)
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@14279 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -40,6 +40,8 @@ import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.service.cmr.email.EmailMessage;
|
||||
import org.alfresco.service.cmr.email.EmailMessageException;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.MimetypeService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
@@ -120,24 +122,54 @@ public class FolderEmailMessageHandler extends AbstractEmailMessageHandler
|
||||
// Write the message content
|
||||
if (message.getBody() != null)
|
||||
{
|
||||
InputStream contentIs = message.getBody().getContent();
|
||||
// The message body is plain text, unless an extension has been provided
|
||||
MimetypeService mimetypeService = getMimetypeService();
|
||||
String mimetype = mimetypeService.guessMimetype(messageSubject);
|
||||
if (mimetype.equals(MimetypeMap.MIMETYPE_BINARY))
|
||||
if (message.getBody().getSize() == -1)
|
||||
{
|
||||
mimetype= MimetypeMap.MIMETYPE_TEXT_PLAIN;
|
||||
// If message body is empty we write space as a content
|
||||
// to make possible rule processing
|
||||
// (Rules don't work on empty documents)
|
||||
writeSpace(contentNodeRef);
|
||||
}
|
||||
else
|
||||
{
|
||||
InputStream contentIs = message.getBody().getContent();
|
||||
// The message body is plain text, unless an extension has been provided
|
||||
MimetypeService mimetypeService = getMimetypeService();
|
||||
String mimetype = mimetypeService.guessMimetype(messageSubject);
|
||||
if (mimetype.equals(MimetypeMap.MIMETYPE_BINARY))
|
||||
{
|
||||
mimetype = MimetypeMap.MIMETYPE_TEXT_PLAIN;
|
||||
}
|
||||
// Use the default encoding. It will get overridden if the body is text.
|
||||
String encoding = message.getBody().getEncoding();
|
||||
|
||||
writeContent(contentNodeRef, contentIs, mimetype, encoding);
|
||||
}
|
||||
// Use the default encoding. It will get overridden if the body is text.
|
||||
String encoding = message.getBody().getEncoding();
|
||||
|
||||
writeContent(contentNodeRef, contentIs, mimetype, encoding);
|
||||
}
|
||||
|
||||
// Add attachments
|
||||
addAttachments(spaceNodeRef, contentNodeRef, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method writes space as a content. We need this space because rules doesn't proceed documents with empty content. We need rule processing for command email messages with
|
||||
* empty body.
|
||||
*
|
||||
* @param nodeRef Reference to the parent node
|
||||
*/
|
||||
private void writeSpace(NodeRef nodeRef)
|
||||
{
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
log.debug("Write space string");
|
||||
}
|
||||
|
||||
ContentService contentService = getContentService();
|
||||
ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true);
|
||||
writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
|
||||
writer.setEncoding("UTF-8");
|
||||
writer.putContent(" ");
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds titled aspect to the specified node.
|
||||
*
|
||||
|
@@ -153,7 +153,7 @@ public class SubethaEmailMessage implements EmailMessage
|
||||
|
||||
try
|
||||
{
|
||||
subject = mimeMessage.getSubject();
|
||||
subject = encodeSubject(mimeMessage.getSubject());
|
||||
}
|
||||
catch (MessagingException e)
|
||||
{
|
||||
@@ -373,7 +373,8 @@ public class SubethaEmailMessage implements EmailMessage
|
||||
|
||||
for (EmailMessagePart attachment : attachments)
|
||||
{
|
||||
if (attachment instanceof SubethaEmailMessagePart) {
|
||||
if (attachment instanceof SubethaEmailMessagePart)
|
||||
{
|
||||
((SubethaEmailMessagePart) attachment).setRmiRegistry(rmiRegistryHost, rmiRegistryPort);
|
||||
}
|
||||
}
|
||||
@@ -410,4 +411,24 @@ public class SubethaEmailMessage implements EmailMessage
|
||||
return attachments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces characters \/*|:"<>? on their hex values. Subject field is used as name of the content, so we need to replace characters that are forbidden in content names.
|
||||
*
|
||||
* @param subject String representing subject
|
||||
* @return Encoded string
|
||||
*/
|
||||
static private String encodeSubject(String subject)
|
||||
{
|
||||
String result = subject.trim();
|
||||
String[][] s = new String[][] { { "\\", "%5c" }, { "/", "%2f" }, { "*", "%2a" }, { "|", "%7c" }, { ":", "%3a" }, { "\"", "%22" }, { "<", "%3c" }, { ">", "%3e" },
|
||||
{ "?", "%3f" } };
|
||||
|
||||
for (int i = 0; i < s.length; i++)
|
||||
{
|
||||
result = result.replace(s[i][0], s[i][1]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
60
source/java/org/alfresco/model/ImapModel.java
Executable file
60
source/java/org/alfresco/model/ImapModel.java
Executable file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program 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 General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.model;
|
||||
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* IMAP Model Constants
|
||||
*
|
||||
* @author Mike Shavnev
|
||||
*/
|
||||
public interface ImapModel
|
||||
{
|
||||
static final String IMAP_MODEL_1_0_URI = "http://www.alfresco.org/model/imap/1.0";
|
||||
|
||||
static final QName ASPECT_IMAP_FOLDER_SUBSCRIBED = QName.createQName(IMAP_MODEL_1_0_URI, "subscribed");
|
||||
static final QName ASPECT_IMAP_FOLDER_NONSELECTABLE = QName.createQName(IMAP_MODEL_1_0_URI, "nonselectable");
|
||||
|
||||
static final QName TYPE_IMAP_CONTENT = QName.createQName(IMAP_MODEL_1_0_URI, "imapContent");
|
||||
static final QName PROP_MESSAGE_FROM = QName.createQName(IMAP_MODEL_1_0_URI, "messageFrom");
|
||||
static final QName PROP_MESSAGE_TO = QName.createQName(IMAP_MODEL_1_0_URI, "messageTo");
|
||||
static final QName PROP_MESSAGE_CC = QName.createQName(IMAP_MODEL_1_0_URI, "messageCc");
|
||||
static final QName PROP_MESSAGE_SUBJECT = QName.createQName(IMAP_MODEL_1_0_URI, "messageSubject");
|
||||
|
||||
static final QName ASPECT_FLAGGABLE = QName.createQName(IMAP_MODEL_1_0_URI, "flaggable");
|
||||
static final QName PROP_FLAG_ANSWERED = QName.createQName(IMAP_MODEL_1_0_URI, "flagAnswered");
|
||||
static final QName PROP_FLAG_DELETED = QName.createQName(IMAP_MODEL_1_0_URI, "flagDeleted");
|
||||
static final QName PROP_FLAG_DRAFT = QName.createQName(IMAP_MODEL_1_0_URI, "flagDraft");
|
||||
static final QName PROP_FLAG_SEEN = QName.createQName(IMAP_MODEL_1_0_URI, "flagSeen");
|
||||
static final QName PROP_FLAG_RECENT = QName.createQName(IMAP_MODEL_1_0_URI, "flagRecent");
|
||||
static final QName PROP_FLAG_FLAGGED = QName.createQName(IMAP_MODEL_1_0_URI, "flagFlagged");
|
||||
|
||||
static final QName TYPE_IMAP_BODY = QName.createQName(IMAP_MODEL_1_0_URI, "imapBody");
|
||||
|
||||
static final QName TYPE_IMAP_ATTACH = QName.createQName(IMAP_MODEL_1_0_URI, "imapAttach");
|
||||
static final QName PROP_ATTACH_ID = QName.createQName(IMAP_MODEL_1_0_URI, "attachID");
|
||||
|
||||
}
|
@@ -58,7 +58,8 @@ public class ScriptActionExecuter extends ActionExecuterAbstractBase
|
||||
private String companyHomePath;
|
||||
private StoreRef storeRef;
|
||||
private ScriptLocation scriptLocation;
|
||||
|
||||
private String webApplicationContextUrl;
|
||||
|
||||
/**
|
||||
* @param serviceRegistry The serviceRegistry to set.
|
||||
*/
|
||||
@@ -94,7 +95,17 @@ public class ScriptActionExecuter extends ActionExecuterAbstractBase
|
||||
{
|
||||
this.scriptLocation = scriptLocation;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the web application context url
|
||||
*
|
||||
* @param webApplicationContextUrl web application context url
|
||||
*/
|
||||
public void setWebApplicationContextUrl(String webApplicationContextUrl)
|
||||
{
|
||||
this.webApplicationContextUrl = webApplicationContextUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow adhoc properties to be passed to this action
|
||||
*
|
||||
@@ -149,7 +160,9 @@ public class ScriptActionExecuter extends ActionExecuterAbstractBase
|
||||
// Add the action to the default model
|
||||
ScriptAction scriptAction = new ScriptAction(this.serviceRegistry, action, this.actionDefinition);
|
||||
model.put("action", scriptAction);
|
||||
|
||||
|
||||
model.put("webApplicationContextUrl", webApplicationContextUrl);
|
||||
|
||||
Object result = null;
|
||||
if (this.scriptLocation == null)
|
||||
{
|
||||
|
264
source/java/org/alfresco/repo/admin/patch/impl/ImapFoldersPatch.java
Executable file
264
source/java/org/alfresco/repo/admin/patch/impl/ImapFoldersPatch.java
Executable file
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program 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 General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.admin.patch.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.alfresco.i18n.I18NUtil;
|
||||
import org.alfresco.repo.admin.patch.AbstractPatch;
|
||||
import org.alfresco.repo.importer.ACPImportPackageHandler;
|
||||
import org.alfresco.repo.importer.ImporterBootstrap;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
import org.alfresco.service.cmr.admin.PatchException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.view.ImporterService;
|
||||
import org.alfresco.service.cmr.view.Location;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
/**
|
||||
* Builds folders tree necessary for IMAP functionality and imports email action scripts.
|
||||
*
|
||||
* 1. Company Home > Data Dictionary > Imap Config > Templates
|
||||
* 2. Company Home > Data Dictionary > Email Actions > search
|
||||
* 3. Company Home > Data Dictionary > Scripts > command-processor.js, command-search.js
|
||||
*
|
||||
* @author Arseny Kovalchuk
|
||||
*/
|
||||
public class ImapFoldersPatch extends AbstractPatch
|
||||
{
|
||||
// messages' ids
|
||||
private static final String MSG_EXISTS = "patch.imapFolders.result.exists";
|
||||
private static final String MSG_CREATED = "patch.imapFolders.result.created";
|
||||
|
||||
// folders' names for path building
|
||||
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 ImporterBootstrap importerBootstrap;
|
||||
private MessageSource messageSource;
|
||||
protected Properties configuration;
|
||||
private ImporterService importerService;
|
||||
|
||||
private NodeRef companyHomeNodeRef;
|
||||
private NodeRef dictionaryNodeRef;
|
||||
private NodeRef scriptsNodeRef;
|
||||
private NodeRef imapConfigFolderNodeRef;
|
||||
private String configFoldersACP;
|
||||
private String emailActionsACP;
|
||||
private String scriptsACP;
|
||||
|
||||
public void setImporterBootstrap(ImporterBootstrap importerBootstrap)
|
||||
{
|
||||
this.importerBootstrap = importerBootstrap;
|
||||
}
|
||||
|
||||
public void setMessageSource(MessageSource messageSource)
|
||||
{
|
||||
this.messageSource = messageSource;
|
||||
}
|
||||
|
||||
public void setImporterService(ImporterService importerService)
|
||||
{
|
||||
this.importerService = importerService;
|
||||
}
|
||||
|
||||
public void setConfigFoldersACP(String configFoldersACP)
|
||||
{
|
||||
this.configFoldersACP = configFoldersACP;
|
||||
}
|
||||
|
||||
public void setEmailActionsACP(String emailActionsACP)
|
||||
{
|
||||
this.emailActionsACP = emailActionsACP;
|
||||
}
|
||||
|
||||
public void setScriptsACP(String scriptsACP)
|
||||
{
|
||||
this.scriptsACP = scriptsACP;
|
||||
}
|
||||
|
||||
protected void checkCommonProperties() throws Exception
|
||||
{
|
||||
checkPropertyNotNull(importerBootstrap, "importerBootstrap");
|
||||
checkPropertyNotNull(messageSource, "messageSource");
|
||||
checkPropertyNotNull(importerService, "importerService");
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
// build the search string to get the company home node
|
||||
StringBuilder sb = new StringBuilder(256);
|
||||
sb.append("/").append(companyHomeChildName);
|
||||
String xpath = sb.toString();
|
||||
// get the company home
|
||||
List<NodeRef> nodeRefs = searchService.selectNodes(storeRootNodeRef, xpath, null, namespaceService, false);
|
||||
if (nodeRefs.size() == 0)
|
||||
{
|
||||
throw new PatchException("XPath didn't return any results: \n" + " root: " + storeRootNodeRef + "\n" + " xpath: " + xpath);
|
||||
}
|
||||
else if (nodeRefs.size() > 1)
|
||||
{
|
||||
throw new PatchException("XPath returned too many results: \n" + " root: " + storeRootNodeRef + "\n" + " xpath: " + xpath + "\n" + " results: " + nodeRefs);
|
||||
}
|
||||
this.companyHomeNodeRef = nodeRefs.get(0);
|
||||
|
||||
// build the search string to get the dictionary node
|
||||
sb.append("/").append(dictionaryChildName);
|
||||
xpath = sb.toString();
|
||||
// get the dictionary node
|
||||
nodeRefs = searchService.selectNodes(storeRootNodeRef, xpath, null, namespaceService, false);
|
||||
if (nodeRefs.size() == 0)
|
||||
{
|
||||
throw new PatchException("XPath didn't return any results: \n" + " root: " + storeRootNodeRef + "\n" + " xpath: " + xpath);
|
||||
}
|
||||
else if (nodeRefs.size() > 1)
|
||||
{
|
||||
throw new PatchException("XPath returned too many results: \n" + " root: " + storeRootNodeRef + "\n" + " xpath: " + xpath + "\n" + " results: " + nodeRefs);
|
||||
}
|
||||
this.dictionaryNodeRef = nodeRefs.get(0);
|
||||
sb.append("/").append(scriptsChildName);
|
||||
xpath = sb.toString();
|
||||
nodeRefs = searchService.selectNodes(storeRootNodeRef, xpath, null, namespaceService, false);
|
||||
if (nodeRefs.size() == 0)
|
||||
{
|
||||
throw new PatchException("XPath didn't return any results: \n" + " root: " + storeRootNodeRef + "\n" + " xpath: " + xpath);
|
||||
}
|
||||
else if (nodeRefs.size() > 1)
|
||||
{
|
||||
throw new PatchException("XPath returned too many results: \n" + " root: " + storeRootNodeRef + "\n" + " xpath: " + xpath + "\n" + " results: " + nodeRefs);
|
||||
}
|
||||
this.scriptsNodeRef = nodeRefs.get(0);
|
||||
// get the ImapConfig node
|
||||
sb.delete((sb.length() - (scriptsChildName.length() + 1)), sb.length());
|
||||
sb.append("/").append(imapConfigChildName);
|
||||
xpath = sb.toString();
|
||||
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.imapConfigFolderNodeRef = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.imapConfigFolderNodeRef = nodeRefs.get(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String applyInternal() throws Exception
|
||||
{
|
||||
checkCommonProperties();
|
||||
setUp();
|
||||
String msg = null;
|
||||
if (imapConfigFolderNodeRef == null)
|
||||
{
|
||||
// import the content
|
||||
RunAsWork<Object> importRunAs = new RunAsWork<Object>()
|
||||
{
|
||||
public Object doWork() throws Exception
|
||||
{
|
||||
importImapConfig();
|
||||
importScripts();
|
||||
importEmailActions();
|
||||
return null;
|
||||
}
|
||||
};
|
||||
AuthenticationUtil.runAs(importRunAs, authenticationContext.getSystemUserName());
|
||||
msg = I18NUtil.getMessage(MSG_CREATED);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg = I18NUtil.getMessage(MSG_EXISTS, imapConfigFolderNodeRef);
|
||||
}
|
||||
return msg;
|
||||
|
||||
}
|
||||
|
||||
private void importImapConfig() throws IOException
|
||||
{
|
||||
importInternal(this.configFoldersACP, this.dictionaryNodeRef);
|
||||
}
|
||||
|
||||
private void importEmailActions() throws IOException
|
||||
{
|
||||
importInternal(this.emailActionsACP, this.dictionaryNodeRef);
|
||||
}
|
||||
|
||||
private void importScripts() throws IOException
|
||||
{
|
||||
importInternal(this.scriptsACP, this.scriptsNodeRef);
|
||||
}
|
||||
|
||||
private void importInternal(String acpName, NodeRef space) throws IOException
|
||||
{
|
||||
ClassPathResource acpResource = new ClassPathResource(acpName);
|
||||
ACPImportPackageHandler acpHandler = new ACPImportPackageHandler(acpResource.getFile(), null);
|
||||
Location importLocation = new Location(space);
|
||||
importerService.importView(acpHandler, importLocation, null, null);
|
||||
}
|
||||
|
||||
}
|
257
source/java/org/alfresco/repo/admin/patch/impl/ImapUsersPatch.java
Executable file
257
source/java/org/alfresco/repo/admin/patch/impl/ImapUsersPatch.java
Executable file
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
* This program 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 General Public License for more details.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
* As a special exception to the terms and conditions of version 2.0 of.
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.admin.patch.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import org.alfresco.i18n.I18NUtil;
|
||||
import org.alfresco.model.ApplicationModel;
|
||||
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.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.search.ResultSet;
|
||||
import org.alfresco.service.cmr.search.SearchParameters;
|
||||
import org.alfresco.service.cmr.search.SearchService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.springframework.context.MessageSource;
|
||||
|
||||
/**
|
||||
* @author Dmitry Vaserin
|
||||
*/
|
||||
public class ImapUsersPatch extends AbstractPatch
|
||||
{
|
||||
// messages' ids
|
||||
private static final String MSG_EXISTS = "patch.imapUserFolders.result.exists";
|
||||
private static final String MSG_CREATED = "patch.imapUserFolders.result.created";
|
||||
|
||||
// folders' names for path building
|
||||
private static final String PROPERTY_COMPANY_HOME_CHILDNAME = "spaces.company_home.childname";
|
||||
private static final String PROPERTY_IMAP_HOME_FOLDER_CHILDNAME = "spaces.imap_home.childname";
|
||||
|
||||
private static final String PROPERTY_ICON = "space-icon-default";
|
||||
private static final String MSG_IMAP_HOME_FOLDER_NAME = "spaces.imap_home.name";
|
||||
private static final String MSG_IMAP_HOME_FOLDER_DESCRIPTION = "spaces.imap_home.description";
|
||||
|
||||
private static final String INBOX_NAME = "INBOX";
|
||||
private static final String INBOX_DECSRIPTION = "INBOX mail box";
|
||||
|
||||
private ImporterBootstrap importerBootstrap;
|
||||
private MessageSource messageSource;
|
||||
|
||||
protected NodeRef companyHomeNodeRef;
|
||||
protected Properties configuration;
|
||||
protected NodeRef imapHomeNodeRef;
|
||||
|
||||
public void setImporterBootstrap(ImporterBootstrap importerBootstrap)
|
||||
{
|
||||
this.importerBootstrap = importerBootstrap;
|
||||
}
|
||||
|
||||
public void setMessageSource(MessageSource messageSource)
|
||||
{
|
||||
this.messageSource = messageSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that required common properties have been set
|
||||
*/
|
||||
protected void checkCommonProperties() throws Exception
|
||||
{
|
||||
checkPropertyNotNull(importerBootstrap, "importerBootstrap");
|
||||
checkPropertyNotNull(namespaceService, "namespaceService");
|
||||
checkPropertyNotNull(searchService, "searchService");
|
||||
checkPropertyNotNull(nodeService, "nodeService");
|
||||
checkPropertyNotNull(messageSource, "messageSource");
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts pertinent references and properties that are common to execution of this and derived patches.
|
||||
*/
|
||||
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 imapHomeChildName = configuration.getProperty(PROPERTY_IMAP_HOME_FOLDER_CHILDNAME);
|
||||
if (imapHomeChildName == null || imapHomeChildName.length() == 0)
|
||||
{
|
||||
throw new PatchException("Bootstrap property '" + PROPERTY_IMAP_HOME_FOLDER_CHILDNAME + "' is not present");
|
||||
}
|
||||
|
||||
// build the search string to get the company home node
|
||||
StringBuilder sb = new StringBuilder(256);
|
||||
sb.append("/").append(companyHomeChildName);
|
||||
String xpath = sb.toString();
|
||||
// get the company home
|
||||
List<NodeRef> nodeRefs = searchService.selectNodes(storeRootNodeRef, xpath, null, namespaceService, false);
|
||||
if (nodeRefs.size() == 0)
|
||||
{
|
||||
throw new PatchException("XPath didn't return any results: \n" + " root: " + storeRootNodeRef + "\n" + " xpath: " + xpath);
|
||||
}
|
||||
else if (nodeRefs.size() > 1)
|
||||
{
|
||||
throw new PatchException("XPath returned too many results: \n" + " root: " + storeRootNodeRef + "\n" + " xpath: " + xpath + "\n" + " results: " + nodeRefs);
|
||||
}
|
||||
this.companyHomeNodeRef = nodeRefs.get(0);
|
||||
|
||||
xpath = imapHomeChildName;
|
||||
nodeRefs = searchService.selectNodes(companyHomeNodeRef, xpath, null, namespaceService, false);
|
||||
if (nodeRefs.size() > 1)
|
||||
{
|
||||
throw new PatchException("XPath returned too many results: \n" + " dictionary node: " + companyHomeNodeRef + "\n" + " xpath: " + xpath + "\n" + " results: "
|
||||
+ nodeRefs);
|
||||
}
|
||||
else if (nodeRefs.size() == 0)
|
||||
{
|
||||
// the node does not exist
|
||||
this.imapHomeNodeRef = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.imapHomeNodeRef = nodeRefs.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String applyInternal() throws Exception
|
||||
{
|
||||
// properties must be set
|
||||
checkCommonProperties();
|
||||
// get useful values
|
||||
setUp();
|
||||
|
||||
String msg = null;
|
||||
|
||||
if (imapHomeNodeRef == null)
|
||||
{
|
||||
// create it
|
||||
createImapHomeFolders();
|
||||
msg = I18NUtil.getMessage(MSG_CREATED, imapHomeNodeRef);
|
||||
}
|
||||
else
|
||||
{
|
||||
// it already exists
|
||||
msg = I18NUtil.getMessage(MSG_EXISTS, imapHomeNodeRef);
|
||||
}
|
||||
|
||||
// done
|
||||
return msg;
|
||||
}
|
||||
|
||||
private void createImapHomeFolders()
|
||||
{
|
||||
// get required properties
|
||||
String imapHomeChildName = configuration.getProperty(PROPERTY_IMAP_HOME_FOLDER_CHILDNAME);
|
||||
if (imapHomeChildName == null)
|
||||
{
|
||||
throw new PatchException("Bootstrap property '" + PROPERTY_IMAP_HOME_FOLDER_CHILDNAME + "' is not present");
|
||||
}
|
||||
|
||||
String name = messageSource.getMessage(MSG_IMAP_HOME_FOLDER_NAME, null, I18NUtil.getLocale());
|
||||
if (name == null || name.length() == 0)
|
||||
{
|
||||
throw new PatchException("Bootstrap property '" + MSG_IMAP_HOME_FOLDER_NAME + "' is not present");
|
||||
}
|
||||
|
||||
String description = messageSource.getMessage(MSG_IMAP_HOME_FOLDER_DESCRIPTION, null, I18NUtil.getLocale());
|
||||
if (description == null || description.length() == 0)
|
||||
{
|
||||
throw new PatchException("Bootstrap property '" + MSG_IMAP_HOME_FOLDER_DESCRIPTION + "' is not present");
|
||||
}
|
||||
|
||||
imapHomeNodeRef = createSpace(companyHomeNodeRef, name, description, imapHomeChildName);
|
||||
|
||||
// Create IMAP Home and "INBOX" for each user
|
||||
createImapUserHomes();
|
||||
|
||||
}
|
||||
|
||||
private void createImapUserHomes()
|
||||
{
|
||||
StringBuilder query = new StringBuilder(128);
|
||||
query.append("@").append(NamespaceService.CONTENT_MODEL_PREFIX).append("\\:userName:*");
|
||||
|
||||
SearchParameters params = new SearchParameters();
|
||||
params.setLanguage(SearchService.LANGUAGE_LUCENE);
|
||||
params.addStore(importerBootstrap.getStoreRef());
|
||||
params.setQuery(query.toString());
|
||||
|
||||
ResultSet results = searchService.query(params);
|
||||
List<NodeRef> people;
|
||||
try
|
||||
{
|
||||
people = results.getNodeRefs();
|
||||
}
|
||||
finally
|
||||
{
|
||||
results.close();
|
||||
}
|
||||
|
||||
for (NodeRef nodeRef : people)
|
||||
{
|
||||
String userName = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_USERNAME);
|
||||
String desc = userName + " " + messageSource.getMessage(MSG_IMAP_HOME_FOLDER_NAME, null, I18NUtil.getLocale());
|
||||
NodeRef userHome = createSpace(imapHomeNodeRef, userName, desc, userName);
|
||||
// Create Inbox
|
||||
createSpace(userHome, INBOX_NAME, INBOX_DECSRIPTION, INBOX_NAME);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private NodeRef createSpace(NodeRef parent, String name, String desc, String childName)
|
||||
{
|
||||
Map<QName, Serializable> properties = new HashMap<QName, Serializable>(7);
|
||||
properties.put(ContentModel.PROP_NAME, name);
|
||||
properties.put(ContentModel.PROP_TITLE, name);
|
||||
properties.put(ContentModel.PROP_DESCRIPTION, desc);
|
||||
properties.put(ApplicationModel.PROP_ICON, PROPERTY_ICON);
|
||||
// create the node
|
||||
ChildAssociationRef childAssocRef = nodeService.createNode(parent, ContentModel.ASSOC_CONTAINS, QName.resolveToQName(namespaceService, childName),
|
||||
ContentModel.TYPE_FOLDER, properties);
|
||||
NodeRef result = childAssocRef.getChildRef();
|
||||
|
||||
// add the required aspects
|
||||
nodeService.addAspect(result, ApplicationModel.ASPECT_UIFACETS, null);
|
||||
return result;
|
||||
}
|
||||
}
|
72
source/java/org/alfresco/repo/imap/AlfrescoImapConst.java
Executable file
72
source/java/org/alfresco/repo/imap/AlfrescoImapConst.java
Executable file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program 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 General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.imap;
|
||||
|
||||
/**
|
||||
* @author Mike Shavnev
|
||||
*/
|
||||
public interface AlfrescoImapConst
|
||||
{
|
||||
|
||||
public static final char HIERARCHY_DELIMITER = '.';
|
||||
public static final String NAMESPACE_PREFIX = "#";
|
||||
public static final String USER_NAMESPACE = "#mail";
|
||||
public static final String INBOX_NAME = "INBOX";
|
||||
|
||||
public static final String BODY_TEXT_PLAIN_NAME = "Body.txt";
|
||||
public static final String BODY_TEXT_HTML_NAME = "Body.html";
|
||||
public static final String MESSAGE_PREFIX = "Message_";
|
||||
// Separator for user enties in flag and subscribe properties
|
||||
public static final String USER_SEPARATOR = ";";
|
||||
|
||||
/**
|
||||
* Defines {@link AlfrescoImapMailFolder} view mode as archive mode. Used for Email Archive View.
|
||||
*/
|
||||
public static final String MODE_ARCHIVE = "archive";
|
||||
/**
|
||||
* Defines {@link AlfrescoImapMailFolder} view mode as virtual mode. Used for IMAP Virtualised View.
|
||||
*/
|
||||
public static final String MODE_VIRTUAL = "virtual";
|
||||
|
||||
// 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 DICTIONARY_TEMPLATE_PREFIX = "emailbody";
|
||||
public static final String PREF_IMAP_FAVOURITE_SITES = "org.alfresco.share.sites.imap.favourites";
|
||||
|
||||
// AlfrescoImapMessage constants
|
||||
public static final String MIME_VERSION = "MIME-Version";
|
||||
public static final String CONTENT_TYPE = "Content-Type";
|
||||
public static final String CONTENT_TRANSFER_ENCODING = "Content-Transfer-Encoding";
|
||||
public static final String MULTIPART_MIXED = "mixed";
|
||||
public static final String CONTENT_ID = "Content-ID";
|
||||
public static final String X_ALF_NODEREF_ID = "X-Alfresco-NodeRef-ID"; // The NodeRef id header
|
||||
public static final String X_ALF_SERVER_UID = "X-Alfresco-Server-UID"; // The unique identifier of Alfresco server
|
||||
public static final String EIGHT_BIT_ENCODING = "8bit";
|
||||
public static final String BASE_64_ENCODING = "base64";
|
||||
public static final String UTF_8 = "UTF-8";
|
||||
|
||||
}
|
958
source/java/org/alfresco/repo/imap/AlfrescoImapHostManager.java
Executable file
958
source/java/org/alfresco/repo/imap/AlfrescoImapHostManager.java
Executable file
@@ -0,0 +1,958 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program 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 General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.imap;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.model.ImapModel;
|
||||
import org.alfresco.repo.imap.config.ImapConfigElement.ImapConfig;
|
||||
import org.alfresco.repo.imap.exception.AlfrescoImapFolderException;
|
||||
import org.alfresco.repo.model.filefolder.FileFolderServiceImpl;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.model.FileExistsException;
|
||||
import org.alfresco.service.cmr.model.FileFolderService;
|
||||
import org.alfresco.service.cmr.model.FileInfo;
|
||||
import org.alfresco.service.cmr.model.FileNotFoundException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.security.AccessStatus;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import com.icegreen.greenmail.imap.AuthorizationException;
|
||||
import com.icegreen.greenmail.imap.ImapHostManager;
|
||||
import com.icegreen.greenmail.store.FolderException;
|
||||
import com.icegreen.greenmail.store.MailFolder;
|
||||
import com.icegreen.greenmail.user.GreenMailUser;
|
||||
import com.icegreen.greenmail.util.GreenMailUtil;
|
||||
|
||||
/**
|
||||
* @author Mike Shavnev
|
||||
*/
|
||||
public class AlfrescoImapHostManager implements ImapHostManager
|
||||
{
|
||||
|
||||
private Log logger = LogFactory.getLog(AlfrescoImapHostManager.class);
|
||||
|
||||
private ServiceRegistry serviceRegistry;
|
||||
|
||||
private NodeService nodeService;
|
||||
private FileFolderService fileFolderService;
|
||||
private ImapHelper imapHelper;
|
||||
|
||||
/**
|
||||
* Returns the hierarchy delimiter for mailboxes on this host.
|
||||
*
|
||||
* @return The hierarchy delimiter character.
|
||||
*/
|
||||
public char getHierarchyDelimiter()
|
||||
{
|
||||
return AlfrescoImapConst.HIERARCHY_DELIMITER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an collection of mailboxes. Method searches mailboxes under mount points defined for a specific user. Mount points include user's IMAP Virtualised Views and Email
|
||||
* Archive Views. This method serves LIST command of the IMAP protocol.
|
||||
*
|
||||
* @param user User making the request
|
||||
* @param mailboxPattern String name of a mailbox possible including a wildcard.
|
||||
* @return Collection of mailboxes matching the pattern.
|
||||
* @throws com.icegreen.greenmail.store.FolderException
|
||||
*/
|
||||
public Collection<MailFolder> listMailboxes(GreenMailUser user, String mailboxPattern) throws FolderException
|
||||
{
|
||||
mailboxPattern = GreenMailUtil.convertFromUtf7(mailboxPattern);
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Listing mailboxes: mailboxPattern=" + mailboxPattern);
|
||||
}
|
||||
mailboxPattern = imapHelper.getMailPathInRepo(mailboxPattern);
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Listing mailboxes: mailboxPattern in alfresco=" + mailboxPattern);
|
||||
}
|
||||
|
||||
Collection<MailFolder> result = new LinkedList<MailFolder>();
|
||||
|
||||
Map<String, NodeRef> mountPoints = imapHelper.getMountPoints();
|
||||
Map<String, ImapConfig> imapConfigs = imapHelper.getImapConfigs();
|
||||
|
||||
NodeRef mountPoint;
|
||||
for (String mountPointName : mountPoints.keySet())
|
||||
{
|
||||
|
||||
mountPoint = mountPoints.get(mountPointName);
|
||||
FileInfo mountPointFileInfo = imapHelper.getFileFolderService().getFileInfo(mountPoint);
|
||||
|
||||
NodeRef mountParent = imapHelper.getNodeService().getParentAssocs(mountPoint).get(0).getParentRef();
|
||||
String mode = imapConfigs.get(mountPointName).getMode();
|
||||
|
||||
if (!mailboxPattern.equals("*"))
|
||||
{
|
||||
mountPoint = mountParent;
|
||||
}
|
||||
|
||||
boolean isVirtualView = imapConfigs.get(mountPointName).getMode().equals(AlfrescoImapConst.MODE_VIRTUAL);
|
||||
Collection<FileInfo> folders = listFolder(mountPoint, user, mailboxPattern, isVirtualView);
|
||||
if (folders != null)
|
||||
{
|
||||
for (FileInfo folder : folders)
|
||||
{
|
||||
result.add(new AlfrescoImapMailFolder(user.getQualifiedMailboxName(), folder, folder.getName(), mode, mountParent, mountPointName, imapHelper));
|
||||
}
|
||||
}
|
||||
if (mailboxPattern.equals("*"))
|
||||
{
|
||||
result.add(new AlfrescoImapMailFolder(user.getQualifiedMailboxName(), mountPointFileInfo, mountPointName, mode, mountParent, mountPointName, imapHelper));
|
||||
}
|
||||
}
|
||||
mountPoint = imapHelper.getUserImapHomeRef(user.getLogin());
|
||||
Collection<FileInfo> imapFolders = listFolder(mountPoint, user, mailboxPattern, false);
|
||||
if (imapFolders != null)
|
||||
{
|
||||
for (FileInfo imapFolder : imapFolders)
|
||||
{
|
||||
result.add(new AlfrescoImapMailFolder(user.getQualifiedMailboxName(), imapFolder, imapFolder.getName(), AlfrescoImapConst.MODE_ARCHIVE, mountPoint, null,
|
||||
imapHelper));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private Collection<FileInfo> listFolder(NodeRef root, GreenMailUser user, String mailboxPattern, boolean isVirtualView) throws FolderException
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Listing mailboxes: mailboxPattern=" + mailboxPattern);
|
||||
}
|
||||
|
||||
Collection<FileInfo> result = new LinkedList<FileInfo>();
|
||||
|
||||
int index = mailboxPattern.indexOf(AlfrescoImapConst.HIERARCHY_DELIMITER);
|
||||
|
||||
String name = null;
|
||||
String remainName = null;
|
||||
|
||||
if (index < 0)
|
||||
{
|
||||
name = mailboxPattern;
|
||||
}
|
||||
else
|
||||
{
|
||||
name = mailboxPattern.substring(0, index);
|
||||
remainName = mailboxPattern.substring(index + 1);
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Listing mailboxes: name=" + name);
|
||||
}
|
||||
|
||||
if (index < 0)
|
||||
{
|
||||
if ("*".equals(name))
|
||||
{
|
||||
List<FileInfo> list = imapHelper.searchFolders(root, name, true, isVirtualView);
|
||||
if (list.size() > 0)
|
||||
{
|
||||
return list;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
else if (name.endsWith("*"))
|
||||
{
|
||||
List<FileInfo> list = imapHelper.searchFolders(root, name.replace('%', '*'), false, isVirtualView);
|
||||
if (list.size() > 0)
|
||||
{
|
||||
result.addAll(list);
|
||||
for (FileInfo fileInfo : list)
|
||||
{
|
||||
List<FileInfo> childList = imapHelper.searchFolders(fileInfo.getNodeRef(), "*", true, isVirtualView);
|
||||
result.addAll(childList);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
else if (name.contains("%") || name.contains("*"))
|
||||
{
|
||||
List<FileInfo> list = imapHelper.searchFolders(root, name.replace('%', '*'), false, isVirtualView);
|
||||
if (list.size() > 0)
|
||||
{
|
||||
return list;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
List<FileInfo> list = imapHelper.searchFolders(root, name, false, isVirtualView);
|
||||
if (list.size() > 0)
|
||||
{
|
||||
return list;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
List<FileInfo> list = imapHelper.searchFolders(root, name.replace('%', '*'), false, isVirtualView);
|
||||
for (FileInfo folder : list)
|
||||
{
|
||||
Collection<FileInfo> childFolders = listFolder(folder.getNodeRef(), user, remainName, isVirtualView);
|
||||
if (childFolders != null)
|
||||
{
|
||||
result.addAll(childFolders);
|
||||
}
|
||||
}
|
||||
|
||||
if (result.isEmpty())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an collection of subscribed mailboxes. To appear in search result mailboxes should have {http://www.alfresco.org/model/imap/1.0}subscribed property specified for
|
||||
* user. Method searches subscribed mailboxes under mount points defined for a specific user. Mount points include user's IMAP Virtualised Views and Email Archive Views. This
|
||||
* method serves LSUB command of the IMAP protocol.
|
||||
*
|
||||
* @param user User making the request
|
||||
* @param mailboxPattern String name of a mailbox possible including a wildcard.
|
||||
* @return Collection of mailboxes matching the pattern.
|
||||
* @throws com.icegreen.greenmail.store.FolderException
|
||||
*/
|
||||
public Collection<MailFolder> listSubscribedMailboxes(GreenMailUser user, String mailboxPattern) throws FolderException
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Listing subscribed mailboxes: mailboxPattern=" + mailboxPattern);
|
||||
}
|
||||
mailboxPattern = imapHelper.getMailPathInRepo(mailboxPattern);
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Listing subscribed mailboxes: mailboxPattern in alfresco=" + mailboxPattern);
|
||||
}
|
||||
|
||||
Collection<MailFolder> result = new LinkedList<MailFolder>();
|
||||
|
||||
Map<String, NodeRef> mountPoints = imapHelper.getMountPoints();
|
||||
Map<String, ImapConfig> imapConfigs = imapHelper.getImapConfigs();
|
||||
|
||||
NodeRef mountPoint;
|
||||
|
||||
for (String mountPointName : mountPoints.keySet())
|
||||
{
|
||||
|
||||
mountPoint = mountPoints.get(mountPointName);
|
||||
FileInfo mountPointFileInfo = imapHelper.getFileFolderService().getFileInfo(mountPoint);
|
||||
NodeRef mountParent = imapHelper.getNodeService().getParentAssocs(mountPoint).get(0).getParentRef();
|
||||
String viewMode = imapConfigs.get(mountPointName).getMode();
|
||||
|
||||
if (!mailboxPattern.equals("*"))
|
||||
{
|
||||
mountPoint = mountParent;
|
||||
}
|
||||
|
||||
boolean isVirtualView = imapConfigs.get(mountPointName).getMode().equals(AlfrescoImapConst.MODE_VIRTUAL);
|
||||
Collection<MailFolder> folders = listSubscribedFolder(mountPoint, mountPoint, user, mailboxPattern, isVirtualView);
|
||||
if (folders != null)
|
||||
{
|
||||
for (MailFolder mailFolder : folders)
|
||||
{
|
||||
AlfrescoImapMailFolder folder = (AlfrescoImapMailFolder) mailFolder;
|
||||
folder.setMountPointName(mountPointName);
|
||||
folder.setViewMode(viewMode);
|
||||
folder.setMountParent(mountParent);
|
||||
}
|
||||
result.addAll(folders);
|
||||
}
|
||||
|
||||
if (mailboxPattern.equals("*"))
|
||||
{
|
||||
if (isSubscribed(mountPointFileInfo, user.getLogin()))
|
||||
{
|
||||
result.add(new AlfrescoImapMailFolder(user.getQualifiedMailboxName(), mountPointFileInfo, mountPointName, viewMode, mountParent, mountPointName, imapHelper));
|
||||
}
|
||||
// \NoSelect
|
||||
else if (hasSubscribedChild(mountPointFileInfo, user.getLogin(), isVirtualView))
|
||||
{
|
||||
result.add(new AlfrescoImapMailFolder(user.getQualifiedMailboxName(), mountPointFileInfo, mountPointName, viewMode, mountParent, mountPointName, imapHelper,
|
||||
false));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
NodeRef root = imapHelper.getSpacesStoreNodeRef();
|
||||
|
||||
root = imapHelper.getUserImapHomeRef(user.getLogin());
|
||||
Collection<MailFolder> imapFolders = listSubscribedFolder(root, root, user, mailboxPattern, false);
|
||||
|
||||
if (imapFolders != null)
|
||||
{
|
||||
result.addAll(imapFolders);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private Collection<MailFolder> listSubscribedFolder(NodeRef mailboxRoot, NodeRef root, GreenMailUser user, String mailboxPattern, boolean isVirtualView) throws FolderException
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Listing mailboxes: mailboxPattern=" + mailboxPattern);
|
||||
}
|
||||
|
||||
int index = mailboxPattern.indexOf(AlfrescoImapConst.HIERARCHY_DELIMITER);
|
||||
|
||||
String name = null;
|
||||
String remainName = null;
|
||||
|
||||
if (index < 0)
|
||||
{
|
||||
name = mailboxPattern;
|
||||
}
|
||||
else
|
||||
{
|
||||
name = mailboxPattern.substring(0, index);
|
||||
remainName = mailboxPattern.substring(index + 1);
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Listing mailboxes: name=" + name);
|
||||
}
|
||||
|
||||
if (index < 0)
|
||||
{
|
||||
if ("*".equals(name))
|
||||
{
|
||||
List<FileInfo> list = imapHelper.searchFolders(root, name, true, isVirtualView);
|
||||
Collection<FileInfo> subscribedList = getSubscribed(list, user.getLogin());
|
||||
|
||||
if (subscribedList.size() > 0)
|
||||
{
|
||||
return createMailFolderList(user, subscribedList, mailboxRoot);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
else if (name.endsWith("*"))
|
||||
{
|
||||
List<FileInfo> fullList = new LinkedList<FileInfo>();
|
||||
List<FileInfo> list = imapHelper.searchFolders(root, name.replace('%', '*'), false, isVirtualView);
|
||||
Collection<FileInfo> subscribedList = getSubscribed(list, user.getLogin());
|
||||
|
||||
if (list.size() > 0)
|
||||
{
|
||||
fullList.addAll(subscribedList);
|
||||
for (FileInfo fileInfo : list)
|
||||
{
|
||||
List<FileInfo> childList = imapHelper.searchFolders(fileInfo.getNodeRef(), "*", true, isVirtualView);
|
||||
fullList.addAll(getSubscribed(childList, user.getLogin()));
|
||||
}
|
||||
return createMailFolderList(user, fullList, mailboxRoot);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
else if ("%".equals(name))
|
||||
{
|
||||
List<FileInfo> list = imapHelper.searchFolders(root, "*", false, isVirtualView);
|
||||
LinkedList<MailFolder> subscribedList = new LinkedList<MailFolder>();
|
||||
|
||||
for (FileInfo fileInfo : list)
|
||||
{
|
||||
if (isSubscribed(fileInfo, user.getLogin()))
|
||||
{
|
||||
// folderName, viewMode, mountPointName will be setted in listSubscribedMailboxes() method
|
||||
subscribedList.add(new AlfrescoImapMailFolder(user.getQualifiedMailboxName(), fileInfo, null, null, mailboxRoot, null, imapHelper));
|
||||
}
|
||||
// \NoSelect
|
||||
else if (hasSubscribedChild(fileInfo, user.getLogin(), isVirtualView))
|
||||
{
|
||||
// folderName, viewMode, mountPointName will be setted in listSubscribedMailboxes() method
|
||||
subscribedList.add(new AlfrescoImapMailFolder(user.getQualifiedMailboxName(), fileInfo, null, null, mailboxRoot, null, imapHelper, false));
|
||||
}
|
||||
}
|
||||
|
||||
return subscribedList;
|
||||
}
|
||||
else if (name.contains("%") || name.contains("*"))
|
||||
{
|
||||
List<FileInfo> list = imapHelper.searchFolders(root, name.replace('%', '*'), false, isVirtualView);
|
||||
Collection<FileInfo> subscribedList = getSubscribed(list, user.getLogin());
|
||||
|
||||
if (subscribedList.size() > 0)
|
||||
{
|
||||
return createMailFolderList(user, subscribedList, mailboxRoot);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
List<FileInfo> list = imapHelper.searchFolders(root, name, false, isVirtualView);
|
||||
Collection<FileInfo> subscribedList = getSubscribed(list, user.getLogin());
|
||||
|
||||
if (subscribedList.size() > 0)
|
||||
{
|
||||
return createMailFolderList(user, subscribedList, mailboxRoot);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// If (index != -1) this is not the last level
|
||||
Collection<MailFolder> result = new LinkedList<MailFolder>();
|
||||
|
||||
List<FileInfo> list = imapHelper.searchFolders(root, name.replace('%', '*'), false, isVirtualView);
|
||||
for (FileInfo folder : list)
|
||||
{
|
||||
Collection<MailFolder> childFolders = listSubscribedFolder(mailboxRoot, folder.getNodeRef(), user, remainName, isVirtualView);
|
||||
|
||||
if (childFolders != null)
|
||||
{
|
||||
result.addAll(childFolders);
|
||||
}
|
||||
}
|
||||
|
||||
if (result.isEmpty())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renames an existing mailbox. The specified mailbox must already exist, the requested name must not exist already but must be able to be created and the user must have rights
|
||||
* to delete the existing mailbox and create a mailbox with the new name. Any inferior hierarchical names must also be renamed. If INBOX is renamed, the contents of INBOX are
|
||||
* transferred to a new mailbox with the new name, but INBOX is not deleted. If INBOX has inferior mailbox these are not renamed. This method serves RENAME command of the IMAP
|
||||
* protocol. <p/> Method searches mailbox under mount points defined for a specific user. Mount points include user's IMAP Virtualised Views and Email Archive Views.
|
||||
*
|
||||
* @param user User making the request.
|
||||
* @param oldMailboxName String name of the existing folder
|
||||
* @param newMailboxName String target new name
|
||||
* @throws com.icegreen.greenmail.store.FolderException if an existing folder with the new name.
|
||||
* @throws AlfrescoImapFolderException if user does not have rights to create the new mailbox.
|
||||
*/
|
||||
|
||||
public void renameMailbox(GreenMailUser user, String oldMailboxName, String newMailboxName) throws FolderException, AuthorizationException
|
||||
{
|
||||
oldMailboxName = GreenMailUtil.convertFromUtf7(oldMailboxName);
|
||||
newMailboxName = GreenMailUtil.convertFromUtf7(newMailboxName);
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Renaming folder: oldMailboxName=" + oldMailboxName + " newMailboxName=" + newMailboxName);
|
||||
}
|
||||
|
||||
AlfrescoImapMailFolder sourceNode = (AlfrescoImapMailFolder) getFolder(user, GreenMailUtil.convertInUtf7(oldMailboxName));
|
||||
|
||||
NodeRef root = imapHelper.getMailboxRootRef(oldMailboxName, user.getLogin());
|
||||
String mailboxRepoName = imapHelper.getMailPathInRepo(newMailboxName);
|
||||
|
||||
StringTokenizer tokenizer = new StringTokenizer(mailboxRepoName, String.valueOf(AlfrescoImapConst.HIERARCHY_DELIMITER));
|
||||
|
||||
NodeRef parentNodeRef = root;
|
||||
while (tokenizer.hasMoreTokens())
|
||||
{
|
||||
String folderName = tokenizer.nextToken();
|
||||
|
||||
if (!tokenizer.hasMoreTokens())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (oldMailboxName.equalsIgnoreCase(AlfrescoImapConst.INBOX_NAME))
|
||||
{
|
||||
// If you trying to rename INBOX
|
||||
// - just copy it to another folder with new name
|
||||
// and leave INBOX (with children) intact.
|
||||
fileFolderService.copy(sourceNode.getFolderInfo().getNodeRef(), parentNodeRef, folderName);
|
||||
List<FileInfo> itemsForRemove = fileFolderService.list(sourceNode.getFolderInfo().getNodeRef());
|
||||
for (FileInfo fileInfo : itemsForRemove)
|
||||
{
|
||||
fileFolderService.delete(fileInfo.getNodeRef());
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
fileFolderService.move(sourceNode.getFolderInfo().getNodeRef(), parentNodeRef, folderName);
|
||||
}
|
||||
return;
|
||||
}
|
||||
catch (FileExistsException e)
|
||||
{
|
||||
throw new FolderException(FolderException.ALREADY_EXISTS_LOCALLY);
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
List<FileInfo> folders = imapHelper.searchFolders(parentNodeRef, folderName, false, true);
|
||||
|
||||
if (folders.size() == 0)
|
||||
{
|
||||
AccessStatus status = imapHelper.hasPermission(parentNodeRef, PermissionService.WRITE);
|
||||
if (status == AccessStatus.DENIED)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Creating folder: Cant't create folder - Permission denied");
|
||||
}
|
||||
throw new AlfrescoImapFolderException(AlfrescoImapFolderException.PERMISSION_DENIED);
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Create mailBox: " + folderName);
|
||||
}
|
||||
FileFolderServiceImpl.makeFolders(fileFolderService, parentNodeRef, Arrays.asList(folderName), ContentModel.TYPE_FOLDER);
|
||||
}
|
||||
else
|
||||
{
|
||||
parentNodeRef = folders.get(0).getNodeRef();
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("MailBox: " + folderName + " already exists");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to a newly created mailbox. The request should specify a mailbox that does not already exist on this server, that could exist on this server and that the
|
||||
* user has rights to create. This method serves CREATE command of the IMAP protocol.
|
||||
*
|
||||
* @param user User making the request.
|
||||
* @param mailboxName String name of the target
|
||||
* @return an Mailbox reference.
|
||||
* @throws com.icegreen.greenmail.store.FolderException if mailbox already exists
|
||||
* @throws AlfrescoImapFolderException if user does not have rights to create the new mailbox.
|
||||
*/
|
||||
public MailFolder createMailbox(GreenMailUser user, String mailboxName) throws AuthorizationException, FolderException
|
||||
{
|
||||
mailboxName = GreenMailUtil.convertFromUtf7(mailboxName);
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Creating folder: " + mailboxName);
|
||||
}
|
||||
|
||||
NodeRef root = imapHelper.getMailboxRootRef(mailboxName, user.getLogin());
|
||||
|
||||
String mountPointName = imapHelper.getMountPointName(mailboxName);
|
||||
String mailboxRepoNam = imapHelper.getMailPathInRepo(mailboxName);
|
||||
StringTokenizer tokenizer = new StringTokenizer(mailboxRepoNam, String.valueOf(AlfrescoImapConst.HIERARCHY_DELIMITER));
|
||||
|
||||
NodeRef parentNodeRef = root;
|
||||
|
||||
while (tokenizer.hasMoreTokens())
|
||||
{
|
||||
String folderName = tokenizer.nextToken();
|
||||
|
||||
List<FileInfo> folders = imapHelper.searchFolders(parentNodeRef, folderName, false, true);
|
||||
|
||||
if (folders.size() == 0)
|
||||
{
|
||||
AccessStatus status = imapHelper.hasPermission(parentNodeRef, PermissionService.WRITE);
|
||||
if (status == AccessStatus.DENIED)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Creating folder: Cant't create folder - Permission denied");
|
||||
}
|
||||
throw new AlfrescoImapFolderException(AlfrescoImapFolderException.PERMISSION_DENIED);
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Create mailBox: " + mailboxName);
|
||||
}
|
||||
FileInfo mailFolder = FileFolderServiceImpl.makeFolders(fileFolderService, parentNodeRef, Arrays.asList(folderName), ContentModel.TYPE_FOLDER);
|
||||
|
||||
|
||||
return new AlfrescoImapMailFolder(user.getQualifiedMailboxName(), mailFolder, folderName, imapHelper.getViewMode(mailboxName), root, mountPointName, imapHelper);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
parentNodeRef = folders.get(0).getNodeRef();
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("MailBox: " + folderName + " already exists");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new FolderException(FolderException.ALREADY_EXISTS_LOCALLY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an existing MailBox. Specified mailbox must already exist on this server, and the user must have rights to delete it. <p/> This method serves DELETE command of the
|
||||
* IMAP protocol.
|
||||
*
|
||||
* @param user User making the request.
|
||||
* @param mailboxName String name of the target
|
||||
* @throws com.icegreen.greenmail.store.FolderException if mailbox has a non-selectable store with children
|
||||
*/
|
||||
public void deleteMailbox(GreenMailUser user, String mailboxName) throws FolderException, AuthorizationException
|
||||
{
|
||||
AlfrescoImapMailFolder folder = (AlfrescoImapMailFolder) getFolder(user, mailboxName);
|
||||
NodeRef nodeRef = folder.getFolderInfo().getNodeRef();
|
||||
|
||||
List<FileInfo> childFolders = imapHelper.searchFolders(nodeRef, "*", false, false);
|
||||
|
||||
if (childFolders.isEmpty())
|
||||
{
|
||||
folder.signalDeletion();
|
||||
// Delete child folders and messages
|
||||
fileFolderService.delete(nodeRef);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (folder.isSelectable())
|
||||
{
|
||||
// Delete all messages for this folder
|
||||
// Don't delete subfolders and their messages
|
||||
List<FileInfo> messages = imapHelper.searchFiles(nodeRef, "*", ImapModel.TYPE_IMAP_CONTENT, false);
|
||||
for (FileInfo message : messages)
|
||||
{
|
||||
fileFolderService.delete(message.getNodeRef());
|
||||
}
|
||||
nodeService.addAspect(nodeRef, ImapModel.ASPECT_IMAP_FOLDER_NONSELECTABLE, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new FolderException(mailboxName + " - Can't delete a non-selectable store with children.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to an existing Mailbox. The requested mailbox must already exists on this server and the requesting user must have at least lookup rights. <p/> It is
|
||||
* also can be used by to obtain hierarchy delimiter by the LIST command: <p/> C: 2 list "" "" <p/> S: * LIST () "." "" <p/> S: 2 OK LIST completed. <p/> Method searches
|
||||
* mailbox under mount points defined for a specific user. Mount points include user's IMAP Virtualised Views and Email Archive Views.
|
||||
*
|
||||
* @param user User making the request.
|
||||
* @param mailboxName String name of the target.
|
||||
* @return an Mailbox reference.
|
||||
*/
|
||||
public MailFolder getFolder(GreenMailUser user, String mailboxName)
|
||||
{
|
||||
mailboxName = GreenMailUtil.convertFromUtf7(mailboxName);
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Getting folder: " + mailboxName);
|
||||
}
|
||||
|
||||
// If MailFolder object is used to obtain hierarchy delimiter by LIST command:
|
||||
// Example:
|
||||
// C: 2 list "" ""
|
||||
// S: * LIST () "." ""
|
||||
// S: 2 OK LIST completed.
|
||||
if ("".equals(mailboxName))
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Request for the hierarchy delimiter");
|
||||
}
|
||||
return new AlfrescoImapMailFolder(user.getQualifiedMailboxName(), null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
NodeRef root = imapHelper.getMailboxRootRef(mailboxName, user.getLogin());
|
||||
String mountPointName = imapHelper.getMountPointName(mailboxName);
|
||||
String mailboxRepoName = imapHelper.getMailPathInRepo(mailboxName);
|
||||
|
||||
StringTokenizer tokenizer = new StringTokenizer(mailboxRepoName, String.valueOf(AlfrescoImapConst.HIERARCHY_DELIMITER));
|
||||
int count = tokenizer.countTokens();
|
||||
NodeRef nodeRef = root;
|
||||
|
||||
while (tokenizer.hasMoreTokens())
|
||||
{
|
||||
String t = tokenizer.nextToken();
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("token=" + t);
|
||||
}
|
||||
count--;
|
||||
|
||||
List<FileInfo> list = imapHelper.searchFolders(nodeRef, t, false, true);
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
if (!list.isEmpty())
|
||||
{
|
||||
|
||||
return new AlfrescoImapMailFolder(user.getQualifiedMailboxName(), list.get(0), list.get(0).getName(), imapHelper.getViewMode(mailboxName), root,
|
||||
mountPointName, imapHelper);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new AlfrescoImapMailFolder(user.getQualifiedMailboxName(), null, null, null, null, null, null);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!list.isEmpty())
|
||||
{
|
||||
nodeRef = list.get(0).getNodeRef();
|
||||
}
|
||||
else
|
||||
{
|
||||
return new AlfrescoImapMailFolder(user.getQualifiedMailboxName(), null, null, null, null, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Error state");
|
||||
}
|
||||
|
||||
/**
|
||||
* Simply calls {@link #getFolder(GreenMailUser, String)}. <p/> Added to implement {@link ImapHostManager}.
|
||||
*/
|
||||
public MailFolder getFolder(GreenMailUser user, String mailboxName, boolean mustExist) throws FolderException
|
||||
{
|
||||
return getFolder(user, mailboxName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the user's INBOX.
|
||||
*
|
||||
* @param user The user making the request.
|
||||
* @return The user's Inbox.
|
||||
*/
|
||||
public MailFolder getInbox(GreenMailUser user) throws FolderException
|
||||
{
|
||||
return getFolder(user, AlfrescoImapConst.INBOX_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Not supported. May be used by GreenMailUser.create() method. <p/> Added to implement {@link ImapHostManager}.
|
||||
*/
|
||||
public void createPrivateMailAccount(GreenMailUser user) throws FolderException
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribes a user to a mailbox. The mailbox must exist locally and the user must have rights to modify it. <p/> This method serves SUBSCRIBE command of the IMAP protocol.
|
||||
*
|
||||
* @param user User making the request
|
||||
* @param mailbox String representation of a mailbox name.
|
||||
*/
|
||||
public void subscribe(final GreenMailUser user, final String mailbox) throws FolderException
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Subscribing: " + mailbox);
|
||||
}
|
||||
AlfrescoImapMailFolder mailFolder = (AlfrescoImapMailFolder) getFolder(user, mailbox);
|
||||
nodeService.addAspect(mailFolder.getFolderInfo().getNodeRef(), ImapModel.ASPECT_IMAP_FOLDER_SUBSCRIBED, null);
|
||||
// This is a multiuser support. Commented due new requirements
|
||||
// AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Void>()
|
||||
// {
|
||||
// public Void doWork() throws Exception
|
||||
// {
|
||||
// AlfrescoImapMailFolder mailFolder = (AlfrescoImapMailFolder) getFolder(user, mailbox);
|
||||
// FileInfo fileInfo = mailFolder.getFolderInfo();
|
||||
// if (fileInfo != null)
|
||||
// {
|
||||
// String subscribedList = (String) nodeService.getProperty(fileInfo.getNodeRef(), ImapModel.PROP_IMAP_FOLDER_SUBSCRIBED);
|
||||
// if (subscribedList == null)
|
||||
// {
|
||||
// subscribedList = "";
|
||||
// }
|
||||
// subscribedList = subscribedList.replaceAll(imapHelper.formatUserEntry(user.getLogin()), "");
|
||||
// subscribedList += imapHelper.formatUserEntry(user.getLogin());
|
||||
// nodeService.setProperty(fileInfo.getNodeRef(), ImapModel.PROP_IMAP_FOLDER_SUBSCRIBED, subscribedList);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// logger.debug("MailBox: " + mailbox + "doesn't exsist. Maybe it was deleted earlier.");
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
// }, AuthenticationUtil.getSystemUserName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsubscribes from a given mailbox. <p/> This method serves UNSUBSCRIBE command of the IMAP protocol.
|
||||
*
|
||||
* @param user User making the request
|
||||
* @param mailbox String representation of a mailbox name.
|
||||
*/
|
||||
public void unsubscribe(final GreenMailUser user, final String mailbox) throws FolderException
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Unsubscribing: " + mailbox);
|
||||
}
|
||||
AlfrescoImapMailFolder mailFolder = (AlfrescoImapMailFolder) getFolder(user, mailbox);
|
||||
nodeService.removeAspect(mailFolder.getFolderInfo().getNodeRef(), ImapModel.ASPECT_IMAP_FOLDER_SUBSCRIBED);
|
||||
|
||||
// This is a multiuser support. Commented due new requirements
|
||||
// AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Void>()
|
||||
// {
|
||||
// public Void doWork() throws Exception
|
||||
// {
|
||||
// AlfrescoImapMailFolder mailFolder = (AlfrescoImapMailFolder) getFolder(user, mailbox);
|
||||
// if (mailFolder.getFolderInfo() != null)
|
||||
// {
|
||||
// FileInfo fileInfo = mailFolder.getFolderInfo();
|
||||
// String subscribedList = (String) nodeService.getProperty(fileInfo.getNodeRef(), ImapModel.PROP_IMAP_FOLDER_SUBSCRIBED);
|
||||
// if (subscribedList == null)
|
||||
// {
|
||||
// subscribedList = "";
|
||||
// }
|
||||
// subscribedList = subscribedList.replaceAll(imapHelper.formatUserEntry(user.getLogin()), "");
|
||||
// nodeService.setProperty(fileInfo.getNodeRef(), ImapModel.PROP_IMAP_FOLDER_SUBSCRIBED, subscribedList);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// logger.debug("MailBox: " + mailbox + " doesn't exsist. Maybe it was deleted earlier.");
|
||||
// }
|
||||
//
|
||||
// return null;
|
||||
// }
|
||||
// }, AuthenticationUtil.getSystemUserName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Not supported. Used by GreenMail class.
|
||||
*/
|
||||
public List getAllMessages()
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
private boolean isSubscribed(FileInfo fileInfo, String userName)
|
||||
{
|
||||
return nodeService.hasAspect(fileInfo.getNodeRef(), ImapModel.ASPECT_IMAP_FOLDER_SUBSCRIBED);
|
||||
// This is a multiuser support. Commented due new requirements
|
||||
|
||||
// Map<QName, Serializable> properties = fileInfo.getProperties();
|
||||
// String subscribedList = (String) properties.get(ImapModel.PROP_IMAP_FOLDER_SUBSCRIBED);
|
||||
// if (subscribedList == null)
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// return subscribedList.contains(imapHelper.formatUserEntry(userName));
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
private Collection<FileInfo> getSubscribed(List<FileInfo> list, String userName)
|
||||
{
|
||||
Collection<FileInfo> result = new LinkedList<FileInfo>();
|
||||
|
||||
for (FileInfo folderInfo : list)
|
||||
{
|
||||
if (isSubscribed(folderInfo, userName))
|
||||
{
|
||||
result.add(folderInfo);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean hasSubscribedChild(FileInfo parent, String userName, boolean isVirtualView)
|
||||
{
|
||||
List<FileInfo> list = imapHelper.searchFolders(parent.getNodeRef(), "*", true, isVirtualView);
|
||||
|
||||
for (FileInfo fileInfo : list)
|
||||
{
|
||||
if (isSubscribed(fileInfo, userName))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private Collection<MailFolder> createMailFolderList(GreenMailUser user, Collection<FileInfo> list, NodeRef imapUserHomeRef)
|
||||
{
|
||||
Collection<MailFolder> result = new LinkedList<MailFolder>();
|
||||
|
||||
for (FileInfo folderInfo : list)
|
||||
{
|
||||
// folderName, viewMode, mountPointName will be setted in listSubscribedMailboxes() method
|
||||
result.add(new AlfrescoImapMailFolder(user.getQualifiedMailboxName(), folderInfo, null, null, imapUserHomeRef, null, imapHelper));
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
// ----------------------Getters and Setters----------------------------
|
||||
|
||||
public void setServiceRegistry(ServiceRegistry serviceRegistry)
|
||||
{
|
||||
this.serviceRegistry = serviceRegistry;
|
||||
}
|
||||
|
||||
public ServiceRegistry getServiceRegistry()
|
||||
{
|
||||
return serviceRegistry;
|
||||
}
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
public void setFileFolderService(FileFolderService fileFolderService)
|
||||
{
|
||||
this.fileFolderService = fileFolderService;
|
||||
}
|
||||
|
||||
public void setImapHelper(ImapHelper imapHelper)
|
||||
{
|
||||
this.imapHelper = imapHelper;
|
||||
}
|
||||
|
||||
}
|
1084
source/java/org/alfresco/repo/imap/AlfrescoImapMailFolder.java
Executable file
1084
source/java/org/alfresco/repo/imap/AlfrescoImapMailFolder.java
Executable file
File diff suppressed because it is too large
Load Diff
508
source/java/org/alfresco/repo/imap/AlfrescoImapMessage.java
Executable file
508
source/java/org/alfresco/repo/imap/AlfrescoImapMessage.java
Executable file
@@ -0,0 +1,508 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program 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 General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.imap;
|
||||
|
||||
import static org.alfresco.repo.imap.AlfrescoImapConst.BASE_64_ENCODING;
|
||||
import static org.alfresco.repo.imap.AlfrescoImapConst.CONTENT_ID;
|
||||
import static org.alfresco.repo.imap.AlfrescoImapConst.CONTENT_TRANSFER_ENCODING;
|
||||
import static org.alfresco.repo.imap.AlfrescoImapConst.CONTENT_TYPE;
|
||||
import static org.alfresco.repo.imap.AlfrescoImapConst.MIME_VERSION;
|
||||
import static org.alfresco.repo.imap.AlfrescoImapConst.UTF_8;
|
||||
import static org.alfresco.repo.imap.AlfrescoImapConst.X_ALF_NODEREF_ID;
|
||||
import static org.alfresco.repo.imap.AlfrescoImapConst.X_ALF_SERVER_UID;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.activation.DataHandler;
|
||||
import javax.activation.DataSource;
|
||||
import javax.mail.Address;
|
||||
import javax.mail.Flags;
|
||||
import javax.mail.MessagingException;
|
||||
import javax.mail.Multipart;
|
||||
import javax.mail.Session;
|
||||
import javax.mail.internet.AddressException;
|
||||
import javax.mail.internet.ContentType;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
import javax.mail.internet.MimeBodyPart;
|
||||
import javax.mail.internet.MimeMessage;
|
||||
import javax.mail.internet.MimeMultipart;
|
||||
import javax.mail.internet.MimeUtility;
|
||||
import javax.mail.util.ByteArrayDataSource;
|
||||
|
||||
import org.alfresco.i18n.I18NUtil;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.model.ImapModel;
|
||||
import org.alfresco.repo.imap.ImapHelper.EmailBodyType;
|
||||
import org.alfresco.service.cmr.model.FileInfo;
|
||||
import org.alfresco.service.cmr.repository.ContentReader;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Extended MimeMessage to represent a content stored in the Alfresco repository.
|
||||
*
|
||||
* @author Arseny Kovalchuk
|
||||
*/
|
||||
public class AlfrescoImapMessage extends MimeMessage
|
||||
{
|
||||
/** Used if imapHelper.getDefaultFromAddress is not set */
|
||||
private static final String DEFAULT_EMAIL_FROM = "alfresco@alfresco.org";
|
||||
private static final String DEFAULT_EMAIL_TO = DEFAULT_EMAIL_FROM;
|
||||
private static final String KOI8R_CHARSET = "koi8-r";
|
||||
|
||||
private static Log logger = LogFactory.getLog(AlfrescoImapMessage.class);
|
||||
|
||||
private ImapHelper imapHelper;
|
||||
private FileInfo messageInfo;
|
||||
|
||||
/**
|
||||
* Constructs {@link AlfrescoImapMessage} object.
|
||||
*
|
||||
* @param fileInfo - reference to the {@link FileInfo} object representing the message.
|
||||
* @param imapHelper - reference to the {@link ImapHelper} object.
|
||||
* @param generateBody - if {@code true} message body will be generated.
|
||||
*
|
||||
* @throws MessagingException if generation of the body fails.
|
||||
*/
|
||||
public AlfrescoImapMessage(FileInfo fileInfo, ImapHelper imapHelper, boolean generateBody) throws MessagingException
|
||||
{
|
||||
super(Session.getDefaultInstance(new Properties()));
|
||||
this.messageInfo = fileInfo;
|
||||
this.imapHelper = imapHelper;
|
||||
if (generateBody)
|
||||
{
|
||||
setMessageHeaders();
|
||||
buildMessage();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs {@link AlfrescoImapMessage} object.
|
||||
*
|
||||
* @param fileInfo - reference to the {@link FileInfo} object representing the message.
|
||||
* @param imapHelper - reference to the {@link ImapHelper} object.
|
||||
* @param message - {@link MimeMessage}
|
||||
* @throws MessagingException
|
||||
*/
|
||||
public AlfrescoImapMessage(FileInfo fileInfo, ImapHelper imapHelper, MimeMessage message) throws MessagingException
|
||||
{
|
||||
super(message);
|
||||
this.messageInfo = fileInfo;
|
||||
this.imapHelper = imapHelper;
|
||||
|
||||
setMessageHeaders();
|
||||
final NodeRef nodeRef = fileInfo.getNodeRef();
|
||||
Map<QName, Serializable> props = new HashMap<QName, Serializable>();
|
||||
props.put(ImapModel.PROP_MESSAGE_FROM, InternetAddress.toString(message.getFrom()));
|
||||
props.put(ImapModel.PROP_MESSAGE_TO, InternetAddress.toString(message.getRecipients(RecipientType.TO)));
|
||||
props.put(ImapModel.PROP_MESSAGE_CC, InternetAddress.toString(message.getRecipients(RecipientType.CC)));
|
||||
|
||||
String[] subj = message.getHeader("Subject");
|
||||
if (subj.length > 0)
|
||||
{
|
||||
props.put(ImapModel.PROP_MESSAGE_SUBJECT, subj[0]);
|
||||
imapHelper.getNodeService().setProperty(nodeRef, ContentModel.PROP_DESCRIPTION, subj[0]);
|
||||
}
|
||||
|
||||
Map<QName, Serializable> allprops = imapHelper.getNodeService().getProperties(fileInfo.getNodeRef());
|
||||
allprops.putAll(props);
|
||||
imapHelper.getNodeService().setProperties(nodeRef, allprops);
|
||||
// setContent(buildMultipart(fileInfo)); - disabled for better performance.
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns message flags.
|
||||
*
|
||||
* @return {@link Flags}
|
||||
*/
|
||||
@Override
|
||||
public synchronized Flags getFlags()
|
||||
{
|
||||
return imapHelper.getFlags(messageInfo);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets message flags.
|
||||
*
|
||||
* @param flags - {@link Flags} object.
|
||||
* @param value - flags value.
|
||||
*/
|
||||
@Override
|
||||
public synchronized void setFlags(Flags flags, boolean value) throws MessagingException
|
||||
{
|
||||
imapHelper.setFlags(messageInfo, flags, value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns {@link FileInfo} object representing message in Alfresco.
|
||||
*
|
||||
* @return reference to the {@link FileInfo} object.
|
||||
*/
|
||||
public FileInfo getMessageInfo()
|
||||
{
|
||||
return messageInfo;
|
||||
}
|
||||
|
||||
private void setMessageHeaders() throws MessagingException
|
||||
{
|
||||
setHeader(MIME_VERSION, "1.0");
|
||||
// Optional headers for further implementation of multiple Alfresco server support.
|
||||
setHeader(X_ALF_NODEREF_ID, messageInfo.getNodeRef().getId());
|
||||
setHeader(X_ALF_SERVER_UID, imapHelper.getAlfrescoServerUID());
|
||||
}
|
||||
|
||||
/**
|
||||
* This method builds MimeMessage based on either ImapModel or ContentModel type.
|
||||
*
|
||||
* @param fileInfo - Source file information {@link FileInfo}
|
||||
* @throws MessagingException
|
||||
*/
|
||||
private void buildMessage() throws MessagingException
|
||||
{
|
||||
final NodeRef nodeRef = messageInfo.getNodeRef();
|
||||
if (ImapModel.TYPE_IMAP_CONTENT.equals(imapHelper.getNodeService().getType(nodeRef)))
|
||||
{
|
||||
buildImapModelMessage();
|
||||
}
|
||||
else
|
||||
{
|
||||
buildContentModelMessage();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method builds MimeMessage based on {@link ImapModel}
|
||||
*
|
||||
* @param fileInfo - Source file information {@link FileInfo}
|
||||
* @throws MessagingException
|
||||
*/
|
||||
private void buildImapModelMessage() throws MessagingException
|
||||
{
|
||||
Map<QName, Serializable> properties = messageInfo.getProperties();
|
||||
setSentDate(messageInfo.getModifiedDate());
|
||||
String prop = (String) properties.get(ImapModel.PROP_MESSAGE_FROM);
|
||||
addFromInternal(prop);
|
||||
prop = (String) properties.get(ImapModel.PROP_MESSAGE_TO);
|
||||
|
||||
if (prop != null && prop.length() > 0)
|
||||
{
|
||||
addRecipients(RecipientType.TO, InternetAddress.parse(prop));
|
||||
}
|
||||
else
|
||||
{
|
||||
addRecipients(RecipientType.TO, DEFAULT_EMAIL_TO);
|
||||
}
|
||||
|
||||
prop = (String) properties.get(ImapModel.PROP_MESSAGE_CC);
|
||||
if (prop != null && prop.length() > 0)
|
||||
{
|
||||
addRecipients(RecipientType.CC, InternetAddress.parse(prop));
|
||||
}
|
||||
|
||||
prop = (String) properties.get(ImapModel.PROP_MESSAGE_SUBJECT);
|
||||
setSubject(prop == null ? messageInfo.getName() : prop);
|
||||
|
||||
setContent(buildImapModelMultipart());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method builds {@link MimeMessage} based on {@link ContentModel}
|
||||
*
|
||||
* @param fileInfo - Source file information {@link FileInfo}
|
||||
* @throws MessagingException
|
||||
*/
|
||||
private void buildContentModelMessage() throws MessagingException
|
||||
{
|
||||
Map<QName, Serializable> properties = messageInfo.getProperties();
|
||||
String prop = null;
|
||||
setSentDate(messageInfo.getModifiedDate());
|
||||
// Add FROM address
|
||||
Address[] addressList = buildSenderFromAddress(properties);
|
||||
addFrom(addressList);
|
||||
// Add TO address
|
||||
addressList = buildRecipientToAddress();
|
||||
addRecipients(RecipientType.TO, addressList);
|
||||
prop = (String) properties.get(ContentModel.PROP_TITLE);
|
||||
try
|
||||
{
|
||||
prop = (prop == null) ? MimeUtility.encodeText(messageInfo.getName(), KOI8R_CHARSET, null) : MimeUtility.encodeText(prop, KOI8R_CHARSET, null);
|
||||
}
|
||||
catch (UnsupportedEncodingException e)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
setSubject(prop);
|
||||
setContent(buildContentModelMultipart());
|
||||
}
|
||||
|
||||
/**
|
||||
* This method builds {@link Multipart} based on {@link ContentModel}
|
||||
*
|
||||
* @param fileInfo - Source file information {@link FileInfo}
|
||||
* @throws MessagingException
|
||||
*/
|
||||
private Multipart buildContentModelMultipart() throws MessagingException
|
||||
{
|
||||
MimeMultipart rootMultipart = new MimeMultipart("alternative");
|
||||
// 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 = imapHelper.getEmailBodyText(messageInfo.getNodeRef(), EmailBodyType.TEXT_PLAIN);
|
||||
rootMultipart.addBodyPart(getTextBodyPart(bodyTxt, EmailBodyType.TEXT_PLAIN.getSubtype()));
|
||||
String bodyHtml = imapHelper.getEmailBodyText(messageInfo.getNodeRef(), EmailBodyType.TEXT_HTML);
|
||||
rootMultipart.addBodyPart(getTextBodyPart(bodyHtml, EmailBodyType.TEXT_HTML.getSubtype()));
|
||||
return rootMultipart;
|
||||
}
|
||||
|
||||
private MimeBodyPart getTextBodyPart(String bodyText, String subtype) throws MessagingException
|
||||
{
|
||||
MimeBodyPart result = new MimeBodyPart();
|
||||
result.setText(bodyText, UTF_8, subtype);
|
||||
result.addHeader(CONTENT_TRANSFER_ENCODING, BASE_64_ENCODING);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method builds {@link Multipart} based on {@link ImapModel}
|
||||
*
|
||||
* @param fileInfo - Source file information {@link FileInfo}
|
||||
* @throws MessagingException
|
||||
*/
|
||||
private Multipart buildImapModelMultipart() throws MessagingException
|
||||
{
|
||||
DataSource source = null;
|
||||
String errorMessage = null;
|
||||
|
||||
// Root multipart - multipart/mixed
|
||||
MimeMultipart rootMultipart = new MimeMultipart("mixed");
|
||||
// Message body - multipart/alternative - consists of two parts: text/plain and text/html
|
||||
MimeMultipart messageBody = new MimeMultipart("alternative");
|
||||
// <------------------------ text html body part ------------------------>
|
||||
List<FileInfo> bodyHtmls = imapHelper.searchFiles(messageInfo.getNodeRef(), "*.html", ImapModel.TYPE_IMAP_BODY, false);
|
||||
ContentType contentType = null;
|
||||
MimeBodyPart textHtmlBodyPart = null;
|
||||
if (bodyHtmls != null && bodyHtmls.size() > 0)
|
||||
{
|
||||
textHtmlBodyPart = new MimeBodyPart();
|
||||
FileInfo bodyHtml = bodyHtmls.get(0);
|
||||
contentType = new ContentType(bodyHtml.getContentData().getMimetype());
|
||||
ContentReader reader = imapHelper.getFileFolderService().getReader(bodyHtml.getNodeRef());
|
||||
try
|
||||
{
|
||||
source = new ByteArrayDataSource(reader.getContentInputStream(), contentType.toString());
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
logger.error(e);
|
||||
errorMessage = e.getMessage();
|
||||
}
|
||||
if (source != null)
|
||||
{
|
||||
textHtmlBodyPart.setDataHandler(new DataHandler(source));
|
||||
textHtmlBodyPart.addHeader(CONTENT_TYPE, bodyHtml.getContentData().getMimetype());
|
||||
// textHtmlBodyPart.addHeader(CONTENT_TRANSFER_ENCODING, EIGHT_BIT_ENCODING);
|
||||
textHtmlBodyPart.addHeader(CONTENT_TRANSFER_ENCODING, BASE_64_ENCODING);
|
||||
}
|
||||
else
|
||||
{
|
||||
textHtmlBodyPart.setText(errorMessage, UTF_8);
|
||||
}
|
||||
messageBody.addBodyPart(textHtmlBodyPart);
|
||||
}
|
||||
// </------------------------ text html body part ------------------------>
|
||||
// <------------------------ text plain body part ------------------------>
|
||||
List<FileInfo> results = imapHelper.searchFiles(messageInfo.getNodeRef(), "*.txt", ImapModel.TYPE_IMAP_BODY, false);
|
||||
MimeBodyPart textPlainBodyPart = null;
|
||||
String text = null;
|
||||
if (results != null && results.size() > 0)
|
||||
{
|
||||
textPlainBodyPart = new MimeBodyPart();
|
||||
FileInfo bodyTxt = results.get(0);
|
||||
text = imapHelper.getFileFolderService().getReader(bodyTxt.getNodeRef()).getContentString();
|
||||
contentType = new ContentType(bodyTxt.getContentData().getMimetype());
|
||||
}
|
||||
else if (textHtmlBodyPart == null)
|
||||
{
|
||||
text = I18NUtil.getMessage("imap.server.info.message_body_not_found");
|
||||
contentType = new ContentType(EmailBodyType.TEXT_PLAIN.getMimeType() + "; charset=UTF-8");
|
||||
}
|
||||
|
||||
textPlainBodyPart.setText(text, contentType.getParameter("charset"), contentType.getSubType());
|
||||
textPlainBodyPart.addHeader(CONTENT_TYPE, contentType.toString());
|
||||
messageBody.addBodyPart(textPlainBodyPart);
|
||||
// </------------------------ text plain body part ------------------------>
|
||||
|
||||
// Body part for multipart/alternative
|
||||
MimeBodyPart messageBodyPart = new MimeBodyPart();
|
||||
messageBodyPart.setContent(messageBody);
|
||||
// Add multipart/alternative into root multipart/mixed...
|
||||
rootMultipart.addBodyPart(messageBodyPart);
|
||||
|
||||
// Process attachments
|
||||
List<FileInfo> attaches = imapHelper.searchFiles(messageInfo.getNodeRef(), "*", ImapModel.TYPE_IMAP_ATTACH, false);
|
||||
|
||||
for (FileInfo attach : attaches)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
errorMessage = null;
|
||||
messageBodyPart = new MimeBodyPart();
|
||||
ContentReader reader = imapHelper.getFileFolderService().getReader(attach.getNodeRef());
|
||||
source = new ByteArrayDataSource(reader.getContentInputStream(), attach.getContentData().getMimetype());
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
logger.error(e);
|
||||
errorMessage = e.getMessage();
|
||||
}
|
||||
if (source != null)
|
||||
{
|
||||
String attachID = (String) imapHelper.getNodeService().getProperty(attach.getNodeRef(), ImapModel.PROP_ATTACH_ID);
|
||||
if (attachID != null)
|
||||
{
|
||||
messageBodyPart.addHeader(CONTENT_ID, attachID);
|
||||
}
|
||||
StringBuilder ct = new StringBuilder(attach.getContentData().getMimetype()).append("; name=\"").append(attach.getName()).append("\"");
|
||||
messageBodyPart.addHeader(CONTENT_TYPE, ct.toString());
|
||||
messageBodyPart.addHeader(CONTENT_TRANSFER_ENCODING, BASE_64_ENCODING);
|
||||
messageBodyPart.setDataHandler(new DataHandler(source));
|
||||
try
|
||||
{
|
||||
messageBodyPart.setFileName(MimeUtility.encodeText(attach.getName(), KOI8R_CHARSET, null));
|
||||
}
|
||||
catch (UnsupportedEncodingException e)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
messageBodyPart.setText(errorMessage, UTF_8);
|
||||
}
|
||||
rootMultipart.addBodyPart(messageBodyPart);
|
||||
}
|
||||
return rootMultipart;
|
||||
}
|
||||
|
||||
private void addFromInternal(String addressesString) throws MessagingException
|
||||
{
|
||||
if (addressesString != null)
|
||||
{
|
||||
addFrom(InternetAddress.parse(addressesString));
|
||||
}
|
||||
else
|
||||
{
|
||||
addFrom(new Address[] { new InternetAddress(DEFAULT_EMAIL_FROM) });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO USE CASE 2: "The To/addressee will be the first email alias found in the parent folders or a default one (TBD)". It seems to be more informative as alike
|
||||
* {@code <user>@<current.domain>}...
|
||||
*
|
||||
* @return Generated TO address {@code <user>@<current.domain>}
|
||||
* @throws AddressException
|
||||
*/
|
||||
private InternetAddress[] buildRecipientToAddress() throws AddressException
|
||||
{
|
||||
InternetAddress[] result = null;
|
||||
String defaultEmailTo = null;
|
||||
// TODO : search first email alias found in the parent folders
|
||||
// if (found) defaultEmailTo = foundAlias
|
||||
// else
|
||||
final String escapedUserName = imapHelper.getCurrentUser().replaceAll("[/,\\,@]", ".");
|
||||
final String userDomain = DEFAULT_EMAIL_TO.split("@")[1];
|
||||
defaultEmailTo = escapedUserName + "@" + userDomain;
|
||||
try
|
||||
{
|
||||
result = InternetAddress.parse(defaultEmailTo);
|
||||
}
|
||||
catch (AddressException e)
|
||||
{
|
||||
logger.error(String.format("Wrong email address '%s'.", defaultEmailTo), e);
|
||||
result = InternetAddress.parse(DEFAULT_EMAIL_TO);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the InternetAddress from the Content Author name if provided. If name not specified, it takes Content Creator name. If content creator does not exists, the default
|
||||
* from address will be returned.
|
||||
*
|
||||
* @param contentAuthor The content author full name.
|
||||
* @return Generated InternetAddress[] array.
|
||||
* @throws AddressException
|
||||
*/
|
||||
private InternetAddress[] buildSenderFromAddress(Map<QName, Serializable> properties) throws AddressException
|
||||
{
|
||||
// Generate FROM address (Content author)
|
||||
InternetAddress[] addressList = null;
|
||||
String prop = (String) properties.get(ContentModel.PROP_AUTHOR);
|
||||
String defaultFromAddress = imapHelper.getDefaultFromAddress();
|
||||
defaultFromAddress = defaultFromAddress == null ? DEFAULT_EMAIL_FROM : defaultFromAddress;
|
||||
try
|
||||
{
|
||||
|
||||
if (prop != null)
|
||||
{
|
||||
StringBuilder contentAuthor = new StringBuilder();
|
||||
contentAuthor.append("\"").append(prop).append("\" <").append(defaultFromAddress).append(">");
|
||||
addressList = InternetAddress.parse(contentAuthor.toString());
|
||||
}
|
||||
else
|
||||
{
|
||||
prop = (String) properties.get(ContentModel.PROP_CREATOR);
|
||||
if (prop != null)
|
||||
{
|
||||
StringBuilder creator = new StringBuilder();
|
||||
creator.append("\"").append(prop).append("\" <").append(defaultFromAddress).append(">");
|
||||
addressList = InternetAddress.parse(creator.toString());
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AddressException(I18NUtil.getMessage("imap.server.error.properties_dont_exist"));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (AddressException e)
|
||||
{
|
||||
addressList = InternetAddress.parse(DEFAULT_EMAIL_FROM);
|
||||
}
|
||||
return addressList;
|
||||
}
|
||||
|
||||
}
|
123
source/java/org/alfresco/repo/imap/AlfrescoImapServer.java
Executable file
123
source/java/org/alfresco/repo/imap/AlfrescoImapServer.java
Executable file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program 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 General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.imap;
|
||||
|
||||
import org.alfresco.util.AbstractLifecycleBean;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
import com.icegreen.greenmail.Managers;
|
||||
import com.icegreen.greenmail.imap.ImapHostManager;
|
||||
import com.icegreen.greenmail.imap.ImapServer;
|
||||
import com.icegreen.greenmail.user.UserManager;
|
||||
import com.icegreen.greenmail.util.ServerSetup;
|
||||
|
||||
/**
|
||||
* @author Mike Shavnev
|
||||
*/
|
||||
public class AlfrescoImapServer extends AbstractLifecycleBean
|
||||
{
|
||||
|
||||
private static Log logger = LogFactory.getLog(AlfrescoImapServer.class);
|
||||
|
||||
private ImapServer serverImpl;
|
||||
|
||||
private int port = 143;
|
||||
|
||||
private ImapHostManager imapHostManager;
|
||||
|
||||
private UserManager imapUserManager;
|
||||
|
||||
private boolean imapServerEnabled;
|
||||
|
||||
private ImapHelper imapHelper;
|
||||
|
||||
public void setImapServerEnabled(boolean imapServerEnabled)
|
||||
{
|
||||
this.imapServerEnabled = imapServerEnabled;
|
||||
}
|
||||
|
||||
public void setPort(int port)
|
||||
{
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public void setImapHostManager(ImapHostManager imapHostManager)
|
||||
{
|
||||
this.imapHostManager = imapHostManager;
|
||||
}
|
||||
|
||||
public void setImapUserManager(UserManager imapUserManager)
|
||||
{
|
||||
this.imapUserManager = imapUserManager;
|
||||
}
|
||||
|
||||
public void setImapHelper(ImapHelper imapHelper)
|
||||
{
|
||||
this.imapHelper = imapHelper;
|
||||
}
|
||||
|
||||
protected void onBootstrap(ApplicationEvent event)
|
||||
{
|
||||
if (imapServerEnabled && imapHelper.isPatchApplied())
|
||||
{
|
||||
Managers imapManagers = new Managers()
|
||||
{
|
||||
public ImapHostManager getImapHostManager()
|
||||
{
|
||||
return imapHostManager;
|
||||
}
|
||||
|
||||
public UserManager getUserManager()
|
||||
{
|
||||
return imapUserManager;
|
||||
}
|
||||
};
|
||||
serverImpl = new ImapServer(new ServerSetup(port, null, ServerSetup.PROTOCOL_IMAP), imapManagers);
|
||||
serverImpl.startService(null);
|
||||
if (logger.isInfoEnabled())
|
||||
{
|
||||
logger.info("IMAP service started on port " + this.port + ".");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("IMAP service is disabled.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void onShutdown(ApplicationEvent event)
|
||||
{
|
||||
if (serverImpl != null)
|
||||
{
|
||||
serverImpl.stopService(null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
107
source/java/org/alfresco/repo/imap/AlfrescoImapUser.java
Executable file
107
source/java/org/alfresco/repo/imap/AlfrescoImapUser.java
Executable file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program 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 General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.imap;
|
||||
|
||||
import javax.mail.internet.MimeMessage;
|
||||
|
||||
import com.icegreen.greenmail.imap.ImapHostManager;
|
||||
import com.icegreen.greenmail.mail.MovingMessage;
|
||||
import com.icegreen.greenmail.user.GreenMailUser;
|
||||
import com.icegreen.greenmail.user.UserException;
|
||||
|
||||
/**
|
||||
* Alfresco implementation of the GreenMailUser interface.
|
||||
*
|
||||
* @author Arseny Kovalchuk
|
||||
*/
|
||||
public class AlfrescoImapUser implements GreenMailUser
|
||||
{
|
||||
private String userName;
|
||||
private char[] password;
|
||||
private String email;
|
||||
|
||||
private ImapHostManager imapHostManager;
|
||||
|
||||
public AlfrescoImapUser(String email, String login, String password, ImapHostManager imapHostManager)
|
||||
{
|
||||
this.email = email;
|
||||
this.userName = login;
|
||||
this.password = password.toCharArray();
|
||||
this.imapHostManager = imapHostManager;
|
||||
}
|
||||
|
||||
public void authenticate(String password) throws UserException
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
// This method is used in the POP3 greenmail implementation, so it is disabled for IMAP
|
||||
// See AlfrescoImapUserManager.test() method.
|
||||
}
|
||||
|
||||
public void create() throws UserException
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void delete() throws UserException
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void deliver(MovingMessage msg) throws UserException
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void deliver(MimeMessage msg) throws UserException
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public String getEmail()
|
||||
{
|
||||
return this.email;
|
||||
}
|
||||
|
||||
public String getLogin()
|
||||
{
|
||||
return this.userName;
|
||||
}
|
||||
|
||||
public String getPassword()
|
||||
{
|
||||
return new String(this.password);
|
||||
}
|
||||
|
||||
public String getQualifiedMailboxName()
|
||||
{
|
||||
return userName;
|
||||
}
|
||||
|
||||
public void setPassword(String password)
|
||||
{
|
||||
this.password = password.toCharArray();
|
||||
}
|
||||
|
||||
}
|
168
source/java/org/alfresco/repo/imap/AlfrescoImapUserManager.java
Executable file
168
source/java/org/alfresco/repo/imap/AlfrescoImapUserManager.java
Executable file
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program 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 General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.imap;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.security.AuthenticationService;
|
||||
import org.alfresco.service.cmr.security.PersonService;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import com.icegreen.greenmail.imap.ImapHostManager;
|
||||
import com.icegreen.greenmail.user.GreenMailUser;
|
||||
import com.icegreen.greenmail.user.UserException;
|
||||
import com.icegreen.greenmail.user.UserManager;
|
||||
|
||||
/**
|
||||
* @author Arseny Kovalchuk
|
||||
*/
|
||||
public class AlfrescoImapUserManager extends UserManager
|
||||
{
|
||||
private Log logger = LogFactory.getLog(AlfrescoImapUserManager.class);
|
||||
|
||||
protected Map<String, GreenMailUser> userMap = Collections.synchronizedMap(new HashMap<String, GreenMailUser>());
|
||||
protected ImapHostManager imapHostManager;
|
||||
|
||||
protected AuthenticationService authenticationService;
|
||||
protected PersonService personService;
|
||||
protected NodeService nodeService;
|
||||
|
||||
public AlfrescoImapUserManager()
|
||||
{
|
||||
super(null);
|
||||
}
|
||||
|
||||
public AlfrescoImapUserManager(ImapHostManager imapHostManager)
|
||||
{
|
||||
this();
|
||||
this.imapHostManager = imapHostManager;
|
||||
}
|
||||
|
||||
public GreenMailUser createUser(String email, String login, String password) throws UserException
|
||||
{
|
||||
// TODO: User creation/addition code should be implemented here (in the AlfrescoImapUserManager).
|
||||
// Following code is not need and not used in the current implementation.
|
||||
GreenMailUser user = new AlfrescoImapUser(email, login, password, imapHostManager);
|
||||
user.create();
|
||||
addUser(user);
|
||||
return user;
|
||||
}
|
||||
|
||||
protected void addUser(GreenMailUser user)
|
||||
{
|
||||
userMap.put(user.getLogin(), user);
|
||||
}
|
||||
|
||||
public GreenMailUser getUser(String login)
|
||||
{
|
||||
return (GreenMailUser) userMap.get(login);
|
||||
}
|
||||
|
||||
public GreenMailUser getUserByEmail(String email)
|
||||
{
|
||||
GreenMailUser ret = getUser(email);
|
||||
if (null == ret)
|
||||
{
|
||||
for (GreenMailUser user : userMap.values())
|
||||
{
|
||||
// TODO: NPE!
|
||||
if (user.getEmail().trim().equalsIgnoreCase(email.trim()))
|
||||
{
|
||||
return user;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void deleteUser(GreenMailUser user) throws UserException
|
||||
{
|
||||
user = (GreenMailUser) userMap.remove(user.getLogin());
|
||||
if (user != null)
|
||||
{
|
||||
user.delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The login method.
|
||||
*
|
||||
* @see com.icegreen.greenmail.imap.commands.LoginCommand#doProcess()
|
||||
*/
|
||||
public boolean test(String userid, String password)
|
||||
{
|
||||
try
|
||||
{
|
||||
authenticationService.authenticate(userid, password.toCharArray());
|
||||
String email = null;
|
||||
if (personService.personExists(userid))
|
||||
{
|
||||
NodeRef personNodeRef = personService.getPerson(userid);
|
||||
email = (String) nodeService.getProperty(personNodeRef, ContentModel.PROP_EMAIL);
|
||||
}
|
||||
GreenMailUser user = new AlfrescoImapUser(email, userid, password, imapHostManager);
|
||||
addUser(user);
|
||||
}
|
||||
catch (AuthenticationException ex)
|
||||
{
|
||||
logger.error("IMAP authentication failed for userid: " + userid);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public ImapHostManager getImapHostManager()
|
||||
{
|
||||
return this.imapHostManager;
|
||||
}
|
||||
|
||||
public void setImapHostManager(ImapHostManager imapHostManager)
|
||||
{
|
||||
this.imapHostManager = imapHostManager;
|
||||
}
|
||||
|
||||
public void setAuthenticationService(AuthenticationService authenticationService)
|
||||
{
|
||||
this.authenticationService = authenticationService;
|
||||
}
|
||||
|
||||
public void setPersonService(PersonService personService)
|
||||
{
|
||||
this.personService = personService;
|
||||
}
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
}
|
980
source/java/org/alfresco/repo/imap/ImapHelper.java
Executable file
980
source/java/org/alfresco/repo/imap/ImapHelper.java
Executable file
@@ -0,0 +1,980 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program 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 General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.imap;
|
||||
|
||||
import static org.alfresco.repo.imap.AlfrescoImapConst.CLASSPATH_TEXT_HTML_TEMPLATE;
|
||||
import static org.alfresco.repo.imap.AlfrescoImapConst.CLASSPATH_TEXT_PLAIN_TEMPLATE;
|
||||
import static org.alfresco.repo.imap.AlfrescoImapConst.DICTIONARY_TEMPLATE_PREFIX;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.mail.Flags;
|
||||
import javax.mail.Flags.Flag;
|
||||
|
||||
import org.alfresco.config.Config;
|
||||
import org.alfresco.config.ConfigService;
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.model.ImapModel;
|
||||
import org.alfresco.repo.admin.patch.PatchInfo;
|
||||
import org.alfresco.repo.admin.patch.PatchService;
|
||||
import org.alfresco.repo.imap.config.ImapConfigElement;
|
||||
import org.alfresco.repo.imap.config.ImapConfigElement.ImapConfig;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.service.cmr.site.SiteInfo;
|
||||
import org.alfresco.service.cmr.site.SiteService;
|
||||
import org.alfresco.repo.template.TemplateNode;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.model.FileFolderService;
|
||||
import org.alfresco.service.cmr.model.FileInfo;
|
||||
import org.alfresco.service.cmr.preference.PreferenceService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.repository.TemplateService;
|
||||
import org.alfresco.service.cmr.search.ResultSet;
|
||||
import org.alfresco.service.cmr.search.SearchService;
|
||||
import org.alfresco.service.cmr.security.AccessStatus;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.AbstractLifecycleBean;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
/**
|
||||
* Helper class to access repository services by IMAP components. Also contains a common helper methods to search and manage IMAP content and other usefull methods. Configured as
|
||||
* {@code <bean id="imapHelper" class="org.alfresco.repo.imap.ImapHelper">} in the {@code imap-server-context.xml} file.
|
||||
*
|
||||
* @author Dmitry Vaserin
|
||||
*/
|
||||
public class ImapHelper extends AbstractLifecycleBean
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(ImapHelper.class);
|
||||
|
||||
private static String PATCH_ID = "patch.imapFolders";
|
||||
|
||||
private NodeService nodeService;
|
||||
private SearchService searchService;
|
||||
private FileFolderService fileFolderService;
|
||||
private TemplateService templateService;
|
||||
private NamespaceService namespaceService;
|
||||
private PermissionService permissionService;
|
||||
private ConfigService configService;
|
||||
private DictionaryService dictionaryService;
|
||||
private PreferenceService preferenceService;
|
||||
private SiteService siteService;
|
||||
|
||||
private ServiceRegistry serviceRegistry;
|
||||
|
||||
private PatchService patchService;
|
||||
|
||||
private String defaultFromAddress;
|
||||
private String webApplicationContextUrl = "http://localhost:8080/alfresco";
|
||||
private String repositoryTemplatePath;
|
||||
private String imapRoot;
|
||||
private NodeRef spacesStoreNodeRef;
|
||||
private NodeRef companyHomeNodeRef;
|
||||
private NodeRef imapRootNodeRef;
|
||||
|
||||
private boolean patchApplied = false;
|
||||
|
||||
private final static Map<QName, Flags.Flag> qNameToFlag;
|
||||
private final static Map<Flags.Flag, QName> flagToQname;
|
||||
|
||||
static
|
||||
{
|
||||
qNameToFlag = new HashMap<QName, Flags.Flag>();
|
||||
qNameToFlag.put(ImapModel.PROP_FLAG_ANSWERED, Flags.Flag.ANSWERED);
|
||||
qNameToFlag.put(ImapModel.PROP_FLAG_DELETED, Flags.Flag.DELETED);
|
||||
qNameToFlag.put(ImapModel.PROP_FLAG_DRAFT, Flags.Flag.DRAFT);
|
||||
qNameToFlag.put(ImapModel.PROP_FLAG_SEEN, Flags.Flag.SEEN);
|
||||
qNameToFlag.put(ImapModel.PROP_FLAG_RECENT, Flags.Flag.RECENT);
|
||||
qNameToFlag.put(ImapModel.PROP_FLAG_FLAGGED, Flags.Flag.FLAGGED);
|
||||
|
||||
flagToQname = new HashMap<Flags.Flag, QName>();
|
||||
flagToQname.put(Flags.Flag.ANSWERED, ImapModel.PROP_FLAG_ANSWERED);
|
||||
flagToQname.put(Flags.Flag.DELETED, ImapModel.PROP_FLAG_DELETED);
|
||||
flagToQname.put(Flags.Flag.DRAFT, ImapModel.PROP_FLAG_DRAFT);
|
||||
flagToQname.put(Flags.Flag.SEEN, ImapModel.PROP_FLAG_SEEN);
|
||||
flagToQname.put(Flags.Flag.RECENT, ImapModel.PROP_FLAG_RECENT);
|
||||
flagToQname.put(Flags.Flag.FLAGGED, ImapModel.PROP_FLAG_FLAGGED);
|
||||
}
|
||||
|
||||
public static enum EmailBodyType
|
||||
{
|
||||
TEXT_PLAIN, TEXT_HTML;
|
||||
|
||||
public String getSubtype()
|
||||
{
|
||||
return name().toLowerCase().substring(5);
|
||||
}
|
||||
|
||||
public String getTypeSubtype()
|
||||
{
|
||||
return name().toLowerCase().replaceAll("_", "");
|
||||
}
|
||||
|
||||
public String getMimeType()
|
||||
{
|
||||
return name().toLowerCase().replaceAll("_", "/");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onShutdown(ApplicationEvent event)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBootstrap(ApplicationEvent event)
|
||||
{
|
||||
AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Void>()
|
||||
{
|
||||
public Void doWork() throws Exception
|
||||
{
|
||||
List<PatchInfo> patches = getPatchService().getPatches(null, null);
|
||||
for (PatchInfo patch : patches)
|
||||
{
|
||||
if (patch.getId().equals(PATCH_ID))
|
||||
{
|
||||
patchApplied = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!patchApplied)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int indexOfStoreDelim = imapRoot.indexOf(StoreRef.URI_FILLER);
|
||||
|
||||
if (indexOfStoreDelim == -1)
|
||||
{
|
||||
throw new RuntimeException("Bad path format, " + StoreRef.URI_FILLER + " not found");
|
||||
}
|
||||
|
||||
indexOfStoreDelim += StoreRef.URI_FILLER.length();
|
||||
|
||||
int indexOfPathDelim = imapRoot.indexOf("/", indexOfStoreDelim);
|
||||
|
||||
if (indexOfPathDelim == -1)
|
||||
{
|
||||
throw new java.lang.RuntimeException("Bad path format, / not found");
|
||||
}
|
||||
|
||||
String storePath = imapRoot.substring(0, indexOfPathDelim);
|
||||
String rootPathInStore = imapRoot.substring(indexOfPathDelim);
|
||||
|
||||
StoreRef storeRef = new StoreRef(storePath);
|
||||
|
||||
if (nodeService.exists(storeRef) == false)
|
||||
{
|
||||
throw new RuntimeException("No store for path: " + storeRef);
|
||||
}
|
||||
|
||||
NodeRef storeRootNodeRef = nodeService.getRootNode(storeRef);
|
||||
|
||||
List<NodeRef> nodeRefs = searchService.selectNodes(storeRootNodeRef, rootPathInStore, null, namespaceService, false);
|
||||
|
||||
if (nodeRefs.size() > 1)
|
||||
{
|
||||
throw new RuntimeException("Multiple possible roots for : \n" + " root path: " + rootPathInStore + "\n" + " results: " + nodeRefs);
|
||||
}
|
||||
else if (nodeRefs.size() == 0)
|
||||
{
|
||||
throw new RuntimeException("No root found for : \n" + " root path: " + rootPathInStore);
|
||||
}
|
||||
|
||||
imapRootNodeRef = nodeRefs.get(0);
|
||||
|
||||
// Get "Company Home" node reference
|
||||
StoreRef store = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "SpacesStore");
|
||||
ResultSet rs = searchService.query(store, SearchService.LANGUAGE_XPATH, "/app:company_home");
|
||||
try
|
||||
{
|
||||
if (rs.length() == 0)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("'Company Home' space doesn't exists.");
|
||||
}
|
||||
companyHomeNodeRef = rs.getNodeRef(0);
|
||||
}
|
||||
finally
|
||||
{
|
||||
rs.close();
|
||||
}
|
||||
|
||||
spacesStoreNodeRef = nodeService.getRootNode(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE);
|
||||
|
||||
return null;
|
||||
}
|
||||
}, AuthenticationUtil.getSystemUserName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for files in specified context
|
||||
*
|
||||
* @param contextNodeRef context folder for search
|
||||
* @param namePattern name pattern for search
|
||||
* @param searchType type for search
|
||||
* @param includeSubFolders include SubFolders
|
||||
* @return list of files with specifed type
|
||||
*/
|
||||
public List<FileInfo> searchFiles(NodeRef contextNodeRef, String namePattern, QName searchType, boolean includeSubFolders)
|
||||
{
|
||||
return search(contextNodeRef, namePattern, searchType, true, false, includeSubFolders);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for mailboxes in specified context
|
||||
*
|
||||
* @param contextNodeRef context folder for search
|
||||
* @param namePattern name pattern for search
|
||||
* @param includeSubFolders include SubFolders
|
||||
* @param isVirtualView is folder in "Virtual" View
|
||||
* @return list of mailboxes
|
||||
*/
|
||||
public List<FileInfo> searchFolders(NodeRef contextNodeRef, String namePattern, boolean includeSubFolders, boolean isVirtualView)
|
||||
{
|
||||
QName searchType = ContentModel.TYPE_FOLDER;
|
||||
if (isVirtualView)
|
||||
{
|
||||
searchType = null;
|
||||
}
|
||||
|
||||
List<FileInfo> result = search(contextNodeRef, namePattern, searchType, false, true, includeSubFolders);
|
||||
if (isVirtualView)
|
||||
{
|
||||
List<SiteInfo> nonFavSites = getNonFavouriteSites(getCurrentUser());
|
||||
for (SiteInfo siteInfo : nonFavSites)
|
||||
{
|
||||
FileInfo nonFavSite = fileFolderService.getFileInfo(siteInfo.getNodeRef());
|
||||
List<FileInfo> siteChilds = search(nonFavSite.getNodeRef(), namePattern, null, false, true, true);
|
||||
result.removeAll(siteChilds);
|
||||
result.remove(nonFavSite);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove folders from Sites
|
||||
List<SiteInfo> sites = siteService.listSites(getCurrentUser());
|
||||
for (SiteInfo siteInfo : sites)
|
||||
{
|
||||
List<FileInfo> siteChilds = search(siteInfo.getNodeRef(), namePattern, null, false, true, true);
|
||||
result.removeAll(siteChilds);
|
||||
}
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for emails in specified folder depend on view mode.
|
||||
*
|
||||
* @param contextNodeRef context folder for search
|
||||
* @param namePattern name pattern for search
|
||||
* @param viewMode context folder view mode
|
||||
* @param includeSubFolders includeSubFolders
|
||||
* @return list of emails that context folder contains.
|
||||
*/
|
||||
public List<FileInfo> searchMails(NodeRef contextNodeRef, String namePattern, String viewMode, boolean includeSubFolders)
|
||||
{
|
||||
|
||||
List<FileInfo> result = new LinkedList<FileInfo>();
|
||||
if (viewMode.equals(AlfrescoImapConst.MODE_ARCHIVE))
|
||||
{
|
||||
result = search(contextNodeRef, namePattern, ImapModel.TYPE_IMAP_CONTENT, false, true, includeSubFolders);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (viewMode.equals(AlfrescoImapConst.MODE_VIRTUAL))
|
||||
{
|
||||
result = search(contextNodeRef, namePattern, null, true, false, includeSubFolders);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<FileInfo> search(NodeRef contextNodeRef, String namePattern, QName searchType, boolean fileSearch, boolean folderSearch, boolean includeSubFolders)
|
||||
{
|
||||
List<FileInfo> result = new LinkedList<FileInfo>();
|
||||
List<FileInfo> searchResult = fileFolderService.search(contextNodeRef, namePattern, fileSearch, folderSearch, includeSubFolders);
|
||||
|
||||
if (searchType == null)
|
||||
{
|
||||
return searchResult;
|
||||
}
|
||||
|
||||
for (FileInfo fileInfo : searchResult)
|
||||
{
|
||||
if (nodeService.getType(fileInfo.getNodeRef()).equals(searchType))
|
||||
{
|
||||
result.add(fileInfo);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get root reference for the specified mailbox
|
||||
*
|
||||
* @param mailboxName mailbox name in IMAP client.
|
||||
* @param userName
|
||||
* @return
|
||||
*/
|
||||
public NodeRef getMailboxRootRef(String mailboxName, String userName)
|
||||
{
|
||||
String rootFolder;
|
||||
int index = mailboxName.indexOf(AlfrescoImapConst.HIERARCHY_DELIMITER);
|
||||
if (index > 0)
|
||||
{
|
||||
rootFolder = mailboxName.substring(0, index);
|
||||
}
|
||||
else
|
||||
{
|
||||
rootFolder = mailboxName;
|
||||
}
|
||||
|
||||
Map<String, ImapConfig> imapConfigs = getImapConfigs();
|
||||
if (imapConfigs.keySet().contains(rootFolder))
|
||||
{
|
||||
Map<String, NodeRef> mountPoints = getMountPoints();
|
||||
NodeRef mountRef = mountPoints.get(rootFolder);
|
||||
return nodeService.getParentAssocs(mountRef).get(0).getParentRef();
|
||||
}
|
||||
else
|
||||
{
|
||||
return getUserImapHomeRef(userName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param userName user name
|
||||
* @return user IMAP home reference
|
||||
*/
|
||||
public NodeRef getUserImapHomeRef(String userName)
|
||||
{
|
||||
return fileFolderService.searchSimple(imapRootNodeRef, userName);
|
||||
}
|
||||
|
||||
public String getCurrentUser()
|
||||
{
|
||||
return AuthenticationUtil.getFullyAuthenticatedUser();
|
||||
}
|
||||
|
||||
public String getUserImapHomeId(String userName)
|
||||
{
|
||||
return getUserImapHomeRef(userName).getId();
|
||||
}
|
||||
|
||||
public NodeRef getImapRootNodeRef()
|
||||
{
|
||||
return imapRootNodeRef;
|
||||
}
|
||||
|
||||
public NodeRef getCompanyHomeNodeRef()
|
||||
{
|
||||
return companyHomeNodeRef;
|
||||
}
|
||||
|
||||
public NodeRef getSpacesStoreNodeRef()
|
||||
{
|
||||
return spacesStoreNodeRef;
|
||||
}
|
||||
|
||||
public void setImapRoot(String imapRoot)
|
||||
{
|
||||
this.imapRoot = imapRoot;
|
||||
}
|
||||
|
||||
public String getDefaultFromAddress()
|
||||
{
|
||||
return defaultFromAddress;
|
||||
}
|
||||
|
||||
public void setDefaultFromAddress(String defaultFromAddress)
|
||||
{
|
||||
this.defaultFromAddress = defaultFromAddress;
|
||||
}
|
||||
|
||||
public String getWebApplicationContextUrl()
|
||||
{
|
||||
return this.webApplicationContextUrl;
|
||||
}
|
||||
|
||||
public void setWebApplicationContextUrl(String webApplicationContextUrl)
|
||||
{
|
||||
this.webApplicationContextUrl = webApplicationContextUrl;
|
||||
}
|
||||
|
||||
public String getRepositoryTemplatePath()
|
||||
{
|
||||
return repositoryTemplatePath;
|
||||
}
|
||||
|
||||
public void setRepositoryTemplatePath(String repositoryTemplatePath)
|
||||
{
|
||||
this.repositoryTemplatePath = repositoryTemplatePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return flags that belong to the specified imap folder.
|
||||
*
|
||||
* @param messageInfo imap folder info.
|
||||
* @return flags.
|
||||
*/
|
||||
public Flags getFlags(FileInfo messageInfo)
|
||||
{
|
||||
Flags flags = new Flags();
|
||||
checkForFlaggableAspect(messageInfo.getNodeRef());
|
||||
Map<QName, Serializable> props = nodeService.getProperties(messageInfo.getNodeRef());
|
||||
|
||||
for (QName key : qNameToFlag.keySet())
|
||||
{
|
||||
Boolean value = (Boolean) props.get(key);
|
||||
if (value != null && value)
|
||||
{
|
||||
flags.add(qNameToFlag.get(key));
|
||||
}
|
||||
}
|
||||
// This is a multiuser flag support. Commented due new requirements
|
||||
// for (QName key : qNameToFlag.keySet())
|
||||
// {
|
||||
// if (key.equals(ImapModel.PROP_FLAG_DELETED))
|
||||
// {
|
||||
// Boolean value = (Boolean) props.get(key);
|
||||
// if (value != null && value)
|
||||
// {
|
||||
// flags.add(qNameToFlag.get(key));
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// String users = (String) props.get(key);
|
||||
//
|
||||
// if (users != null && users.indexOf(formatUserEntry(getCurrentUser())) >= 0)
|
||||
// {
|
||||
// flags.add(qNameToFlag.get(key));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set flags to the specified imapFolder.
|
||||
*
|
||||
* @param messageInfo FileInfo of imap Folder.
|
||||
* @param flags flags to set.
|
||||
* @param value value to set.
|
||||
*/
|
||||
public void setFlags(FileInfo messageInfo, Flags flags, boolean value)
|
||||
{
|
||||
checkForFlaggableAspect(messageInfo.getNodeRef());
|
||||
for (Flags.Flag flag : flags.getSystemFlags())
|
||||
{
|
||||
setFlag(messageInfo, flag, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set flags to the specified imapFolder.
|
||||
*
|
||||
* @param messageInfo FileInfo of imap Folder
|
||||
* @param flag flag to set.
|
||||
* @param value value value to set.
|
||||
*/
|
||||
public void setFlag(final FileInfo messageInfo, final Flag flag, final boolean value)
|
||||
{
|
||||
checkForFlaggableAspect(messageInfo.getNodeRef());
|
||||
nodeService.setProperty(messageInfo.getNodeRef(), flagToQname.get(flag), value);
|
||||
|
||||
// This is a multiuser flag support. Commented due new requirements
|
||||
// if (flagToQname.get(flag).equals(ImapModel.PROP_FLAG_DELETED))
|
||||
// {
|
||||
// nodeService.setProperty(messageInfo.getNodeRef(), flagToQname.get(flag), value);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Void>()
|
||||
// {
|
||||
// public Void doWork() throws Exception
|
||||
// {
|
||||
//
|
||||
// String users = (String) nodeService.getProperty(messageInfo.getNodeRef(), flagToQname.get(flag));
|
||||
// if (value)
|
||||
// {
|
||||
// if (users == null)
|
||||
// {
|
||||
// users = "";
|
||||
// }
|
||||
// users += formatUserEntry(getCurrentUser());
|
||||
//
|
||||
// }
|
||||
// else if (users != null)
|
||||
// {
|
||||
// users = users.replace(formatUserEntry(getCurrentUser()), "");
|
||||
//
|
||||
// }
|
||||
// nodeService.setProperty(messageInfo.getNodeRef(), flagToQname.get(flag), users);
|
||||
// return null;
|
||||
// }
|
||||
// }, AuthenticationUtil.getSystemUserName());
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the given authentication has a particular permission for the given node.
|
||||
*
|
||||
* @param nodeRef nodeRef of the node
|
||||
* @param permission permission for check
|
||||
* @return the access status
|
||||
*/
|
||||
public AccessStatus hasPermission(NodeRef nodeRef, String permission)
|
||||
{
|
||||
return permissionService.hasPermission(nodeRef, permission);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change userName into following format ;userName;
|
||||
*
|
||||
* @param userName
|
||||
* @return
|
||||
*/
|
||||
public String formatUserEntry(String userName)
|
||||
{
|
||||
return AlfrescoImapConst.USER_SEPARATOR + userName + AlfrescoImapConst.USER_SEPARATOR;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method should returns a unique identifier of Alfresco server. The possible UID may be calculated based on IP address, Server port, MAC address, Web Application context.
|
||||
* This UID should be parseable into initial components. This necessary for the implementation of the following case: If the message being copied (e.g. drag-and-drop) between
|
||||
* two different Alfresco accounts in the IMAP client, we must unambiguously identify from which Alfresco server this message being copied. The message itself does not contain
|
||||
* content data, so we must download it from the initial server (e.g. using download content servlet) and save it into destination repository.
|
||||
*
|
||||
* @return String representation of unique identifier of Alfresco server
|
||||
*/
|
||||
public String getAlfrescoServerUID()
|
||||
{
|
||||
// TODO Implement as javadoc says.
|
||||
return "Not-Implemented";
|
||||
}
|
||||
|
||||
/**
|
||||
* Map of mount points. Name of mount point == key in the map.
|
||||
*
|
||||
* @return Map of mount points.
|
||||
*/
|
||||
public Map<String, NodeRef> getMountPoints()
|
||||
{
|
||||
Map<String, ImapConfig> imapConfigs = getImapConfigs();
|
||||
Map<String, NodeRef> mountPoints = new HashMap<String, NodeRef>();
|
||||
|
||||
for (ImapConfig config : imapConfigs.values())
|
||||
{
|
||||
// Get node reference
|
||||
StoreRef store = new StoreRef(config.getStore());
|
||||
ResultSet rs = searchService.query(store, SearchService.LANGUAGE_XPATH, config.getRootPath());
|
||||
if (rs.length() == 0)
|
||||
{
|
||||
logger.warn("Didn't find " + config.getName());
|
||||
}
|
||||
else
|
||||
{
|
||||
NodeRef nodeRef = rs.getNodeRef(0);
|
||||
mountPoints.put(config.getName(), nodeRef);
|
||||
}
|
||||
rs.close();
|
||||
}
|
||||
return mountPoints;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return map of imap configs. Name of config == key in the map
|
||||
*
|
||||
* @return map of imap configs.
|
||||
*/
|
||||
public Map<String, ImapConfig> getImapConfigs()
|
||||
{
|
||||
Config imapConfig = configService.getConfig("imapConfig");
|
||||
ImapConfigElement imapConfigElement = (ImapConfigElement) imapConfig.getConfigElement(ImapConfigElement.CONFIG_ELEMENT_ID);
|
||||
return imapConfigElement.getImapConfigs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return view mode ("virtual" or "archive") for specified mailbox.
|
||||
*
|
||||
* @param mailboxName name of the mailbox in IMAP client.
|
||||
* @return view mode of the specified mailbox.
|
||||
*/
|
||||
public String getViewMode(String mailboxName)
|
||||
{
|
||||
String rootFolder;
|
||||
int index = mailboxName.indexOf(AlfrescoImapConst.HIERARCHY_DELIMITER);
|
||||
if (index > 0)
|
||||
{
|
||||
rootFolder = mailboxName.substring(0, index);
|
||||
}
|
||||
else
|
||||
{
|
||||
rootFolder = mailboxName;
|
||||
}
|
||||
Map<String, ImapConfig> imapConfigs = getImapConfigs();
|
||||
if (imapConfigs.keySet().contains(rootFolder))
|
||||
{
|
||||
return imapConfigs.get(rootFolder).getMode();
|
||||
}
|
||||
else
|
||||
{
|
||||
return AlfrescoImapConst.MODE_ARCHIVE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return mount point name, which was specified in imap-config.xml for the current mailbox.
|
||||
*
|
||||
* @param mailboxName mailbox name in IMAP client.
|
||||
* @return mount point name or null.
|
||||
*/
|
||||
public String getMountPointName(String mailboxName)
|
||||
{
|
||||
String rootFolder;
|
||||
int index = mailboxName.indexOf(AlfrescoImapConst.HIERARCHY_DELIMITER);
|
||||
if (index > 0)
|
||||
{
|
||||
rootFolder = mailboxName.substring(0, index);
|
||||
}
|
||||
else
|
||||
{
|
||||
rootFolder = mailboxName;
|
||||
}
|
||||
Map<String, ImapConfig> imapConfigs = getImapConfigs();
|
||||
if (imapConfigs.keySet().contains(rootFolder))
|
||||
{
|
||||
return rootFolder;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert mailpath from IMAP client representation to the alfresco representation view. (e.g. with default settings "getMailPathInRepo(Repository_virtual.Imap Home)" will
|
||||
* return "Company Home.Imap Home")
|
||||
*
|
||||
* @param mailPath mailbox path in IMAP client
|
||||
* @return mailbox path in alfresco
|
||||
*/
|
||||
public String getMailPathInRepo(String mailPath)
|
||||
{
|
||||
String rootFolder;
|
||||
String remain = "";
|
||||
int index = mailPath.indexOf(AlfrescoImapConst.HIERARCHY_DELIMITER);
|
||||
if (index > 0)
|
||||
{
|
||||
rootFolder = mailPath.substring(0, index);
|
||||
remain = mailPath.substring(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
rootFolder = mailPath;
|
||||
}
|
||||
Map<String, ImapConfig> imapConfigs = getImapConfigs();
|
||||
if (imapConfigs.keySet().contains(rootFolder))
|
||||
{
|
||||
Map<String, NodeRef> mountPoints = getMountPoints();
|
||||
NodeRef rootRef = mountPoints.get(rootFolder);
|
||||
String rootName = nodeService.getProperty(rootRef, ContentModel.PROP_NAME).toString();
|
||||
|
||||
return rootName + remain;
|
||||
}
|
||||
else
|
||||
{
|
||||
return mailPath;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return list of sites, that belong to the specified user and not marked as "Imap favourite"
|
||||
*
|
||||
* @param userName name of user
|
||||
* @return List of nonFavourite sites.
|
||||
*/
|
||||
public List<SiteInfo> getNonFavouriteSites(String userName)
|
||||
{
|
||||
List<SiteInfo> nonFavSites = new LinkedList<SiteInfo>();
|
||||
Map<String, Serializable> prefs = preferenceService.getPreferences(userName, AlfrescoImapConst.PREF_IMAP_FAVOURITE_SITES);
|
||||
List<SiteInfo> sites = siteService.listSites(userName);
|
||||
for (SiteInfo siteInfo : sites)
|
||||
{
|
||||
String key = AlfrescoImapConst.PREF_IMAP_FAVOURITE_SITES + "." + siteInfo.getShortName();
|
||||
Boolean isImapFavourite = (Boolean) prefs.get(key);
|
||||
if (isImapFavourite == null || !isImapFavourite)
|
||||
{
|
||||
nonFavSites.add(siteInfo);
|
||||
}
|
||||
}
|
||||
|
||||
return nonFavSites;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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}.
|
||||
* @return Text representing email body for ContentModel node.
|
||||
*/
|
||||
public String getEmailBodyText(NodeRef nodeRef, EmailBodyType type)
|
||||
{
|
||||
return templateService.processTemplate(getDefaultEmailBodyTemplate(type), createEmailTemplateModel(nodeRef));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns default email body template. This method trying to find a template on the path in the repository first e.g. {@code "Data Dictionary > IMAP Templates >"}. This path
|
||||
* should be set as the property of the "imapHelper" bean. In this case it returns {@code NodeRef.toString()} of the template. If there are no template in the repository it
|
||||
* returns a default template on the classpath.
|
||||
*
|
||||
* @param type One of the {@link EmailBodyType}.
|
||||
* @return String representing template classpath path or NodeRef.toString().
|
||||
*/
|
||||
public String getDefaultEmailBodyTemplate(EmailBodyType type)
|
||||
{
|
||||
String result = null;
|
||||
switch (type)
|
||||
{
|
||||
case TEXT_HTML:
|
||||
result = CLASSPATH_TEXT_HTML_TEMPLATE;
|
||||
break;
|
||||
case TEXT_PLAIN:
|
||||
result = CLASSPATH_TEXT_PLAIN_TEMPLATE;
|
||||
break;
|
||||
}
|
||||
final StringBuilder templateName = new StringBuilder(DICTIONARY_TEMPLATE_PREFIX).append("-").append(type.getTypeSubtype()).append(".ftl");
|
||||
int indexOfStoreDelim = repositoryTemplatePath.indexOf(StoreRef.URI_FILLER);
|
||||
if (indexOfStoreDelim == -1)
|
||||
{
|
||||
logger.error("Bad path format, " + StoreRef.URI_FILLER + " not found");
|
||||
return result;
|
||||
}
|
||||
indexOfStoreDelim += StoreRef.URI_FILLER.length();
|
||||
int indexOfPathDelim = repositoryTemplatePath.indexOf("/", indexOfStoreDelim);
|
||||
if (indexOfPathDelim == -1)
|
||||
{
|
||||
logger.error("Bad path format, / not found");
|
||||
return result;
|
||||
}
|
||||
final String storePath = repositoryTemplatePath.substring(0, indexOfPathDelim);
|
||||
final String rootPathInStore = repositoryTemplatePath.substring(indexOfPathDelim);
|
||||
final String query = String.format("+PATH:\"%1$s/*\" +@cm\\:name:\"%2$s\"", rootPathInStore, templateName.toString());
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Using template path :" + repositoryTemplatePath + "/" + templateName);
|
||||
logger.debug("Query: " + query);
|
||||
}
|
||||
StoreRef storeRef = new StoreRef(storePath);
|
||||
ResultSet resultSet = searchService.query(storeRef, "lucene", query);
|
||||
if (resultSet == null || resultSet.length() == 0)
|
||||
{
|
||||
logger.error(String.format("IMAP message template '%1$s' does not exist in the path '%2$s'.", templateName, repositoryTemplatePath));
|
||||
return result;
|
||||
}
|
||||
result = resultSet.getNodeRef(0).toString();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds default email template model for TemplateProcessor
|
||||
*
|
||||
* @param ref NodeRef of the target content.
|
||||
* @return Map that includes template model objects.
|
||||
*/
|
||||
private Map<String, Object> createEmailTemplateModel(NodeRef ref)
|
||||
{
|
||||
Map<String, Object> model = new HashMap<String, Object>(8, 1.0f);
|
||||
TemplateNode tn = new TemplateNode(ref, serviceRegistry, null);
|
||||
model.put("document", tn);
|
||||
NodeRef parent = nodeService.getPrimaryParent(ref).getParentRef();
|
||||
model.put("space", new TemplateNode(parent, serviceRegistry, null));
|
||||
model.put("date", new Date());
|
||||
model.put("contextUrl", new String(getWebApplicationContextUrl()));
|
||||
model.put("alfTicket", new String(serviceRegistry.getAuthenticationService().getCurrentTicket()));
|
||||
return model;
|
||||
}
|
||||
|
||||
private void checkForFlaggableAspect(NodeRef nodeRef)
|
||||
{
|
||||
if (!nodeService.hasAspect(nodeRef, ImapModel.ASPECT_FLAGGABLE))
|
||||
{
|
||||
Map<QName, Serializable> aspectProperties = new HashMap<QName, Serializable>();
|
||||
nodeService.addAspect(nodeRef, ImapModel.ASPECT_FLAGGABLE, aspectProperties);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isPatchApplied()
|
||||
{
|
||||
return patchApplied;
|
||||
}
|
||||
|
||||
// ----------------------Getters and Setters----------------------------
|
||||
|
||||
public NodeService getNodeService()
|
||||
{
|
||||
return nodeService;
|
||||
}
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
public SearchService getSearchService()
|
||||
{
|
||||
return searchService;
|
||||
}
|
||||
|
||||
public void setSearchService(SearchService searchService)
|
||||
{
|
||||
this.searchService = searchService;
|
||||
}
|
||||
|
||||
public FileFolderService getFileFolderService()
|
||||
{
|
||||
return fileFolderService;
|
||||
}
|
||||
|
||||
public void setFileFolderService(FileFolderService fileFolderService)
|
||||
{
|
||||
this.fileFolderService = fileFolderService;
|
||||
}
|
||||
|
||||
public TemplateService getTemplateService()
|
||||
{
|
||||
return templateService;
|
||||
}
|
||||
|
||||
public void setTemplateService(TemplateService templateService)
|
||||
{
|
||||
this.templateService = templateService;
|
||||
}
|
||||
|
||||
public NamespaceService getNamespaceService()
|
||||
{
|
||||
return namespaceService;
|
||||
}
|
||||
|
||||
public void setNamespaceService(NamespaceService namespaceService)
|
||||
{
|
||||
this.namespaceService = namespaceService;
|
||||
}
|
||||
|
||||
public PermissionService getPermissionService()
|
||||
{
|
||||
return permissionService;
|
||||
}
|
||||
|
||||
public void setPermissionService(PermissionService permissionService)
|
||||
{
|
||||
this.permissionService = permissionService;
|
||||
}
|
||||
|
||||
public ConfigService getConfigService()
|
||||
{
|
||||
return configService;
|
||||
}
|
||||
|
||||
public void setConfigService(ConfigService configService)
|
||||
{
|
||||
this.configService = configService;
|
||||
}
|
||||
|
||||
public DictionaryService getDictionaryService()
|
||||
{
|
||||
return dictionaryService;
|
||||
}
|
||||
|
||||
public void setDictionaryService(DictionaryService dictionaryService)
|
||||
{
|
||||
this.dictionaryService = dictionaryService;
|
||||
}
|
||||
|
||||
public PreferenceService getPreferenceService()
|
||||
{
|
||||
return preferenceService;
|
||||
}
|
||||
|
||||
public void setPreferenceService(PreferenceService preferenceService)
|
||||
{
|
||||
this.preferenceService = preferenceService;
|
||||
}
|
||||
|
||||
public SiteService getSiteService()
|
||||
{
|
||||
return siteService;
|
||||
}
|
||||
|
||||
public void setSiteService(SiteService siteService)
|
||||
{
|
||||
this.siteService = siteService;
|
||||
}
|
||||
|
||||
public ServiceRegistry getServiceRegistry()
|
||||
{
|
||||
return serviceRegistry;
|
||||
}
|
||||
|
||||
public void setServiceRegistry(ServiceRegistry serviceRegistry)
|
||||
{
|
||||
this.serviceRegistry = serviceRegistry;
|
||||
}
|
||||
|
||||
public PatchService getPatchService()
|
||||
{
|
||||
return patchService;
|
||||
}
|
||||
|
||||
public void setPatchService(PatchService patchService)
|
||||
{
|
||||
this.patchService = patchService;
|
||||
}
|
||||
|
||||
}
|
143
source/java/org/alfresco/repo/imap/config/ImapConfigElement.java
Executable file
143
source/java/org/alfresco/repo/imap/config/ImapConfigElement.java
Executable file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program 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 General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.imap.config;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.config.ConfigElement;
|
||||
import org.alfresco.config.element.ConfigElementAdapter;
|
||||
|
||||
public class ImapConfigElement extends ConfigElementAdapter
|
||||
{
|
||||
private static final long serialVersionUID = -6911139959296875159L;
|
||||
|
||||
public static final String CONFIG_ELEMENT_ID = "imapConfig";
|
||||
|
||||
private Map<String, ImapConfig> imapConfigs = new LinkedHashMap<String, ImapConfig>(8, 10f);
|
||||
|
||||
public ImapConfigElement()
|
||||
{
|
||||
super(CONFIG_ELEMENT_ID);
|
||||
}
|
||||
|
||||
public ImapConfigElement(String name)
|
||||
{
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigElement combine(ConfigElement configElement)
|
||||
{
|
||||
ImapConfigElement combined = new ImapConfigElement();
|
||||
|
||||
// add all the imapConfigs from this element
|
||||
for (ImapConfig imapConfig : getImapConfigs().values())
|
||||
{
|
||||
combined.addImapConfig(imapConfig);
|
||||
}
|
||||
|
||||
// add all the imapConfigs from the given element
|
||||
for (ImapConfig imapConfig : ((ImapConfigElement) configElement).getImapConfigs().values())
|
||||
{
|
||||
combined.addImapConfig(imapConfig);
|
||||
}
|
||||
|
||||
return combined;
|
||||
}
|
||||
|
||||
public Map<String, ImapConfig> getImapConfigs()
|
||||
{
|
||||
return imapConfigs;
|
||||
}
|
||||
|
||||
public ImapConfig getImapConfig(String name)
|
||||
{
|
||||
return imapConfigs.get(name);
|
||||
}
|
||||
|
||||
void addImapConfig(ImapConfig imapConfig)
|
||||
{
|
||||
imapConfigs.put(imapConfig.getName(), imapConfig);
|
||||
}
|
||||
|
||||
public static class ImapConfig implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 424330549937129149L;
|
||||
|
||||
private String name;
|
||||
private String mode;
|
||||
private String store;
|
||||
private String rootPath;
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getMode()
|
||||
{
|
||||
return mode;
|
||||
}
|
||||
|
||||
public void setMode(String mode)
|
||||
{
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
public String getStore()
|
||||
{
|
||||
return store;
|
||||
}
|
||||
|
||||
public void setStore(String store)
|
||||
{
|
||||
this.store = store;
|
||||
}
|
||||
|
||||
public String getRootPath()
|
||||
{
|
||||
return rootPath;
|
||||
}
|
||||
|
||||
public void setRootPath(String rootPath)
|
||||
{
|
||||
this.rootPath = rootPath;
|
||||
}
|
||||
|
||||
public static long getSerialVersionUID()
|
||||
{
|
||||
return serialVersionUID;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
81
source/java/org/alfresco/repo/imap/config/ImapElementReader.java
Executable file
81
source/java/org/alfresco/repo/imap/config/ImapElementReader.java
Executable file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program 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 General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.imap.config;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.alfresco.config.ConfigElement;
|
||||
import org.alfresco.config.ConfigException;
|
||||
import org.alfresco.config.xml.elementreader.ConfigElementReader;
|
||||
import org.alfresco.repo.imap.config.ImapConfigElement.ImapConfig;
|
||||
import org.dom4j.Element;
|
||||
|
||||
public class ImapElementReader implements ConfigElementReader
|
||||
{
|
||||
|
||||
private static final String ELEMENT_IMAP_CONFIG = "imapConfig";
|
||||
private static final String ELEMENT_IMAP = "imap";
|
||||
private static final String ELEMENT_STORE = "store";
|
||||
private static final String ELEMENT_ROOTPATH = "rootPath";
|
||||
|
||||
private static final String ATTR_NAME = "name";
|
||||
private static final String ATTR_MODE = "mode";
|
||||
|
||||
public ConfigElement parse(Element element)
|
||||
{
|
||||
ImapConfigElement configElement = null;
|
||||
|
||||
if (element != null)
|
||||
{
|
||||
String elementName = element.getName();
|
||||
if (elementName.equals(ELEMENT_IMAP_CONFIG) == false)
|
||||
{
|
||||
throw new ConfigException("ImapElementReader can parse '" + ELEMENT_IMAP_CONFIG + "' elements only, the element passed is '" + elementName + "'");
|
||||
}
|
||||
|
||||
configElement = new ImapConfigElement();
|
||||
|
||||
for (Iterator<Element> items = element.elementIterator(ELEMENT_IMAP); items.hasNext();)
|
||||
{
|
||||
Element item = items.next();
|
||||
|
||||
String name = item.attributeValue(ATTR_NAME);
|
||||
String mode = item.attributeValue(ATTR_MODE);
|
||||
String store = item.element(ELEMENT_STORE).getStringValue();
|
||||
String rootPath = item.element(ELEMENT_ROOTPATH).getStringValue();
|
||||
|
||||
ImapConfig imapConfig = new ImapConfig();
|
||||
imapConfig.setName(name);
|
||||
imapConfig.setMode(mode);
|
||||
imapConfig.setStore(store);
|
||||
imapConfig.setRootPath(rootPath);
|
||||
|
||||
configElement.addImapConfig(imapConfig);
|
||||
}
|
||||
}
|
||||
return configElement;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program 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 General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.imap.exception;
|
||||
|
||||
import com.icegreen.greenmail.store.FolderException;
|
||||
|
||||
/**
|
||||
* Thrown on an inappropriate attempt to modify a folder.
|
||||
*
|
||||
* @author Ivan Rybnikov
|
||||
*/
|
||||
public class AlfrescoImapFolderException extends FolderException
|
||||
{
|
||||
|
||||
private static final long serialVersionUID = -2721708848846740336L;
|
||||
|
||||
public final static String PERMISSION_DENIED = "Can't create folder - Permission denied";
|
||||
|
||||
public AlfrescoImapFolderException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
@@ -48,6 +48,8 @@ import org.dom4j.io.SAXReader;
|
||||
import org.mozilla.javascript.Context;
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
|
||||
import com.werken.saxpath.XPathReader;
|
||||
|
||||
/**
|
||||
* Search component for use by the ScriptService.
|
||||
* <p>
|
||||
@@ -215,6 +217,26 @@ public final class Search extends BaseScopableProcessorExtension
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validation Xpath query
|
||||
*
|
||||
* @param query xpath query
|
||||
* @return true if xpath query valid
|
||||
*/
|
||||
public boolean isValidXpathQuery(String query)
|
||||
{
|
||||
try
|
||||
{
|
||||
XPathReader reader = new XPathReader();
|
||||
reader.parse(query);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a Lucene search
|
||||
*
|
||||
|
Reference in New Issue
Block a user