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