/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.portlet.trash.service.impl;
import com.liferay.portal.kernel.dao.orm.QueryUtil;
import com.liferay.portal.kernel.dao.search.SearchPaginationUtil;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.TrashPermissionException;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.security.auth.PrincipalException;
import com.liferay.portal.kernel.security.permission.ActionKeys;
import com.liferay.portal.kernel.security.permission.PermissionChecker;
import com.liferay.portal.kernel.service.ServiceContext;
import com.liferay.portal.kernel.transaction.Transactional;
import com.liferay.portal.kernel.trash.TrashActionKeys;
import com.liferay.portal.kernel.trash.TrashHandler;
import com.liferay.portal.kernel.trash.TrashHandlerRegistryUtil;
import com.liferay.portal.kernel.util.OrderByComparator;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.util.PropsValues;
import com.liferay.portlet.trash.model.impl.TrashEntryImpl;
import com.liferay.portlet.trash.service.base.TrashEntryServiceBaseImpl;
import com.liferay.trash.kernel.model.TrashEntry;
import com.liferay.trash.kernel.model.TrashEntryConstants;
import com.liferay.trash.kernel.model.TrashEntryList;
import com.liferay.trash.kernel.model.TrashEntrySoap;
import java.util.ArrayList;
import java.util.List;
/**
* The trash entry remote service is responsible for returning trash entries.
* For more information on trash entries services and TrashEntry, see {@link
* TrashEntryLocalServiceImpl}.
*
* @author Julio Camarero
* @author Zsolt Berentey
*/
public class TrashEntryServiceImpl extends TrashEntryServiceBaseImpl {
/**
* Deletes the trash entries with the matching group ID considering
* permissions.
*
* @param groupId the primary key of the group
*/
@Override
@Transactional(noRollbackFor = {TrashPermissionException.class})
public void deleteEntries(long groupId) throws PortalException {
boolean throwTrashPermissionException = false;
List<TrashEntry> entries = trashEntryPersistence.findByGroupId(groupId);
PermissionChecker permissionChecker = getPermissionChecker();
for (TrashEntry entry : entries) {
entry = trashEntryPersistence.fetchByPrimaryKey(entry.getEntryId());
if (entry == null) {
continue;
}
try {
TrashHandler trashHandler =
TrashHandlerRegistryUtil.getTrashHandler(
entry.getClassName());
if (!trashHandler.hasTrashPermission(
permissionChecker, 0, entry.getClassPK(),
ActionKeys.VIEW)) {
continue;
}
deleteEntry(entry);
}
catch (TrashPermissionException tpe) {
// LPS-52675
if (_log.isDebugEnabled()) {
_log.debug(tpe, tpe);
}
throwTrashPermissionException = true;
}
catch (Exception e) {
_log.error(e, e);
}
}
if (throwTrashPermissionException) {
throw new TrashPermissionException(
TrashPermissionException.EMPTY_TRASH);
}
}
/**
* Deletes the trash entries with the primary keys.
*
* @param entryIds the primary keys of the trash entries
*/
@Override
@Transactional(noRollbackFor = {TrashPermissionException.class})
public void deleteEntries(long[] entryIds) throws PortalException {
boolean throwTrashPermissionException = false;
for (long entryId : entryIds) {
try {
deleteEntry(entryId);
}
catch (TrashPermissionException tpe) {
// LPS-52675
if (_log.isDebugEnabled()) {
_log.debug(tpe, tpe);
}
throwTrashPermissionException = true;
}
}
if (throwTrashPermissionException) {
throw new TrashPermissionException(
TrashPermissionException.EMPTY_TRASH);
}
}
/**
* Deletes the trash entry with the primary key.
*
* <p>
* This method throws a {@link TrashPermissionException} with type {@link
* TrashPermissionException#DELETE} if the user did not have permission to
* delete the trash entry.
* </p>
*
* @param entryId the primary key of the trash entry
*/
@Override
public void deleteEntry(long entryId) throws PortalException {
TrashEntry entry = trashEntryPersistence.findByPrimaryKey(entryId);
deleteEntry(entry);
}
/**
* Deletes the trash entry with the entity class name and class primary key.
*
* <p>
* This method throws a {@link TrashPermissionException} with type {@link
* TrashPermissionException#DELETE} if the user did not have permission to
* delete the trash entry.
* </p>
*
* @param className the class name of the entity
* @param classPK the primary key of the entity
*/
@Override
public void deleteEntry(String className, long classPK)
throws PortalException {
TrashEntry entry = trashEntryLocalService.fetchEntry(
className, classPK);
if (entry == null) {
entry = new TrashEntryImpl();
entry.setClassName(className);
entry.setClassPK(classPK);
}
deleteEntry(entry);
}
/**
* Returns the trash entries with the matching group ID.
*
* @param groupId the primary key of the group
* @return the matching trash entries
*/
@Override
public TrashEntryList getEntries(long groupId) throws PrincipalException {
return getEntries(groupId, QueryUtil.ALL_POS, QueryUtil.ALL_POS, null);
}
/**
* Returns a range of all the trash entries matching the group ID.
*
* @param groupId the primary key of the group
* @param start the lower bound of the range of trash entries to return
* @param end the upper bound of the range of trash entries to return (not
* inclusive)
* @param obc the comparator to order the trash entries (optionally
* <code>null</code>)
* @return the range of matching trash entries ordered by comparator
* <code>obc</code>
*/
@Override
public TrashEntryList getEntries(
long groupId, int start, int end, OrderByComparator<TrashEntry> obc)
throws PrincipalException {
return getEntries(groupId, null, start, end, obc);
}
@Override
public List<TrashEntry> getEntries(long groupId, String className)
throws PrincipalException {
long classNameId = classNameLocalService.getClassNameId(className);
List<TrashEntry> entries = trashEntryPersistence.findByG_C(
groupId, classNameId);
return filterEntries(entries);
}
/**
* Returns a range of all the trash entries matching the group ID.
*
* @param groupId the primary key of the group
* @param className the class name of the entity
* @param start the lower bound of the range of trash entries to return
* @param end the upper bound of the range of trash entries to return (not
* inclusive)
* @param obc the comparator to order the trash entries (optionally
* <code>null</code>)
* @return the range of matching trash entries ordered by comparator
* <code>obc</code>
*/
@Override
public TrashEntryList getEntries(
long groupId, String className, int start, int end,
OrderByComparator<TrashEntry> obc)
throws PrincipalException {
TrashEntryList trashEntriesList = new TrashEntryList();
int entriesCount = trashEntryPersistence.countByGroupId(groupId);
boolean approximate = false;
if (entriesCount > PropsValues.TRASH_SEARCH_LIMIT) {
approximate = true;
}
trashEntriesList.setApproximate(approximate);
List<TrashEntry> entries = null;
if (Validator.isNotNull(className)) {
long classNameId = classNameLocalService.getClassNameId(className);
entries = trashEntryPersistence.findByG_C(
groupId, classNameId, 0, end + PropsValues.TRASH_SEARCH_LIMIT,
obc);
}
else {
entries = trashEntryPersistence.findByGroupId(
groupId, 0, end + PropsValues.TRASH_SEARCH_LIMIT, obc);
}
List<TrashEntry> filteredEntries = filterEntries(entries);
int total = filteredEntries.size();
if ((start == QueryUtil.ALL_POS) && (end == QueryUtil.ALL_POS)) {
start = 0;
end = total;
}
int[] startAndEnd = SearchPaginationUtil.calculateStartAndEnd(
start, end, total);
start = startAndEnd[0];
end = startAndEnd[1];
filteredEntries = filteredEntries.subList(start, end);
trashEntriesList.setArray(TrashEntrySoap.toSoapModels(filteredEntries));
trashEntriesList.setCount(total);
return trashEntriesList;
}
/**
* Moves the trash entry with the entity class name and primary key,
* restoring it to a new location identified by the destination container
* model ID.
*
* <p>
* This method throws a {@link TrashPermissionException} if the user did not
* have the permission to perform one of the necessary operations. The
* exception is created with a type specific to the operation:
* </p>
*
* <ul>
* <li>
* {@link TrashPermissionException#MOVE} - if the user did not have
* permission to move the trash entry to the new
* destination
* </li>
* <li>
* {@link TrashPermissionException#RESTORE} - if the user did not have
* permission to restore the trash entry
* </li>
* </ul>
*
* @param className the class name of the entity
* @param classPK the primary key of the entity
* @param destinationContainerModelId the primary key of the new location
* @param serviceContext the service context to be applied (optionally
* <code>null</code>)
*/
@Override
public void moveEntry(
String className, long classPK, long destinationContainerModelId,
ServiceContext serviceContext)
throws PortalException {
PermissionChecker permissionChecker = getPermissionChecker();
long scopeGroupId = 0;
if (serviceContext != null) {
scopeGroupId = serviceContext.getScopeGroupId();
}
TrashHandler trashHandler = TrashHandlerRegistryUtil.getTrashHandler(
className);
destinationContainerModelId =
trashHandler.getDestinationContainerModelId(
classPK, destinationContainerModelId);
if (!trashHandler.hasTrashPermission(
permissionChecker, scopeGroupId, destinationContainerModelId,
TrashActionKeys.MOVE)) {
throw new TrashPermissionException(TrashPermissionException.MOVE);
}
if (trashHandler.isInTrash(classPK) &&
!trashHandler.hasTrashPermission(
permissionChecker, 0, classPK, TrashActionKeys.RESTORE)) {
throw new TrashPermissionException(
TrashPermissionException.RESTORE);
}
TrashEntry trashEntry = trashHandler.getTrashEntry(classPK);
if (trashEntry.isTrashEntry(className, classPK)) {
trashHandler.checkRestorableEntry(
trashEntry, destinationContainerModelId, StringPool.BLANK);
}
else {
trashHandler.checkRestorableEntry(
classPK, destinationContainerModelId, StringPool.BLANK);
}
trashHandler.moveTrashEntry(
getUserId(), classPK, destinationContainerModelId, serviceContext);
}
@Override
public TrashEntry restoreEntry(long entryId) throws PortalException {
return restoreEntry(entryId, 0, null);
}
/**
* Restores the trash entry to its original location. In order to handle a
* duplicate trash entry already existing at the original location, either
* pass in the primary key of the existing trash entry's entity to overwrite
* or pass in a new name to give to the trash entry being restored.
*
* <p>
* This method throws a {@link TrashPermissionException} if the user did not
* have the permission to perform one of the necessary operations. The
* exception is created with a type specific to the operation:
* </p>
*
* <ul>
* <li>
* {@link TrashPermissionException#RESTORE} - if the user did not have
* permission to restore the trash entry
* </li>
* <li>
* {@link TrashPermissionException#RESTORE_OVERWRITE} - if the user did not
* have permission to delete the existing trash entry
* </li>
* <li>
* {@link TrashPermissionException#RESTORE_RENAME} - if the user did not
* have permission to rename the trash entry
* </li>
* </ul>
*
* @param entryId the primary key of the trash entry to restore
* @param overrideClassPK the primary key of the entity to overwrite
* (optionally <code>0</code>)
* @param name a new name to give to the trash entry being restored
* (optionally <code>null</code>)
* @return the restored trash entry
*/
@Override
public TrashEntry restoreEntry(
long entryId, long overrideClassPK, String name)
throws PortalException {
PermissionChecker permissionChecker = getPermissionChecker();
TrashEntry entry = trashEntryPersistence.findByPrimaryKey(entryId);
TrashHandler trashHandler = TrashHandlerRegistryUtil.getTrashHandler(
entry.getClassName());
if (!trashHandler.hasTrashPermission(
permissionChecker, 0, entry.getClassPK(),
TrashActionKeys.RESTORE)) {
throw new TrashPermissionException(
TrashPermissionException.RESTORE);
}
if (overrideClassPK > 0) {
if (!trashHandler.hasTrashPermission(
permissionChecker, 0, overrideClassPK,
TrashActionKeys.OVERWRITE)) {
throw new TrashPermissionException(
TrashPermissionException.RESTORE_OVERWRITE);
}
trashHandler.deleteTrashEntry(overrideClassPK);
trashHandler.checkRestorableEntry(
entry, TrashEntryConstants.DEFAULT_CONTAINER_ID, null);
}
else if (name != null) {
if (!trashHandler.hasTrashPermission(
permissionChecker, 0, entry.getClassPK(),
TrashActionKeys.RENAME)) {
throw new TrashPermissionException(
TrashPermissionException.RESTORE_RENAME);
}
trashHandler.checkRestorableEntry(
entry, TrashEntryConstants.DEFAULT_CONTAINER_ID, name);
trashHandler.updateTitle(entry.getClassPK(), name);
}
trashHandler.restoreTrashEntry(getUserId(), entry.getClassPK());
return entry;
}
@Override
public TrashEntry restoreEntry(String className, long classPK)
throws PortalException {
return restoreEntry(className, classPK, 0, null);
}
@Override
public TrashEntry restoreEntry(
String className, long classPK, long overrideClassPK, String name)
throws PortalException {
TrashEntry trashEntry = trashEntryPersistence.fetchByC_C(
classNameLocalService.getClassNameId(className), classPK);
if (trashEntry != null) {
return restoreEntry(trashEntry.getEntryId(), overrideClassPK, name);
}
return null;
}
protected void deleteEntry(TrashEntry entry) throws PortalException {
PermissionChecker permissionChecker = getPermissionChecker();
TrashHandler trashHandler = TrashHandlerRegistryUtil.getTrashHandler(
entry.getClassName());
if (!trashHandler.hasTrashPermission(
permissionChecker, 0, entry.getClassPK(), ActionKeys.DELETE)) {
throw new TrashPermissionException(TrashPermissionException.DELETE);
}
trashHandler.deleteTrashEntry(entry.getClassPK());
}
protected List<TrashEntry> filterEntries(List<TrashEntry> entries)
throws PrincipalException {
List<TrashEntry> filteredEntries = new ArrayList<>();
PermissionChecker permissionChecker = getPermissionChecker();
for (TrashEntry entry : entries) {
String className = entry.getClassName();
long classPK = entry.getClassPK();
try {
TrashHandler trashHandler =
TrashHandlerRegistryUtil.getTrashHandler(className);
if (trashHandler.hasTrashPermission(
permissionChecker, 0, classPK, ActionKeys.VIEW)) {
filteredEntries.add(entry);
}
}
catch (Exception e) {
_log.error(e, e);
}
}
return filteredEntries;
}
private static final Log _log = LogFactoryUtil.getLog(
TrashEntryServiceImpl.class);
}