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.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, 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            /**
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(entryQuery.getAllTagIdsArray());
258                    filteredEntryQuery.setAnyCategoryIds(
259                            AssetUtil.filterCategoryIds(
260                                    getPermissionChecker(), entryQuery.getAnyCategoryIds()));
261                    filteredEntryQuery.setAnyTagIds(entryQuery.getAnyTagIds());
262    
263                    return filteredEntryQuery;
264            }
265    
266            protected Object[] filterEntryQuery(
267                            AssetEntryQuery entryQuery, boolean returnEntriesCountOnly)
268                    throws PortalException {
269    
270                    ThreadLocalCache<Object[]> threadLocalCache =
271                            ThreadLocalCacheManager.getThreadLocalCache(
272                                    Lifecycle.REQUEST, AssetEntryServiceImpl.class.getName());
273    
274                    String key = entryQuery.toString();
275    
276                    key = key.concat(StringPool.POUND).concat(
277                            Boolean.toString(returnEntriesCountOnly));
278    
279                    Object[] results = threadLocalCache.get(key);
280    
281                    if (results != null) {
282                            return results;
283                    }
284    
285                    if (returnEntriesCountOnly && !entryQuery.isEnablePermissions()) {
286                            int entriesCount = assetEntryLocalService.getEntriesCount(
287                                    entryQuery);
288    
289                            results = new Object[] {null, entriesCount};
290    
291                            threadLocalCache.put(key, results);
292    
293                            return results;
294                    }
295    
296                    int end = entryQuery.getEnd();
297                    int start = entryQuery.getStart();
298    
299                    if (entryQuery.isEnablePermissions()) {
300                            entryQuery.setEnd(end + PropsValues.ASSET_FILTER_SEARCH_LIMIT);
301                            entryQuery.setStart(0);
302                    }
303    
304                    List<AssetEntry> entries = assetEntryLocalService.getEntries(
305                            entryQuery);
306    
307                    List<AssetEntry> filteredEntries = null;
308                    int filteredEntriesCount = 0;
309    
310                    if (entryQuery.isEnablePermissions()) {
311                            PermissionChecker permissionChecker = getPermissionChecker();
312    
313                            filteredEntries = new ArrayList<>();
314    
315                            for (AssetEntry entry : entries) {
316                                    String className = entry.getClassName();
317                                    long classPK = entry.getClassPK();
318    
319                                    AssetRendererFactory<?> assetRendererFactory =
320                                            AssetRendererFactoryRegistryUtil.
321                                                    getAssetRendererFactoryByClassName(className);
322    
323                                    try {
324                                            if (assetRendererFactory.hasPermission(
325                                                            permissionChecker, classPK, ActionKeys.VIEW)) {
326    
327                                                    filteredEntries.add(entry);
328                                            }
329                                    }
330                                    catch (Exception e) {
331                                    }
332    
333                                    if ((end != QueryUtil.ALL_POS) &&
334                                            (filteredEntries.size() > end)) {
335    
336                                            break;
337                                    }
338                            }
339    
340                            filteredEntriesCount = filteredEntries.size();
341    
342                            if ((end != QueryUtil.ALL_POS) && (start != QueryUtil.ALL_POS)) {
343                                    if (end > filteredEntriesCount) {
344                                            end = filteredEntriesCount;
345                                    }
346    
347                                    if (start > filteredEntriesCount) {
348                                            start = filteredEntriesCount;
349                                    }
350    
351                                    filteredEntries = filteredEntries.subList(start, end);
352                            }
353    
354                            entryQuery.setEnd(end);
355                            entryQuery.setStart(start);
356                    }
357                    else {
358                            filteredEntries = entries;
359                            filteredEntriesCount = filteredEntries.size();
360                    }
361    
362                    results = new Object[] {filteredEntries, filteredEntriesCount};
363    
364                    threadLocalCache.put(key, results);
365    
366                    return results;
367            }
368    
369            protected boolean hasEntryQueryResults(
370                    AssetEntryQuery originalEntryQuery,
371                    AssetEntryQuery filteredEntryQuery) {
372    
373                    if (originalEntryQuery.getAllCategoryIds().length >
374                                    filteredEntryQuery.getAllCategoryIds().length) {
375    
376                            // No results will be available if the user must have access to all
377                            // category ids, but the user has access to fewer category ids in
378                            // the filtered entry query than what was specified in the original
379                            // entry query
380    
381                            return true;
382                    }
383    
384                    if (originalEntryQuery.getAllTagIds().length >
385                                    filteredEntryQuery.getAllTagIds().length) {
386    
387                            // No results will be available if the user must have access to all
388                            // tag ids, but the user has access to fewer tag ids in the filtered
389                            // entry query than what was specified in the original entry query
390    
391                            return true;
392                    }
393    
394                    if ((originalEntryQuery.getAnyCategoryIds().length > 0) &&
395                            (filteredEntryQuery.getAnyCategoryIds().length == 0)) {
396    
397                            // No results will be available if the original entry query
398                            // specified at least one category id, but the filtered entry query
399                            // shows that the user does not have access to any category ids
400    
401                            return true;
402                    }
403    
404                    if ((originalEntryQuery.getAnyTagIds().length > 0) &&
405                            (filteredEntryQuery.getAnyTagIds().length == 0)) {
406    
407                            // No results will be available if the original entry query
408                            // specified at least one tag id, but the filtered entry query shows
409                            // that the user does not have access to any tag ids
410    
411                            return true;
412                    }
413    
414                    return false;
415            }
416    
417            private static final Log _log = LogFactoryUtil.getLog(
418                    AssetEntryServiceImpl.class);
419    
420    }