com.bluexml.side.Framework.alfresco.notification.NotificationHelper.java Source code

Java tutorial

Introduction

Here is the source code for com.bluexml.side.Framework.alfresco.notification.NotificationHelper.java

Source

/*
Copyright (C) 2007-20013  BlueXML - www.bluexml.com
    
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
    
You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package com.bluexml.side.Framework.alfresco.notification;

import java.io.InputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.alfresco.model.ContentModel;
import org.alfresco.repo.action.executer.MailActionExecuter;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.model.FileNotFoundException;
import org.alfresco.service.cmr.repository.ContentReader;
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.SearchService;
import org.alfresco.service.cmr.security.AuthorityType;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.cmr.site.SiteInfo;
import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.extensions.surf.util.I18NUtil;

public class NotificationHelper {
    static Log logger = LogFactory.getLog(NotificationHelper.class);

    // email sending action can be set to work in background
    boolean runInBackground = true;

    // true to enable server to reload properties without restart, useful if properties files are stored in alfresco repository
    boolean dynamicLoading = true;

    // use a fake mailer for debug purpose
    boolean usefakeEmailer = false;

    // force  recipients email advanced debug purpose
    protected String forcedEmail = null;

    public static String TYPE_CONTENT_PREFIX = "cm";
    protected static String PROPERTIES_PATH = "notification.properties";
    protected static String PROPERTIES_IN_DICTIONARY_PATH = "/app:company_home/app:dictionary/app:email_templates/app:notify_email_templates/";
    public static String TYPE_CALANDAR_NSURI = "http://www.alfresco.org/model/calendar";
    public static String TYPE_CALANDAR_PREFIX = "ia";
    public static String TYPE_CALANDAR_EVENT = "{http://www.alfresco.org/model/calendar}calendarEvent";
    public static String TYPE_CALANDAR_SPACE = "{http://www.alfresco.org/model/calendar}calendar";

    public static String ROOT_NOTIFICATION = "NOTIFICATION";

    public static String profile_notification_document_new = "profile_notification_document_new";
    public static String profile_notification_document_change = "profile_notification_document_change";
    public static String profile_notification_document_delete = "profile_notification_document_delete";
    public static String profile_notification_event_new = "profile_notification_event_new";
    public static String profile_notification_event_change = "profile_notification_event_change";
    public static String profile_notification_event_delete = "profile_notification_event_delete";
    public static String profile_notification_group = "profile_notification_group";

    // user language preference key
    public static String profile_language = "user_language";

    // defaults values
    public static boolean default_preferences = false;
    public static String default_language = "fr_FR";

    private Map<String, Properties> props;

    public boolean isRunInBackground() {
        return runInBackground;
    }

    public void setRunInBackground(boolean runInBackground) {
        this.runInBackground = runInBackground;
    }

    public boolean isDynamicLoading() {
        return dynamicLoading;
    }

    public void setDynamicLoading(boolean dynamicLoading) {
        this.dynamicLoading = dynamicLoading;
    }

    public boolean isUsefakeEmailer() {
        return usefakeEmailer;
    }

    public void setUsefakeEmailer(boolean usefakeEmailer) {
        this.usefakeEmailer = usefakeEmailer;
    }

    public String getForcedEmail() {
        return forcedEmail;
    }

    public void setForcedEmail(String forcedEmail) {
        this.forcedEmail = forcedEmail;
    }

    protected ServiceRegistry serviceRegistry;

    public ServiceRegistry getServiceRegistry() {
        return serviceRegistry;
    }

    public void setServiceRegistry(ServiceRegistry serviceRegistry) {
        this.serviceRegistry = serviceRegistry;
    }

    private String getUserPreferencesString(NodeRef userId) {
        // get preferences from Preson Node or cache
        String preferencesString = null;
        ContentReader reader = serviceRegistry.getContentService().getReader(userId,
                ContentModel.PROP_PREFERENCE_VALUES);
        if (reader != null) {
            preferencesString = reader.getContentString();
        }

        return preferencesString;
    }

    public Map<String, Object> getUserPreferences(NodeRef user) throws Exception {
        boolean useDefault = true;
        boolean useDefault_lang = true;
        Map<String, Object> userPreferencies = new HashMap<String, Object>();
        String pref = getUserPreferencesString(user);
        if (pref != null) {

            JSONObject root = new JSONObject(pref);
            if (!root.isNull(ROOT_NOTIFICATION)) {
                String prefsString = root.getString(ROOT_NOTIFICATION).replaceFirst("^\\(", "").replaceFirst("\\)$",
                        "");
                JSONObject root_NOTIFICATION = new JSONObject(prefsString);

                // get configuration for Documents
                Boolean doc_new = getNotificationValueFor(root_NOTIFICATION, profile_notification_document_new);
                userPreferencies.put(profile_notification_document_new, doc_new);
                Boolean doc_change = getNotificationValueFor(root_NOTIFICATION,
                        profile_notification_document_change);
                userPreferencies.put(profile_notification_document_change, doc_change);
                Boolean doc_delete = getNotificationValueFor(root_NOTIFICATION,
                        profile_notification_document_delete);
                userPreferencies.put(profile_notification_document_delete, doc_delete);

                // get configuration for Events
                Boolean event_new = getNotificationValueFor(root_NOTIFICATION, profile_notification_event_new);
                userPreferencies.put(profile_notification_event_new, event_new);
                Boolean event_change = getNotificationValueFor(root_NOTIFICATION,
                        profile_notification_event_change);
                userPreferencies.put(profile_notification_event_change, event_change);
                Boolean event_delete = getNotificationValueFor(root_NOTIFICATION,
                        profile_notification_event_delete);
                userPreferencies.put(profile_notification_event_delete, event_delete);
                useDefault = false;
            }

            if (!root.isNull(profile_language)) {
                String language = root.getString(profile_language);
                userPreferencies.put(profile_language, language);
                useDefault_lang = false;
            } else {
                logger.debug("use default language (user_language not found in user profile)");
            }
        }

        if (useDefault) {
            // set default values
            userPreferencies.put(profile_notification_document_new, default_preferences);
            userPreferencies.put(profile_notification_document_change, default_preferences);
            userPreferencies.put(profile_notification_document_delete, default_preferences);
            userPreferencies.put(profile_notification_event_new, default_preferences);
            userPreferencies.put(profile_notification_event_change, default_preferences);
            userPreferencies.put(profile_notification_event_delete, default_preferences);

        }

        if (useDefault_lang) {
            userPreferencies.put(profile_language, default_language);
        }

        return userPreferencies;
    }

    private boolean getNotificationValueFor(JSONObject root_NOTIFICATION, String key) throws JSONException {
        return root_NOTIFICATION.has(key) ? root_NOTIFICATION.getBoolean(key) : false;
    }

    public Object getUserPreference(NodeRef user, String key) throws Exception {
        Object obj = getUserPreferences(user).get(key);
        if (obj == null)
            return true;
        else
            return obj;
    }

    public void sendMails(List<String> dests, String eventType, NodeRef document, String language,
            Map<String, Object> model) throws Exception {
        sendMails(dests, eventType, document, language, model, null, null);
    }

    public void sendMails(List<String> dests, String eventType, NodeRef document, Map<String, Object> model,
            String propertyFileName, ArrayList<String> resourceCustomPaths) throws Exception {
        if (logger.isDebugEnabled())
            logger.debug("dests :" + dests + " - eventType :" + eventType + " - document : " + document
                    + " - model : " + model + " - resourceCustomPath : " + resourceCustomPaths);
        List<String> userIds_filtered = getPersonList(dests);
        GroupByMap<String> gblanguage = new GroupByMap<String>();

        for (String user : userIds_filtered) {
            NodeRef person = serviceRegistry.getPersonService().getPerson(user);
            Boolean userPreference = (Boolean) getUserPreference(person, eventType);
            if (userPreference) {
                gblanguage.put(getUserPreference(person, profile_language), user);
            }
            if (logger.isDebugEnabled())
                logger.debug(user + " preference for " + eventType + " :" + userPreference);
        }

        if (logger.isDebugEnabled())
            logger.debug("userGroup :" + gblanguage);

        for (Map.Entry<Object, List<String>> entry : gblanguage.getEntrySet()) {
            // send mail for users with language
            List<String> users = entry.getValue();
            String language = (String) entry.getKey();
            sendMails(users, eventType, document, language, model, propertyFileName, resourceCustomPaths);
        }
    }

    public void sendMails(List<String> dests, String eventType, NodeRef document, String language,
            Map<String, Object> model, String propertyFileName, ArrayList<String> resourceCustomPaths)
            throws Exception {
        EmailTest emailTest = new EmailTest(serviceRegistry);

        Properties propertiesFor = getPropertiesFor(language, propertyFileName, resourceCustomPaths);
        String forcedEamilFromProperty = propertiesFor.getProperty("forcedEmail");

        if (forcedEamilFromProperty != null) {
            setForcedEmail(forcedEamilFromProperty);
        }

        logger.debug("send mail for " + eventType + " to " + dests);
        Action ac = serviceRegistry.getActionService().createAction("mail");
        // run in background to avoid performance issues
        ac.setExecuteAsynchronously(Boolean
                .parseBoolean(propertiesFor.getProperty("runInBackground", Boolean.toString(runInBackground))));

        //getAttributs(site, docName,docType, docUrl, Isdocument, owner)
        String subjectKey = "mail.notification." + eventType + ".subject";
        Serializable subject = propertiesFor.getProperty(subjectKey);
        logger.debug("email subject " + subjectKey + "=" + subject);
        //evaluer le sujet

        // get nodeRef template
        String templateKey = "mail.notification." + eventType + ".templates";
        String t = propertiesFor.getProperty(templateKey);

        logger.debug("template path " + templateKey + "=" + t);
        NodeRef templateRef = getNodeRefFromPath(t);

        // set actions parameters
        Map<String, Serializable> parameterValues = new HashMap<String, Serializable>();

        if (forcedEmail != null) {
            logger.warn("BEWARE SendMail action used forced email adress :" + forcedEmail);
            logger.info("To whitch off this, edit/check :");
            logger.info("* alfresco/module/SIDE_notification3411E/context/service-context.xml");
            logger.info(
                    "* notification properties files in \"Data Dictionary > Email Templates > Notify Email Templates\"");
            parameterValues.put(MailActionExecuter.PARAM_TO, (Serializable) forcedEmail);
        } else {
            parameterValues.put(MailActionExecuter.PARAM_TO_MANY, (Serializable) dests);
        }

        /* manage case that template need alternative model
        String emailText = "default email body please to use templates";
        if (runInBackground && eventType.contains("delete")) {
           // instantiate the template before calling the action 
           // build the email template model
           model = emailTest.createEmailTemplateModel(document);
        }
        if (model == null) {
           // let emailAction to interpret template
           parameterValues.put(MailActionExecuter.PARAM_TEMPLATE, templateRef);
        } else {
           // beware this not work in background
           emailText = serviceRegistry.getTemplateService().processTemplate(templateRef.toString(), model);
        }*/
        Map<String, Object> modelAll = emailTest.createEmailTemplateModel(document);
        if (!serviceRegistry.getNodeService().getType(document)
                .equals(QName.createQName("{http://www.alfresco.org/model/calendar}calendarEvent"))) {
            Map<String, Object> docAttributs = getDocAttributs(document);
            if (docAttributs != null) {
                modelAll.putAll(docAttributs);
            }
            modelAll.put("userInfo", getUserDetails());
        }
        if (model != null)
            modelAll.putAll(model);
        String emailText = serviceRegistry.getTemplateService().processTemplate(templateRef.toString(), modelAll);
        subject = serviceRegistry.getTemplateService().processTemplateString(null, (String) subject, modelAll);
        parameterValues.put(MailActionExecuter.PARAM_SUBJECT, subject);

        parameterValues.put(MailActionExecuter.PARAM_TEXT, emailText);

        ac.setParameterValues(parameterValues);

        // schedule the email sending
        if (Boolean.parseBoolean(propertiesFor.getProperty("usefakeEmailer", Boolean.toString(usefakeEmailer)))) {

            emailTest.doAction(dests, (String) subject, document, templateRef, modelAll);
        } else {
            serviceRegistry.getActionService().executeAction(ac, document);
        }

        logger.debug("########### NotificationHelper.sendMails() END");
    }

    private Object getUserDetails() {
        String userName = serviceRegistry.getAuthenticationService().getCurrentUserName();
        NodeRef user = serviceRegistry.getPersonService().getPerson(userName);
        String result = "";
        String firstName = (String) serviceRegistry.getNodeService().getProperty(user, ContentModel.PROP_FIRSTNAME);
        String lastName = (String) serviceRegistry.getNodeService().getProperty(user, ContentModel.PROP_LASTNAME);
        String email = (String) serviceRegistry.getNodeService().getProperty(user, ContentModel.PROP_EMAIL);
        if (firstName != null) {
            result += firstName + " ";
        }
        if (lastName != null) {
            result += lastName + " ";
        }
        if (email != null) {
            result += email;
        }
        return result;
    }

    // get site, docName, docType, docUrl, isDocument, owner
    private Map<String, Object> getDocAttributs(NodeRef document) {
        Map<String, Object> result = new HashMap<String, Object>();

        //get docType and isDocument
        NodeRef parent = serviceRegistry.getNodeService().getPrimaryParent(document).getParentRef();
        do {
            if (serviceRegistry.getNodeService().getProperty(parent, ContentModel.PROP_NAME)
                    .equals("documentLibrary")) {
                if (serviceRegistry.getNodeService().getType(document)
                        .equals(QName.createQName("{http://www.alfresco.org/model/forum/1.0}post"))) {
                    result.put("docType", "commentaire sur le document");
                    result.put("isDocument", false);
                } else {
                    result.put("docType", "document");
                    result.put("isDocument", true);
                }
                break;
            } else if (serviceRegistry.getNodeService().getProperty(parent, ContentModel.PROP_NAME)
                    .equals("wiki")) {
                if (serviceRegistry.getNodeService().getType(document)
                        .equals(QName.createQName("{http://www.alfresco.org/model/forum/1.0}post"))) {
                    result.put("docType", "commentaire sur le lien");
                    result.put("isDocument", false);
                } else {
                    result.put("docType", "wiki");
                    result.put("isDocument", false);
                }
                break;
            } else if (serviceRegistry.getNodeService().getProperty(parent, ContentModel.PROP_NAME)
                    .equals("dataLists")) {
                result.put("docType", "document liste de donne");
                result.put("isDocument", false);
                break;
            } else if (serviceRegistry.getNodeService().getProperty(parent, ContentModel.PROP_NAME)
                    .equals("discussions")) {
                result.put("docType", "discussion");
                result.put("isDocument", false);
                break;
            } else if (serviceRegistry.getNodeService().getProperty(parent, ContentModel.PROP_NAME)
                    .equals("blog")) {
                if (serviceRegistry.getNodeService().getType(document)
                        .equals(QName.createQName("{http://www.alfresco.org/model/forum/1.0}post"))) {
                    result.put("docType", "commentaire sur le blog");
                    result.put("isDocument", false);
                } else {
                    result.put("docType", "blog");
                    result.put("isDocument", false);
                }
                break;
            } else if (serviceRegistry.getNodeService().getProperty(parent, ContentModel.PROP_NAME)
                    .equals("links")) {
                if (serviceRegistry.getNodeService().getType(document)
                        .equals(QName.createQName("{http://www.alfresco.org/model/forum/1.0}post"))) {
                    result.put("docType", "commentaire sur le lien");
                    result.put("isDocument", false);
                } else {
                    result.put("docType", "lien");
                    result.put("isDocument", false);
                }
                break;
            }
            parent = serviceRegistry.getNodeService().getPrimaryParent(parent).getParentRef();
        } while (parent != null);

        if (parent != null) {

            //Get document if it is a comment or a discussion
            NodeRef temp = null;
            try {
                if (result.get("docType").equals("discussion")) {
                    temp = getDocument(QName.createQName("{http://www.alfresco.org/model/forum/1.0}topic"),
                            document, result);
                } else if (result.get("docType").equals("commentaire sur le document")
                        || result.get("docType").equals("commentaire sur le lien")
                        || result.get("docType").equals("commentaire sur le blog")
                        || result.get("docType").equals("commentaire sur le wiki")) {
                    temp = getDocument(ContentModel.TYPE_CONTENT, document, result);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (temp != null) {
                document = temp;
            }

            //get document site title
            SiteInfo siteInfo = serviceRegistry.getSiteService().getSite(document);
            result.put("site", siteInfo.getShortName());

            //get docName
            String docName = (String) serviceRegistry.getNodeService().getProperty(document,
                    ContentModel.PROP_NAME);
            result.put("docName", docName);

            //get docUrl
            result.put("docUrl", "document-details?nodeRef=" + document.getStoreRef() + "/" + document.getId());

            //get owner
            String owner = serviceRegistry.getOwnableService().getOwner(document);
            NodeRef onwerNodeRef = serviceRegistry.getPersonService().getPerson(owner);
            if (onwerNodeRef != null) {
                result.put("owner", onwerNodeRef);
            }

            return result;
        }
        return null;
    }

    protected NodeRef getDocument(QName parentType, NodeRef document, Map<String, Object> docAttributs)
            throws FileNotFoundException {
        NodeRef result = null;
        NodeRef parent = null;

        parent = serviceRegistry.getNodeService().getPrimaryParent(document).getParentRef();
        do {
            if (serviceRegistry.getNodeService().getType(parent).equals(parentType)) {
                result = parent;
                break;
            }
            parent = serviceRegistry.getNodeService().getPrimaryParent(parent).getParentRef();
        } while (serviceRegistry.getNodeService().getPrimaryParent(document) != null);
        if (result == null) {
            throw new FileNotFoundException("Parent document not found for comment or discussion");
        }
        return result;
    }

    private NodeRef getNodeRefFromPath(String t) throws FileNotFoundException {
        NodeRef companyHome = null;
        if (logger.isDebugEnabled()) {
            logger.debug("getNodeRefFromPath t=" + t);
        }
        ResultSet rs = serviceRegistry.getSearchService().query(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE,
                SearchService.LANGUAGE_XPATH, t);

        try {
            if (rs.length() == 0) {
                throw new FileNotFoundException("Didn't find " + t);
            }
            companyHome = rs.getNodeRef(0);
        } finally {
            rs.close();
        }
        return companyHome;
    }

    /**
     * This method loads the 'notification_<language>.properties' file from the Dictionary path of Alfresco repository as Properties
     * @param language the language to load
     * @return the set of properties for this language
     * @throws Exception
     */
    public Properties getPropertiesFor(String language) throws Exception {
        return getPropertiesFor(language, null, null);
    }

    /**
     * This method loads the 'notification_<language>.properties' file from the Dictionary path of Alfresco repository and then overwrite the properties 
     * whith the properties files successively contains in resourceCustomPaths[i]+"/cm:"+propertyFileName.basename+<language>+propertyFileName.extension
     * @param language the language to load; if not null the propertyFileName is modified in propertyFileName.basename+<language>+propertyFileName.extension; if null the propertyFileName is not modified
     * @param propertyFileName the property file name to load
     * @param resourceCustomPaths a list of folder where the propertyFileName may be loaded (with the embedded language if not null)
     * @return the set of properties for this language
     * @throws Exception
     */
    public Properties getPropertiesFor(String language, String propertyFileName,
            ArrayList<String> resourceCustomPaths) throws Exception {
        if (props == null) {
            props = new HashMap<String, Properties>();
        }
        if (language == null) {
            Locale loc = I18NUtil.getLocale();
            if (loc == null || loc.toString() == null) {
                language = "fr_FR";
            } else {
                language = loc.toString();
            }
        }
        logger.trace("language :" + language);
        Properties langueExist = props.get(language);
        if (langueExist == null || dynamicLoading) {
            // load properties
            Properties prop = getProperties(language, propertyFileName, resourceCustomPaths);
            props.put(language, prop);
        }
        // not dynamic so return cached object
        return props.get(language);
    }

    /**
     * This method loads the propertyFileName file from the Dictionary path of Alfresco repository and then overwrite the properties 
     * whith the properties files successively contains in resourceCustomPaths[i]+"/cm:"+propertyFileName
     * @param propertyFileName the property file name to load; if null, set to "notification.properties"
     * @param resourceCustomPaths a list of folder where the propertyFileName may be loade
     * @return the set of properties
     * @throws Exception
     */
    public Properties getProperties(String propertyFileName, ArrayList<String> resourceCustomPaths)
            throws Exception {
        return getProperties(null, propertyFileName, resourceCustomPaths);
    }

    /**
     * This method loads the propertyFileName file from the Dictionary path of Alfresco repository (and if not found from classpath) 
     * and then overwrite the properties with the properties files successively contains in resourceCustomPaths[i]+"/cm:"+propertyFileName
     * @param propertyFileName the property file name to load; if null, set to "notification.properties"
     * @param resourceCustomPaths a list of folder where the propertyFileName may be loaded
     * @return the set of properties
     * @throws Exception
     */
    public Properties getProperties(String language, String propertyFileName, ArrayList<String> resourceCustomPaths)
            throws Exception {
        // load properties
        Properties prop = new Properties();
        if (propertyFileName == null)
            propertyFileName = PROPERTIES_PATH;
        // search in alfresco dictionary
        prop.load(getPropertiesInputStream(language, propertyFileName, PROPERTIES_IN_DICTIONARY_PATH, true));
        // custom properties
        if (resourceCustomPaths != null && !resourceCustomPaths.isEmpty()) {
            for (String resourceCustomPath : resourceCustomPaths) {
                Properties customProp = new Properties();
                InputStream s = getPropertiesInputStream(language, propertyFileName, resourceCustomPath, false);
                if (s != null) {
                    customProp.load(s);
                    prop.putAll(customProp);
                }
            }
        }
        logger.trace("Properties loaded :" + prop);
        return prop;
    }

    /**
     * This method loads the 'notification_<language>.properties' file from the Dictionary path of Alfresco repository as InputStream
     * @param language
     * @return the inputstream 'notification_<language>.properties' content
     */
    public InputStream getPropertiesInputStream(String language) {
        // search in alfresco dictionary
        return getPropertiesInputStream(language, PROPERTIES_PATH, PROPERTIES_IN_DICTIONARY_PATH, true);
    }

    /**
     * This method loads the  file resourceCustomPaths+"/cm:"+propertyFileName.basename+<language>+propertyFileName.extension as InputStream
     * @param language the language to load; if not null the propertyFileName is modified in propertyFileName.basename+<language>+propertyFileName.extension; if null the propertyFileName is not modified
     * @param propertyFileName the property file name to load
     * @param resourceCustomPath the folder where the propertyFileName may be loaded (with the embedded language if not null)
     * @param classPath if true, the propertyFileName is loaded from the classpath (without resourceCustomPath)
     * @return the inputstream resourceCustomPaths+"/cm:"+propertyFileName.basename+<language>+propertyFileName.extension content
     */
    public InputStream getPropertiesInputStream(String language, String propertyFileName, String resourceCustomPath,
            boolean classPath) {
        InputStream s = null;
        // compute path with language
        String[] path_dictionary = propertyFileName.split("\\.");
        if (!resourceCustomPath.endsWith("/"))
            resourceCustomPath += "/";
        path_dictionary[0] = resourceCustomPath + TYPE_CONTENT_PREFIX + ":" + path_dictionary[0];
        String resourcePath_dictionary = path_dictionary[0];
        if (language != null)
            resourcePath_dictionary += "_" + language;
        resourcePath_dictionary += "." + path_dictionary[1];

        if (logger.isDebugEnabled()) {
            logger.debug("getPropertiesInputStream path_dictionary=" + path_dictionary);
            logger.debug("getPropertiesInputStream language=" + language);
            logger.debug("getPropertiesInputStream resourcePath_dictionary=" + resourcePath_dictionary);
        }

        try {
            // try to get the template that match the language (country[variant]?)
            s = getInputStream(resourcePath_dictionary);
        } catch (FileNotFoundException e) {
            s = null;
            String country = null;
            if (language != null) {
                logger.debug("no perfect match try on country");
                // no perfect match found, try to get template for country (without variant)
                Locale parseLocale = I18NUtil.parseLocale(language);
                logger.debug("local country :" + parseLocale.getCountry());
                logger.debug("local variant :" + parseLocale.getVariant());
                country = parseLocale.getCountry().toLowerCase();
                if (!language.equals(country)) {
                    // try on country ?
                    resourcePath_dictionary = path_dictionary[0] + "_" + country + "." + path_dictionary[1];
                    try {
                        s = getInputStream(resourcePath_dictionary);
                    } catch (FileNotFoundException e1) {
                        logger.debug("no match on country");
                    }
                }
            }
            if (s == null && classPath) {
                // file not exist so go ahead, and search for the default configuration for this country
                if (country != null) {
                    language = country;
                    logger.debug("Load default configuration from classPath");
                    // search in classPath (for default values)
                    String[] path = PROPERTIES_PATH.split("\\.");
                    String resourcePath = path[0] + "_" + language + "." + path[1];
                    s = this.getClass().getResourceAsStream(resourcePath);
                }
                if (s == null) {
                    // not found so we load default file
                    s = this.getClass().getResourceAsStream(PROPERTIES_PATH);
                    logger.debug("configuration for language :" + language + " not found, so use default language");
                }
            }
        }
        return s;
    }

    private InputStream getInputStream(String resourcePath_dictionary) throws FileNotFoundException {
        NodeRef nodeProperties = getNodeRefFromPath(resourcePath_dictionary);
        ContentReader reader = serviceRegistry.getContentService().getReader(nodeProperties,
                ContentModel.PROP_CONTENT);
        logger.debug("Properties loaded from :" + resourcePath_dictionary);
        return reader.getContentInputStream();

    }

    public List<String> getPersonList(List<String> authorities) {
        PersonService personService = serviceRegistry.getPersonService();
        List<String> recipients = new ArrayList<String>(authorities.size());
        for (String authority : authorities) {
            AuthorityType authType = AuthorityType.getAuthorityType(authority);
            if (authType.equals(AuthorityType.USER)) {
                if (personService.personExists(authority) == true) {
                    recipients.add(authority);
                }
            } else if (authType.equals(AuthorityType.GROUP)) {
                Set<String> users = serviceRegistry.getAuthorityService()
                        .getContainedAuthorities(AuthorityType.USER, authority, false);
                recipients.addAll(users);
            }
        }
        return recipients;
    }

}