001    /**
002     * Copyright (c) 2000-2013 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.trash.service.impl;
016    
017    import com.liferay.portal.TrashPermissionException;
018    import com.liferay.portal.kernel.dao.orm.QueryUtil;
019    import com.liferay.portal.kernel.dao.search.SearchPaginationUtil;
020    import com.liferay.portal.kernel.exception.PortalException;
021    import com.liferay.portal.kernel.exception.SystemException;
022    import com.liferay.portal.kernel.log.Log;
023    import com.liferay.portal.kernel.log.LogFactoryUtil;
024    import com.liferay.portal.kernel.transaction.Transactional;
025    import com.liferay.portal.kernel.trash.TrashActionKeys;
026    import com.liferay.portal.kernel.trash.TrashHandler;
027    import com.liferay.portal.kernel.trash.TrashHandlerRegistryUtil;
028    import com.liferay.portal.kernel.util.OrderByComparator;
029    import com.liferay.portal.kernel.util.StringPool;
030    import com.liferay.portal.security.auth.PrincipalException;
031    import com.liferay.portal.security.permission.ActionKeys;
032    import com.liferay.portal.security.permission.PermissionChecker;
033    import com.liferay.portal.service.ServiceContext;
034    import com.liferay.portal.util.PropsValues;
035    import com.liferay.portlet.trash.TrashEntryConstants;
036    import com.liferay.portlet.trash.model.TrashEntry;
037    import com.liferay.portlet.trash.model.TrashEntryList;
038    import com.liferay.portlet.trash.model.TrashEntrySoap;
039    import com.liferay.portlet.trash.model.impl.TrashEntryImpl;
040    import com.liferay.portlet.trash.service.base.TrashEntryServiceBaseImpl;
041    
042    import java.util.ArrayList;
043    import java.util.List;
044    
045    /**
046     * The trash entry remote service is responsible for returning trash entries.
047     * For more information on trash entries services and TrashEntry, see {@link
048     * com.liferay.portlet.trash.service.impl.TrashEntryLocalServiceImpl}.
049     *
050     * @author Julio Camarero
051     * @author Zsolt Berentey
052     */
053    public class TrashEntryServiceImpl extends TrashEntryServiceBaseImpl {
054    
055            /**
056             * Deletes the trash entries with the matching group ID considering
057             * permissions.
058             *
059             * @param  groupId the primary key of the group
060             * @throws PortalException if a portal exception occurred
061             * @throws SystemException if a system exception occurred
062             */
063            @Override
064            @Transactional(noRollbackFor = {TrashPermissionException.class})
065            public void deleteEntries(long groupId)
066                    throws PortalException, SystemException {
067    
068                    boolean throwTrashPermissionException = false;
069    
070                    List<TrashEntry> entries = trashEntryPersistence.findByGroupId(groupId);
071    
072                    PermissionChecker permissionChecker = getPermissionChecker();
073    
074                    for (TrashEntry entry : entries) {
075                            try {
076                                    TrashHandler trashHandler =
077                                            TrashHandlerRegistryUtil.getTrashHandler(
078                                                    entry.getClassName());
079    
080                                    if (!trashHandler.hasTrashPermission(
081                                                    permissionChecker, 0, entry.getClassPK(),
082                                                    ActionKeys.VIEW)) {
083    
084                                            continue;
085                                    }
086    
087                                    deleteEntry(entry);
088                            }
089                            catch (TrashPermissionException tpe) {
090                                    throwTrashPermissionException = true;
091                            }
092                            catch (Exception e) {
093                                    _log.error(e, e);
094                            }
095                    }
096    
097                    if (throwTrashPermissionException) {
098                            throw new TrashPermissionException(
099                                    TrashPermissionException.EMPTY_TRASH);
100                    }
101            }
102    
103            /**
104             * Deletes the trash entries with the primary keys.
105             *
106             * @param  entryIds the primary keys of the trash entries
107             * @throws PortalException if a trash entry with the primary key could not
108             *         be found or if the user did not have permission to delete any one
109             *         of the trash entries
110             * @throws SystemException if a system exception occurred
111             */
112            @Override
113            @Transactional(noRollbackFor = {TrashPermissionException.class})
114            public void deleteEntries(long[] entryIds)
115                    throws PortalException, SystemException {
116    
117                    boolean throwTrashPermissionException = false;
118    
119                    for (long entryId : entryIds) {
120                            try {
121                                    deleteEntry(entryId);
122                            }
123                            catch (TrashPermissionException tpe) {
124                                    throwTrashPermissionException = true;
125                            }
126                    }
127    
128                    if (throwTrashPermissionException) {
129                            throw new TrashPermissionException(
130                                    TrashPermissionException.EMPTY_TRASH);
131                    }
132            }
133    
134            /**
135             * Deletes the trash entry with the primary key.
136             *
137             * <p>
138             * This method throws a {@link TrashPermissionException} with type {@link
139             * TrashPermissionException#DELETE} if the user did not have permission to
140             * delete the trash entry.
141             * </p>
142             *
143             * @param  entryId the primary key of the trash entry
144             * @throws PortalException if a trash entry with the primary key could not
145             *         be found or if the user did not have permission to delete the
146             *         trash entry
147             * @throws SystemException if a system exception occurred
148             */
149            @Override
150            public void deleteEntry(long entryId)
151                    throws PortalException, SystemException {
152    
153                    TrashEntry entry = trashEntryPersistence.findByPrimaryKey(entryId);
154    
155                    deleteEntry(entry);
156            }
157    
158            /**
159             * Deletes the trash entry with the entity class name and class primary key.
160             *
161             * <p>
162             * This method throws a {@link TrashPermissionException} with type {@link
163             * TrashPermissionException#DELETE} if the user did not have permission to
164             * delete the trash entry.
165             * </p>
166             *
167             * @param  className the class name of the entity
168             * @param  classPK the primary key of the entity
169             * @throws PortalException if a trash entry with the entity class name and
170             *         primary key could not be found or if the user did not have
171             *         permission to delete the entry
172             * @throws SystemException if a system exception occurred
173             */
174            @Override
175            public void deleteEntry(String className, long classPK)
176                    throws PortalException, SystemException {
177    
178                    TrashEntry entry = trashEntryLocalService.fetchEntry(
179                            className, classPK);
180    
181                    if (entry == null) {
182                            entry = new TrashEntryImpl();
183    
184                            entry.setClassName(className);
185                            entry.setClassPK(classPK);
186                    }
187    
188                    deleteEntry(entry);
189            }
190    
191            /**
192             * Returns the trash entries with the matching group ID.
193             *
194             * @param  groupId the primary key of the group
195             * @return the matching trash entries
196             * @throws PrincipalException if a principal exception occurred
197             * @throws SystemException if a system exception occurred
198             */
199            @Override
200            public TrashEntryList getEntries(long groupId)
201                    throws PrincipalException, SystemException {
202    
203                    return getEntries(groupId, QueryUtil.ALL_POS, QueryUtil.ALL_POS, null);
204            }
205    
206            /**
207             * Returns a range of all the trash entries matching the group ID.
208             *
209             * @param  groupId the primary key of the group
210             * @param  start the lower bound of the range of trash entries to return
211             * @param  end the upper bound of the range of trash entries to return (not
212             *         inclusive)
213             * @param  obc the comparator to order the trash entries (optionally
214             *         <code>null</code>)
215             * @return the range of matching trash entries ordered by comparator
216             *         <code>obc</code>
217             * @throws PrincipalException if a system exception occurred
218             * @throws SystemException if a system exception occurred
219             */
220            @Override
221            public TrashEntryList getEntries(
222                            long groupId, int start, int end, OrderByComparator obc)
223                    throws PrincipalException, SystemException {
224    
225                    TrashEntryList trashEntriesList = new TrashEntryList();
226    
227                    int entriesCount = trashEntryPersistence.countByGroupId(groupId);
228    
229                    boolean approximate = entriesCount > PropsValues.TRASH_SEARCH_LIMIT;
230    
231                    trashEntriesList.setApproximate(approximate);
232    
233                    List<TrashEntry> entries = trashEntryPersistence.findByGroupId(
234                            groupId, 0, end + PropsValues.TRASH_SEARCH_LIMIT, obc);
235    
236                    List<TrashEntry> filteredEntries = new ArrayList<TrashEntry>();
237    
238                    PermissionChecker permissionChecker = getPermissionChecker();
239    
240                    for (TrashEntry entry : entries) {
241                            String className = entry.getClassName();
242                            long classPK = entry.getClassPK();
243    
244                            try {
245                                    TrashHandler trashHandler =
246                                            TrashHandlerRegistryUtil.getTrashHandler(className);
247    
248                                    if (trashHandler.hasTrashPermission(
249                                                    permissionChecker, 0, classPK, ActionKeys.VIEW)) {
250    
251                                            filteredEntries.add(entry);
252                                    }
253                            }
254                            catch (Exception e) {
255                                    _log.error(e, e);
256                            }
257                    }
258    
259                    int total = filteredEntries.size();
260    
261                    if ((start == QueryUtil.ALL_POS) && (end == QueryUtil.ALL_POS)) {
262                            start = 0;
263                            end = total;
264                    }
265    
266                    int[] startAndEnd = SearchPaginationUtil.calculateStartAndEnd(
267                            start, end, total);
268    
269                    start = startAndEnd[0];
270                    end = startAndEnd[1];
271    
272                    filteredEntries = filteredEntries.subList(start, end);
273    
274                    trashEntriesList.setArray(TrashEntrySoap.toSoapModels(filteredEntries));
275                    trashEntriesList.setCount(total);
276    
277                    return trashEntriesList;
278            }
279    
280            /**
281             * Moves the trash entry with the entity class name and primary key,
282             * restoring it to a new location identified by the destination container
283             * model ID.
284             *
285             * <p>
286             * This method throws a {@link TrashPermissionException} if the user did not
287             * have the permission to perform one of the necessary operations. The
288             * exception is created with a type specific to the operation:
289             * </p>
290             *
291             * <ul>
292             * <li>
293             * {@link TrashPermissionException#MOVE} - if the user did not have
294             * permission to move the trash entry to the new
295             * destination
296             * </li>
297             * <li>
298             * {@link TrashPermissionException#RESTORE} - if the user did not have
299             * permission to restore the trash entry
300             * </li>
301             * </ul>
302             *
303             * @param  className the class name of the entity
304             * @param  classPK the primary key of the entity
305             * @param  destinationContainerModelId the primary key of the new location
306             * @param  serviceContext the service context to be applied (optionally
307             *         <code>null</code>)
308             * @throws PortalException if a matching trash entry could not be found, if
309             *         the user did not have permission to move the trash entry to the
310             *         new location, if the user did not have permission to restore the
311             *         trash entry, if a duplicate trash entry exists at the new
312             *         location, or if a portal exception occurred
313             * @throws SystemException if a system exception occurred
314             */
315            @Override
316            public void moveEntry(
317                            String className, long classPK, long destinationContainerModelId,
318                            ServiceContext serviceContext)
319                    throws PortalException, SystemException {
320    
321                    PermissionChecker permissionChecker = getPermissionChecker();
322    
323                    long scopeGroupId = 0;
324    
325                    if (serviceContext != null) {
326                            scopeGroupId = serviceContext.getScopeGroupId();
327                    }
328    
329                    TrashHandler trashHandler = TrashHandlerRegistryUtil.getTrashHandler(
330                            className);
331    
332                    if (!trashHandler.hasTrashPermission(
333                                    permissionChecker, scopeGroupId, destinationContainerModelId,
334                                    TrashActionKeys.MOVE)) {
335    
336                            throw new TrashPermissionException(TrashPermissionException.MOVE);
337                    }
338    
339                    if (trashHandler.isInTrash(classPK) &&
340                            !trashHandler.hasTrashPermission(
341                                    permissionChecker, 0, classPK, TrashActionKeys.RESTORE)) {
342    
343                            throw new TrashPermissionException(
344                                    TrashPermissionException.RESTORE);
345                    }
346    
347                    TrashEntry trashEntry = trashHandler.getTrashEntry(classPK);
348    
349                    if (trashEntry.isTrashEntry(className, classPK)) {
350                            trashHandler.checkDuplicateTrashEntry(
351                                    trashEntry, destinationContainerModelId, StringPool.BLANK);
352                    }
353                    else {
354                            trashHandler.checkDuplicateEntry(
355                                    classPK, destinationContainerModelId, StringPool.BLANK);
356                    }
357    
358                    trashHandler.moveTrashEntry(
359                            getUserId(), classPK, destinationContainerModelId, serviceContext);
360            }
361    
362            @Override
363            public TrashEntry restoreEntry(long entryId)
364                    throws PortalException, SystemException {
365    
366                    return restoreEntry(entryId, 0, null);
367            }
368    
369            /**
370             * Restores the trash entry to its original location. In order to handle a
371             * duplicate trash entry already existing at the original location, either
372             * pass in the primary key of the existing trash entry's entity to overwrite
373             * or pass in a new name to give to the trash entry being restored.
374             *
375             * <p>
376             * This method throws a {@link TrashPermissionException} if the user did not
377             * have the permission to perform one of the necessary operations. The
378             * exception is created with a type specific to the operation:
379             * </p>
380             *
381             * <ul>
382             * <li>
383             * {@link TrashPermissionException#RESTORE} - if the user did not have
384             * permission to restore the trash entry
385             * </li>
386             * <li>
387             * {@link TrashPermissionException#RESTORE_OVERWRITE} - if the user did not
388             * have permission to delete the existing trash entry
389             * </li>
390             * <li>
391             * {@link TrashPermissionException#RESTORE_RENAME} - if the user did not
392             * have permission to rename the trash entry
393             * </li>
394             * </ul>
395             *
396             * @param  entryId the primary key of the trash entry to restore
397             * @param  overrideClassPK the primary key of the entity to overwrite
398             *         (optionally <code>0</code>)
399             * @param  name a new name to give to the trash entry being restored
400             *         (optionally <code>null</code>)
401             * @return the restored trash entry
402             * @throws PortalException if a matching trash entry could not be found, if
403             *         the user did not have permission to overwrite an existing trash
404             *         entry, to rename the trash entry being restored, or to restore
405             *         the trash entry in general
406             * @throws SystemException if a system exception occurred
407             */
408            @Override
409            public TrashEntry restoreEntry(
410                            long entryId, long overrideClassPK, String name)
411                    throws PortalException, SystemException {
412    
413                    PermissionChecker permissionChecker = getPermissionChecker();
414    
415                    TrashEntry entry = trashEntryPersistence.findByPrimaryKey(entryId);
416    
417                    TrashHandler trashHandler = TrashHandlerRegistryUtil.getTrashHandler(
418                            entry.getClassName());
419    
420                    if (!trashHandler.hasTrashPermission(
421                                    permissionChecker, 0, entry.getClassPK(),
422                                    TrashActionKeys.RESTORE)) {
423    
424                            throw new TrashPermissionException(
425                                    TrashPermissionException.RESTORE);
426                    }
427    
428                    if (overrideClassPK > 0) {
429                            if (!trashHandler.hasTrashPermission(
430                                            permissionChecker, 0, overrideClassPK,
431                                            TrashActionKeys.OVERWRITE)) {
432    
433                                    throw new TrashPermissionException(
434                                            TrashPermissionException.RESTORE_OVERWRITE);
435                            }
436    
437                            trashHandler.deleteTrashEntry(overrideClassPK);
438    
439                            trashHandler.checkDuplicateTrashEntry(
440                                    entry, TrashEntryConstants.DEFAULT_CONTAINER_ID, null);
441                    }
442                    else if (name != null) {
443                            if (!trashHandler.hasTrashPermission(
444                                            permissionChecker, 0, entry.getClassPK(),
445                                            TrashActionKeys.RENAME)) {
446    
447                                    throw new TrashPermissionException(
448                                            TrashPermissionException.RESTORE_RENAME);
449                            }
450    
451                            trashHandler.checkDuplicateTrashEntry(
452                                    entry, TrashEntryConstants.DEFAULT_CONTAINER_ID, name);
453    
454                            trashHandler.updateTitle(entry.getClassPK(), name);
455                    }
456    
457                    trashHandler.restoreTrashEntry(getUserId(), entry.getClassPK());
458    
459                    return entry;
460            }
461    
462            protected void deleteEntry(TrashEntry entry)
463                    throws PortalException, SystemException {
464    
465                    PermissionChecker permissionChecker = getPermissionChecker();
466    
467                    TrashHandler trashHandler = TrashHandlerRegistryUtil.getTrashHandler(
468                            entry.getClassName());
469    
470                    if (!trashHandler.hasTrashPermission(
471                                    permissionChecker, 0, entry.getClassPK(), ActionKeys.DELETE)) {
472    
473                            throw new TrashPermissionException(TrashPermissionException.DELETE);
474                    }
475    
476                    trashHandler.deleteTrashEntry(entry.getClassPK());
477            }
478    
479            private static Log _log = LogFactoryUtil.getLog(
480                    TrashEntryServiceImpl.class);
481    
482    }