001
014
015 package com.liferay.portlet.trash.util;
016
017 import com.liferay.document.library.kernel.store.DLStoreUtil;
018 import com.liferay.portal.kernel.exception.PortalException;
019 import com.liferay.portal.kernel.language.LanguageUtil;
020 import com.liferay.portal.kernel.log.Log;
021 import com.liferay.portal.kernel.log.LogFactoryUtil;
022 import com.liferay.portal.kernel.model.ContainerModel;
023 import com.liferay.portal.kernel.model.Group;
024 import com.liferay.portal.kernel.model.TrashedModel;
025 import com.liferay.portal.kernel.portlet.LiferayPortletResponse;
026 import com.liferay.portal.kernel.portlet.PortletProvider;
027 import com.liferay.portal.kernel.portlet.PortletProviderUtil;
028 import com.liferay.portal.kernel.portlet.PortletURLUtil;
029 import com.liferay.portal.kernel.search.Document;
030 import com.liferay.portal.kernel.search.Field;
031 import com.liferay.portal.kernel.search.Hits;
032 import com.liferay.portal.kernel.security.pacl.DoPrivileged;
033 import com.liferay.portal.kernel.service.GroupLocalServiceUtil;
034 import com.liferay.portal.kernel.service.permission.PortletPermissionUtil;
035 import com.liferay.portal.kernel.servlet.SessionMessages;
036 import com.liferay.portal.kernel.theme.ThemeDisplay;
037 import com.liferay.portal.kernel.trash.TrashHandler;
038 import com.liferay.portal.kernel.trash.TrashHandlerRegistryUtil;
039 import com.liferay.portal.kernel.trash.TrashRenderer;
040 import com.liferay.portal.kernel.util.ArrayUtil;
041 import com.liferay.portal.kernel.util.Constants;
042 import com.liferay.portal.kernel.util.FastDateFormatFactoryUtil;
043 import com.liferay.portal.kernel.util.GetterUtil;
044 import com.liferay.portal.kernel.util.OrderByComparator;
045 import com.liferay.portal.kernel.util.PortalUtil;
046 import com.liferay.portal.kernel.util.PrefsPropsUtil;
047 import com.liferay.portal.kernel.util.PropsKeys;
048 import com.liferay.portal.kernel.util.StringBundler;
049 import com.liferay.portal.kernel.util.StringPool;
050 import com.liferay.portal.kernel.util.StringUtil;
051 import com.liferay.portal.kernel.util.UnicodeProperties;
052 import com.liferay.portal.kernel.util.Validator;
053 import com.liferay.portal.kernel.util.WebKeys;
054 import com.liferay.portal.util.PropsValues;
055 import com.liferay.portlet.trash.model.impl.TrashEntryImpl;
056 import com.liferay.trash.kernel.model.TrashEntry;
057 import com.liferay.trash.kernel.model.TrashVersion;
058 import com.liferay.trash.kernel.service.TrashEntryLocalServiceUtil;
059 import com.liferay.trash.kernel.service.TrashVersionLocalServiceUtil;
060 import com.liferay.trash.kernel.util.Trash;
061 import com.liferay.trash.kernel.util.TrashUtil;
062 import com.liferay.trash.kernel.util.comparator.EntryCreateDateComparator;
063 import com.liferay.trash.kernel.util.comparator.EntryTypeComparator;
064 import com.liferay.trash.kernel.util.comparator.EntryUserNameComparator;
065
066 import java.text.Format;
067
068 import java.util.ArrayList;
069 import java.util.Collections;
070 import java.util.Date;
071 import java.util.HashMap;
072 import java.util.List;
073 import java.util.Map;
074
075 import javax.portlet.ActionRequest;
076 import javax.portlet.PortletException;
077 import javax.portlet.PortletRequest;
078 import javax.portlet.PortletURL;
079
080 import javax.servlet.http.HttpServletRequest;
081
082
086 @DoPrivileged
087 public class TrashImpl implements Trash {
088
089 @Override
090 public void addBaseModelBreadcrumbEntries(
091 HttpServletRequest request,
092 LiferayPortletResponse liferayPortletResponse, String className,
093 long classPK, PortletURL containerModelURL)
094 throws PortalException, PortletException {
095
096 addBreadcrumbEntries(
097 request, liferayPortletResponse, className, classPK, "classPK",
098 containerModelURL, true);
099 }
100
101 @Override
102 public void addContainerModelBreadcrumbEntries(
103 HttpServletRequest request,
104 LiferayPortletResponse liferayPortletResponse, String className,
105 long classPK, PortletURL containerModelURL)
106 throws PortalException, PortletException {
107
108 ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
109 WebKeys.THEME_DISPLAY);
110
111 TrashHandler trashHandler = TrashHandlerRegistryUtil.getTrashHandler(
112 className);
113
114 String rootContainerModelTitle = LanguageUtil.get(
115 themeDisplay.getLocale(), trashHandler.getRootContainerModelName());
116
117 if (classPK == 0) {
118 PortalUtil.addPortletBreadcrumbEntry(
119 request, rootContainerModelTitle, null);
120
121 return;
122 }
123
124 containerModelURL.setParameter("containerModelId", "0");
125
126 PortalUtil.addPortletBreadcrumbEntry(
127 request, rootContainerModelTitle, containerModelURL.toString());
128
129 addBreadcrumbEntries(
130 request, liferayPortletResponse, className, classPK,
131 "containerModelId", containerModelURL, false);
132 }
133
134 @Override
135 public void addTrashSessionMessages(
136 ActionRequest actionRequest, List<TrashedModel> trashedModels) {
137
138 addTrashSessionMessages(
139 actionRequest, trashedModels, Constants.MOVE_TO_TRASH);
140 }
141
142 @Override
143 public void addTrashSessionMessages(
144 ActionRequest actionRequest, List<TrashedModel> trashedModels,
145 String cmd) {
146
147 ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
148 WebKeys.THEME_DISPLAY);
149
150 List<String> classNames = new ArrayList<>();
151 List<Long> restoreTrashEntryIds = new ArrayList<>();
152 List<String> titles = new ArrayList<>();
153
154 for (int i = 0; i < trashedModels.size(); i++) {
155 try {
156 TrashedModel trashedModel = trashedModels.get(i);
157
158 TrashEntry trashEntry = trashedModel.getTrashEntry();
159
160 TrashHandler trashHandler = trashedModel.getTrashHandler();
161
162 TrashRenderer trashRenderer = trashHandler.getTrashRenderer(
163 trashedModel.getTrashEntryClassPK());
164
165 classNames.add(trashRenderer.getClassName());
166 restoreTrashEntryIds.add(trashEntry.getEntryId());
167 titles.add(trashRenderer.getTitle(themeDisplay.getLocale()));
168 }
169 catch (Exception e) {
170 }
171 }
172
173 Map<String, String[]> data = new HashMap<>();
174
175 data.put(Constants.CMD, new String[] {cmd});
176
177 data.put(
178 "deleteEntryClassName",
179 ArrayUtil.toStringArray(classNames.toArray()));
180 data.put("deleteEntryTitle", ArrayUtil.toStringArray(titles.toArray()));
181 data.put(
182 "restoreTrashEntryIds",
183 ArrayUtil.toStringArray(restoreTrashEntryIds.toArray()));
184
185 SessionMessages.add(
186 actionRequest,
187 PortalUtil.getPortletId(actionRequest) +
188 SessionMessages.KEY_SUFFIX_DELETE_SUCCESS_DATA,
189 data);
190 }
191
192 @Override
193 public void addTrashSessionMessages(
194 ActionRequest actionRequest, TrashedModel trashedModel) {
195
196 addTrashSessionMessages(
197 actionRequest, trashedModel, Constants.MOVE_TO_TRASH);
198 }
199
200 @Override
201 public void addTrashSessionMessages(
202 ActionRequest actionRequest, TrashedModel trashedModel, String cmd) {
203
204 List<TrashedModel> trashedModels = new ArrayList<>();
205
206 trashedModels.add(trashedModel);
207
208 addTrashSessionMessages(actionRequest, trashedModels, cmd);
209 }
210
211 @Override
212 public void deleteEntriesAttachments(
213 long companyId, long repositoryId, Date date,
214 String[] attachmentFileNames) {
215
216 for (String attachmentFileName : attachmentFileNames) {
217 String trashTime = TrashUtil.getTrashTime(
218 attachmentFileName, TRASH_TIME_SEPARATOR);
219
220 long timestamp = GetterUtil.getLong(trashTime);
221
222 if (timestamp < date.getTime()) {
223 DLStoreUtil.deleteDirectory(
224 companyId, repositoryId, attachmentFileName);
225 }
226 }
227 }
228
229 @Override
230 public Group disableTrash(Group group) {
231 UnicodeProperties typeSettingsProperties =
232 group.getParentLiveGroupTypeSettingsProperties();
233
234 typeSettingsProperties.setProperty("trashEnabled", StringPool.FALSE);
235
236 group.setTypeSettingsProperties(typeSettingsProperties);
237
238 return GroupLocalServiceUtil.updateGroup(group);
239 }
240
241 @Override
242 public List<TrashEntry> getEntries(Hits hits) {
243 List<TrashEntry> entries = new ArrayList<>();
244
245 for (Document document : hits.getDocs()) {
246 String entryClassName = GetterUtil.getString(
247 document.get(Field.ENTRY_CLASS_NAME));
248 long classPK = GetterUtil.getLong(
249 document.get(Field.ENTRY_CLASS_PK));
250
251 try {
252 TrashEntry entry = TrashEntryLocalServiceUtil.fetchEntry(
253 entryClassName, classPK);
254
255 if (entry == null) {
256 String userName = GetterUtil.getString(
257 document.get(Field.REMOVED_BY_USER_NAME));
258
259 Date removedDate = document.getDate(Field.REMOVED_DATE);
260
261 entry = new TrashEntryImpl();
262
263 entry.setUserName(userName);
264 entry.setCreateDate(removedDate);
265
266 TrashHandler trashHandler =
267 TrashHandlerRegistryUtil.getTrashHandler(
268 entryClassName);
269
270 TrashRenderer trashRenderer = trashHandler.getTrashRenderer(
271 classPK);
272
273 entry.setClassName(trashRenderer.getClassName());
274 entry.setClassPK(trashRenderer.getClassPK());
275
276 String rootEntryClassName = GetterUtil.getString(
277 document.get(Field.ROOT_ENTRY_CLASS_NAME));
278 long rootEntryClassPK = GetterUtil.getLong(
279 document.get(Field.ROOT_ENTRY_CLASS_PK));
280
281 TrashEntry rootTrashEntry =
282 TrashEntryLocalServiceUtil.fetchEntry(
283 rootEntryClassName, rootEntryClassPK);
284
285 if (rootTrashEntry != null) {
286 entry.setRootEntry(rootTrashEntry);
287 }
288 }
289
290 entries.add(entry);
291 }
292 catch (Exception e) {
293 if (_log.isWarnEnabled()) {
294 _log.warn(
295 "Unable to find trash entry for " + entryClassName +
296 " with primary key " + classPK);
297 }
298 }
299 }
300
301 return entries;
302 }
303
304 @Override
305 public OrderByComparator<TrashEntry> getEntryOrderByComparator(
306 String orderByCol, String orderByType) {
307
308 boolean orderByAsc = false;
309
310 if (orderByType.equals("asc")) {
311 orderByAsc = true;
312 }
313
314 OrderByComparator<TrashEntry> orderByComparator = null;
315
316 if (orderByCol.equals("removed-by")) {
317 orderByComparator = new EntryUserNameComparator(orderByAsc);
318 }
319 else if (orderByCol.equals("removed-date")) {
320 orderByComparator = new EntryCreateDateComparator(orderByAsc);
321 }
322 else if (orderByCol.equals("type")) {
323 orderByComparator = new EntryTypeComparator(orderByAsc);
324 }
325
326 return orderByComparator;
327 }
328
329 @Override
330 public int getMaxAge(Group group) {
331 int trashEntriesMaxAge = PrefsPropsUtil.getInteger(
332 group.getCompanyId(), PropsKeys.TRASH_ENTRIES_MAX_AGE,
333 PropsValues.TRASH_ENTRIES_MAX_AGE);
334
335 UnicodeProperties typeSettingsProperties =
336 group.getParentLiveGroupTypeSettingsProperties();
337
338 return GetterUtil.getInteger(
339 typeSettingsProperties.getProperty("trashEntriesMaxAge"),
340 trashEntriesMaxAge);
341 }
342
343 @Override
344 public String getNewName(String oldName, String token) {
345 StringBundler sb = new StringBundler(3);
346
347 sb.append(oldName);
348 sb.append(StringPool.SPACE);
349 sb.append(token);
350
351 return sb.toString();
352 }
353
354 @Override
355 public String getNewName(
356 ThemeDisplay themeDisplay, String className, long classPK,
357 String oldName)
358 throws PortalException {
359
360 TrashRenderer trashRenderer = null;
361
362 if (Validator.isNotNull(className) && (classPK > 0)) {
363 TrashHandler trashHandler =
364 TrashHandlerRegistryUtil.getTrashHandler(className);
365
366 trashRenderer = trashHandler.getTrashRenderer(classPK);
367 }
368
369 Format dateFormatDateTime = FastDateFormatFactoryUtil.getDateTime(
370 themeDisplay.getLocale(), themeDisplay.getTimeZone());
371
372 StringBundler sb = new StringBundler(3);
373
374 sb.append(StringPool.OPEN_PARENTHESIS);
375 sb.append(
376 StringUtil.replace(
377 dateFormatDateTime.format(new Date()),
378 new String[] {StringPool.SLASH, StringPool.COLON},
379 new String[] {StringPool.PERIOD, StringPool.PERIOD}));
380 sb.append(StringPool.CLOSE_PARENTHESIS);
381
382 if (trashRenderer != null) {
383 return trashRenderer.getNewName(oldName, sb.toString());
384 }
385 else {
386 return getNewName(oldName, sb.toString());
387 }
388 }
389
390 @Override
391 public String getOriginalTitle(String title) {
392 return getOriginalTitle(title, "title", TRASH_PREFIX);
393 }
394
395 @Override
396 public String getOriginalTitle(String title, String paramName) {
397 return getOriginalTitle(title, paramName, TRASH_PREFIX);
398 }
399
400 @Override
401 public String getTrashTime(String title, String separator) {
402 int index = title.lastIndexOf(separator);
403
404 if (index < 0) {
405 return StringPool.BLANK;
406 }
407
408 return title.substring(index + 1, title.length());
409 }
410
411 @Override
412 public String getTrashTitle(long trashEntryId) {
413 return getTrashTitle(trashEntryId, TRASH_PREFIX);
414 }
415
416 @Override
417 public PortletURL getViewContentURL(
418 HttpServletRequest request, long trashEntryId)
419 throws PortalException {
420
421 TrashEntry trashEntry = TrashEntryLocalServiceUtil.fetchEntry(
422 trashEntryId);
423
424 return getViewContentURL(
425 request, trashEntry.getClassName(), trashEntry.getClassPK());
426 }
427
428 @Override
429 public PortletURL getViewContentURL(
430 HttpServletRequest request, String className, long classPK)
431 throws PortalException {
432
433 ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
434 WebKeys.THEME_DISPLAY);
435
436 String portletId = PortletProviderUtil.getPortletId(
437 TrashEntry.class.getName(), PortletProvider.Action.VIEW);
438
439 if (!themeDisplay.isSignedIn() ||
440 !isTrashEnabled(themeDisplay.getScopeGroupId()) ||
441 !PortletPermissionUtil.hasControlPanelAccessPermission(
442 themeDisplay.getPermissionChecker(),
443 themeDisplay.getScopeGroupId(), portletId)) {
444
445 return null;
446 }
447
448 TrashHandler trashHandler = TrashHandlerRegistryUtil.getTrashHandler(
449 className);
450
451 if (trashHandler.isInTrashContainer(classPK)) {
452 TrashEntry trashEntry = trashHandler.getTrashEntry(classPK);
453
454 className = trashEntry.getClassName();
455 classPK = trashEntry.getClassPK();
456
457 trashHandler = TrashHandlerRegistryUtil.getTrashHandler(className);
458 }
459
460 TrashRenderer trashRenderer = trashHandler.getTrashRenderer(classPK);
461
462 if (trashRenderer == null) {
463 return null;
464 }
465
466 PortletURL portletURL = PortalUtil.getControlPanelPortletURL(
467 request, portletId, PortletRequest.RENDER_PHASE);
468
469 portletURL.setParameter("mvcPath", "/view_content.jsp");
470 portletURL.setParameter("redirect", themeDisplay.getURLCurrent());
471
472 TrashEntry trashEntry = TrashEntryLocalServiceUtil.getEntry(
473 className, classPK);
474
475 if (trashEntry.getRootEntry() != null) {
476 portletURL.setParameter("className", className);
477 portletURL.setParameter("classPK", String.valueOf(classPK));
478 }
479 else {
480 portletURL.setParameter(
481 "trashEntryId", String.valueOf(trashEntry.getEntryId()));
482 }
483
484 portletURL.setParameter("showAssetMetadata", Boolean.TRUE.toString());
485
486 return portletURL;
487 }
488
489 @Override
490 public PortletURL getViewURL(HttpServletRequest request)
491 throws PortalException {
492
493 ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
494 WebKeys.THEME_DISPLAY);
495
496 String portletId = PortletProviderUtil.getPortletId(
497 TrashEntry.class.getName(), PortletProvider.Action.VIEW);
498
499 if (!themeDisplay.isSignedIn() ||
500 !isTrashEnabled(themeDisplay.getScopeGroupId()) ||
501 !PortletPermissionUtil.hasControlPanelAccessPermission(
502 themeDisplay.getPermissionChecker(),
503 themeDisplay.getScopeGroupId(), portletId)) {
504
505 return null;
506 }
507
508 PortletURL portletURL = PortalUtil.getControlPanelPortletURL(
509 request, portletId, PortletRequest.RENDER_PHASE);
510
511 portletURL.setParameter("redirect", themeDisplay.getURLCurrent());
512
513 return portletURL;
514 }
515
516 @Override
517 public boolean isInTrash(String className, long classPK)
518 throws PortalException {
519
520 TrashHandler trashHandler = TrashHandlerRegistryUtil.getTrashHandler(
521 className);
522
523 if (trashHandler == null) {
524 return false;
525 }
526
527 return trashHandler.isInTrash(classPK);
528 }
529
530 @Override
531 public boolean isTrashEnabled(Group group) {
532 boolean companyTrashEnabled = PrefsPropsUtil.getBoolean(
533 group.getCompanyId(), PropsKeys.TRASH_ENABLED);
534
535 if (!companyTrashEnabled) {
536 return false;
537 }
538
539 UnicodeProperties typeSettingsProperties =
540 group.getParentLiveGroupTypeSettingsProperties();
541
542 return GetterUtil.getBoolean(
543 typeSettingsProperties.getProperty("trashEnabled"), true);
544 }
545
546 @Override
547 public boolean isTrashEnabled(long groupId) throws PortalException {
548 return isTrashEnabled(GroupLocalServiceUtil.getGroup(groupId));
549 }
550
551 @Override
552 public boolean isValidTrashTitle(String title) {
553 return isValidTrashTitle(title, TRASH_PREFIX);
554 }
555
556 protected void addBreadcrumbEntries(
557 HttpServletRequest request,
558 LiferayPortletResponse liferayPortletResponse, String className,
559 long classPK, String paramName, PortletURL containerModelURL,
560 boolean checkInTrashContainers)
561 throws PortalException, PortletException {
562
563 ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
564 WebKeys.THEME_DISPLAY);
565
566 PortletURL portletURL = PortletURLUtil.clone(
567 containerModelURL, liferayPortletResponse);
568
569 TrashHandler trashHandler = TrashHandlerRegistryUtil.getTrashHandler(
570 className);
571
572 List<ContainerModel> containerModels =
573 trashHandler.getParentContainerModels(classPK);
574
575 Collections.reverse(containerModels);
576
577 for (ContainerModel containerModel : containerModels) {
578 TrashHandler containerModelTrashHandler =
579 TrashHandlerRegistryUtil.getTrashHandler(
580 containerModel.getModelClassName());
581
582 if (checkInTrashContainers &&
583 !containerModelTrashHandler.isInTrash(
584 containerModel.getContainerModelId())) {
585
586 continue;
587 }
588
589 portletURL.setParameter(
590 paramName,
591 String.valueOf(containerModel.getContainerModelId()));
592
593 String name = containerModel.getContainerModelName();
594
595 if (containerModelTrashHandler.isInTrash(
596 containerModel.getContainerModelId())) {
597
598 name = TrashUtil.getOriginalTitle(name);
599 }
600
601 PortalUtil.addPortletBreadcrumbEntry(
602 request, name, portletURL.toString());
603 }
604
605 TrashRenderer trashRenderer = trashHandler.getTrashRenderer(classPK);
606
607 PortalUtil.addPortletBreadcrumbEntry(
608 request, trashRenderer.getTitle(themeDisplay.getLocale()), null);
609 }
610
611 protected String getOriginalTitle(
612 String title, String paramName, String prefix) {
613
614 if (!isValidTrashTitle(title, prefix)) {
615 return title;
616 }
617
618 title = title.substring(prefix.length());
619
620 long trashEntryId = GetterUtil.getLong(title);
621
622 if (trashEntryId <= 0) {
623 return title;
624 }
625
626 try {
627 TrashEntry trashEntry = TrashEntryLocalServiceUtil.fetchEntry(
628 trashEntryId);
629
630 if (trashEntry == null) {
631 TrashVersion trashVersion =
632 TrashVersionLocalServiceUtil.getTrashVersion(trashEntryId);
633
634 title = trashVersion.getTypeSettingsProperty(paramName);
635 }
636 else {
637 title = trashEntry.getTypeSettingsProperty(paramName);
638 }
639 }
640 catch (Exception e) {
641 if (_log.isDebugEnabled()) {
642 _log.debug(
643 "No trash entry or trash version exists with ID " +
644 trashEntryId);
645 }
646 }
647
648 return title;
649 }
650
651 protected String getTrashTitle(long trashEntryId, String prefix) {
652 return prefix.concat(String.valueOf(trashEntryId));
653 }
654
655 protected boolean isValidTrashTitle(String title, String prefix) {
656 if (title.startsWith(prefix)) {
657 return true;
658 }
659
660 return false;
661 }
662
663 protected final String TRASH_PREFIX = StringPool.SLASH;
664
665 private static final Log _log = LogFactoryUtil.getLog(TrashImpl.class);
666
667 }