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.util;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.exception.SystemException;
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.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.trash.TrashHandler;
027    import com.liferay.portal.kernel.trash.TrashHandlerRegistryUtil;
028    import com.liferay.portal.kernel.trash.TrashRenderer;
029    import com.liferay.portal.kernel.util.CharPool;
030    import com.liferay.portal.kernel.util.FastDateFormatFactoryUtil;
031    import com.liferay.portal.kernel.util.GetterUtil;
032    import com.liferay.portal.kernel.util.OrderByComparator;
033    import com.liferay.portal.kernel.util.PrefsPropsUtil;
034    import com.liferay.portal.kernel.util.PropsKeys;
035    import com.liferay.portal.kernel.util.StringBundler;
036    import com.liferay.portal.kernel.util.StringPool;
037    import com.liferay.portal.kernel.util.StringUtil;
038    import com.liferay.portal.kernel.util.UnicodeProperties;
039    import com.liferay.portal.kernel.util.Validator;
040    import com.liferay.portal.model.ContainerModel;
041    import com.liferay.portal.model.Group;
042    import com.liferay.portal.model.Layout;
043    import com.liferay.portal.service.GroupLocalServiceUtil;
044    import com.liferay.portal.service.permission.PortletPermissionUtil;
045    import com.liferay.portal.theme.ThemeDisplay;
046    import com.liferay.portal.util.PortalUtil;
047    import com.liferay.portal.util.PortletKeys;
048    import com.liferay.portal.util.PropsValues;
049    import com.liferay.portal.util.WebKeys;
050    import com.liferay.portlet.documentlibrary.store.DLStoreUtil;
051    import com.liferay.portlet.trash.model.TrashEntry;
052    import com.liferay.portlet.trash.model.impl.TrashEntryImpl;
053    import com.liferay.portlet.trash.service.TrashEntryLocalServiceUtil;
054    import com.liferay.portlet.trash.util.comparator.EntryCreateDateComparator;
055    import com.liferay.portlet.trash.util.comparator.EntryTypeComparator;
056    import com.liferay.portlet.trash.util.comparator.EntryUserNameComparator;
057    
058    import java.text.Format;
059    
060    import java.util.ArrayList;
061    import java.util.Collections;
062    import java.util.Date;
063    import java.util.List;
064    
065    import javax.portlet.PortletRequest;
066    import javax.portlet.PortletURL;
067    
068    import javax.servlet.http.HttpServletRequest;
069    
070    /**
071     * @author Sergio Gonz??lez
072     * @author Julio Camarero
073     */
074    @DoPrivileged
075    public class TrashImpl implements Trash {
076    
077            @Override
078            public void addBaseModelBreadcrumbEntries(
079                            HttpServletRequest request, String className, long classPK,
080                            PortletURL containerModelURL)
081                    throws PortalException, SystemException {
082    
083                    addBreadcrumbEntries(
084                            request, className, classPK, "classPK", containerModelURL);
085            }
086    
087            @Override
088            public void addContainerModelBreadcrumbEntries(
089                            HttpServletRequest request, String className, long classPK,
090                            PortletURL containerModelURL)
091                    throws PortalException, SystemException {
092    
093                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
094                            WebKeys.THEME_DISPLAY);
095    
096                    TrashHandler trashHandler = TrashHandlerRegistryUtil.getTrashHandler(
097                            className);
098    
099                    String rootContainerModelName = LanguageUtil.get(
100                            themeDisplay.getLocale(), trashHandler.getRootContainerModelName());
101    
102                    if (classPK == 0) {
103                            PortalUtil.addPortletBreadcrumbEntry(
104                                    request, rootContainerModelName, null);
105    
106                            return;
107                    }
108    
109                    containerModelURL.setParameter("containerModelId", "0");
110    
111                    PortalUtil.addPortletBreadcrumbEntry(
112                            request, rootContainerModelName, containerModelURL.toString());
113    
114                    addBreadcrumbEntries(
115                            request, className, classPK, "containerModelId", containerModelURL);
116            }
117    
118            @Override
119            public void deleteEntriesAttachments(
120                            long companyId, long repositoryId, Date date,
121                            String[] attachmentFileNames)
122                    throws PortalException, SystemException {
123    
124                    for (String attachmentFileName : attachmentFileNames) {
125                            String trashTime = TrashUtil.getTrashTime(
126                                    attachmentFileName, TRASH_TIME_SEPARATOR);
127    
128                            long timestamp = GetterUtil.getLong(trashTime);
129    
130                            if (timestamp < date.getTime()) {
131                                    DLStoreUtil.deleteDirectory(
132                                            companyId, repositoryId, attachmentFileName);
133                            }
134                    }
135            }
136    
137            @Override
138            public List<TrashEntry> getEntries(Hits hits) {
139                    List<TrashEntry> entries = new ArrayList<TrashEntry>();
140    
141                    for (Document document : hits.getDocs()) {
142                            String entryClassName = GetterUtil.getString(
143                                    document.get(Field.ENTRY_CLASS_NAME));
144                            long classPK = GetterUtil.getLong(
145                                    document.get(Field.ENTRY_CLASS_PK));
146    
147                            try {
148                                    TrashEntry entry = TrashEntryLocalServiceUtil.fetchEntry(
149                                            entryClassName, classPK);
150    
151                                    if (entry == null) {
152                                            String userName = GetterUtil.getString(
153                                                    document.get(Field.REMOVED_BY_USER_NAME));
154    
155                                            Date removedDate = document.getDate(Field.REMOVED_DATE);
156    
157                                            entry = new TrashEntryImpl();
158    
159                                            entry.setClassName(entryClassName);
160                                            entry.setClassPK(classPK);
161    
162                                            entry.setUserName(userName);
163                                            entry.setCreateDate(removedDate);
164    
165                                            String rootEntryClassName = GetterUtil.getString(
166                                                    document.get(Field.ROOT_ENTRY_CLASS_NAME));
167                                            long rootEntryClassPK = GetterUtil.getLong(
168                                                    document.get(Field.ROOT_ENTRY_CLASS_PK));
169    
170                                            TrashEntry rootTrashEntry =
171                                                    TrashEntryLocalServiceUtil.fetchEntry(
172                                                            rootEntryClassName, rootEntryClassPK);
173    
174                                            if (rootTrashEntry != null) {
175                                                    entry.setRootEntry(rootTrashEntry);
176                                            }
177                                    }
178    
179                                    entries.add(entry);
180                            }
181                            catch (Exception e) {
182                                    if (_log.isWarnEnabled()) {
183                                            _log.warn(
184                                                    "Unable to find trash entry for " + entryClassName +
185                                                            " with primary key " + classPK);
186                                    }
187                            }
188                    }
189    
190                    return entries;
191            }
192    
193            @Override
194            public OrderByComparator getEntryOrderByComparator(
195                    String orderByCol, String orderByType) {
196    
197                    boolean orderByAsc = false;
198    
199                    if (orderByType.equals("asc")) {
200                            orderByAsc = true;
201                    }
202    
203                    OrderByComparator orderByComparator = null;
204    
205                    if (orderByCol.equals("removed-by")) {
206                            orderByComparator = new EntryUserNameComparator(orderByAsc);
207                    }
208                    else if (orderByCol.equals("removed-date")) {
209                            orderByComparator = new EntryCreateDateComparator(orderByAsc);
210                    }
211                    else if (orderByCol.equals("type")) {
212                            orderByComparator = new EntryTypeComparator(orderByAsc);
213                    }
214    
215                    return orderByComparator;
216            }
217    
218            @Override
219            public int getMaxAge(Group group) throws PortalException, SystemException {
220                    if (group.isLayout()) {
221                            group = group.getParentGroup();
222                    }
223    
224                    int trashEntriesMaxAge = PrefsPropsUtil.getInteger(
225                            group.getCompanyId(), PropsKeys.TRASH_ENTRIES_MAX_AGE,
226                            PropsValues.TRASH_ENTRIES_MAX_AGE);
227    
228                    UnicodeProperties typeSettingsProperties =
229                            group.getTypeSettingsProperties();
230    
231                    return GetterUtil.getInteger(
232                            typeSettingsProperties.getProperty("trashEntriesMaxAge"),
233                            trashEntriesMaxAge);
234            }
235    
236            @Override
237            public String getNewName(String oldName, String token) {
238                    StringBundler sb = new StringBundler(3);
239    
240                    sb.append(oldName);
241                    sb.append(StringPool.SPACE);
242                    sb.append(token);
243    
244                    return sb.toString();
245            }
246    
247            @Override
248            public String getNewName(
249                            ThemeDisplay themeDisplay, String className, long classPK,
250                            String oldName)
251                    throws PortalException, SystemException {
252    
253                    TrashRenderer trashRenderer = null;
254    
255                    if (Validator.isNotNull(className) && (classPK > 0)) {
256                            TrashHandler trashHandler =
257                                    TrashHandlerRegistryUtil.getTrashHandler(className);
258    
259                            trashRenderer = trashHandler.getTrashRenderer(classPK);
260                    }
261    
262                    Format dateFormatDateTime = FastDateFormatFactoryUtil.getDateTime(
263                            themeDisplay.getLocale(), themeDisplay.getTimeZone());
264    
265                    StringBundler sb = new StringBundler(3);
266    
267                    sb.append(StringPool.OPEN_PARENTHESIS);
268                    sb.append(
269                            StringUtil.replace(
270                                    dateFormatDateTime.format(new Date()), CharPool.SLASH,
271                                    CharPool.PERIOD));
272                    sb.append(StringPool.CLOSE_PARENTHESIS);
273    
274                    if (trashRenderer != null) {
275                            return trashRenderer.getNewName(oldName, sb.toString());
276                    }
277                    else {
278                            return getNewName(oldName, sb.toString());
279                    }
280            }
281    
282            @Override
283            public String getOriginalTitle(String title) {
284                    return getOriginalTitle(title, StringPool.SLASH);
285            }
286    
287            @Override
288            public String getTrashTime(String title, String separator) {
289                    int index = title.lastIndexOf(separator);
290    
291                    if (index < 0) {
292                            return StringPool.BLANK;
293                    }
294    
295                    return title.substring(index + 1, title.length());
296            }
297    
298            @Override
299            public String getTrashTitle(long trashEntryId) {
300                    return getTrashTitle(trashEntryId, StringPool.SLASH);
301            }
302    
303            @Override
304            public PortletURL getViewContentURL(
305                            HttpServletRequest request, String className, long classPK)
306                    throws PortalException, SystemException {
307    
308                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
309                            WebKeys.THEME_DISPLAY);
310    
311                    if (!themeDisplay.isSignedIn() ||
312                            !isTrashEnabled(themeDisplay.getScopeGroupId()) ||
313                            !PortletPermissionUtil.hasControlPanelAccessPermission(
314                                    themeDisplay.getPermissionChecker(),
315                                    themeDisplay.getScopeGroupId(), PortletKeys.TRASH)) {
316    
317                            return null;
318                    }
319    
320                    TrashHandler trashHandler = TrashHandlerRegistryUtil.getTrashHandler(
321                            className);
322    
323                    if (trashHandler.isInTrashContainer(classPK)) {
324                            ContainerModel containerModel = trashHandler.getTrashContainer(
325                                    classPK);
326    
327                            className = containerModel.getModelClassName();
328                            classPK = containerModel.getContainerModelId();
329    
330                            trashHandler = TrashHandlerRegistryUtil.getTrashHandler(className);
331                    }
332    
333                    TrashRenderer trashRenderer = trashHandler.getTrashRenderer(classPK);
334    
335                    if (trashRenderer == null) {
336                            return null;
337                    }
338    
339                    Layout layout = themeDisplay.getLayout();
340    
341                    PortletURL portletURL = PortalUtil.getControlPanelPortletURL(
342                            request, PortletKeys.TRASH, layout.getLayoutId(),
343                            PortletRequest.RENDER_PHASE);
344    
345                    portletURL.setParameter("struts_action", "/trash/view_content");
346                    portletURL.setParameter("redirect", themeDisplay.getURLCurrent());
347    
348                    TrashEntry trashEntry = TrashEntryLocalServiceUtil.getEntry(
349                            className, classPK);
350    
351                    if (trashEntry.getRootEntry() != null) {
352                            portletURL.setParameter("className", className);
353                            portletURL.setParameter("classPK", String.valueOf(classPK));
354                    }
355                    else {
356                            portletURL.setParameter(
357                                    "trashEntryId", String.valueOf(trashEntry.getEntryId()));
358                    }
359    
360                    portletURL.setParameter("type", trashRenderer.getType());
361                    portletURL.setParameter("showActions", Boolean.FALSE.toString());
362                    portletURL.setParameter("showAssetMetadata", Boolean.TRUE.toString());
363                    portletURL.setParameter("showEditURL", Boolean.FALSE.toString());
364    
365                    return portletURL;
366            }
367    
368            @Override
369            public boolean isInTrash(String className, long classPK)
370                    throws PortalException, SystemException {
371    
372                    TrashHandler trashHandler = TrashHandlerRegistryUtil.getTrashHandler(
373                            className);
374    
375                    if (trashHandler == null) {
376                            return false;
377                    }
378    
379                    if (trashHandler.isInTrash(classPK) ||
380                            trashHandler.isInTrashContainer(classPK)) {
381    
382                            return true;
383                    }
384    
385                    return false;
386            }
387    
388            @Override
389            public boolean isTrashEnabled(long groupId)
390                    throws PortalException, SystemException {
391    
392                    Group group = GroupLocalServiceUtil.getGroup(groupId);
393    
394                    UnicodeProperties typeSettingsProperties =
395                            group.getParentLiveGroupTypeSettingsProperties();
396    
397                    boolean companyTrashEnabled = PrefsPropsUtil.getBoolean(
398                            group.getCompanyId(), PropsKeys.TRASH_ENABLED);
399    
400                    if (!companyTrashEnabled) {
401                            return false;
402                    }
403    
404                    return GetterUtil.getBoolean(
405                            typeSettingsProperties.getProperty("trashEnabled"), true);
406            }
407    
408            protected void addBreadcrumbEntries(
409                            HttpServletRequest request, String className, long classPK,
410                            String paramName, PortletURL containerModelURL)
411                    throws PortalException, SystemException {
412    
413                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
414                            WebKeys.THEME_DISPLAY);
415    
416                    TrashHandler trashHandler = TrashHandlerRegistryUtil.getTrashHandler(
417                            className);
418    
419                    List<ContainerModel> containerModels =
420                            trashHandler.getParentContainerModels(classPK);
421    
422                    Collections.reverse(containerModels);
423    
424                    containerModelURL.setParameter("struts_action", "/trash/view");
425    
426                    PortalUtil.addPortletBreadcrumbEntry(
427                            request, LanguageUtil.get(themeDisplay.getLocale(), "recycle-bin"),
428                            containerModelURL.toString());
429    
430                    for (ContainerModel containerModel : containerModels) {
431                            TrashHandler containerModelTrashHandler =
432                                    TrashHandlerRegistryUtil.getTrashHandler(
433                                            containerModel.getModelClassName());
434    
435                            if (!containerModelTrashHandler.isInTrash(
436                                            containerModel.getContainerModelId()) &&
437                                    (containerModelTrashHandler.getTrashContainer(
438                                            containerModel.getContainerModelId()) == null)) {
439    
440                                    continue;
441                            }
442    
443                            containerModelURL.setParameter(
444                                    "struts_action", "/trash/view_content");
445    
446                            containerModelURL.setParameter(
447                                    paramName,
448                                    String.valueOf(containerModel.getContainerModelId()));
449    
450                            String name = containerModel.getContainerModelName();
451    
452                            if (containerModelTrashHandler.isInTrash(
453                                            containerModel.getContainerModelId())) {
454    
455                                    name = TrashUtil.getOriginalTitle(name);
456                            }
457    
458                            PortalUtil.addPortletBreadcrumbEntry(
459                                    request, name, containerModelURL.toString());
460                    }
461    
462                    TrashRenderer trashRenderer = trashHandler.getTrashRenderer(classPK);
463    
464                    PortalUtil.addPortletBreadcrumbEntry(
465                            request, trashRenderer.getTitle(themeDisplay.getLocale()), null);
466            }
467    
468            protected String getOriginalTitle(String title, String prefix) {
469                    if (!title.startsWith(prefix)) {
470                            return title;
471                    }
472    
473                    title = title.substring(prefix.length());
474    
475                    long trashEntryId = GetterUtil.getLong(title);
476    
477                    if (trashEntryId <= 0) {
478                            return title;
479                    }
480    
481                    try {
482                            TrashEntry trashEntry = TrashEntryLocalServiceUtil.getEntry(
483                                    trashEntryId);
484    
485                            title = trashEntry.getTypeSettingsProperty("title");
486                    }
487                    catch (Exception e) {
488                            if (_log.isDebugEnabled()) {
489                                    _log.debug("No trash entry exists with ID " + trashEntryId);
490                            }
491                    }
492    
493                    return title;
494            }
495    
496            protected String getTrashTitle(long trashEntryId, String prefix) {
497                    return prefix.concat(String.valueOf(trashEntryId));
498            }
499    
500            private static Log _log = LogFactoryUtil.getLog(TrashImpl.class);
501    
502    }