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.util.ArrayUtil;
024    import com.liferay.portal.kernel.util.StringPool;
025    import com.liferay.portal.model.User;
026    import com.liferay.portal.security.permission.ActionKeys;
027    import com.liferay.portal.security.permission.PermissionChecker;
028    import com.liferay.portal.util.PropsValues;
029    import com.liferay.portlet.asset.AssetRendererFactoryRegistryUtil;
030    import com.liferay.portlet.asset.model.AssetEntry;
031    import com.liferay.portlet.asset.model.AssetEntryDisplay;
032    import com.liferay.portlet.asset.model.AssetRendererFactory;
033    import com.liferay.portlet.asset.service.base.AssetEntryServiceBaseImpl;
034    import com.liferay.portlet.asset.service.permission.AssetCategoryPermission;
035    import com.liferay.portlet.asset.service.permission.AssetTagPermission;
036    import com.liferay.portlet.asset.service.persistence.AssetEntryQuery;
037    import com.liferay.portlet.social.model.SocialActivityConstants;
038    
039    import java.util.ArrayList;
040    import java.util.Date;
041    import java.util.List;
042    
043    /**
044     * @author Brian Wing Shun Chan
045     * @author Jorge Ferrer
046     * @author Bruno Farache
047     * @author Raymond Augé
048     */
049    public class AssetEntryServiceImpl extends AssetEntryServiceBaseImpl {
050    
051            public List<AssetEntry> getCompanyEntries(
052                            long companyId, int start, int end)
053                    throws SystemException {
054    
055                    return assetEntryLocalService.getCompanyEntries(companyId, start, end);
056            }
057    
058            public int getCompanyEntriesCount(long companyId) throws SystemException {
059                    return assetEntryLocalService.getCompanyEntriesCount(companyId);
060            }
061    
062            public AssetEntryDisplay[] getCompanyEntryDisplays(
063                            long companyId, int start, int end, String languageId)
064                    throws SystemException {
065    
066                    return assetEntryLocalService.getCompanyEntryDisplays(
067                            companyId, start, end, languageId);
068            }
069    
070            public List<AssetEntry> getEntries(AssetEntryQuery entryQuery)
071                    throws PortalException, SystemException {
072    
073                    AssetEntryQuery filteredEntryQuery = buildFilteredEntryQuery(
074                            entryQuery);
075    
076                    if (hasEntryQueryResults(entryQuery, filteredEntryQuery)) {
077                            return new ArrayList<AssetEntry>();
078                    }
079    
080                    Object[] results = filterEntryQuery(filteredEntryQuery);
081    
082                    return (List<AssetEntry>)results[0];
083            }
084    
085            public int getEntriesCount(AssetEntryQuery entryQuery)
086                    throws PortalException, SystemException {
087    
088                    AssetEntryQuery filteredEntryQuery = buildFilteredEntryQuery(
089                            entryQuery);
090    
091                    if (hasEntryQueryResults(entryQuery, filteredEntryQuery)) {
092                            return 0;
093                    }
094    
095                    Object[] results = filterEntryQuery(filteredEntryQuery);
096    
097                    return (Integer)results[1];
098            }
099    
100            public AssetEntry getEntry(long entryId)
101                    throws PortalException, SystemException {
102    
103                    return assetEntryLocalService.getEntry(entryId);
104            }
105    
106            public AssetEntry incrementViewCounter(String className, long classPK)
107                    throws PortalException, SystemException {
108    
109                    if (!PropsValues.ASSET_ENTRY_INCREMENT_VIEW_COUNTER_ENABLED) {
110                            return null;
111                    }
112    
113                    User user = getGuestOrUser();
114    
115                    assetEntryLocalService.incrementViewCounter(
116                            user.getUserId(), className, classPK, 1);
117    
118                    AssetEntry assetEntry = assetEntryLocalService.getEntry(
119                            className, classPK);
120    
121                    if (!user.isDefaultUser()) {
122                            socialActivityLocalService.addActivity(
123                                    user.getUserId(), assetEntry.getGroupId(), className, classPK,
124                                    SocialActivityConstants.TYPE_VIEW, StringPool.BLANK, 0);
125                    }
126    
127                    return assetEntry;
128            }
129    
130            public AssetEntryDisplay[] searchEntryDisplays(
131                            long companyId, long[] groupIds, String className, String keywords,
132                            String languageId, int start, int end)
133                    throws SystemException {
134    
135                    return assetEntryLocalService.searchEntryDisplays(
136                            companyId, groupIds, className, keywords, languageId, start, end);
137            }
138    
139            public int searchEntryDisplaysCount(
140                            long companyId, long[] groupIds, String className, String keywords,
141                            String languageId)
142                    throws SystemException {
143    
144                    return assetEntryLocalService.searchEntryDisplaysCount(
145                            companyId, groupIds, className, keywords, languageId);
146            }
147    
148            public AssetEntry updateEntry(
149                            long groupId, String className, long classPK, String classUuid,
150                            long classTypeId, long[] categoryIds, String[] tagNames,
151                            boolean visible, Date startDate, Date endDate, Date publishDate,
152                            Date expirationDate, String mimeType, String title,
153                            String description, String summary, String url, String layoutUuid,
154                            int height, int width, Integer priority, boolean sync)
155                    throws PortalException, SystemException {
156    
157                    return assetEntryLocalService.updateEntry(
158                            getUserId(), groupId, className, classPK, classUuid, classTypeId,
159                            categoryIds, tagNames, visible, startDate, endDate, publishDate,
160                            expirationDate, mimeType, title, description, summary, url,
161                            layoutUuid, height, width, priority, sync);
162            }
163    
164            protected AssetEntryQuery buildFilteredEntryQuery(
165                            AssetEntryQuery entryQuery)
166                    throws PortalException, SystemException {
167    
168                    // Return an entry query with only the category ids and tag ids that the
169                    // user has access to
170    
171                    AssetEntryQuery filteredEntryQuery = new AssetEntryQuery(entryQuery);
172    
173                    filteredEntryQuery.setAllCategoryIds(
174                            filterCategoryIds(entryQuery.getAllCategoryIds()));
175                    filteredEntryQuery.setAllTagIds(
176                            filterTagIds(entryQuery.getAllTagIds()));
177                    filteredEntryQuery.setAnyCategoryIds(
178                            filterCategoryIds(entryQuery.getAnyCategoryIds()));
179                    filteredEntryQuery.setAnyTagIds(
180                            filterTagIds(entryQuery.getAnyTagIds()));
181    
182                    return filteredEntryQuery;
183            }
184    
185            protected long[] filterCategoryIds(long[] categoryIds)
186                    throws PortalException, SystemException {
187    
188                    List<Long> viewableCategoryIds = new ArrayList<Long>();
189    
190                    for (long categoryId : categoryIds) {
191                            if (AssetCategoryPermission.contains(
192                                            getPermissionChecker(), categoryId, ActionKeys.VIEW)) {
193    
194                                    viewableCategoryIds.add(categoryId);
195                            }
196                    }
197    
198                    return ArrayUtil.toArray(
199                            viewableCategoryIds.toArray(new Long[viewableCategoryIds.size()]));
200            }
201    
202            protected Object[] filterEntryQuery(AssetEntryQuery entryQuery)
203                    throws PortalException, SystemException {
204    
205                    ThreadLocalCache<Object[]> threadLocalCache =
206                            ThreadLocalCacheManager.getThreadLocalCache(
207                                    Lifecycle.REQUEST, AssetEntryServiceImpl.class.getName());
208    
209                    String key = entryQuery.toString();
210    
211                    Object[] results = threadLocalCache.get(key);
212    
213                    if (results != null) {
214                            return results;
215                    }
216    
217                    int end = entryQuery.getEnd();
218                    int start = entryQuery.getStart();
219    
220                    if (entryQuery.isEnablePermissions()) {
221                            entryQuery.setEnd(end + PropsValues.ASSET_FILTER_SEARCH_LIMIT);
222                            entryQuery.setStart(0);
223                    }
224    
225                    List<AssetEntry> entries = assetEntryLocalService.getEntries(
226                            entryQuery);
227    
228                    List<AssetEntry> filteredEntries = null;
229                    int filteredEntriesCount = 0;
230    
231                    if (entryQuery.isEnablePermissions()) {
232                            PermissionChecker permissionChecker = getPermissionChecker();
233    
234                            filteredEntries = new ArrayList<AssetEntry>();
235    
236                            for (AssetEntry entry : entries) {
237                                    String className = entry.getClassName();
238                                    long classPK = entry.getClassPK();
239    
240                                    AssetRendererFactory assetRendererFactory =
241                                            AssetRendererFactoryRegistryUtil.
242                                                    getAssetRendererFactoryByClassName(className);
243    
244                                    try {
245                                            if (assetRendererFactory.hasPermission(
246                                                            permissionChecker, classPK, ActionKeys.VIEW)) {
247    
248                                                    filteredEntries.add(entry);
249                                            }
250                                    }
251                                    catch (Exception e) {
252                                    }
253    
254                                    if (filteredEntries.size() > end) {
255                                            break;
256                                    }
257                            }
258    
259                            filteredEntriesCount = filteredEntries.size();
260    
261                            if ((end != QueryUtil.ALL_POS) && (start != QueryUtil.ALL_POS)) {
262                                    if (end > filteredEntriesCount) {
263                                            end = filteredEntriesCount;
264                                    }
265    
266                                    if (start > filteredEntriesCount) {
267                                            start = filteredEntriesCount;
268                                    }
269    
270                                    filteredEntries = filteredEntries.subList(start, end);
271                            }
272    
273                            entryQuery.setEnd(end);
274                            entryQuery.setStart(start);
275                    }
276                    else {
277                            filteredEntries = entries;
278                            filteredEntriesCount = entries.size();
279                    }
280    
281                    results = new Object[] {filteredEntries, filteredEntriesCount};
282    
283                    threadLocalCache.put(key, results);
284    
285                    return results;
286            }
287    
288            protected long[] filterTagIds(long[] tagIds)
289                    throws PortalException, SystemException {
290    
291                    List<Long> viewableTagIds = new ArrayList<Long>();
292    
293                    for (long tagId : tagIds) {
294                            if (AssetTagPermission.contains(
295                                            getPermissionChecker(), tagId, ActionKeys.VIEW)) {
296    
297                                    viewableTagIds.add(tagId);
298                            }
299                    }
300    
301                    return ArrayUtil.toArray(
302                            viewableTagIds.toArray(new Long[viewableTagIds.size()]));
303            }
304    
305            protected boolean hasEntryQueryResults(
306                    AssetEntryQuery originalEntryQuery,
307                    AssetEntryQuery filteredEntryQuery) {
308    
309                    if (originalEntryQuery.getAllCategoryIds().length >
310                                    filteredEntryQuery.getAllCategoryIds().length) {
311    
312                            // No results will be available if the user must have access to all
313                            // category ids, but the user has access to fewer category ids in
314                            // the filtered entry query than what was specified in the original
315                            // entry query
316    
317                            return true;
318                    }
319    
320                    if (originalEntryQuery.getAllTagIds().length >
321                                    filteredEntryQuery.getAllTagIds().length) {
322    
323                            // No results will be available if the user must have access to all
324                            // tag ids, but the user has access to fewer tag ids in the filtered
325                            // entry query than what was specified in the original entry query
326    
327                            return true;
328                    }
329    
330                    if ((originalEntryQuery.getAnyCategoryIds().length > 0) &&
331                            (filteredEntryQuery.getAnyCategoryIds().length == 0)) {
332    
333                            // No results will be available if the original entry query
334                            // specified at least one category id, but the filtered entry query
335                            // shows that the user does not have access to any category ids
336    
337                            return true;
338                    }
339    
340                    if ((originalEntryQuery.getAnyTagIds().length > 0) &&
341                            (filteredEntryQuery.getAnyTagIds().length == 0)) {
342    
343                            // No results will be available if the original entry query
344                            // specified at least one tag id, but the filtered entry query
345                            // shows that the user does not have access to any tag ids
346    
347                            return true;
348                    }
349    
350                    return false;
351            }
352    
353    }