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