001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.asset.service.impl;
016    
017    import com.liferay.portal.kernel.cache.Lifecycle;
018    import com.liferay.portal.kernel.cache.ThreadLocalCache;
019    import com.liferay.portal.kernel.cache.ThreadLocalCacheManager;
020    import com.liferay.portal.kernel.dao.orm.QueryUtil;
021    import com.liferay.portal.kernel.exception.PortalException;
022    import com.liferay.portal.kernel.exception.SystemException;
023    import com.liferay.portal.kernel.log.Log;
024    import com.liferay.portal.kernel.log.LogFactoryUtil;
025    import com.liferay.portal.kernel.util.ArrayUtil;
026    import com.liferay.portal.kernel.util.StringPool;
027    import com.liferay.portal.model.User;
028    import com.liferay.portal.security.permission.ActionKeys;
029    import com.liferay.portal.security.permission.PermissionChecker;
030    import com.liferay.portal.util.PropsValues;
031    import com.liferay.portlet.asset.AssetRendererFactoryRegistryUtil;
032    import com.liferay.portlet.asset.model.AssetEntry;
033    import com.liferay.portlet.asset.model.AssetRendererFactory;
034    import com.liferay.portlet.asset.service.base.AssetEntryServiceBaseImpl;
035    import com.liferay.portlet.asset.service.permission.AssetCategoryPermission;
036    import com.liferay.portlet.asset.service.permission.AssetEntryPermission;
037    import com.liferay.portlet.asset.service.permission.AssetTagPermission;
038    import com.liferay.portlet.asset.service.persistence.AssetEntryQuery;
039    import com.liferay.portlet.social.model.SocialActivityConstants;
040    
041    import java.util.ArrayList;
042    import java.util.Date;
043    import java.util.List;
044    
045    /**
046     * @author Brian Wing Shun Chan
047     * @author Jorge Ferrer
048     * @author Bruno Farache
049     * @author Raymond Augé
050     */
051    public class AssetEntryServiceImpl extends AssetEntryServiceBaseImpl {
052    
053            public List<AssetEntry> getCompanyEntries(
054                            long companyId, int start, int end)
055                    throws SystemException {
056    
057                    List<AssetEntry> entries = new ArrayList<AssetEntry>();
058    
059                    List<AssetEntry> companyEntries =
060                            assetEntryLocalService.getCompanyEntries(companyId, start, end);
061    
062                    for (AssetEntry entry : companyEntries) {
063                            try {
064                                    if (AssetEntryPermission.contains(
065                                                    getPermissionChecker(), entry, ActionKeys.VIEW)) {
066    
067                                            entries.add(entry);
068                                    }
069                            }
070                            catch (PortalException pe) {
071                                    if (_log.isWarnEnabled()) {
072                                            _log.warn(pe, pe);
073                                    }
074                            }
075                    }
076    
077                    return entries;
078            }
079    
080            public int getCompanyEntriesCount(long companyId) throws SystemException {
081                    return assetEntryLocalService.getCompanyEntriesCount(companyId);
082            }
083    
084            public List<AssetEntry> getEntries(AssetEntryQuery entryQuery)
085                    throws PortalException, SystemException {
086    
087                    AssetEntryQuery filteredEntryQuery = buildFilteredEntryQuery(
088                            entryQuery);
089    
090                    if (hasEntryQueryResults(entryQuery, filteredEntryQuery)) {
091                            return new ArrayList<AssetEntry>();
092                    }
093    
094                    Object[] results = filterEntryQuery(filteredEntryQuery, false);
095    
096                    return (List<AssetEntry>)results[0];
097            }
098    
099            public int getEntriesCount(AssetEntryQuery entryQuery)
100                    throws PortalException, SystemException {
101    
102                    AssetEntryQuery filteredEntryQuery = buildFilteredEntryQuery(
103                            entryQuery);
104    
105                    if (hasEntryQueryResults(entryQuery, filteredEntryQuery)) {
106                            return 0;
107                    }
108    
109                    Object[] results = filterEntryQuery(filteredEntryQuery, true);
110    
111                    return (Integer)results[1];
112            }
113    
114            public AssetEntry getEntry(long entryId)
115                    throws PortalException, SystemException {
116    
117                    AssetEntryPermission.check(
118                            getPermissionChecker(), entryId, ActionKeys.VIEW);
119    
120                    return assetEntryLocalService.getEntry(entryId);
121            }
122    
123            public AssetEntry incrementViewCounter(String className, long classPK)
124                    throws PortalException, SystemException {
125    
126                    if (!PropsValues.ASSET_ENTRY_INCREMENT_VIEW_COUNTER_ENABLED) {
127                            return null;
128                    }
129    
130                    AssetEntryPermission.check(
131                            getPermissionChecker(), className, classPK, ActionKeys.VIEW);
132    
133                    User user = getGuestOrUser();
134    
135                    assetEntryLocalService.incrementViewCounter(
136                            user.getUserId(), className, classPK, 1);
137    
138                    AssetEntry assetEntry = assetEntryLocalService.getEntry(
139                            className, classPK);
140    
141                    if (!user.isDefaultUser()) {
142                            socialActivityLocalService.addActivity(
143                                    user.getUserId(), assetEntry.getGroupId(), className, classPK,
144                                    SocialActivityConstants.TYPE_VIEW, StringPool.BLANK, 0);
145                    }
146    
147                    return assetEntry;
148            }
149    
150            public AssetEntry updateEntry(
151                            long groupId, Date createDate, Date modifiedDate, String className,
152                            long classPK, String classUuid, long classTypeId,
153                            long[] categoryIds, String[] tagNames, boolean visible,
154                            Date startDate, Date endDate, Date expirationDate, String mimeType,
155                            String title, String description, String summary, String url,
156                            String layoutUuid, int height, int width, Integer priority,
157                            boolean sync)
158                    throws PortalException, SystemException {
159    
160                    AssetEntryPermission.check(
161                            getPermissionChecker(), className, classPK, ActionKeys.UPDATE);
162    
163                    return assetEntryLocalService.updateEntry(
164                            getUserId(), groupId, createDate, modifiedDate, className, classPK,
165                            classUuid, classTypeId, categoryIds, tagNames, visible, startDate,
166                            endDate, expirationDate, mimeType, title, description, summary, url,
167                            layoutUuid, height, width, priority, sync);
168            }
169    
170            /**
171             * @deprecated {@link #updateEntry(long, String, long, String, long, long[],
172             *             String[], boolean, Date, Date, Date, String, String, String,
173             *             String, String, String, int, int, Integer, boolean)}
174             */
175            public AssetEntry updateEntry(
176                            long groupId, String className, long classPK, String classUuid,
177                            long classTypeId, long[] categoryIds, String[] tagNames,
178                            boolean visible, Date startDate, Date endDate, Date publishDate,
179                            Date expirationDate, String mimeType, String title,
180                            String description, String summary, String url, String layoutUuid,
181                            int height, int width, Integer priority, boolean sync)
182                    throws PortalException, SystemException {
183    
184                    AssetEntryPermission.check(
185                            getPermissionChecker(), className, classPK, ActionKeys.UPDATE);
186    
187                    return assetEntryLocalService.updateEntry(
188                            getUserId(), groupId, className, classPK, classUuid, classTypeId,
189                            categoryIds, tagNames, visible, startDate, endDate, expirationDate,
190                            mimeType, title, description, summary, url, layoutUuid, height,
191                            width, priority, sync);
192            }
193    
194            /**
195             * @deprecated {@link #updateEntry(long, Date, Date. String, long, String,
196             *             long, long[], String[], boolean, Date, Date, Date, String,
197             *             String, String, String, String, String, int, int, Integer,
198             *             boolean)}
199             */
200            public AssetEntry updateEntry(
201                            long groupId, String className, long classPK, String classUuid,
202                            long classTypeId, long[] categoryIds, String[] tagNames,
203                            boolean visible, Date startDate, Date endDate, Date expirationDate,
204                            String mimeType, String title, String description, String summary,
205                            String url, String layoutUuid, int height, int width,
206                            Integer priority, boolean sync)
207                    throws PortalException, SystemException {
208    
209                    return assetEntryLocalService.updateEntry(
210                            getUserId(), groupId, null, null, className, classPK, classUuid,
211                            classTypeId, categoryIds, tagNames, visible, startDate, endDate,
212                            expirationDate, mimeType, title, description, summary, url,
213                            layoutUuid, height, width, priority, sync);
214            }
215    
216            protected AssetEntryQuery buildFilteredEntryQuery(
217                            AssetEntryQuery entryQuery)
218                    throws PortalException, SystemException {
219    
220                    // Return an entry query with only the category ids and tag ids that the
221                    // user has access to
222    
223                    AssetEntryQuery filteredEntryQuery = new AssetEntryQuery(entryQuery);
224    
225                    filteredEntryQuery.setAllCategoryIds(
226                            filterCategoryIds(entryQuery.getAllCategoryIds()));
227                    filteredEntryQuery.setAllTagIdsArray(
228                            filterTagIdsArray(entryQuery.getAllTagIdsArray()));
229                    filteredEntryQuery.setAnyCategoryIds(
230                            filterCategoryIds(entryQuery.getAnyCategoryIds()));
231                    filteredEntryQuery.setAnyTagIds(
232                            filterTagIds(entryQuery.getAnyTagIds()));
233    
234                    return filteredEntryQuery;
235            }
236    
237            protected long[] filterCategoryIds(long[] categoryIds)
238                    throws PortalException, SystemException {
239    
240                    List<Long> viewableCategoryIds = new ArrayList<Long>();
241    
242                    for (long categoryId : categoryIds) {
243                            if (AssetCategoryPermission.contains(
244                                            getPermissionChecker(), categoryId, ActionKeys.VIEW)) {
245    
246                                    viewableCategoryIds.add(categoryId);
247                            }
248                    }
249    
250                    return ArrayUtil.toArray(
251                            viewableCategoryIds.toArray(new Long[viewableCategoryIds.size()]));
252            }
253    
254            protected Object[] filterEntryQuery(
255                            AssetEntryQuery entryQuery, boolean returnEntriesCountOnly)
256                    throws PortalException, SystemException {
257    
258                    ThreadLocalCache<Object[]> threadLocalCache =
259                            ThreadLocalCacheManager.getThreadLocalCache(
260                                    Lifecycle.REQUEST, AssetEntryServiceImpl.class.getName());
261    
262                    String key = entryQuery.toString();
263    
264                    key = key.concat(StringPool.POUND).concat(
265                            Boolean.toString(returnEntriesCountOnly));
266    
267                    Object[] results = threadLocalCache.get(key);
268    
269                    if (results != null) {
270                            return results;
271                    }
272    
273                    if (returnEntriesCountOnly && !entryQuery.isEnablePermissions()) {
274                            int entriesCount = assetEntryLocalService.getEntriesCount(
275                                    entryQuery);
276    
277                            results = new Object[] {null, entriesCount};
278    
279                            threadLocalCache.put(key, results);
280    
281                            return results;
282                    }
283    
284                    int end = entryQuery.getEnd();
285                    int start = entryQuery.getStart();
286    
287                    if (entryQuery.isEnablePermissions()) {
288                            entryQuery.setEnd(end + PropsValues.ASSET_FILTER_SEARCH_LIMIT);
289                            entryQuery.setStart(0);
290                    }
291    
292                    List<AssetEntry> entries = assetEntryLocalService.getEntries(
293                            entryQuery);
294    
295                    List<AssetEntry> filteredEntries = null;
296                    int filteredEntriesCount = 0;
297    
298                    if (entryQuery.isEnablePermissions()) {
299                            PermissionChecker permissionChecker = getPermissionChecker();
300    
301                            filteredEntries = new ArrayList<AssetEntry>();
302    
303                            for (AssetEntry entry : entries) {
304                                    String className = entry.getClassName();
305                                    long classPK = entry.getClassPK();
306    
307                                    AssetRendererFactory assetRendererFactory =
308                                            AssetRendererFactoryRegistryUtil.
309                                                    getAssetRendererFactoryByClassName(className);
310    
311                                    try {
312                                            if (assetRendererFactory.hasPermission(
313                                                            permissionChecker, classPK, ActionKeys.VIEW)) {
314    
315                                                    filteredEntries.add(entry);
316                                            }
317                                    }
318                                    catch (Exception e) {
319                                    }
320    
321                                    if ((end != QueryUtil.ALL_POS) &&
322                                            (filteredEntries.size() > end)) {
323    
324                                            break;
325                                    }
326                            }
327    
328                            filteredEntriesCount = filteredEntries.size();
329    
330                            if ((end != QueryUtil.ALL_POS) && (start != QueryUtil.ALL_POS)) {
331                                    if (end > filteredEntriesCount) {
332                                            end = filteredEntriesCount;
333                                    }
334    
335                                    if (start > filteredEntriesCount) {
336                                            start = filteredEntriesCount;
337                                    }
338    
339                                    filteredEntries = filteredEntries.subList(start, end);
340                            }
341    
342                            entryQuery.setEnd(end);
343                            entryQuery.setStart(start);
344                    }
345                    else {
346                            filteredEntries = entries;
347                            filteredEntriesCount = filteredEntries.size();
348                    }
349    
350                    results = new Object[] {filteredEntries, filteredEntriesCount};
351    
352                    threadLocalCache.put(key, results);
353    
354                    return results;
355            }
356    
357            protected long[] filterTagIds(long[] tagIds)
358                    throws PortalException, SystemException {
359    
360                    List<Long> viewableTagIds = new ArrayList<Long>();
361    
362                    for (long tagId : tagIds) {
363                            if (AssetTagPermission.contains(
364                                            getPermissionChecker(), tagId, ActionKeys.VIEW)) {
365    
366                                    viewableTagIds.add(tagId);
367                            }
368                    }
369    
370                    return ArrayUtil.toArray(
371                            viewableTagIds.toArray(new Long[viewableTagIds.size()]));
372            }
373    
374            protected long[][] filterTagIdsArray(long[][] tagIdsArray)
375                    throws PortalException, SystemException {
376    
377                    List<long[]> viewableTagIdsArray = new ArrayList<long[]>();
378    
379                    for (int i = 0; i< tagIdsArray.length; i++) {
380                            long[] tagIds = tagIdsArray[i];
381    
382                            List<Long> viewableTagIds = new ArrayList<Long>();
383    
384                            for (long tagId : tagIds) {
385                                    if (AssetTagPermission.contains(
386                                                    getPermissionChecker(), tagId, ActionKeys.VIEW)) {
387    
388                                            viewableTagIds.add(tagId);
389                                    }
390                            }
391    
392                            viewableTagIdsArray.add(
393                                    ArrayUtil.toArray(
394                                            viewableTagIds.toArray(new Long[viewableTagIds.size()])));
395                    }
396    
397                    return viewableTagIdsArray.toArray(
398                            new long[viewableTagIdsArray.size()][]);
399            }
400    
401            protected boolean hasEntryQueryResults(
402                    AssetEntryQuery originalEntryQuery,
403                    AssetEntryQuery filteredEntryQuery) {
404    
405                    if (originalEntryQuery.getAllCategoryIds().length >
406                                    filteredEntryQuery.getAllCategoryIds().length) {
407    
408                            // No results will be available if the user must have access to all
409                            // category ids, but the user has access to fewer category ids in
410                            // the filtered entry query than what was specified in the original
411                            // entry query
412    
413                            return true;
414                    }
415    
416                    if (originalEntryQuery.getAllTagIds().length >
417                                    filteredEntryQuery.getAllTagIds().length) {
418    
419                            // No results will be available if the user must have access to all
420                            // tag ids, but the user has access to fewer tag ids in the filtered
421                            // entry query than what was specified in the original entry query
422    
423                            return true;
424                    }
425    
426                    if ((originalEntryQuery.getAnyCategoryIds().length > 0) &&
427                            (filteredEntryQuery.getAnyCategoryIds().length == 0)) {
428    
429                            // No results will be available if the original entry query
430                            // specified at least one category id, but the filtered entry query
431                            // shows that the user does not have access to any category ids
432    
433                            return true;
434                    }
435    
436                    if ((originalEntryQuery.getAnyTagIds().length > 0) &&
437                            (filteredEntryQuery.getAnyTagIds().length == 0)) {
438    
439                            // No results will be available if the original entry query
440                            // specified at least one tag id, but the filtered entry query
441                            // shows that the user does not have access to any tag ids
442    
443                            return true;
444                    }
445    
446                    return false;
447            }
448    
449            private static Log _log = LogFactoryUtil.getLog(
450                    AssetEntryServiceImpl.class);
451    
452    }