001    /**
002     * Copyright (c) 2000-present 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.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.search.Document;
023    import com.liferay.portal.kernel.search.Field;
024    import com.liferay.portal.kernel.search.Hits;
025    import com.liferay.portal.kernel.security.pacl.DoPrivileged;
026    import com.liferay.portal.kernel.servlet.SessionMessages;
027    import com.liferay.portal.kernel.trash.TrashHandler;
028    import com.liferay.portal.kernel.trash.TrashHandlerRegistryUtil;
029    import com.liferay.portal.kernel.trash.TrashRenderer;
030    import com.liferay.portal.kernel.util.ArrayUtil;
031    import com.liferay.portal.kernel.util.CharPool;
032    import com.liferay.portal.kernel.util.Constants;
033    import com.liferay.portal.kernel.util.FastDateFormatFactoryUtil;
034    import com.liferay.portal.kernel.util.GetterUtil;
035    import com.liferay.portal.kernel.util.OrderByComparator;
036    import com.liferay.portal.kernel.util.PrefsPropsUtil;
037    import com.liferay.portal.kernel.util.PropsKeys;
038    import com.liferay.portal.kernel.util.StringBundler;
039    import com.liferay.portal.kernel.util.StringPool;
040    import com.liferay.portal.kernel.util.StringUtil;
041    import com.liferay.portal.kernel.util.UnicodeProperties;
042    import com.liferay.portal.kernel.util.Validator;
043    import com.liferay.portal.model.ContainerModel;
044    import com.liferay.portal.model.Group;
045    import com.liferay.portal.model.Layout;
046    import com.liferay.portal.model.TrashedModel;
047    import com.liferay.portal.service.GroupLocalServiceUtil;
048    import com.liferay.portal.service.permission.PortletPermissionUtil;
049    import com.liferay.portal.theme.ThemeDisplay;
050    import com.liferay.portal.util.PortalUtil;
051    import com.liferay.portal.util.PortletKeys;
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    /**
082     * @author Sergio Gonz??lez
083     * @author Julio Camarero
084     */
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);
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 =
114                            trashHandler.getRootContainerModelTitle(
115                                    classPK, themeDisplay.getLocale());
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);
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<String>();
151                    List<Long> restoreTrashEntryIds = new ArrayList<Long>();
152                    List<String> titles = new ArrayList<String>();
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<String, String[]>();
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, 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<TrashedModel>();
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                    throws PortalException {
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 List<TrashEntry> getEntries(Hits hits) {
231                    List<TrashEntry> entries = new ArrayList<TrashEntry>();
232    
233                    for (Document document : hits.getDocs()) {
234                            String entryClassName = GetterUtil.getString(
235                                    document.get(Field.ENTRY_CLASS_NAME));
236                            long classPK = GetterUtil.getLong(
237                                    document.get(Field.ENTRY_CLASS_PK));
238    
239                            try {
240                                    TrashEntry entry = TrashEntryLocalServiceUtil.fetchEntry(
241                                            entryClassName, classPK);
242    
243                                    if (entry == null) {
244                                            String userName = GetterUtil.getString(
245                                                    document.get(Field.REMOVED_BY_USER_NAME));
246    
247                                            Date removedDate = document.getDate(Field.REMOVED_DATE);
248    
249                                            entry = new TrashEntryImpl();
250    
251                                            entry.setClassName(entryClassName);
252                                            entry.setClassPK(classPK);
253    
254                                            entry.setUserName(userName);
255                                            entry.setCreateDate(removedDate);
256    
257                                            String rootEntryClassName = GetterUtil.getString(
258                                                    document.get(Field.ROOT_ENTRY_CLASS_NAME));
259                                            long rootEntryClassPK = GetterUtil.getLong(
260                                                    document.get(Field.ROOT_ENTRY_CLASS_PK));
261    
262                                            TrashEntry rootTrashEntry =
263                                                    TrashEntryLocalServiceUtil.fetchEntry(
264                                                            rootEntryClassName, rootEntryClassPK);
265    
266                                            if (rootTrashEntry != null) {
267                                                    entry.setRootEntry(rootTrashEntry);
268                                            }
269                                    }
270    
271                                    entries.add(entry);
272                            }
273                            catch (Exception e) {
274                                    if (_log.isWarnEnabled()) {
275                                            _log.warn(
276                                                    "Unable to find trash entry for " + entryClassName +
277                                                            " with primary key " + classPK);
278                                    }
279                            }
280                    }
281    
282                    return entries;
283            }
284    
285            @Override
286            public OrderByComparator<TrashEntry> getEntryOrderByComparator(
287                    String orderByCol, String orderByType) {
288    
289                    boolean orderByAsc = false;
290    
291                    if (orderByType.equals("asc")) {
292                            orderByAsc = true;
293                    }
294    
295                    OrderByComparator<TrashEntry> orderByComparator = null;
296    
297                    if (orderByCol.equals("removed-by")) {
298                            orderByComparator = new EntryUserNameComparator(orderByAsc);
299                    }
300                    else if (orderByCol.equals("removed-date")) {
301                            orderByComparator = new EntryCreateDateComparator(orderByAsc);
302                    }
303                    else if (orderByCol.equals("type")) {
304                            orderByComparator = new EntryTypeComparator(orderByAsc);
305                    }
306    
307                    return orderByComparator;
308            }
309    
310            @Override
311            public int getMaxAge(Group group) {
312                    int trashEntriesMaxAge = PrefsPropsUtil.getInteger(
313                            group.getCompanyId(), PropsKeys.TRASH_ENTRIES_MAX_AGE,
314                            PropsValues.TRASH_ENTRIES_MAX_AGE);
315    
316                    UnicodeProperties typeSettingsProperties =
317                            group.getParentLiveGroupTypeSettingsProperties();
318    
319                    return GetterUtil.getInteger(
320                            typeSettingsProperties.getProperty("trashEntriesMaxAge"),
321                            trashEntriesMaxAge);
322            }
323    
324            @Override
325            public String getNewName(String oldName, String token) {
326                    StringBundler sb = new StringBundler(3);
327    
328                    sb.append(oldName);
329                    sb.append(StringPool.SPACE);
330                    sb.append(token);
331    
332                    return sb.toString();
333            }
334    
335            @Override
336            public String getNewName(
337                            ThemeDisplay themeDisplay, String className, long classPK,
338                            String oldName)
339                    throws PortalException {
340    
341                    TrashRenderer trashRenderer = null;
342    
343                    if (Validator.isNotNull(className) && (classPK > 0)) {
344                            TrashHandler trashHandler =
345                                    TrashHandlerRegistryUtil.getTrashHandler(className);
346    
347                            trashRenderer = trashHandler.getTrashRenderer(classPK);
348                    }
349    
350                    Format dateFormatDateTime = FastDateFormatFactoryUtil.getDateTime(
351                            themeDisplay.getLocale(), themeDisplay.getTimeZone());
352    
353                    StringBundler sb = new StringBundler(3);
354    
355                    sb.append(StringPool.OPEN_PARENTHESIS);
356                    sb.append(
357                            StringUtil.replace(
358                                    dateFormatDateTime.format(new Date()), CharPool.SLASH,
359                                    CharPool.PERIOD));
360                    sb.append(StringPool.CLOSE_PARENTHESIS);
361    
362                    if (trashRenderer != null) {
363                            return trashRenderer.getNewName(oldName, sb.toString());
364                    }
365                    else {
366                            return getNewName(oldName, sb.toString());
367                    }
368            }
369    
370            @Override
371            public String getOriginalTitle(String title) {
372                    return getOriginalTitle(title, "title", StringPool.SLASH);
373            }
374    
375            @Override
376            public String getOriginalTitle(String title, String paramName) {
377                    return getOriginalTitle(title, paramName, StringPool.SLASH);
378            }
379    
380            @Override
381            public String getTrashTime(String title, String separator) {
382                    int index = title.lastIndexOf(separator);
383    
384                    if (index < 0) {
385                            return StringPool.BLANK;
386                    }
387    
388                    return title.substring(index + 1, title.length());
389            }
390    
391            @Override
392            public String getTrashTitle(long trashEntryId) {
393                    return getTrashTitle(trashEntryId, StringPool.SLASH);
394            }
395    
396            @Override
397            public PortletURL getViewContentURL(
398                            HttpServletRequest request, String className, long classPK)
399                    throws PortalException {
400    
401                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
402                            WebKeys.THEME_DISPLAY);
403    
404                    if (!themeDisplay.isSignedIn() ||
405                            !isTrashEnabled(themeDisplay.getScopeGroupId()) ||
406                            !PortletPermissionUtil.hasControlPanelAccessPermission(
407                                    themeDisplay.getPermissionChecker(),
408                                    themeDisplay.getScopeGroupId(), PortletKeys.TRASH)) {
409    
410                            return null;
411                    }
412    
413                    TrashHandler trashHandler = TrashHandlerRegistryUtil.getTrashHandler(
414                            className);
415    
416                    if (trashHandler.isInTrashContainer(classPK)) {
417                            TrashEntry trashEntry = trashHandler.getTrashEntry(classPK);
418    
419                            className = trashEntry.getClassName();
420                            classPK = trashEntry.getClassPK();
421    
422                            trashHandler = TrashHandlerRegistryUtil.getTrashHandler(className);
423                    }
424    
425                    TrashRenderer trashRenderer = trashHandler.getTrashRenderer(classPK);
426    
427                    if (trashRenderer == null) {
428                            return null;
429                    }
430    
431                    Layout layout = themeDisplay.getLayout();
432    
433                    PortletURL portletURL = PortalUtil.getControlPanelPortletURL(
434                            request, PortletKeys.TRASH, layout.getLayoutId(),
435                            PortletRequest.RENDER_PHASE);
436    
437                    portletURL.setParameter("struts_action", "/trash/view_content");
438                    portletURL.setParameter("redirect", themeDisplay.getURLCurrent());
439    
440                    TrashEntry trashEntry = TrashEntryLocalServiceUtil.getEntry(
441                            className, classPK);
442    
443                    if (trashEntry.getRootEntry() != null) {
444                            portletURL.setParameter("className", className);
445                            portletURL.setParameter("classPK", String.valueOf(classPK));
446                    }
447                    else {
448                            portletURL.setParameter(
449                                    "trashEntryId", String.valueOf(trashEntry.getEntryId()));
450                    }
451    
452                    portletURL.setParameter("type", trashRenderer.getType());
453                    portletURL.setParameter("showActions", Boolean.FALSE.toString());
454                    portletURL.setParameter("showAssetMetadata", Boolean.TRUE.toString());
455                    portletURL.setParameter("showEditURL", Boolean.FALSE.toString());
456    
457                    return portletURL;
458            }
459    
460            @Override
461            public boolean isInTrash(String className, long classPK)
462                    throws PortalException {
463    
464                    TrashHandler trashHandler = TrashHandlerRegistryUtil.getTrashHandler(
465                            className);
466    
467                    if (trashHandler == null) {
468                            return false;
469                    }
470    
471                    return trashHandler.isInTrash(classPK);
472            }
473    
474            @Override
475            public boolean isTrashEnabled(Group group) {
476                    boolean companyTrashEnabled = PrefsPropsUtil.getBoolean(
477                            group.getCompanyId(), PropsKeys.TRASH_ENABLED);
478    
479                    if (!companyTrashEnabled) {
480                            return false;
481                    }
482    
483                    UnicodeProperties typeSettingsProperties =
484                            group.getParentLiveGroupTypeSettingsProperties();
485    
486                    return GetterUtil.getBoolean(
487                            typeSettingsProperties.getProperty("trashEnabled"), true);
488            }
489    
490            @Override
491            public boolean isTrashEnabled(long groupId) throws PortalException {
492                    return isTrashEnabled(GroupLocalServiceUtil.getGroup(groupId));
493            }
494    
495            protected void addBreadcrumbEntries(
496                            HttpServletRequest request,
497                            LiferayPortletResponse liferayPortletResponse, String className,
498                            long classPK, String paramName, PortletURL containerModelURL)
499                    throws PortalException, PortletException {
500    
501                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
502                            WebKeys.THEME_DISPLAY);
503    
504                    PortletURL portletURL = PortletURLUtil.clone(
505                            containerModelURL, liferayPortletResponse);
506    
507                    portletURL.setParameter("struts_action", "/trash/view");
508    
509                    PortalUtil.addPortletBreadcrumbEntry(
510                            request, LanguageUtil.get(themeDisplay.getLocale(), "recycle-bin"),
511                            portletURL.toString());
512    
513                    TrashHandler trashHandler = TrashHandlerRegistryUtil.getTrashHandler(
514                            className);
515    
516                    List<ContainerModel> containerModels =
517                            trashHandler.getParentContainerModels(classPK);
518    
519                    Collections.reverse(containerModels);
520    
521                    for (ContainerModel containerModel : containerModels) {
522                            TrashHandler containerModelTrashHandler =
523                                    TrashHandlerRegistryUtil.getTrashHandler(
524                                            containerModel.getModelClassName());
525    
526                            if (!containerModelTrashHandler.isInTrash(
527                                            containerModel.getContainerModelId())) {
528    
529                                    continue;
530                            }
531    
532                            portletURL.setParameter("struts_action", "/trash/view_content");
533    
534                            portletURL.setParameter(
535                                    paramName,
536                                    String.valueOf(containerModel.getContainerModelId()));
537    
538                            String name = containerModel.getContainerModelName();
539    
540                            if (containerModelTrashHandler.isInTrash(
541                                            containerModel.getContainerModelId())) {
542    
543                                    name = TrashUtil.getOriginalTitle(name);
544                            }
545    
546                            PortalUtil.addPortletBreadcrumbEntry(
547                                    request, name, portletURL.toString());
548                    }
549    
550                    TrashRenderer trashRenderer = trashHandler.getTrashRenderer(classPK);
551    
552                    PortalUtil.addPortletBreadcrumbEntry(
553                            request, trashRenderer.getTitle(themeDisplay.getLocale()), null);
554            }
555    
556            protected String getOriginalTitle(
557                    String title, String paramName, String prefix) {
558    
559                    if (!title.startsWith(prefix)) {
560                            return title;
561                    }
562    
563                    title = title.substring(prefix.length());
564    
565                    long trashEntryId = GetterUtil.getLong(title);
566    
567                    if (trashEntryId <= 0) {
568                            return title;
569                    }
570    
571                    try {
572                            TrashEntry trashEntry = TrashEntryLocalServiceUtil.fetchEntry(
573                                    trashEntryId);
574    
575                            if (trashEntry == null) {
576                                    TrashVersion trashVersion =
577                                            TrashVersionLocalServiceUtil.getTrashVersion(trashEntryId);
578    
579                                    title = trashVersion.getTypeSettingsProperty(paramName);
580                            }
581                            else {
582                                    title = trashEntry.getTypeSettingsProperty(paramName);
583                            }
584                    }
585                    catch (Exception e) {
586                            if (_log.isDebugEnabled()) {
587                                    _log.debug(
588                                            "No trash entry or trash version exists with ID " +
589                                                    trashEntryId);
590                            }
591                    }
592    
593                    return title;
594            }
595    
596            protected String getTrashTitle(long trashEntryId, String prefix) {
597                    return prefix.concat(String.valueOf(trashEntryId));
598            }
599    
600            private static Log _log = LogFactoryUtil.getLog(TrashImpl.class);
601    
602    }