001/*
002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Bogdan Stefanescu
018 *     Ricardo Dias
019 *     Estelle Giuly
020 */
021package org.nuxeo.ecm.automation.features;
022
023import java.util.ArrayList;
024import java.util.Collection;
025import java.util.List;
026import java.util.Set;
027
028import org.apache.commons.lang.StringEscapeUtils;
029import org.apache.commons.lang.StringUtils;
030import org.apache.commons.logging.Log;
031import org.apache.commons.logging.LogFactory;
032import org.nuxeo.ecm.automation.core.scripting.CoreFunctions;
033import org.nuxeo.ecm.automation.core.util.StringList;
034import org.nuxeo.ecm.core.api.CoreSession;
035import org.nuxeo.ecm.core.api.DocumentModel;
036import org.nuxeo.ecm.core.api.DocumentRef;
037import org.nuxeo.ecm.core.api.IdRef;
038import org.nuxeo.ecm.core.api.NuxeoPrincipal;
039import org.nuxeo.ecm.core.api.PathRef;
040import org.nuxeo.ecm.core.query.sql.NXQL;
041import org.nuxeo.ecm.core.uidgen.UIDGeneratorService;
042import org.nuxeo.ecm.core.uidgen.UIDSequencer;
043import org.nuxeo.ecm.directory.Session;
044import org.nuxeo.ecm.directory.api.DirectoryService;
045import org.nuxeo.ecm.platform.usermanager.UserManager;
046import org.nuxeo.runtime.api.Framework;
047
048/**
049 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
050 */
051public class PlatformFunctions extends CoreFunctions {
052
053    private volatile DirectoryService dirService;
054
055    private static final Log log = LogFactory.getLog(PlatformFunctions.class);
056
057    private volatile UserManager userMgr;
058
059    public UserManager getUserManager() {
060        if (userMgr == null) {
061            userMgr = Framework.getService(UserManager.class);
062        }
063        return userMgr;
064    }
065
066    public DirectoryService getDirService() {
067        if (dirService == null) {
068            dirService = Framework.getService(DirectoryService.class);
069        }
070        return dirService;
071    }
072
073    public String getVocabularyLabel(String voc, String key) {
074        try (Session session = getDirService().open(voc)) {
075            if (!session.hasEntry(key)) {
076                log.debug("Unable to find the key '" + key + "' in the vocabulary '" + voc + "'.");
077                return key;
078            }
079            DocumentModel doc = session.getEntry(key);
080            return (String) doc.getPropertyValue("label"); // no schema prefix for vocabularies
081        }
082    }
083
084    public NuxeoPrincipal getPrincipal(String username) {
085        return getUserManager().getPrincipal(username);
086    }
087
088    protected String getEmail(NuxeoPrincipal principal, String userSchemaName, String userEmailFieldName) {
089        if (principal == null) {
090            return null;
091        }
092        return (String) principal.getModel().getProperty(userSchemaName, userEmailFieldName);
093    }
094
095    public String getEmail(String username) {
096        UserManager userManager = getUserManager();
097        return getEmail(userManager.getPrincipal(username), userManager.getUserSchemaName(),
098                userManager.getUserEmailField());
099    }
100
101    public Set<NuxeoPrincipal> getPrincipalsFromGroup(String group) {
102        return getPrincipalsFromGroup(group, false);
103    }
104
105    public Set<NuxeoPrincipal> getPrincipalsFromGroup(String group, boolean ignoreGroups) {
106        PrincipalHelper ph = new PrincipalHelper(getUserManager(), null);
107        return ph.getPrincipalsFromGroup(group, !ignoreGroups);
108    }
109
110    public StringList getEmailsFromGroup(String group) {
111        return getEmailsFromGroup(group, false);
112    }
113
114    public StringList getEmailsFromGroup(String group, boolean ignoreGroups) {
115        PrincipalHelper ph = new PrincipalHelper(getUserManager(), null);
116        Set<String> emails = ph.getEmailsFromGroup(group, !ignoreGroups);
117        return new StringList(emails);
118    }
119
120    public StringList getPrincipalEmails(List<NuxeoPrincipal> principals) {
121        StringList result = new StringList(principals.size());
122        String schemaName = getUserManager().getUserSchemaName();
123        String fieldName = getUserManager().getUserEmailField();
124        for (NuxeoPrincipal principal : principals) {
125            String email = getEmail(principal, schemaName, fieldName);
126            if (!StringUtils.isEmpty(email)) {
127                result.add(email);
128            }
129        }
130        return result;
131    }
132
133    public StringList getEmails(List<String> usernames) {
134        return getEmails(usernames, false);
135    }
136
137    /**
138     * Returns user emails
139     *
140     * @param usernames list of user names
141     * @param usePrefix indicates if user resolution takes into account nuxeo prefix <b>user:</b>
142     * @since 5.5
143     */
144    public StringList getEmails(List<String> usernames, boolean usePrefix) {
145        if (usernames == null) {
146            return new StringList(0);
147        }
148        UserManager userManager = getUserManager();
149        StringList result = new StringList(usernames.size());
150        String schemaName = getUserManager().getUserSchemaName();
151        String fieldName = getUserManager().getUserEmailField();
152        for (String username : usernames) {
153            NuxeoPrincipal principal = null;
154            if (usePrefix) {
155                if (username.startsWith(NuxeoPrincipal.PREFIX)) {
156                    principal = userManager.getPrincipal(username.replace(NuxeoPrincipal.PREFIX, ""));
157                }
158            } else {
159                principal = userManager.getPrincipal(username);
160            }
161            if (principal != null) {
162                String email = getEmail(principal, schemaName, fieldName);
163                if (!StringUtils.isEmpty(email)) {
164                    result.add(email);
165                }
166            }
167        }
168        return result;
169    }
170
171    public String getNextId(final String key) {
172        return getNextId(key, "hibernateSequencer");
173    }
174
175    public String getNextId(final String key, final String sequencerName) {
176        UIDGeneratorService uidGeneratorService = Framework.getService(UIDGeneratorService.class);
177        UIDSequencer seq = uidGeneratorService.getSequencer(sequencerName);
178        return Long.toString(seq.getNextLong(key));
179    }
180
181    public static String htmlEscape(String str) {
182        return StringEscapeUtils.escapeHtml(str);
183    }
184
185    /**
186     * Escapes a string according to NXQL escaping rules.
187     * <p>
188     * The resulting string is safe to include between single quotes in a NXQL expression.
189     *
190     * @param str the input string
191     * @return the escaped string
192     * @since 6.0-HF21, 7.10
193     */
194    public static String nxqlEscape(String str) {
195        return NXQL.escapeStringInner(str);
196    }
197
198    /**
199     * Concatenate into the list given as first argument other arguments. Other arguments will be explosed if it is a
200     * list of object. ex: concatenateInto(myList, a, anotherList) with a is scalar object and anotherList is a list of
201     * object will produced myList.add(a) and the same for each object contained into the anotherList list.
202     *
203     * @param <T>
204     * @param list List of values of type A
205     * @param values Value can be instance of java.util.Collection<Object> or an array of Objects or simply a scalar
206     *            Object. If Null, the parameter is ignored
207     * @return the list that contains the list contain and value (see value description)
208     * @exception xxxxx if in values there is at least one object type not compatible with the collection list
209     */
210    @SuppressWarnings("unchecked")
211    public <T> List<T> concatenateIntoList(List<T> list, Object... values) {
212
213        if (list == null) {
214            throw new IllegalArgumentException("First parameter must not be null");
215        }
216
217        for (Object value : values) {
218            if (value == null) {
219                continue;
220            }
221
222            if (value instanceof Object[]) {
223                for (Object subValue : (Object[]) value) {
224                    if (subValue != null) {
225                        list.add((T) subValue);
226                    }
227                }
228                continue;
229            }
230
231            if (value instanceof Collection) {
232                for (Object subValue : (Collection<Object>) value) {
233                    if (subValue != null) {
234                        list.add((T) subValue);
235                    }
236                }
237                continue;
238            }
239
240            list.add((T) value);
241
242        }
243        return list;
244    }
245
246    /**
247     * Idem than concatenateInto except that a new list is created.
248     */
249    public <T> List<T> concatenateValuesAsNewList(Object... values) {
250
251        List<T> result = new ArrayList<T>();
252        return concatenateIntoList(result, values);
253    }
254
255    /**
256     * Checks if a document with the supplied id (or path) exists.
257     * @param session The CoreSession to obtain the document
258     * @param idOrPath The document Id or path
259     * @return true if the document exists, or false otherwise
260     */
261    public boolean documentExists(CoreSession session, String idOrPath) {
262        DocumentRef documentRef = idOrPath.startsWith("/") ? new PathRef(idOrPath) : new IdRef(idOrPath);
263        return session.exists(documentRef);
264    }
265
266}