001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
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, String className, long classPK, String classUuid,
152                            long classTypeId, long[] categoryIds, String[] tagNames,
153                            boolean visible, Date startDate, Date endDate, Date publishDate,
154                            Date expirationDate, String mimeType, String title,
155                            String description, String summary, String url, String layoutUuid,
156                            int height, int width, Integer priority, boolean sync)
157                    throws PortalException, SystemException {
158    
159                    AssetEntryPermission.check(
160                            getPermissionChecker(), className, classPK, ActionKeys.UPDATE);
161    
162                    return assetEntryLocalService.updateEntry(
163                            getUserId(), groupId, className, classPK, classUuid, classTypeId,
164                            categoryIds, tagNames, visible, startDate, endDate, publishDate,
165                            expirationDate, mimeType, title, description, summary, url,
166                            layoutUuid, height, width, priority, sync);
167            }
168    
169            protected AssetEntryQuery buildFilteredEntryQuery(
170                            AssetEntryQuery entryQuery)
171                    throws PortalException, SystemException {
172    
173                    // Return an entry query with only the category ids and tag ids that the
174                    // user has access to
175    
176                    AssetEntryQuery filteredEntryQuery = new AssetEntryQuery(entryQuery);
177    
178                    filteredEntryQuery.setAllCategoryIds(
179                            filterCategoryIds(entryQuery.getAllCategoryIds()));
180                    filteredEntryQuery.setAllTagIdsArray(
181                            filterTagIdsArray(entryQuery.getAllTagIdsArray()));
182                    filteredEntryQuery.setAnyCategoryIds(
183                            filterCategoryIds(entryQuery.getAnyCategoryIds()));
184                    filteredEntryQuery.setAnyTagIds(
185                            filterTagIds(entryQuery.getAnyTagIds()));
186    
187                    return filteredEntryQuery;
188            }
189    
190            protected long[] filterCategoryIds(long[] categoryIds)
191                    throws PortalException, SystemException {
192    
193                    List<Long> viewableCategoryIds = new ArrayList<Long>();
194    
195                    for (long categoryId : categoryIds) {
196                            if (AssetCategoryPermission.contains(
197                                            getPermissionChecker(), categoryId, ActionKeys.VIEW)) {
198    
199                                    viewableCategoryIds.add(categoryId);
200                            }
201                    }
202    
203                    return ArrayUtil.toArray(
204                            viewableCategoryIds.toArray(new Long[viewableCategoryIds.size()]));
205            }
206    
207            protected Object[] filterEntryQuery(
208                            AssetEntryQuery entryQuery, boolean returnEntriesCountOnly)
209                    throws PortalException, SystemException {
210    
211                    ThreadLocalCache<Object[]> threadLocalCache =
212                            ThreadLocalCacheManager.getThreadLocalCache(
213                                    Lifecycle.REQUEST, AssetEntryServiceImpl.class.getName());
214    
215                    String key = entryQuery.toString();
216    
217                    key = key.concat(StringPool.POUND).concat(
218                            Boolean.toString(returnEntriesCountOnly));
219    
220                    Object[] results = threadLocalCache.get(key);
221    
222                    if (results != null) {
223                            return results;
224                    }
225    
226                    if (returnEntriesCountOnly && !entryQuery.isEnablePermissions()) {
227                            int entriesCount = assetEntryLocalService.getEntriesCount(
228                                    entryQuery);
229    
230                            results = new Object[] {null, entriesCount};
231    
232                            threadLocalCache.put(key, results);
233    
234                            return results;
235                    }
236    
237                    int end = entryQuery.getEnd();
238                    int start = entryQuery.getStart();
239    
240                    if (entryQuery.isEnablePermissions()) {
241                            entryQuery.setEnd(end + PropsValues.ASSET_FILTER_SEARCH_LIMIT);
242                            entryQuery.setStart(0);
243                    }
244    
245                    List<AssetEntry> entries = assetEntryLocalService.getEntries(
246                            entryQuery);
247    
248                    List<AssetEntry> filteredEntries = null;
249                    int filteredEntriesCount = 0;
250    
251                    if (entryQuery.isEnablePermissions()) {
252                            PermissionChecker permissionChecker = getPermissionChecker();
253    
254                            filteredEntries = new ArrayList<AssetEntry>();
255    
256                            for (AssetEntry entry : entries) {
257                                    String className = entry.getClassName();
258                                    long classPK = entry.getClassPK();
259    
260                                    AssetRendererFactory assetRendererFactory =
261                                            AssetRendererFactoryRegistryUtil.
262                                                    getAssetRendererFactoryByClassName(className);
263    
264                                    try {
265                                            if (assetRendererFactory.hasPermission(
266                                                            permissionChecker, classPK, ActionKeys.VIEW)) {
267    
268                                                    filteredEntries.add(entry);
269                                            }
270                                    }
271                                    catch (Exception e) {
272                                    }
273    
274                                    if ((end != QueryUtil.ALL_POS) &&
275                                            (filteredEntries.size() > end)) {
276    
277                                            break;
278                                    }
279                            }
280    
281                            filteredEntriesCount = filteredEntries.size();
282    
283                            if ((end != QueryUtil.ALL_POS) && (start != QueryUtil.ALL_POS)) {
284                                    if (end > filteredEntriesCount) {
285                                            end = filteredEntriesCount;
286                                    }
287    
288                                    if (start > filteredEntriesCount) {
289                                            start = filteredEntriesCount;
290                                    }
291    
292                                    filteredEntries = filteredEntries.subList(start, end);
293                            }
294    
295                            entryQuery.setEnd(end);
296                            entryQuery.setStart(start);
297                    }
298                    else {
299                            filteredEntries = entries;
300                            filteredEntriesCount = filteredEntries.size();
301                    }
302    
303                    results = new Object[] {filteredEntries, filteredEntriesCount};
304    
305                    threadLocalCache.put(key, results);
306    
307                    return results;
308            }
309    
310            protected long[] filterTagIds(long[] tagIds)
311                    throws PortalException, SystemException {
312    
313                    List<Long> viewableTagIds = new ArrayList<Long>();
314    
315                    for (long tagId : tagIds) {
316                            if (AssetTagPermission.contains(
317                                            getPermissionChecker(), tagId, ActionKeys.VIEW)) {
318    
319                                    viewableTagIds.add(tagId);
320                            }
321                    }
322    
323                    return ArrayUtil.toArray(
324                            viewableTagIds.toArray(new Long[viewableTagIds.size()]));
325            }
326    
327            protected long[][] filterTagIdsArray(long[][] tagIdsArray)
328                    throws PortalException, SystemException {
329    
330                    List<long[]> viewableTagIdsArray = new ArrayList<long[]>();
331    
332                    for (int i = 0; i< tagIdsArray.length; i++) {
333                            long tagIds[] = tagIdsArray[i];
334    
335                            List<Long> viewableTagIds = new ArrayList<Long>();
336    
337                            for (long tagId : tagIds) {
338                                    if (AssetTagPermission.contains(
339                                                    getPermissionChecker(), tagId, ActionKeys.VIEW)) {
340    
341                                            viewableTagIds.add(tagId);
342                                    }
343                            }
344    
345                            viewableTagIdsArray.add(
346                                    ArrayUtil.toArray(
347                                            viewableTagIds.toArray(new Long[viewableTagIds.size()])));
348                    }
349    
350                    return viewableTagIdsArray.toArray(
351                            new long[viewableTagIdsArray.size()][]);
352            }
353    
354            protected boolean hasEntryQueryResults(
355                    AssetEntryQuery originalEntryQuery,
356                    AssetEntryQuery filteredEntryQuery) {
357    
358                    if (originalEntryQuery.getAllCategoryIds().length >
359                                    filteredEntryQuery.getAllCategoryIds().length) {
360    
361                            // No results will be available if the user must have access to all
362                            // category ids, but the user has access to fewer category ids in
363                            // the filtered entry query than what was specified in the original
364                            // entry query
365    
366                            return true;
367                    }
368    
369                    if (originalEntryQuery.getAllTagIds().length >
370                                    filteredEntryQuery.getAllTagIds().length) {
371    
372                            // No results will be available if the user must have access to all
373                            // tag ids, but the user has access to fewer tag ids in the filtered
374                            // entry query than what was specified in the original entry query
375    
376                            return true;
377                    }
378    
379                    if ((originalEntryQuery.getAnyCategoryIds().length > 0) &&
380                            (filteredEntryQuery.getAnyCategoryIds().length == 0)) {
381    
382                            // No results will be available if the original entry query
383                            // specified at least one category id, but the filtered entry query
384                            // shows that the user does not have access to any category ids
385    
386                            return true;
387                    }
388    
389                    if ((originalEntryQuery.getAnyTagIds().length > 0) &&
390                            (filteredEntryQuery.getAnyTagIds().length == 0)) {
391    
392                            // No results will be available if the original entry query
393                            // specified at least one tag id, but the filtered entry query
394                            // shows that the user does not have access to any tag ids
395    
396                            return true;
397                    }
398    
399                    return false;
400            }
401    
402            private static Log _log = LogFactoryUtil.getLog(
403                    AssetEntryServiceImpl.class);
404    
405    }