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