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