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.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.log.Log;
023    import com.liferay.portal.kernel.log.LogFactoryUtil;
024    import com.liferay.portal.kernel.util.StringPool;
025    import com.liferay.portal.security.permission.ActionKeys;
026    import com.liferay.portal.security.permission.PermissionChecker;
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, Integer 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, Integer)}
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            /**
195             * @deprecated As of 6.2.0, replaced by {@link #updateEntry(long, String,
196             *             long, String, long, long[], String[], boolean, Date, Date,
197             *             Date, String, String, String, String, String, String, int,
198             *             int, Integer, boolean)}
199             */
200            @Deprecated
201            @Override
202            public AssetEntry updateEntry(
203                            long groupId, String className, long classPK, String classUuid,
204                            long classTypeId, long[] categoryIds, String[] tagNames,
205                            boolean visible, Date startDate, Date endDate, Date publishDate,
206                            Date expirationDate, String mimeType, String title,
207                            String description, String summary, String url, String layoutUuid,
208                            int height, int width, Integer priority, boolean sync)
209                    throws PortalException {
210    
211                    AssetEntryPermission.check(
212                            getPermissionChecker(), className, classPK, ActionKeys.UPDATE);
213    
214                    return assetEntryLocalService.updateEntry(
215                            getUserId(), groupId, className, classPK, classUuid, classTypeId,
216                            categoryIds, tagNames, visible, startDate, endDate, expirationDate,
217                            mimeType, title, description, summary, url, layoutUuid, height,
218                            width, priority, sync);
219            }
220    
221            /**
222             * @deprecated As of 6.2.0, replaced by {@link #updateEntry(long, Date,
223             *             Date, String, long, String, long, long[], String[], boolean,
224             *             Date, Date, Date, String, String, String, String, String,
225             *             String, int, int, Integer, boolean)}
226             */
227            @Deprecated
228            @Override
229            public AssetEntry updateEntry(
230                            long groupId, String className, long classPK, String classUuid,
231                            long classTypeId, long[] categoryIds, String[] tagNames,
232                            boolean visible, Date startDate, Date endDate, Date expirationDate,
233                            String mimeType, String title, String description, String summary,
234                            String url, String layoutUuid, int height, int width,
235                            Integer priority, boolean sync)
236                    throws PortalException {
237    
238                    return assetEntryLocalService.updateEntry(
239                            getUserId(), groupId, null, null, className, classPK, classUuid,
240                            classTypeId, categoryIds, tagNames, visible, startDate, endDate,
241                            expirationDate, mimeType, title, description, summary, url,
242                            layoutUuid, height, width, priority, sync);
243            }
244    
245            protected AssetEntryQuery buildFilteredEntryQuery(
246                            AssetEntryQuery entryQuery)
247                    throws PortalException {
248    
249                    // Return an entry query with only the category ids and tag ids that the
250                    // user has access to
251    
252                    AssetEntryQuery filteredEntryQuery = new AssetEntryQuery(entryQuery);
253    
254                    filteredEntryQuery.setAllCategoryIds(
255                            AssetUtil.filterCategoryIds(
256                                    getPermissionChecker(), entryQuery.getAllCategoryIds()));
257                    filteredEntryQuery.setAllTagIdsArray(
258                            AssetUtil.filterTagIdsArray(
259                                    getPermissionChecker(), entryQuery.getAllTagIdsArray()));
260                    filteredEntryQuery.setAnyCategoryIds(
261                            AssetUtil.filterCategoryIds(
262                                    getPermissionChecker(), entryQuery.getAnyCategoryIds()));
263                    filteredEntryQuery.setAnyTagIds(
264                            AssetUtil.filterTagIds(
265                                    getPermissionChecker(), entryQuery.getAnyTagIds()));
266    
267                    return filteredEntryQuery;
268            }
269    
270            protected Object[] filterEntryQuery(
271                            AssetEntryQuery entryQuery, boolean returnEntriesCountOnly)
272                    throws PortalException {
273    
274                    ThreadLocalCache<Object[]> threadLocalCache =
275                            ThreadLocalCacheManager.getThreadLocalCache(
276                                    Lifecycle.REQUEST, AssetEntryServiceImpl.class.getName());
277    
278                    String key = entryQuery.toString();
279    
280                    key = key.concat(StringPool.POUND).concat(
281                            Boolean.toString(returnEntriesCountOnly));
282    
283                    Object[] results = threadLocalCache.get(key);
284    
285                    if (results != null) {
286                            return results;
287                    }
288    
289                    if (returnEntriesCountOnly && !entryQuery.isEnablePermissions()) {
290                            int entriesCount = assetEntryLocalService.getEntriesCount(
291                                    entryQuery);
292    
293                            results = new Object[] {null, entriesCount};
294    
295                            threadLocalCache.put(key, results);
296    
297                            return results;
298                    }
299    
300                    int end = entryQuery.getEnd();
301                    int start = entryQuery.getStart();
302    
303                    if (entryQuery.isEnablePermissions()) {
304                            entryQuery.setEnd(end + PropsValues.ASSET_FILTER_SEARCH_LIMIT);
305                            entryQuery.setStart(0);
306                    }
307    
308                    List<AssetEntry> entries = assetEntryLocalService.getEntries(
309                            entryQuery);
310    
311                    List<AssetEntry> filteredEntries = null;
312                    int filteredEntriesCount = 0;
313    
314                    if (entryQuery.isEnablePermissions()) {
315                            PermissionChecker permissionChecker = getPermissionChecker();
316    
317                            filteredEntries = new ArrayList<>();
318    
319                            for (AssetEntry entry : entries) {
320                                    String className = entry.getClassName();
321                                    long classPK = entry.getClassPK();
322    
323                                    AssetRendererFactory assetRendererFactory =
324                                            AssetRendererFactoryRegistryUtil.
325                                                    getAssetRendererFactoryByClassName(className);
326    
327                                    try {
328                                            if (assetRendererFactory.hasPermission(
329                                                            permissionChecker, classPK, ActionKeys.VIEW)) {
330    
331                                                    filteredEntries.add(entry);
332                                            }
333                                    }
334                                    catch (Exception e) {
335                                    }
336    
337                                    if ((end != QueryUtil.ALL_POS) &&
338                                            (filteredEntries.size() > end)) {
339    
340                                            break;
341                                    }
342                            }
343    
344                            filteredEntriesCount = filteredEntries.size();
345    
346                            if ((end != QueryUtil.ALL_POS) && (start != QueryUtil.ALL_POS)) {
347                                    if (end > filteredEntriesCount) {
348                                            end = filteredEntriesCount;
349                                    }
350    
351                                    if (start > filteredEntriesCount) {
352                                            start = filteredEntriesCount;
353                                    }
354    
355                                    filteredEntries = filteredEntries.subList(start, end);
356                            }
357    
358                            entryQuery.setEnd(end);
359                            entryQuery.setStart(start);
360                    }
361                    else {
362                            filteredEntries = entries;
363                            filteredEntriesCount = filteredEntries.size();
364                    }
365    
366                    results = new Object[] {filteredEntries, filteredEntriesCount};
367    
368                    threadLocalCache.put(key, results);
369    
370                    return results;
371            }
372    
373            protected boolean hasEntryQueryResults(
374                    AssetEntryQuery originalEntryQuery,
375                    AssetEntryQuery filteredEntryQuery) {
376    
377                    if (originalEntryQuery.getAllCategoryIds().length >
378                                    filteredEntryQuery.getAllCategoryIds().length) {
379    
380                            // No results will be available if the user must have access to all
381                            // category ids, but the user has access to fewer category ids in
382                            // the filtered entry query than what was specified in the original
383                            // entry query
384    
385                            return true;
386                    }
387    
388                    if (originalEntryQuery.getAllTagIds().length >
389                                    filteredEntryQuery.getAllTagIds().length) {
390    
391                            // No results will be available if the user must have access to all
392                            // tag ids, but the user has access to fewer tag ids in the filtered
393                            // entry query than what was specified in the original entry query
394    
395                            return true;
396                    }
397    
398                    if ((originalEntryQuery.getAnyCategoryIds().length > 0) &&
399                            (filteredEntryQuery.getAnyCategoryIds().length == 0)) {
400    
401                            // No results will be available if the original entry query
402                            // specified at least one category id, but the filtered entry query
403                            // shows that the user does not have access to any category ids
404    
405                            return true;
406                    }
407    
408                    if ((originalEntryQuery.getAnyTagIds().length > 0) &&
409                            (filteredEntryQuery.getAnyTagIds().length == 0)) {
410    
411                            // No results will be available if the original entry query
412                            // specified at least one tag id, but the filtered entry query shows
413                            // that the user does not have access to any tag ids
414    
415                            return true;
416                    }
417    
418                    return false;
419            }
420    
421            private static final Log _log = LogFactoryUtil.getLog(
422                    AssetEntryServiceImpl.class);
423    
424    }