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 List<AssetEntry> getCompanyEntries(
053                    long companyId, int start, int end) {
054    
055                    List<AssetEntry> entries = new ArrayList<AssetEntry>();
056    
057                    List<AssetEntry> companyEntries =
058                            assetEntryLocalService.getCompanyEntries(companyId, start, end);
059    
060                    for (AssetEntry entry : companyEntries) {
061                            try {
062                                    if (AssetEntryPermission.contains(
063                                                    getPermissionChecker(), entry, ActionKeys.VIEW)) {
064    
065                                            entries.add(entry);
066                                    }
067                            }
068                            catch (PortalException pe) {
069                                    if (_log.isWarnEnabled()) {
070                                            _log.warn(pe, pe);
071                                    }
072                            }
073                    }
074    
075                    return entries;
076            }
077    
078            @Override
079            public int getCompanyEntriesCount(long companyId) {
080                    return assetEntryLocalService.getCompanyEntriesCount(companyId);
081            }
082    
083            @Override
084            public List<AssetEntry> getEntries(AssetEntryQuery entryQuery)
085                    throws PortalException {
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            @Override
100            public int getEntriesCount(AssetEntryQuery entryQuery)
101                    throws PortalException {
102    
103                    AssetEntryQuery filteredEntryQuery = buildFilteredEntryQuery(
104                            entryQuery);
105    
106                    if (hasEntryQueryResults(entryQuery, filteredEntryQuery)) {
107                            return 0;
108                    }
109    
110                    Object[] results = filterEntryQuery(filteredEntryQuery, true);
111    
112                    return (Integer)results[1];
113            }
114    
115            @Override
116            public AssetEntry getEntry(long entryId) throws PortalException {
117                    AssetEntryPermission.check(
118                            getPermissionChecker(), entryId, ActionKeys.VIEW);
119    
120                    return assetEntryLocalService.getEntry(entryId);
121            }
122    
123            @Override
124            public AssetEntry incrementViewCounter(String className, long classPK)
125                    throws PortalException {
126    
127                    AssetEntryPermission.check(
128                            getPermissionChecker(), className, classPK, ActionKeys.VIEW);
129    
130                    return assetEntryLocalService.incrementViewCounter(
131                            getGuestOrUserId(), className, classPK);
132            }
133    
134            @Override
135            public AssetEntry updateEntry(
136                            long groupId, Date createDate, Date modifiedDate, String className,
137                            long classPK, String classUuid, long classTypeId,
138                            long[] categoryIds, String[] tagNames, boolean visible,
139                            Date startDate, Date endDate, Date expirationDate, String mimeType,
140                            String title, String description, String summary, String url,
141                            String layoutUuid, int height, int width, Integer priority,
142                            boolean sync)
143                    throws PortalException {
144    
145                    AssetEntryPermission.check(
146                            getPermissionChecker(), className, classPK, ActionKeys.UPDATE);
147    
148                    return assetEntryLocalService.updateEntry(
149                            getUserId(), groupId, createDate, modifiedDate, className, classPK,
150                            classUuid, classTypeId, categoryIds, tagNames, visible, startDate,
151                            endDate, expirationDate, mimeType, title, description, summary, url,
152                            layoutUuid, height, width, priority, sync);
153            }
154    
155            /**
156             * @deprecated As of 6.2.0, replaced by {@link #updateEntry(long, String,
157             *             long, String, long, long[], String[], boolean, Date, Date,
158             *             Date, String, String, String, String, String, String, int,
159             *             int, Integer, boolean)}
160             */
161            @Deprecated
162            @Override
163            public AssetEntry updateEntry(
164                            long groupId, String className, long classPK, String classUuid,
165                            long classTypeId, long[] categoryIds, String[] tagNames,
166                            boolean visible, Date startDate, Date endDate, Date publishDate,
167                            Date expirationDate, String mimeType, String title,
168                            String description, String summary, String url, String layoutUuid,
169                            int height, int width, Integer priority, boolean sync)
170                    throws PortalException {
171    
172                    AssetEntryPermission.check(
173                            getPermissionChecker(), className, classPK, ActionKeys.UPDATE);
174    
175                    return assetEntryLocalService.updateEntry(
176                            getUserId(), groupId, className, classPK, classUuid, classTypeId,
177                            categoryIds, tagNames, visible, startDate, endDate, expirationDate,
178                            mimeType, title, description, summary, url, layoutUuid, height,
179                            width, priority, sync);
180            }
181    
182            /**
183             * @deprecated As of 6.2.0, replaced by {@link #updateEntry(long, Date,
184             *             Date, String, long, String, long, long[], String[], boolean,
185             *             Date, Date, Date, String, String, String, String, String,
186             *             String, int, int, Integer, boolean)}
187             */
188            @Deprecated
189            @Override
190            public AssetEntry updateEntry(
191                            long groupId, String className, long classPK, String classUuid,
192                            long classTypeId, long[] categoryIds, String[] tagNames,
193                            boolean visible, Date startDate, Date endDate, Date expirationDate,
194                            String mimeType, String title, String description, String summary,
195                            String url, String layoutUuid, int height, int width,
196                            Integer priority, boolean sync)
197                    throws PortalException {
198    
199                    return assetEntryLocalService.updateEntry(
200                            getUserId(), groupId, null, null, className, classPK, classUuid,
201                            classTypeId, categoryIds, tagNames, visible, startDate, endDate,
202                            expirationDate, mimeType, title, description, summary, url,
203                            layoutUuid, height, width, priority, sync);
204            }
205    
206            protected AssetEntryQuery buildFilteredEntryQuery(
207                            AssetEntryQuery entryQuery)
208                    throws PortalException {
209    
210                    // Return an entry query with only the category ids and tag ids that the
211                    // user has access to
212    
213                    AssetEntryQuery filteredEntryQuery = new AssetEntryQuery(entryQuery);
214    
215                    filteredEntryQuery.setAllCategoryIds(
216                            AssetUtil.filterCategoryIds(
217                                    getPermissionChecker(), entryQuery.getAllCategoryIds()));
218                    filteredEntryQuery.setAllTagIdsArray(
219                            AssetUtil.filterTagIdsArray(
220                                    getPermissionChecker(), entryQuery.getAllTagIdsArray()));
221                    filteredEntryQuery.setAnyCategoryIds(
222                            AssetUtil.filterCategoryIds(
223                                    getPermissionChecker(), entryQuery.getAnyCategoryIds()));
224                    filteredEntryQuery.setAnyTagIds(
225                            AssetUtil.filterTagIds(
226                                    getPermissionChecker(), entryQuery.getAnyTagIds()));
227    
228                    return filteredEntryQuery;
229            }
230    
231            protected Object[] filterEntryQuery(
232                            AssetEntryQuery entryQuery, boolean returnEntriesCountOnly)
233                    throws PortalException {
234    
235                    ThreadLocalCache<Object[]> threadLocalCache =
236                            ThreadLocalCacheManager.getThreadLocalCache(
237                                    Lifecycle.REQUEST, AssetEntryServiceImpl.class.getName());
238    
239                    String key = entryQuery.toString();
240    
241                    key = key.concat(StringPool.POUND).concat(
242                            Boolean.toString(returnEntriesCountOnly));
243    
244                    Object[] results = threadLocalCache.get(key);
245    
246                    if (results != null) {
247                            return results;
248                    }
249    
250                    if (returnEntriesCountOnly && !entryQuery.isEnablePermissions()) {
251                            int entriesCount = assetEntryLocalService.getEntriesCount(
252                                    entryQuery);
253    
254                            results = new Object[] {null, entriesCount};
255    
256                            threadLocalCache.put(key, results);
257    
258                            return results;
259                    }
260    
261                    int end = entryQuery.getEnd();
262                    int start = entryQuery.getStart();
263    
264                    if (entryQuery.isEnablePermissions()) {
265                            entryQuery.setEnd(end + PropsValues.ASSET_FILTER_SEARCH_LIMIT);
266                            entryQuery.setStart(0);
267                    }
268    
269                    List<AssetEntry> entries = assetEntryLocalService.getEntries(
270                            entryQuery);
271    
272                    List<AssetEntry> filteredEntries = null;
273                    int filteredEntriesCount = 0;
274    
275                    if (entryQuery.isEnablePermissions()) {
276                            PermissionChecker permissionChecker = getPermissionChecker();
277    
278                            filteredEntries = new ArrayList<AssetEntry>();
279    
280                            for (AssetEntry entry : entries) {
281                                    String className = entry.getClassName();
282                                    long classPK = entry.getClassPK();
283    
284                                    AssetRendererFactory assetRendererFactory =
285                                            AssetRendererFactoryRegistryUtil.
286                                                    getAssetRendererFactoryByClassName(className);
287    
288                                    try {
289                                            if (assetRendererFactory.hasPermission(
290                                                            permissionChecker, classPK, ActionKeys.VIEW)) {
291    
292                                                    filteredEntries.add(entry);
293                                            }
294                                    }
295                                    catch (Exception e) {
296                                    }
297    
298                                    if ((end != QueryUtil.ALL_POS) &&
299                                            (filteredEntries.size() > end)) {
300    
301                                            break;
302                                    }
303                            }
304    
305                            filteredEntriesCount = filteredEntries.size();
306    
307                            if ((end != QueryUtil.ALL_POS) && (start != QueryUtil.ALL_POS)) {
308                                    if (end > filteredEntriesCount) {
309                                            end = filteredEntriesCount;
310                                    }
311    
312                                    if (start > filteredEntriesCount) {
313                                            start = filteredEntriesCount;
314                                    }
315    
316                                    filteredEntries = filteredEntries.subList(start, end);
317                            }
318    
319                            entryQuery.setEnd(end);
320                            entryQuery.setStart(start);
321                    }
322                    else {
323                            filteredEntries = entries;
324                            filteredEntriesCount = filteredEntries.size();
325                    }
326    
327                    results = new Object[] {filteredEntries, filteredEntriesCount};
328    
329                    threadLocalCache.put(key, results);
330    
331                    return results;
332            }
333    
334            protected boolean hasEntryQueryResults(
335                    AssetEntryQuery originalEntryQuery,
336                    AssetEntryQuery filteredEntryQuery) {
337    
338                    if (originalEntryQuery.getAllCategoryIds().length >
339                                    filteredEntryQuery.getAllCategoryIds().length) {
340    
341                            // No results will be available if the user must have access to all
342                            // category ids, but the user has access to fewer category ids in
343                            // the filtered entry query than what was specified in the original
344                            // entry query
345    
346                            return true;
347                    }
348    
349                    if (originalEntryQuery.getAllTagIds().length >
350                                    filteredEntryQuery.getAllTagIds().length) {
351    
352                            // No results will be available if the user must have access to all
353                            // tag ids, but the user has access to fewer tag ids in the filtered
354                            // entry query than what was specified in the original entry query
355    
356                            return true;
357                    }
358    
359                    if ((originalEntryQuery.getAnyCategoryIds().length > 0) &&
360                            (filteredEntryQuery.getAnyCategoryIds().length == 0)) {
361    
362                            // No results will be available if the original entry query
363                            // specified at least one category id, but the filtered entry query
364                            // shows that the user does not have access to any category ids
365    
366                            return true;
367                    }
368    
369                    if ((originalEntryQuery.getAnyTagIds().length > 0) &&
370                            (filteredEntryQuery.getAnyTagIds().length == 0)) {
371    
372                            // No results will be available if the original entry query
373                            // specified at least one tag id, but the filtered entry query shows
374                            // that the user does not have access to any tag ids
375    
376                            return true;
377                    }
378    
379                    return false;
380            }
381    
382            private static final Log _log = LogFactoryUtil.getLog(
383                    AssetEntryServiceImpl.class);
384    
385    }