001    /**
002     * Copyright (c) 2000-present 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.asset.kernel.AssetRendererFactoryRegistryUtil;
018    import com.liferay.asset.kernel.model.AssetEntry;
019    import com.liferay.asset.kernel.model.AssetRendererFactory;
020    import com.liferay.asset.kernel.service.persistence.AssetEntryQuery;
021    import com.liferay.portal.kernel.cache.thread.local.Lifecycle;
022    import com.liferay.portal.kernel.cache.thread.local.ThreadLocalCache;
023    import com.liferay.portal.kernel.cache.thread.local.ThreadLocalCacheManager;
024    import com.liferay.portal.kernel.dao.orm.QueryUtil;
025    import com.liferay.portal.kernel.exception.PortalException;
026    import com.liferay.portal.kernel.log.Log;
027    import com.liferay.portal.kernel.log.LogFactoryUtil;
028    import com.liferay.portal.kernel.security.permission.ActionKeys;
029    import com.liferay.portal.kernel.security.permission.PermissionChecker;
030    import com.liferay.portal.kernel.util.StringPool;
031    import com.liferay.portal.util.PropsValues;
032    import com.liferay.portlet.asset.service.base.AssetEntryServiceBaseImpl;
033    import com.liferay.portlet.asset.service.permission.AssetEntryPermission;
034    import com.liferay.portlet.asset.util.AssetUtil;
035    
036    import java.util.ArrayList;
037    import java.util.Date;
038    import java.util.List;
039    
040    /**
041     * Provides the remote service for accessing and updating asset entries. Its
042     * methods include permission checks.
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            @Override
052            public AssetEntry fetchEntry(long entryId) throws PortalException {
053                    AssetEntry entry = assetEntryLocalService.fetchEntry(entryId);
054    
055                    if (entry != null) {
056                            AssetEntryPermission.check(
057                                    getPermissionChecker(), entry, ActionKeys.VIEW);
058                    }
059    
060                    return entry;
061            }
062    
063            @Override
064            public List<AssetEntry> getCompanyEntries(
065                    long companyId, int start, int end) {
066    
067                    List<AssetEntry> entries = new ArrayList<>();
068    
069                    List<AssetEntry> companyEntries =
070                            assetEntryLocalService.getCompanyEntries(companyId, start, end);
071    
072                    for (AssetEntry entry : companyEntries) {
073                            try {
074                                    if (AssetEntryPermission.contains(
075                                                    getPermissionChecker(), entry, ActionKeys.VIEW)) {
076    
077                                            entries.add(entry);
078                                    }
079                            }
080                            catch (PortalException pe) {
081                                    if (_log.isWarnEnabled()) {
082                                            _log.warn(pe, pe);
083                                    }
084                            }
085                    }
086    
087                    return entries;
088            }
089    
090            @Override
091            public int getCompanyEntriesCount(long companyId) {
092                    return assetEntryLocalService.getCompanyEntriesCount(companyId);
093            }
094    
095            @Override
096            public List<AssetEntry> getEntries(AssetEntryQuery entryQuery)
097                    throws PortalException {
098    
099                    AssetEntryQuery filteredEntryQuery = buildFilteredEntryQuery(
100                            entryQuery);
101    
102                    if (hasEntryQueryResults(entryQuery, filteredEntryQuery)) {
103                            return new ArrayList<>();
104                    }
105    
106                    Object[] results = filterEntryQuery(filteredEntryQuery, false);
107    
108                    return (List<AssetEntry>)results[0];
109            }
110    
111            @Override
112            public int getEntriesCount(AssetEntryQuery entryQuery)
113                    throws PortalException {
114    
115                    AssetEntryQuery filteredEntryQuery = buildFilteredEntryQuery(
116                            entryQuery);
117    
118                    if (hasEntryQueryResults(entryQuery, filteredEntryQuery)) {
119                            return 0;
120                    }
121    
122                    Object[] results = filterEntryQuery(filteredEntryQuery, true);
123    
124                    return (Integer)results[1];
125            }
126    
127            @Override
128            public AssetEntry getEntry(long entryId) throws PortalException {
129                    AssetEntryPermission.check(
130                            getPermissionChecker(), entryId, ActionKeys.VIEW);
131    
132                    return assetEntryLocalService.getEntry(entryId);
133            }
134    
135            @Override
136            public AssetEntry incrementViewCounter(String className, long classPK)
137                    throws PortalException {
138    
139                    AssetEntryPermission.check(
140                            getPermissionChecker(), className, classPK, ActionKeys.VIEW);
141    
142                    return assetEntryLocalService.incrementViewCounter(
143                            getGuestOrUserId(), className, classPK);
144            }
145    
146            @Override
147            public AssetEntry updateEntry(
148                            long groupId, Date createDate, Date modifiedDate, String className,
149                            long classPK, String classUuid, long classTypeId,
150                            long[] categoryIds, String[] tagNames, boolean listable,
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, Double priority)
155                    throws PortalException {
156    
157                    AssetEntryPermission.check(
158                            getPermissionChecker(), className, classPK, ActionKeys.UPDATE);
159    
160                    return assetEntryLocalService.updateEntry(
161                            getUserId(), groupId, createDate, modifiedDate, className, classPK,
162                            classUuid, classTypeId, categoryIds, tagNames, listable, visible,
163                            startDate, endDate, publishDate, expirationDate, mimeType, title,
164                            description, summary, url, layoutUuid, height, width, priority);
165            }
166    
167            /**
168             * @deprecated As of 7.0.0, replaced by {@link #updateEntry(long, Date,
169             *             Date, String, long, String, long, long[], String[], boolean,
170             *             boolean, Date, Date, Date, Date, String, String, String,
171             *             String, String, String, int, int, Double)}
172             */
173            @Deprecated
174            @Override
175            public AssetEntry updateEntry(
176                            long groupId, Date createDate, Date modifiedDate, String className,
177                            long classPK, String classUuid, long classTypeId,
178                            long[] categoryIds, String[] tagNames, boolean listable,
179                            boolean visible, Date startDate, Date endDate, Date expirationDate,
180                            String mimeType, String title, String description, String summary,
181                            String url, String layoutUuid, int height, int width,
182                            Double priority)
183                    throws PortalException {
184    
185                    AssetEntryPermission.check(
186                            getPermissionChecker(), className, classPK, ActionKeys.UPDATE);
187    
188                    return assetEntryLocalService.updateEntry(
189                            getUserId(), groupId, createDate, modifiedDate, className, classPK,
190                            classUuid, classTypeId, categoryIds, tagNames, listable, visible,
191                            startDate, endDate, expirationDate, mimeType, title, description,
192                            summary, url, layoutUuid, height, width, priority);
193            }
194    
195            /**
196             * @deprecated As of 7.0.0, replaced by {@link #updateEntry(long, Date,
197             *             Date, String, long, String, long, long[], String[], boolean,
198             *             boolean, Date, Date, Date, Date, String, String, String,
199             *             String, String, String, int, int, Double)}
200             */
201            @Deprecated
202            @Override
203            public AssetEntry updateEntry(
204                            long groupId, Date createDate, Date modifiedDate, String className,
205                            long classPK, String classUuid, long classTypeId,
206                            long[] categoryIds, String[] tagNames, boolean visible,
207                            Date startDate, Date endDate, Date expirationDate, String mimeType,
208                            String title, String description, String summary, String url,
209                            String layoutUuid, int height, int width, Integer priority,
210                            boolean sync)
211                    throws PortalException {
212    
213                    AssetEntryPermission.check(
214                            getPermissionChecker(), className, classPK, ActionKeys.UPDATE);
215    
216                    return assetEntryLocalService.updateEntry(
217                            getUserId(), groupId, createDate, modifiedDate, className, classPK,
218                            classUuid, classTypeId, categoryIds, tagNames, visible, startDate,
219                            endDate, expirationDate, mimeType, title, description, summary, url,
220                            layoutUuid, height, width, priority, sync);
221            }
222    
223            protected AssetEntryQuery buildFilteredEntryQuery(
224                            AssetEntryQuery entryQuery)
225                    throws PortalException {
226    
227                    // Return an entry query with only the category ids and tag ids that the
228                    // user has access to
229    
230                    AssetEntryQuery filteredEntryQuery = new AssetEntryQuery(entryQuery);
231    
232                    filteredEntryQuery.setAllCategoryIds(
233                            AssetUtil.filterCategoryIds(
234                                    getPermissionChecker(), entryQuery.getAllCategoryIds()));
235                    filteredEntryQuery.setAllTagIdsArray(entryQuery.getAllTagIdsArray());
236                    filteredEntryQuery.setAnyCategoryIds(
237                            AssetUtil.filterCategoryIds(
238                                    getPermissionChecker(), entryQuery.getAnyCategoryIds()));
239                    filteredEntryQuery.setAnyTagIds(entryQuery.getAnyTagIds());
240    
241                    return filteredEntryQuery;
242            }
243    
244            protected Object[] filterEntryQuery(
245                            AssetEntryQuery entryQuery, boolean returnEntriesCountOnly)
246                    throws PortalException {
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<>();
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 boolean hasEntryQueryResults(
348                    AssetEntryQuery originalEntryQuery,
349                    AssetEntryQuery filteredEntryQuery) {
350    
351                    if (originalEntryQuery.getAllCategoryIds().length >
352                                    filteredEntryQuery.getAllCategoryIds().length) {
353    
354                            // No results will be available if the user must have access to all
355                            // category ids, but the user has access to fewer category ids in
356                            // the filtered entry query than what was specified in the original
357                            // entry query
358    
359                            return true;
360                    }
361    
362                    if (originalEntryQuery.getAllTagIds().length >
363                                    filteredEntryQuery.getAllTagIds().length) {
364    
365                            // No results will be available if the user must have access to all
366                            // tag ids, but the user has access to fewer tag ids in the filtered
367                            // entry query than what was specified in the original entry query
368    
369                            return true;
370                    }
371    
372                    if ((originalEntryQuery.getAnyCategoryIds().length > 0) &&
373                            (filteredEntryQuery.getAnyCategoryIds().length == 0)) {
374    
375                            // No results will be available if the original entry query
376                            // specified at least one category id, but the filtered entry query
377                            // shows that the user does not have access to any category ids
378    
379                            return true;
380                    }
381    
382                    if ((originalEntryQuery.getAnyTagIds().length > 0) &&
383                            (filteredEntryQuery.getAnyTagIds().length == 0)) {
384    
385                            // No results will be available if the original entry query
386                            // specified at least one tag id, but the filtered entry query shows
387                            // that the user does not have access to any tag ids
388    
389                            return true;
390                    }
391    
392                    return false;
393            }
394    
395            private static final Log _log = LogFactoryUtil.getLog(
396                    AssetEntryServiceImpl.class);
397    
398    }