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.portal.kernel.cache.thread.local.Lifecycle;
018    import com.liferay.portal.kernel.cache.thread.local.ThreadLocalCache;
019    import com.liferay.portal.kernel.cache.thread.local.ThreadLocalCacheManager;
020    import com.liferay.portal.kernel.dao.orm.QueryUtil;
021    import com.liferay.portal.kernel.exception.PortalException;
022    import com.liferay.portal.kernel.log.Log;
023    import com.liferay.portal.kernel.log.LogFactoryUtil;
024    import com.liferay.portal.kernel.security.permission.ActionKeys;
025    import com.liferay.portal.kernel.security.permission.PermissionChecker;
026    import com.liferay.portal.kernel.util.StringPool;
027    import com.liferay.portal.util.PropsValues;
028    import com.liferay.portlet.asset.AssetRendererFactoryRegistryUtil;
029    import com.liferay.portlet.asset.model.AssetEntry;
030    import com.liferay.portlet.asset.model.AssetRendererFactory;
031    import com.liferay.portlet.asset.service.base.AssetEntryServiceBaseImpl;
032    import com.liferay.portlet.asset.service.permission.AssetEntryPermission;
033    import com.liferay.portlet.asset.service.persistence.AssetEntryQuery;
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 visible,
151                            Date startDate, Date endDate, Date expirationDate, String mimeType,
152                            String title, String description, String summary, String url,
153                            String layoutUuid, int height, int width, Double priority)
154                    throws PortalException {
155    
156                    AssetEntryPermission.check(
157                            getPermissionChecker(), className, classPK, ActionKeys.UPDATE);
158    
159                    return assetEntryLocalService.updateEntry(
160                            getUserId(), groupId, createDate, modifiedDate, className, classPK,
161                            classUuid, classTypeId, categoryIds, tagNames, visible, startDate,
162                            endDate, expirationDate, mimeType, title, description, summary, url,
163                            layoutUuid, height, width, priority);
164            }
165    
166            /**
167             * @deprecated As of 7.0.0, replaced by {@link #updateEntry(long, Date,
168             *             Date, String, long, String, long, long[], String[], boolean,
169             *             Date, Date, Date, String, String, String, String, String,
170             *             String, int, int, Double)}
171             */
172            @Deprecated
173            @Override
174            public AssetEntry updateEntry(
175                            long groupId, Date createDate, Date modifiedDate, String className,
176                            long classPK, String classUuid, long classTypeId,
177                            long[] categoryIds, String[] tagNames, boolean visible,
178                            Date startDate, Date endDate, Date expirationDate, String mimeType,
179                            String title, String description, String summary, String url,
180                            String layoutUuid, int height, int width, Integer priority,
181                            boolean sync)
182                    throws PortalException {
183    
184                    AssetEntryPermission.check(
185                            getPermissionChecker(), className, classPK, ActionKeys.UPDATE);
186    
187                    return assetEntryLocalService.updateEntry(
188                            getUserId(), groupId, createDate, modifiedDate, className, classPK,
189                            classUuid, classTypeId, categoryIds, tagNames, visible, startDate,
190                            endDate, expirationDate, mimeType, title, description, summary, url,
191                            layoutUuid, height, width, priority, sync);
192            }
193    
194            protected AssetEntryQuery buildFilteredEntryQuery(
195                            AssetEntryQuery entryQuery)
196                    throws PortalException {
197    
198                    // Return an entry query with only the category ids and tag ids that the
199                    // user has access to
200    
201                    AssetEntryQuery filteredEntryQuery = new AssetEntryQuery(entryQuery);
202    
203                    filteredEntryQuery.setAllCategoryIds(
204                            AssetUtil.filterCategoryIds(
205                                    getPermissionChecker(), entryQuery.getAllCategoryIds()));
206                    filteredEntryQuery.setAllTagIdsArray(entryQuery.getAllTagIdsArray());
207                    filteredEntryQuery.setAnyCategoryIds(
208                            AssetUtil.filterCategoryIds(
209                                    getPermissionChecker(), entryQuery.getAnyCategoryIds()));
210                    filteredEntryQuery.setAnyTagIds(entryQuery.getAnyTagIds());
211    
212                    return filteredEntryQuery;
213            }
214    
215            protected Object[] filterEntryQuery(
216                            AssetEntryQuery entryQuery, boolean returnEntriesCountOnly)
217                    throws PortalException {
218    
219                    ThreadLocalCache<Object[]> threadLocalCache =
220                            ThreadLocalCacheManager.getThreadLocalCache(
221                                    Lifecycle.REQUEST, AssetEntryServiceImpl.class.getName());
222    
223                    String key = entryQuery.toString();
224    
225                    key = key.concat(StringPool.POUND).concat(
226                            Boolean.toString(returnEntriesCountOnly));
227    
228                    Object[] results = threadLocalCache.get(key);
229    
230                    if (results != null) {
231                            return results;
232                    }
233    
234                    if (returnEntriesCountOnly && !entryQuery.isEnablePermissions()) {
235                            int entriesCount = assetEntryLocalService.getEntriesCount(
236                                    entryQuery);
237    
238                            results = new Object[] {null, entriesCount};
239    
240                            threadLocalCache.put(key, results);
241    
242                            return results;
243                    }
244    
245                    int end = entryQuery.getEnd();
246                    int start = entryQuery.getStart();
247    
248                    if (entryQuery.isEnablePermissions()) {
249                            entryQuery.setEnd(end + PropsValues.ASSET_FILTER_SEARCH_LIMIT);
250                            entryQuery.setStart(0);
251                    }
252    
253                    List<AssetEntry> entries = assetEntryLocalService.getEntries(
254                            entryQuery);
255    
256                    List<AssetEntry> filteredEntries = null;
257                    int filteredEntriesCount = 0;
258    
259                    if (entryQuery.isEnablePermissions()) {
260                            PermissionChecker permissionChecker = getPermissionChecker();
261    
262                            filteredEntries = new ArrayList<>();
263    
264                            for (AssetEntry entry : entries) {
265                                    String className = entry.getClassName();
266                                    long classPK = entry.getClassPK();
267    
268                                    AssetRendererFactory<?> assetRendererFactory =
269                                            AssetRendererFactoryRegistryUtil.
270                                                    getAssetRendererFactoryByClassName(className);
271    
272                                    try {
273                                            if (assetRendererFactory.hasPermission(
274                                                            permissionChecker, classPK, ActionKeys.VIEW)) {
275    
276                                                    filteredEntries.add(entry);
277                                            }
278                                    }
279                                    catch (Exception e) {
280                                    }
281    
282                                    if ((end != QueryUtil.ALL_POS) &&
283                                            (filteredEntries.size() > end)) {
284    
285                                            break;
286                                    }
287                            }
288    
289                            filteredEntriesCount = filteredEntries.size();
290    
291                            if ((end != QueryUtil.ALL_POS) && (start != QueryUtil.ALL_POS)) {
292                                    if (end > filteredEntriesCount) {
293                                            end = filteredEntriesCount;
294                                    }
295    
296                                    if (start > filteredEntriesCount) {
297                                            start = filteredEntriesCount;
298                                    }
299    
300                                    filteredEntries = filteredEntries.subList(start, end);
301                            }
302    
303                            entryQuery.setEnd(end);
304                            entryQuery.setStart(start);
305                    }
306                    else {
307                            filteredEntries = entries;
308                            filteredEntriesCount = filteredEntries.size();
309                    }
310    
311                    results = new Object[] {filteredEntries, filteredEntriesCount};
312    
313                    threadLocalCache.put(key, results);
314    
315                    return results;
316            }
317    
318            protected boolean hasEntryQueryResults(
319                    AssetEntryQuery originalEntryQuery,
320                    AssetEntryQuery filteredEntryQuery) {
321    
322                    if (originalEntryQuery.getAllCategoryIds().length >
323                                    filteredEntryQuery.getAllCategoryIds().length) {
324    
325                            // No results will be available if the user must have access to all
326                            // category ids, but the user has access to fewer category ids in
327                            // the filtered entry query than what was specified in the original
328                            // entry query
329    
330                            return true;
331                    }
332    
333                    if (originalEntryQuery.getAllTagIds().length >
334                                    filteredEntryQuery.getAllTagIds().length) {
335    
336                            // No results will be available if the user must have access to all
337                            // tag ids, but the user has access to fewer tag ids in the filtered
338                            // entry query than what was specified in the original entry query
339    
340                            return true;
341                    }
342    
343                    if ((originalEntryQuery.getAnyCategoryIds().length > 0) &&
344                            (filteredEntryQuery.getAnyCategoryIds().length == 0)) {
345    
346                            // No results will be available if the original entry query
347                            // specified at least one category id, but the filtered entry query
348                            // shows that the user does not have access to any category ids
349    
350                            return true;
351                    }
352    
353                    if ((originalEntryQuery.getAnyTagIds().length > 0) &&
354                            (filteredEntryQuery.getAnyTagIds().length == 0)) {
355    
356                            // No results will be available if the original entry query
357                            // specified at least one tag id, but the filtered entry query shows
358                            // that the user does not have access to any tag ids
359    
360                            return true;
361                    }
362    
363                    return false;
364            }
365    
366            private static final Log _log = LogFactoryUtil.getLog(
367                    AssetEntryServiceImpl.class);
368    
369    }