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