001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.gwt;
029
030import org.opencms.ade.galleries.CmsPreviewService;
031import org.opencms.file.CmsFile;
032import org.opencms.file.CmsObject;
033import org.opencms.file.CmsProject;
034import org.opencms.file.CmsProperty;
035import org.opencms.file.CmsPropertyDefinition;
036import org.opencms.file.CmsResource;
037import org.opencms.file.CmsResource.CmsResourceUndoMode;
038import org.opencms.file.CmsResourceFilter;
039import org.opencms.file.CmsUser;
040import org.opencms.file.CmsVfsResourceNotFoundException;
041import org.opencms.file.history.CmsHistoryProject;
042import org.opencms.file.history.I_CmsHistoryResource;
043import org.opencms.file.types.CmsResourceTypeBinary;
044import org.opencms.file.types.CmsResourceTypeImage;
045import org.opencms.file.types.CmsResourceTypePlain;
046import org.opencms.file.types.CmsResourceTypePointer;
047import org.opencms.file.types.CmsResourceTypeXmlContainerPage;
048import org.opencms.file.types.CmsResourceTypeXmlContent;
049import org.opencms.file.types.CmsResourceTypeXmlPage;
050import org.opencms.file.types.I_CmsResourceType;
051import org.opencms.gwt.shared.CmsAvailabilityInfoBean;
052import org.opencms.gwt.shared.CmsBrokenLinkBean;
053import org.opencms.gwt.shared.CmsClientDateBean;
054import org.opencms.gwt.shared.CmsDeleteResourceBean;
055import org.opencms.gwt.shared.CmsExternalLinkInfoBean;
056import org.opencms.gwt.shared.CmsGwtConstants;
057import org.opencms.gwt.shared.CmsHistoryResourceBean;
058import org.opencms.gwt.shared.CmsHistoryResourceCollection;
059import org.opencms.gwt.shared.CmsHistoryVersion;
060import org.opencms.gwt.shared.CmsHistoryVersion.OfflineOnline;
061import org.opencms.gwt.shared.CmsListInfoBean;
062import org.opencms.gwt.shared.CmsListInfoBean.LockIcon;
063import org.opencms.gwt.shared.CmsLockReportInfo;
064import org.opencms.gwt.shared.CmsPrepareEditResponse;
065import org.opencms.gwt.shared.CmsPreviewInfo;
066import org.opencms.gwt.shared.CmsPrincipalBean;
067import org.opencms.gwt.shared.CmsQuickLaunchData;
068import org.opencms.gwt.shared.CmsQuickLaunchParams;
069import org.opencms.gwt.shared.CmsRenameInfoBean;
070import org.opencms.gwt.shared.CmsReplaceInfo;
071import org.opencms.gwt.shared.CmsResourceStatusBean;
072import org.opencms.gwt.shared.CmsRestoreInfoBean;
073import org.opencms.gwt.shared.CmsVfsEntryBean;
074import org.opencms.gwt.shared.alias.CmsAliasBean;
075import org.opencms.gwt.shared.property.CmsPropertiesBean;
076import org.opencms.gwt.shared.property.CmsPropertyChangeSet;
077import org.opencms.gwt.shared.rpc.I_CmsVfsService;
078import org.opencms.i18n.CmsLocaleManager;
079import org.opencms.i18n.CmsMessages;
080import org.opencms.jsp.CmsJspTagContainer;
081import org.opencms.loader.CmsImageScaler;
082import org.opencms.loader.CmsLoaderException;
083import org.opencms.lock.CmsLock;
084import org.opencms.lock.CmsLockType;
085import org.opencms.main.CmsException;
086import org.opencms.main.CmsIllegalArgumentException;
087import org.opencms.main.CmsLog;
088import org.opencms.main.OpenCms;
089import org.opencms.relations.CmsRelation;
090import org.opencms.relations.CmsRelationFilter;
091import org.opencms.search.CmsSearchManager;
092import org.opencms.security.CmsAccessControlEntry;
093import org.opencms.security.I_CmsPrincipal;
094import org.opencms.util.CmsDateUtil;
095import org.opencms.util.CmsMacroResolver;
096import org.opencms.util.CmsRequestUtil;
097import org.opencms.util.CmsStringUtil;
098import org.opencms.util.CmsUUID;
099import org.opencms.workplace.comparison.CmsHistoryListUtil;
100import org.opencms.workplace.explorer.CmsResourceUtil;
101import org.opencms.xml.containerpage.CmsXmlContainerPageFactory;
102import org.opencms.xml.content.CmsXmlContentFactory;
103import org.opencms.xml.content.CmsXmlContentProperty;
104import org.opencms.xml.page.CmsXmlPageFactory;
105
106import java.text.DateFormat;
107import java.util.ArrayList;
108import java.util.Collections;
109import java.util.Date;
110import java.util.HashMap;
111import java.util.HashSet;
112import java.util.LinkedHashMap;
113import java.util.List;
114import java.util.Locale;
115import java.util.Map;
116import java.util.Set;
117
118import org.apache.commons.collections.CollectionUtils;
119import org.apache.commons.logging.Log;
120
121import com.google.common.collect.HashMultimap;
122import com.google.common.collect.Lists;
123import com.google.common.collect.Multimap;
124
125/**
126 * A service class for reading the VFS tree.<p>
127 *
128 * @since 8.0.0
129 */
130public class CmsVfsService extends CmsGwtService implements I_CmsVfsService {
131
132    /** The static log object for this class. */
133    private static final Log LOG = CmsLog.getLog(CmsVfsService.class);
134
135    /** The allowed preview mime types. Checked for binary content only. */
136    private static Set<String> m_previewMimeTypes = new HashSet<String>();
137
138    /** Serialization id. */
139    private static final long serialVersionUID = -383483666952834348L;
140
141    /** Initialize the preview mime types. */
142    static {
143        CollectionUtils.addAll(
144            m_previewMimeTypes,
145            (new String[] {
146                "application/msword",
147                "application/pdf",
148                "application/excel",
149                "application/mspowerpoint",
150                "application/zip"}));
151    }
152
153    /** A helper object containing the implementations of the alias-related service methods. */
154    private CmsAliasHelper m_aliasHelper = new CmsAliasHelper();
155
156    /**
157     * Adds the lock state information to the resource info bean.<p>
158     *
159     * @param cms the CMS context
160     * @param resource the resource to get the page info for
161     * @param resourceInfo the resource info to add the lock state to
162     *
163     * @return the resource info bean
164     *
165     * @throws CmsException if something else goes wrong
166     */
167    public static CmsListInfoBean addLockInfo(CmsObject cms, CmsResource resource, CmsListInfoBean resourceInfo)
168    throws CmsException {
169
170        Locale locale = OpenCms.getWorkplaceManager().getWorkplaceLocale(cms);
171        CmsResourceUtil resourceUtil = new CmsResourceUtil(cms, resource);
172        CmsLock lock = resourceUtil.getLock();
173        LockIcon icon = LockIcon.NONE;
174        String iconTitle = null;
175        CmsLockType lockType = lock.getType();
176        if (!lock.isOwnedBy(cms.getRequestContext().getCurrentUser())) {
177            if ((lockType == CmsLockType.EXCLUSIVE)
178                || (lockType == CmsLockType.INHERITED)
179                || (lockType == CmsLockType.TEMPORARY)) {
180                icon = LockIcon.CLOSED;
181            } else if ((lockType == CmsLockType.SHARED_EXCLUSIVE) || (lockType == CmsLockType.SHARED_INHERITED)) {
182                icon = LockIcon.SHARED_CLOSED;
183            }
184        } else {
185            if ((lockType == CmsLockType.EXCLUSIVE)
186                || (lockType == CmsLockType.INHERITED)
187                || (lockType == CmsLockType.TEMPORARY)) {
188                icon = LockIcon.OPEN;
189            } else if ((lockType == CmsLockType.SHARED_EXCLUSIVE) || (lockType == CmsLockType.SHARED_INHERITED)) {
190                icon = LockIcon.SHARED_OPEN;
191            }
192        }
193        if ((lock.getUserId() != null) && !lock.getUserId().isNullUUID()) {
194            CmsUser lockOwner = cms.readUser(lock.getUserId());
195            iconTitle = Messages.get().getBundle(locale).key(Messages.GUI_LOCKED_BY_1, lockOwner.getFullName());
196            resourceInfo.addAdditionalInfo(
197                Messages.get().getBundle(locale).key(Messages.GUI_LOCKED_OWNER_0),
198                lockOwner.getFullName());
199        }
200        resourceInfo.setLockIcon(icon);
201        resourceInfo.setLockIconTitle(iconTitle);
202        if (icon != LockIcon.NONE) {
203            resourceInfo.setTitle(resourceInfo.getTitle() + " (" + iconTitle + ")");
204        }
205        return resourceInfo;
206    }
207
208    /**
209     * Formats a date given the current user's workplace locale.<p>
210     *
211     * @param cms the current CMS context
212     * @param date the date to format
213     *
214     * @return the formatted date
215     */
216    public static String formatDateTime(CmsObject cms, long date) {
217
218        return CmsDateUtil.getDateTime(
219            new Date(date),
220            DateFormat.MEDIUM,
221            OpenCms.getWorkplaceManager().getWorkplaceLocale(cms));
222    }
223
224    /**
225     * Gets the availability dialog information for the given resource.<p>
226     *
227     * @param cms the CMS context
228     * @param res the resource for which to get the availability info
229     * @return the availability info
230     *
231     * @throws CmsException if something goes wrong
232     */
233    public static CmsAvailabilityInfoBean getAvailabilityInfoStatic(CmsObject cms, CmsResource res)
234    throws CmsException {
235
236        CmsAvailabilityInfoBean result = new CmsAvailabilityInfoBean();
237        String resourceSitePath = cms.getRequestContext().removeSiteRoot(res.getRootPath());
238        result.setVfsPath(resourceSitePath);
239
240        I_CmsResourceType type = OpenCms.getResourceManager().getResourceType(res.getTypeId());
241        result.setResType(type.getTypeName());
242
243        result.setDateReleased(res.getDateReleased());
244        result.setDateExpired(res.getDateExpired());
245
246        String notificationInterval = cms.readPropertyObject(
247            res,
248            CmsPropertyDefinition.PROPERTY_NOTIFICATION_INTERVAL,
249            false).getValue();
250        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(notificationInterval)) {
251            result.setNotificationInterval(Integer.valueOf(notificationInterval).intValue());
252        }
253
254        String notificationEnabled = cms.readPropertyObject(
255            res,
256            CmsPropertyDefinition.PROPERTY_ENABLE_NOTIFICATION,
257            false).getValue();
258        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(notificationEnabled)) {
259            result.setNotificationEnabled(Boolean.valueOf(notificationEnabled).booleanValue());
260        }
261
262        result.setHasSiblings(cms.readSiblings(resourceSitePath, CmsResourceFilter.ALL).size() > 1);
263
264        result.setResponsibles(getResponsiblesStatic(cms, res.getRootPath()));
265
266        return result;
267    }
268
269    /**
270     * Returns the no preview reason if there is any.<p>
271     *
272     * @param cms the current cms context
273     * @param resource the resource to check
274     *
275     * @return the no preview reason if there is any
276     */
277    public static String getNoPreviewReason(CmsObject cms, CmsResource resource) {
278
279        Locale locale = OpenCms.getWorkplaceManager().getWorkplaceLocale(cms);
280        String noPreviewReason = null;
281        if (resource.getState().isDeleted() && !(resource instanceof I_CmsHistoryResource)) {
282            noPreviewReason = Messages.get().getBundle(locale).key(Messages.GUI_NO_PREVIEW_DELETED_0);
283        } else if (resource.isFolder()) {
284            noPreviewReason = Messages.get().getBundle(locale).key(Messages.GUI_NO_PREVIEW_FOLDER_0);
285        } else {
286            String siteRoot = OpenCms.getSiteManager().getSiteRoot(resource.getRootPath());
287            // previewing only resources that are in the same site or don't have a site root at all
288            if ((siteRoot != null) && !siteRoot.equals(cms.getRequestContext().getSiteRoot())) {
289                noPreviewReason = Messages.get().getBundle(locale).key(Messages.GUI_NO_PREVIEW_OTHER_SITE_0);
290            } else if (resource.getTypeId() == CmsResourceTypeBinary.getStaticTypeId()) {
291                String mimeType = OpenCms.getResourceManager().getMimeType(resource.getName(), null, "empty");
292                if (!m_previewMimeTypes.contains(mimeType)) {
293                    noPreviewReason = Messages.get().getBundle(locale).key(Messages.GUI_NO_PREVIEW_WRONG_MIME_TYPE_0);
294                }
295            }
296        }
297        return noPreviewReason;
298    }
299
300    /**
301     * Gets page information of a resource.<p>
302     *
303     * @param cms the CMS context
304     * @param res the resource
305     *
306     * @return gets the page information for the given resource
307     *
308     * @throws CmsException if the resource info can not be read
309     */
310    public static CmsListInfoBean getPageInfo(CmsObject cms, CmsResource res) throws CmsException {
311
312        CmsListInfoBean result = new CmsListInfoBean();
313        addPageInfo(cms, res, result);
314        return result;
315    }
316
317    /**
318     * Returns a bean to display the {@link org.opencms.gwt.client.ui.CmsListItemWidget} including the lock state.<p>
319     *
320     * @param cms the CMS context
321     * @param resource the resource to get the page info for
322     *
323     * @return a bean to display the {@link org.opencms.gwt.client.ui.CmsListItemWidget}.<p>
324     *
325     * @throws CmsLoaderException if the resource type could not be found
326     * @throws CmsException if something else goes wrong
327     */
328    public static CmsListInfoBean getPageInfoWithLock(CmsObject cms, CmsResource resource)
329    throws CmsLoaderException, CmsException {
330
331        CmsListInfoBean result = getPageInfo(cms, resource);
332        addLockInfo(cms, resource, result);
333        return result;
334    }
335
336    /**
337     * Gets the responsible principals for a resource with a given path.<p>
338     *
339     * @param cms the CMS context
340     * @param vfsPath the path of the resource
341     * @return the map of principals, with the principals as keys and the path as values
342     *
343     * @throws CmsException if something goes wrong
344     */
345    public static Map<CmsPrincipalBean, String> getResponsiblesStatic(CmsObject cms, String vfsPath)
346    throws CmsException {
347
348        Map<CmsPrincipalBean, String> result = new HashMap<CmsPrincipalBean, String>();
349        List<CmsResource> parentResources = new ArrayList<CmsResource>();
350        String resourceSitePath = cms.getRequestContext().removeSiteRoot(vfsPath);
351        // get all parent folders of the current file
352        parentResources = cms.readPath(resourceSitePath, CmsResourceFilter.IGNORE_EXPIRATION);
353
354        for (CmsResource resource : parentResources) {
355            String storedSiteRoot = cms.getRequestContext().getSiteRoot();
356            String sitePath = cms.getRequestContext().removeSiteRoot(resource.getRootPath());
357            try {
358
359                cms.getRequestContext().setSiteRoot("/");
360                List<CmsAccessControlEntry> entries = cms.getAccessControlEntries(resource.getRootPath(), false);
361                for (CmsAccessControlEntry ace : entries) {
362                    if (ace.isResponsible()) {
363                        I_CmsPrincipal principal = cms.lookupPrincipal(ace.getPrincipal());
364                        if (principal != null) {
365                            CmsPrincipalBean prinBean = new CmsPrincipalBean(
366                                principal.getName(),
367                                principal.getDescription(),
368                                principal.isGroup());
369                            if (!resource.getRootPath().equals(vfsPath)) {
370                                if (resource.getRootPath().startsWith(storedSiteRoot)) {
371                                    result.put(prinBean, sitePath);
372                                } else {
373                                    result.put(prinBean, resource.getRootPath());
374                                }
375                            } else {
376                                result.put(prinBean, null);
377                            }
378                        }
379                    }
380                }
381            } finally {
382                cms.getRequestContext().setSiteRoot(storedSiteRoot);
383            }
384        }
385        return result;
386    }
387
388    /**
389     * Processes a file path, which may have macros in it, so it can be opened by the XML content editor.<p>
390     *
391     * @param cms the current CMS context
392     * @param res the resource for which the context menu option has been selected
393     * @param pathWithMacros the file path which may contain macros
394     *
395     * @return the processed file path
396     */
397    public static String prepareFileNameForEditor(CmsObject cms, CmsResource res, String pathWithMacros) {
398
399        String subsite = OpenCms.getADEManager().getSubSiteRoot(cms, res.getRootPath());
400        CmsMacroResolver resolver = new CmsMacroResolver();
401        if (subsite != null) {
402            resolver.addMacro("subsite", cms.getRequestContext().removeSiteRoot(subsite));
403        }
404        String path = resolver.resolveMacros(pathWithMacros).replaceAll("/+", "/");
405        return path;
406    }
407
408    /**
409     * Gets page information of a resource and adds it to the given list info bean.<p>
410     *
411     * @param cms the CMS context
412     * @param resource the resource
413     * @param listInfo the list info bean to add the information to
414     *
415     * @return the list info bean
416     *
417     * @throws CmsException if the resource info can not be read
418     */
419    protected static CmsListInfoBean addPageInfo(CmsObject cms, CmsResource resource, CmsListInfoBean listInfo)
420    throws CmsException {
421
422        listInfo.setResourceState(resource.getState());
423
424        String title = cms.readPropertyObject(resource, CmsPropertyDefinition.PROPERTY_TITLE, false).getValue();
425        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(title)) {
426            listInfo.setTitle(title);
427        } else {
428            listInfo.setTitle(resource.getName());
429        }
430        listInfo.setSubTitle(cms.getSitePath(resource));
431        String secure = cms.readPropertyObject(resource, CmsPropertyDefinition.PROPERTY_SECURE, true).getValue();
432        if (Boolean.parseBoolean(secure)) {
433            listInfo.setStateIcon(CmsListInfoBean.StateIcon.secure);
434        } else {
435            String export = cms.readPropertyObject(resource, CmsPropertyDefinition.PROPERTY_EXPORT, true).getValue();
436            if (Boolean.parseBoolean(export)) {
437                listInfo.setStateIcon(CmsListInfoBean.StateIcon.export);
438            } else {
439                listInfo.setStateIcon(CmsListInfoBean.StateIcon.standard);
440            }
441        }
442        String resTypeName = OpenCms.getResourceManager().getResourceType(resource.getTypeId()).getTypeName();
443        String key = OpenCms.getWorkplaceManager().getExplorerTypeSetting(resTypeName).getKey();
444        Locale currentLocale = OpenCms.getWorkplaceManager().getWorkplaceLocale(cms);
445        CmsMessages messages = OpenCms.getWorkplaceManager().getMessages(currentLocale);
446        String resTypeNiceName = messages.key(key);
447        listInfo.addAdditionalInfo(
448            messages.key(org.opencms.workplace.commons.Messages.GUI_LABEL_TYPE_0),
449            resTypeNiceName);
450        listInfo.setResourceType(resTypeName);
451        return listInfo;
452    }
453
454    /**
455     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#createNewExternalLink(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
456     */
457    public void createNewExternalLink(String title, String link, String resourceName, String parentFolderPath)
458    throws CmsRpcException {
459
460        CmsObject cms = getCmsObject();
461        try {
462            CmsProperty titleProp = new CmsProperty(CmsPropertyDefinition.PROPERTY_TITLE, title, null);
463            @SuppressWarnings("deprecation")
464            CmsResource resource = cms.createResource(
465                CmsStringUtil.joinPaths(parentFolderPath, resourceName),
466                CmsResourceTypePointer.getStaticTypeId(),
467                new byte[0],
468                Collections.singletonList(titleProp));
469            CmsFile file = cms.readFile(resource);
470            file.setContents(link.getBytes(CmsLocaleManager.getResourceEncoding(cms, resource)));
471            cms.writeFile(file);
472            tryUnlock(resource);
473            // update the offline search indices
474            OpenCms.getSearchManager().updateOfflineIndexes(2 * CmsSearchManager.DEFAULT_OFFLINE_UPDATE_FREQNENCY);
475        } catch (Exception e) {
476            error(e);
477        }
478    }
479
480    /**
481     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#createPropertyDefinition(java.lang.String)
482     */
483    public void createPropertyDefinition(String name) throws CmsRpcException {
484
485        CmsObject cms = getCmsObject();
486        try {
487            cms.createPropertyDefinition(name.trim());
488        } catch (Exception e) {
489            error(e);
490        }
491
492    }
493
494    /**
495     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#deleteResource(org.opencms.util.CmsUUID)
496     */
497    public void deleteResource(CmsUUID structureId) throws CmsRpcException {
498
499        try {
500            CmsObject cms = getCmsObject();
501            CmsResource res = cms.readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION);
502            deleteResource(res);
503        } catch (Throwable e) {
504            error(e);
505        }
506    }
507
508    /**
509     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#deleteResource(java.lang.String)
510     */
511    public void deleteResource(String sitePath) throws CmsRpcException {
512
513        try {
514            CmsResource res = getCmsObject().readResource(sitePath, CmsResourceFilter.IGNORE_EXPIRATION);
515            deleteResource(res);
516        } catch (Throwable e) {
517            error(e);
518        }
519    }
520
521    /**
522     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#forceUnlock(org.opencms.util.CmsUUID)
523     */
524    public void forceUnlock(CmsUUID structureId) throws CmsRpcException {
525
526        try {
527            CmsResource resource = getCmsObject().readResource(structureId, CmsResourceFilter.ALL);
528            // get the current lock
529            CmsLock currentLock = getCmsObject().getLock(resource);
530            // check if the resource is locked at all
531            if (currentLock.getEditionLock().isUnlocked() && currentLock.getSystemLock().isUnlocked()) {
532                getCmsObject().lockResourceTemporary(resource);
533            } else {
534                getCmsObject().changeLock(resource);
535            }
536            getCmsObject().unlockResource(resource);
537        } catch (Throwable e) {
538            error(e);
539        }
540    }
541
542    /**
543     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#getAliasesForPage(org.opencms.util.CmsUUID)
544     */
545    public List<CmsAliasBean> getAliasesForPage(CmsUUID uuid) throws CmsRpcException {
546
547        try {
548            return m_aliasHelper.getAliasesForPage(uuid);
549        } catch (Throwable e) {
550            error(e);
551            return null;
552        }
553    }
554
555    /**
556     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#getAvailabilityInfo(org.opencms.util.CmsUUID)
557     */
558    public CmsAvailabilityInfoBean getAvailabilityInfo(CmsUUID structureId) throws CmsRpcException {
559
560        try {
561            CmsResource res = getCmsObject().readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION);
562            return getAvailabilityInfo(res);
563        } catch (Throwable e) {
564            error(e);
565            return null; // will never be reached
566        }
567    }
568
569    /**
570     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#getAvailabilityInfo(java.lang.String)
571     */
572    public CmsAvailabilityInfoBean getAvailabilityInfo(String vfsPath) throws CmsRpcException {
573
574        try {
575            CmsResource res = getCmsObject().readResource(vfsPath, CmsResourceFilter.IGNORE_EXPIRATION);
576            return getAvailabilityInfo(res);
577        } catch (Throwable e) {
578            error(e);
579            return null; // will never be reached
580        }
581    }
582
583    /**
584     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#getBrokenLinks(org.opencms.util.CmsUUID)
585     */
586    public CmsDeleteResourceBean getBrokenLinks(CmsUUID structureId) throws CmsRpcException {
587
588        try {
589            CmsResource entryResource = getCmsObject().readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION);
590
591            return getBrokenLinks(entryResource);
592        } catch (Throwable e) {
593            error(e);
594            return null; // will never be reached
595        }
596    }
597
598    /**
599     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#getBrokenLinks(java.lang.String)
600     */
601    public CmsDeleteResourceBean getBrokenLinks(String sitePath) throws CmsRpcException {
602
603        try {
604            CmsResource entryResource = getCmsObject().readResource(sitePath, CmsResourceFilter.IGNORE_EXPIRATION);
605
606            return getBrokenLinks(entryResource);
607        } catch (Throwable e) {
608            error(e);
609            return null; // will never be reached
610        }
611    }
612
613    /**
614     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#getChildren(java.lang.String)
615     */
616    public List<CmsVfsEntryBean> getChildren(String path) throws CmsRpcException {
617
618        try {
619            CmsObject cms = getCmsObject();
620            List<CmsResource> resources = new ArrayList<CmsResource>();
621            resources.addAll(cms.getResourcesInFolder(path, CmsResourceFilter.DEFAULT));
622            List<CmsVfsEntryBean> result = makeEntryBeans(resources, false);
623            return result;
624        } catch (Throwable e) {
625            error(e);
626        }
627        return null;
628    }
629
630    /**
631     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#getDefaultProperties(java.util.List)
632     */
633    public Map<CmsUUID, Map<String, CmsXmlContentProperty>> getDefaultProperties(List<CmsUUID> structureIds)
634    throws CmsRpcException {
635
636        try {
637            CmsPropertyEditorHelper helper = new CmsPropertyEditorHelper(getCmsObject());
638            return helper.getDefaultProperties(structureIds);
639        } catch (Throwable e) {
640            error(e);
641            return null;
642        }
643    }
644
645    /**
646     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#getDefinedProperties()
647     */
648    public ArrayList<String> getDefinedProperties() throws CmsRpcException {
649
650        CmsObject cms = getCmsObject();
651        try {
652            List<CmsPropertyDefinition> definitions = cms.readAllPropertyDefinitions();
653            ArrayList<String> result = new ArrayList<String>();
654            for (CmsPropertyDefinition def : definitions) {
655                result.add(def.getName());
656            }
657            return result;
658        } catch (Exception e) {
659            error(e);
660            return null;
661        }
662    }
663
664    /**
665     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#getFileReplaceInfo(org.opencms.util.CmsUUID)
666     */
667    public CmsReplaceInfo getFileReplaceInfo(CmsUUID structureId) throws CmsRpcException {
668
669        CmsReplaceInfo result = null;
670        try {
671            CmsObject cms = getCmsObject();
672            CmsResource res = cms.readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION);
673            CmsListInfoBean fileInfo = getPageInfo(res);
674            boolean isLockable = cms.getLock(res).isLockableBy(cms.getRequestContext().getCurrentUser());
675            long maxFileSize = OpenCms.getWorkplaceManager().getFileBytesMaxUploadSize(cms);
676            result = new CmsReplaceInfo(fileInfo, cms.getSitePath(res), isLockable, maxFileSize);
677        } catch (Throwable e) {
678            error(e);
679        }
680        return result;
681    }
682
683    /**
684     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#getHistoryPreviewInfo(org.opencms.util.CmsUUID, java.lang.String, org.opencms.gwt.shared.CmsHistoryVersion)
685     */
686    public CmsPreviewInfo getHistoryPreviewInfo(CmsUUID structureId, String locale, CmsHistoryVersion versionBean)
687    throws CmsRpcException {
688
689        try {
690            CmsObject cms = getCmsObject();
691            CmsResource previewResource = null;
692            if (versionBean.getVersionNumber() != null) {
693                previewResource = (CmsResource)(cms.readResource(
694                    structureId,
695                    versionBean.getVersionNumber().intValue()));
696            } else if (versionBean.isOffline()) {
697                previewResource = cms.readResource(structureId, CmsResourceFilter.ALL);
698            } else if (versionBean.isOnline()) {
699                CmsProject online = cms.readProject(CmsProject.ONLINE_PROJECT_ID);
700                cms = OpenCms.initCmsObject(cms);
701                cms.getRequestContext().setCurrentProject(online);
702                previewResource = cms.readResource(structureId, CmsResourceFilter.ALL);
703            }
704            CmsFile previewFile = cms.readFile(previewResource);
705            return getPreviewInfo(cms, previewFile, CmsLocaleManager.getLocale(locale));
706        } catch (Exception e) {
707            error(e);
708            return null; // return statement will never be reached
709        }
710    }
711
712    /**
713     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#getLockReportInfo(org.opencms.util.CmsUUID)
714     */
715    public CmsLockReportInfo getLockReportInfo(CmsUUID structureId) throws CmsRpcException {
716
717        CmsLockReportInfo result = null;
718        CmsObject cms = getCmsObject();
719        try {
720            CmsResource resource = cms.readResource(structureId, CmsResourceFilter.ALL);
721            List<CmsListInfoBean> lockedInfos = new ArrayList<CmsListInfoBean>();
722            List<CmsResource> lockedResources = cms.getBlockingLockedResources(resource);
723            if (lockedResources != null) {
724                for (CmsResource lockedResource : lockedResources) {
725                    lockedInfos.add(getPageInfoWithLock(cms, lockedResource));
726                }
727            }
728            result = new CmsLockReportInfo(getPageInfoWithLock(cms, resource), lockedInfos);
729        } catch (Throwable e) {
730            error(e);
731        }
732        return result;
733    }
734
735    /**
736     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#getPageInfo(org.opencms.util.CmsUUID)
737     */
738    public CmsListInfoBean getPageInfo(CmsUUID structureId) throws CmsRpcException {
739
740        try {
741            CmsResource res = getCmsObject().readResource(structureId, CmsResourceFilter.ALL);
742            return getPageInfo(res);
743        } catch (Throwable e) {
744            error(e);
745            return null; // will never be reached
746        }
747    }
748
749    /**
750     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#getPageInfo(java.lang.String)
751     */
752    public CmsListInfoBean getPageInfo(String vfsPath) throws CmsRpcException {
753
754        try {
755            CmsResource res = getCmsObject().readResource(vfsPath, CmsResourceFilter.IGNORE_EXPIRATION);
756            return getPageInfo(res);
757        } catch (Throwable e) {
758            error(e);
759            return null; // will never be reached
760        }
761    }
762
763    /**
764     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#getPreviewInfo(org.opencms.util.CmsUUID, java.lang.String)
765     */
766    public CmsPreviewInfo getPreviewInfo(CmsUUID structureId, String locale) throws CmsRpcException {
767
768        CmsPreviewInfo result = null;
769        try {
770            result = getPreviewInfo(
771                getCmsObject(),
772                getCmsObject().readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION),
773                CmsLocaleManager.getLocale(locale));
774        } catch (Exception e) {
775            error(e);
776        }
777        return result;
778
779    }
780
781    /**
782     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#getPreviewInfo(java.lang.String, java.lang.String)
783     */
784    public CmsPreviewInfo getPreviewInfo(String sitePath, String locale) throws CmsRpcException {
785
786        CmsPreviewInfo result = null;
787        try {
788            result = getPreviewInfo(
789                getCmsObject(),
790                getCmsObject().readResource(sitePath, CmsResourceFilter.IGNORE_EXPIRATION),
791                CmsLocaleManager.getLocale(locale));
792        } catch (Exception e) {
793            error(e);
794        }
795        return result;
796    }
797
798    /**
799     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#getRenameInfo(org.opencms.util.CmsUUID)
800     */
801    public CmsRenameInfoBean getRenameInfo(CmsUUID structureId) throws CmsRpcException {
802
803        try {
804            CmsObject cms = getCmsObject();
805            CmsResource resource = cms.readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION);
806            CmsListInfoBean listInfo = getPageInfo(resource);
807            String sitePath = cms.getSitePath(resource);
808            return new CmsRenameInfoBean(sitePath, structureId, listInfo);
809        } catch (Throwable e) {
810            error(e);
811            return null;
812        }
813    }
814
815    /**
816     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#getResourceHistory(org.opencms.util.CmsUUID)
817     */
818    public CmsHistoryResourceCollection getResourceHistory(CmsUUID structureId) throws CmsRpcException {
819
820        try {
821            CmsHistoryResourceCollection result = getResourceHistoryInternal(structureId);
822            CmsListInfoBean info = getPageInfo(structureId);
823            result.setContentInfo(info);
824            return result;
825
826        } catch (Exception e) {
827            error(e);
828            return null; // return statement will  never be reached
829        }
830    }
831
832    /**
833     * Internal version of getResourceHistory.<p>
834     *
835     * @param structureId the structure id of the resource
836     *
837     * @return the resource history
838     *
839     * @throws CmsException if something goes wrong
840     */
841    public CmsHistoryResourceCollection getResourceHistoryInternal(CmsUUID structureId) throws CmsException {
842
843        CmsHistoryResourceCollection result = new CmsHistoryResourceCollection();
844        CmsObject cms = getCmsObject();
845        CmsResource resource = cms.readResource(structureId, CmsResourceFilter.ALL);
846        List<I_CmsHistoryResource> versions = cms.readAllAvailableVersions(resource);
847        if (!resource.getState().isUnchanged()) {
848            result.add(createHistoryResourceBean(cms, resource, true, -1));
849        }
850        int maxVersion = 0;
851
852        if (versions.isEmpty()) {
853            try {
854                CmsProject online = cms.readProject(CmsProject.ONLINE_PROJECT_ID);
855                CmsObject onlineCms = OpenCms.initCmsObject(cms);
856                onlineCms.getRequestContext().setCurrentProject(online);
857                CmsResource onlineResource = onlineCms.readResource(structureId, CmsResourceFilter.ALL);
858                CmsHistoryResourceBean onlineResBean = createHistoryResourceBean(onlineCms, onlineResource, false, 0);
859                result.add(onlineResBean);
860            } catch (CmsVfsResourceNotFoundException e) {
861                LOG.info(e.getLocalizedMessage(), e);
862            } catch (Exception e) {
863                LOG.error(e.getLocalizedMessage(), e);
864            }
865        } else {
866            for (I_CmsHistoryResource historyRes : versions) {
867                maxVersion = Math.max(maxVersion, historyRes.getVersion());
868            }
869            for (I_CmsHistoryResource historyRes : versions) {
870                CmsHistoryResourceBean historyBean = createHistoryResourceBean(
871                    cms,
872                    (CmsResource)historyRes,
873                    false,
874                    maxVersion);
875                result.add(historyBean);
876            }
877        }
878        return result;
879    }
880
881    /**
882     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#getResourceStatus(org.opencms.util.CmsUUID, java.lang.String, boolean, java.util.List)
883     */
884    public CmsResourceStatusBean getResourceStatus(
885        CmsUUID structureId,
886        String contentLocale,
887        boolean includeTargets,
888        List<CmsUUID> additionalTargets) throws CmsRpcException {
889
890        try {
891            CmsObject cms = getCmsObject();
892            CmsDefaultResourceStatusProvider provider = new CmsDefaultResourceStatusProvider();
893            return provider.getResourceStatus(cms, structureId, contentLocale, includeTargets, additionalTargets);
894        } catch (Throwable e) {
895            error(e);
896            return null;
897        }
898    }
899
900    /**
901     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#getRestoreInfo(org.opencms.util.CmsUUID)
902     */
903    public CmsRestoreInfoBean getRestoreInfo(CmsUUID structureId) throws CmsRpcException {
904
905        try {
906            CmsObject cms = getCmsObject();
907            CmsResource resource = cms.readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION);
908            CmsListInfoBean listInfo = getPageInfo(resource);
909            CmsRestoreInfoBean result = new CmsRestoreInfoBean();
910            result.setListInfoBean(listInfo);
911
912            CmsObject onlineCms = OpenCms.initCmsObject(cms);
913            CmsProject onlineProject = cms.readProject(CmsProject.ONLINE_PROJECT_NAME);
914            onlineCms.getRequestContext().setCurrentProject(onlineProject);
915            CmsResource onlineResource = onlineCms.readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION);
916            result.setOnlinePath(onlineResource.getRootPath());
917            result.setOfflinePath(resource.getRootPath());
918
919            String offlineDate = formatDateTime(resource.getDateLastModified());
920            String onlineDate = formatDateTime(onlineResource.getDateLastModified());
921            result.setOfflineDate(offlineDate);
922            result.setOnlineDate(onlineDate);
923            result.setStructureId(structureId);
924
925            CmsObject offlineRootCms = OpenCms.initCmsObject(cms);
926            offlineRootCms.getRequestContext().setSiteRoot("");
927            CmsObject onlineRootCms = OpenCms.initCmsObject(onlineCms);
928            onlineRootCms.getRequestContext().setSiteRoot("");
929            String parent = CmsResource.getParentFolder(onlineResource.getRootPath());
930            boolean canUndoMove = offlineRootCms.existsResource(parent, CmsResourceFilter.IGNORE_EXPIRATION);
931
932            result.setCanUndoMove(canUndoMove);
933
934            return result;
935        } catch (Throwable e) {
936            error(e);
937            return null;
938        }
939    }
940
941    /**
942     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#getRootEntries()
943     */
944    public List<CmsVfsEntryBean> getRootEntries() throws CmsRpcException {
945
946        try {
947            CmsObject cms = getCmsObject();
948            List<CmsResource> roots = new ArrayList<CmsResource>();
949            roots.add(cms.readResource("/", CmsResourceFilter.IGNORE_EXPIRATION));
950            return makeEntryBeans(roots, true);
951        } catch (CmsException e) {
952            error(e);
953        }
954        return null;
955    }
956
957    /**
958     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#getSitePath(org.opencms.util.CmsUUID)
959     */
960    public String getSitePath(CmsUUID structureId) {
961
962        try {
963            CmsResource resource = getCmsObject().readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION);
964            return getCmsObject().getSitePath(resource);
965        } catch (CmsException e) {
966            if (LOG.isWarnEnabled()) {
967                LOG.warn(e.getMessageContainer(), e);
968            }
969        }
970        return null;
971    }
972
973    /**
974     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#loadLinkInfo(org.opencms.util.CmsUUID)
975     */
976    public CmsExternalLinkInfoBean loadLinkInfo(CmsUUID structureId) throws CmsRpcException {
977
978        CmsExternalLinkInfoBean info = new CmsExternalLinkInfoBean();
979        CmsObject cms = getCmsObject();
980        try {
981            CmsResource linkResource = cms.readResource(structureId, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED);
982            addPageInfo(cms, linkResource, info);
983            CmsFile linkFile = cms.readFile(linkResource);
984            OpenCms.getLocaleManager();
985            String link = new String(linkFile.getContents(), CmsLocaleManager.getResourceEncoding(cms, linkResource));
986            info.setLink(link);
987            info.setSitePath(cms.getSitePath(linkResource));
988        } catch (Exception e) {
989            error(e);
990        }
991        return info;
992    }
993
994    /**
995     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#loadPropertyData(org.opencms.util.CmsUUID)
996     */
997    public CmsPropertiesBean loadPropertyData(CmsUUID id) throws CmsRpcException {
998
999        CmsObject cms = getCmsObject();
1000        try {
1001            CmsPropertyEditorHelper helper = new CmsPropertyEditorHelper(cms);
1002            return helper.loadPropertyData(id);
1003        } catch (Throwable e) {
1004            error(e);
1005        }
1006        return null;
1007    }
1008
1009    /**
1010     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#loadQuickLaunchItems(org.opencms.gwt.shared.CmsQuickLaunchParams)
1011     */
1012    public List<CmsQuickLaunchData> loadQuickLaunchItems(CmsQuickLaunchParams params) throws CmsRpcException {
1013
1014        try {
1015            CmsQuickLaunchProvider provider = new CmsQuickLaunchProvider(getCmsObject());
1016            return provider.getQuickLaunchData(params);
1017        } catch (Exception e) {
1018            error(e);
1019            return null;
1020        }
1021    }
1022
1023    /**
1024     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#prepareEdit(org.opencms.util.CmsUUID, java.lang.String)
1025     */
1026    public CmsPrepareEditResponse prepareEdit(CmsUUID currentPageId, String pathWithMacros) throws CmsRpcException {
1027
1028        try {
1029            CmsObject cms = getCmsObject();
1030            CmsResource resource = null;
1031            if (cms.existsResource(pathWithMacros, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)) {
1032                resource = cms.readResource(pathWithMacros, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED);
1033            } else {
1034                CmsResource currentPage = cms.readResource(currentPageId, CmsResourceFilter.IGNORE_EXPIRATION);
1035                String path = prepareFileNameForEditor(cms, currentPage, pathWithMacros);
1036                resource = cms.readResource(path, CmsResourceFilter.IGNORE_EXPIRATION);
1037            }
1038            ensureLock(resource);
1039            CmsPrepareEditResponse result = new CmsPrepareEditResponse();
1040            result.setRootPath(resource.getRootPath());
1041            result.setSitePath(cms.getSitePath(resource));
1042            result.setStructureId(resource.getStructureId());
1043            return result;
1044        } catch (Throwable e) {
1045            error(e);
1046        }
1047        return null;
1048    }
1049
1050    /**
1051     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#renameResource(org.opencms.util.CmsUUID, java.lang.String)
1052     */
1053    public String renameResource(CmsUUID structureId, String newName) throws CmsRpcException {
1054
1055        try {
1056            return renameResourceInternal(structureId, newName);
1057        } catch (Throwable e) {
1058            error(e);
1059            return null;
1060        }
1061    }
1062
1063    /**
1064     * Internal implementation for renaming a resource.<p>
1065     *
1066     * @param structureId the structure id of the resource to rename
1067     * @param newName the new resource name
1068     * @return either null if the rename was successful, or an error message
1069     *
1070     * @throws CmsException if something goes wrong
1071     */
1072    public String renameResourceInternal(CmsUUID structureId, String newName) throws CmsException {
1073
1074        CmsObject cms = getCmsObject();
1075        Locale locale = OpenCms.getWorkplaceManager().getWorkplaceLocale(cms);
1076        try {
1077            CmsResource.checkResourceName(newName);
1078        } catch (CmsIllegalArgumentException e) {
1079            return e.getLocalizedMessage(locale);
1080        }
1081        CmsResource resource = cms.readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION);
1082        String oldSitePath = cms.getSitePath(resource);
1083        String parentPath = CmsResource.getParentFolder(oldSitePath);
1084        String newSitePath = CmsStringUtil.joinPaths(parentPath, newName);
1085        try {
1086            ensureLock(resource);
1087            cms.moveResource(oldSitePath, newSitePath);
1088            resource = cms.readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION);
1089        } catch (CmsException e) {
1090            return e.getLocalizedMessage(OpenCms.getWorkplaceManager().getWorkplaceLocale(cms));
1091        }
1092        tryUnlock(resource);
1093        return null;
1094    }
1095
1096    /**
1097     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#restoreResource(org.opencms.util.CmsUUID, int)
1098     */
1099    public void restoreResource(CmsUUID structureId, int version) throws CmsRpcException {
1100
1101        CmsObject cms = getCmsObject();
1102        try {
1103            ensureLock(structureId);
1104            cms.restoreResourceVersion(structureId, version);
1105            try {
1106                CmsResource res = cms.readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION);
1107                cms.unlockResource(res);
1108            } catch (Exception e) {
1109                LOG.error(e.getLocalizedMessage(), e);
1110            }
1111
1112        } catch (Exception e) {
1113            error(e);
1114            return; // return stmt  will never be reached
1115        }
1116
1117    }
1118
1119    /**
1120     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#saveAliases(org.opencms.util.CmsUUID, java.util.List)
1121     */
1122    public void saveAliases(CmsUUID structureId, List<CmsAliasBean> aliasBeans) throws CmsRpcException {
1123
1124        try {
1125            m_aliasHelper.saveAliases(structureId, aliasBeans);
1126        } catch (Throwable e) {
1127            error(e);
1128        }
1129    }
1130
1131    /**
1132     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#saveExternalLink(org.opencms.util.CmsUUID, java.lang.String, java.lang.String, java.lang.String)
1133     */
1134    public void saveExternalLink(CmsUUID structureId, String title, String link, String fileName)
1135    throws CmsRpcException {
1136
1137        try {
1138            CmsObject cms = getCmsObject();
1139            CmsResource res = cms.readResource(structureId);
1140            ensureLock(res);
1141            CmsFile file = cms.readFile(res);
1142            String oldLink = new String(file.getContents(), CmsLocaleManager.getResourceEncoding(cms, res));
1143            if (!oldLink.equals(link)) {
1144                file.setContents(link.getBytes(CmsLocaleManager.getResourceEncoding(cms, res)));
1145                cms.writeFile(file);
1146            }
1147            CmsProperty titleProp = cms.readPropertyObject(res, CmsPropertyDefinition.PROPERTY_TITLE, false);
1148            if (titleProp.isNullProperty()) {
1149                titleProp = new CmsProperty(CmsPropertyDefinition.PROPERTY_TITLE, title, null);
1150                cms.writePropertyObject(cms.getSitePath(res), titleProp);
1151            } else if (!titleProp.getValue().equals(title)) {
1152                titleProp.setStructureValue(title);
1153                cms.writePropertyObject(cms.getSitePath(res), titleProp);
1154            }
1155            if (!res.getName().equals(fileName)) {
1156                String oldSitePath = cms.getSitePath(res);
1157                String newSitePath = CmsStringUtil.joinPaths(CmsResource.getParentFolder(oldSitePath), fileName);
1158                getCmsObject().renameResource(oldSitePath, newSitePath);
1159            }
1160            tryUnlock(res);
1161            // update the offline search indices
1162            OpenCms.getSearchManager().updateOfflineIndexes(2 * CmsSearchManager.DEFAULT_OFFLINE_UPDATE_FREQNENCY);
1163        } catch (Exception e) {
1164            error(e);
1165        }
1166    }
1167
1168    /**
1169     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#saveProperties(org.opencms.gwt.shared.property.CmsPropertyChangeSet)
1170     */
1171    public void saveProperties(CmsPropertyChangeSet changes) throws CmsRpcException {
1172
1173        String origSiteRoot = getCmsObject().getRequestContext().getSiteRoot();
1174        try {
1175            getCmsObject().getRequestContext().setSiteRoot("");
1176            CmsPropertyEditorHelper helper = new CmsPropertyEditorHelper(getCmsObject());
1177            helper.saveProperties(changes);
1178        } catch (Throwable t) {
1179            error(t);
1180        } finally {
1181            getCmsObject().getRequestContext().setSiteRoot(origSiteRoot);
1182        }
1183    }
1184
1185    /**
1186     * Sets the current cms context.<p>
1187     *
1188     * @param cms the current cms context to set
1189     */
1190    @Override
1191    public synchronized void setCms(CmsObject cms) {
1192
1193        super.setCms(cms);
1194        m_aliasHelper.setCms(cms);
1195    }
1196
1197    /**
1198     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#substituteLinkForRootPath(java.lang.String, java.lang.String)
1199     */
1200    public String substituteLinkForRootPath(String currentSiteRoot, String rootPath) throws CmsRpcException {
1201
1202        String result = null;
1203        try {
1204            CmsObject cms = OpenCms.initCmsObject(getCmsObject());
1205            cms.getRequestContext().setSiteRoot(currentSiteRoot);
1206            result = OpenCms.getLinkManager().substituteLinkForRootPath(cms, rootPath);
1207        } catch (CmsException e) {
1208            error(e);
1209        }
1210        return result;
1211    }
1212
1213    /**
1214     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#syncDeleteResource(org.opencms.util.CmsUUID)
1215     */
1216    public void syncDeleteResource(CmsUUID structureId) throws CmsRpcException {
1217
1218        deleteResource(structureId);
1219    }
1220
1221    /**
1222     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#undelete(org.opencms.util.CmsUUID)
1223     */
1224    public void undelete(CmsUUID structureId) throws CmsRpcException {
1225
1226        try {
1227            CmsObject cms = OpenCms.initCmsObject(getCmsObject());
1228            cms.getRequestContext().setSiteRoot("");
1229            CmsResource resource = cms.readResource(structureId, CmsResourceFilter.ALL);
1230            ensureLock(resource);
1231            cms.undeleteResource(resource.getRootPath(), true);
1232        } catch (Exception e) {
1233            error(e);
1234        }
1235    }
1236
1237    /**
1238     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#undoChanges(org.opencms.util.CmsUUID, boolean)
1239     */
1240    public void undoChanges(CmsUUID structureId, boolean undoMove) throws CmsRpcException {
1241
1242        try {
1243            CmsObject cms = getCmsObject();
1244            CmsResource resource = cms.readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION);
1245            ensureLock(resource);
1246            CmsResourceUndoMode mode = undoMove ? CmsResource.UNDO_MOVE_CONTENT : CmsResource.UNDO_CONTENT;
1247            String path = cms.getSitePath(resource);
1248            cms.undoChanges(path, mode);
1249            try {
1250                resource = cms.readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION);
1251                path = cms.getSitePath(resource);
1252                cms.unlockResource(path);
1253            } catch (CmsException e) {
1254                LOG.info("Could not unlock resource after undoing changes: " + e.getLocalizedMessage(), e);
1255            }
1256        } catch (Throwable e) {
1257            error(e);
1258        }
1259    }
1260
1261    /**
1262     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#validateAliases(org.opencms.util.CmsUUID, java.util.Map)
1263     */
1264    public Map<String, String> validateAliases(CmsUUID uuid, Map<String, String> aliasPaths) throws CmsRpcException {
1265
1266        try {
1267            return m_aliasHelper.validateAliases(uuid, aliasPaths);
1268        } catch (Throwable e) {
1269            error(e);
1270        }
1271        return null;
1272
1273    }
1274
1275    /**
1276     * Creates a "broken link" bean based on a resource.<p>
1277     *
1278     * @param resource the resource
1279     *
1280     * @return the "broken link" bean with the data from the resource
1281     *
1282     * @throws CmsException if something goes wrong
1283     */
1284    protected CmsBrokenLinkBean createSitemapBrokenLinkBean(CmsResource resource) throws CmsException {
1285
1286        CmsObject cms = getCmsObject();
1287        CmsProperty titleProp = cms.readPropertyObject(resource, CmsPropertyDefinition.PROPERTY_TITLE, true);
1288        String typeName = OpenCms.getResourceManager().getResourceType(resource).getTypeName();
1289        String defaultTitle = "";
1290        String title = titleProp.getValue(defaultTitle);
1291        String path = cms.getSitePath(resource);
1292        String subtitle = path;
1293
1294        CmsBrokenLinkBean result = new CmsBrokenLinkBean(resource.getStructureId(), title, subtitle, typeName);
1295
1296        return result;
1297    }
1298
1299    /**
1300     * Helper method for creating a VFS entry bean from a resource.<p>
1301     *
1302     * @param resource the resource whose data should be stored in the bean
1303     * @param root true if the resource is a root resource
1304     *
1305     * @return the data bean representing the resource
1306     *
1307     * @throws CmsException if something goes wrong
1308     */
1309    protected CmsVfsEntryBean makeEntryBean(CmsResource resource, boolean root) throws CmsException {
1310
1311        CmsObject cms = getCmsObject();
1312        boolean isFolder = resource.isFolder();
1313        String name = root ? "/" : resource.getName();
1314        String path = cms.getSitePath(resource);
1315        boolean hasChildren = false;
1316        if (isFolder) {
1317            List<CmsResource> children = cms.getResourcesInFolder(
1318                cms.getRequestContext().getSitePath(resource),
1319                CmsResourceFilter.DEFAULT);
1320            if (!children.isEmpty()) {
1321                hasChildren = true;
1322            }
1323        }
1324        String resourceType = OpenCms.getResourceManager().getResourceType(resource.getTypeId()).getTypeName();
1325
1326        return new CmsVfsEntryBean(path, name, resourceType, isFolder, hasChildren);
1327    }
1328
1329    /**
1330     * Helper method for creating a list of VFS entry beans from a list of the corresponding resources.<p>
1331     *
1332     * @param resources the list of resources which should be converted to entry beans
1333     * @param root true if the resources in the list are root resources
1334     *
1335     * @return the list of VFS entry beans for the resources
1336     *
1337     * @throws CmsException if something goes wrong
1338     */
1339    protected List<CmsVfsEntryBean> makeEntryBeans(List<CmsResource> resources, boolean root) throws CmsException {
1340
1341        List<CmsVfsEntryBean> result = new ArrayList<CmsVfsEntryBean>();
1342        for (CmsResource res : resources) {
1343            result.add(makeEntryBean(res, root));
1344        }
1345        return result;
1346    }
1347
1348    /**
1349     * Adds additional info items for broken links.<p>
1350     *
1351     * @param cms the CMS context to use
1352     * @param resource the resource from which the additional infos should be read
1353     * @param result the result in which to store the additional info
1354     */
1355    private void addBrokenLinkAdditionalInfo(CmsObject cms, CmsResource resource, CmsBrokenLinkBean result) {
1356
1357        String dateLastModifiedLabel = org.opencms.workplace.commons.Messages.get().getBundle(
1358            OpenCms.getWorkplaceManager().getWorkplaceLocale(cms)).key(
1359                org.opencms.workplace.commons.Messages.GUI_LABEL_DATE_LAST_MODIFIED_0);
1360        String dateLastModified = CmsVfsService.formatDateTime(cms, resource.getDateLastModified());
1361
1362        String userLastModifiedLabel = org.opencms.workplace.commons.Messages.get().getBundle(
1363            OpenCms.getWorkplaceManager().getWorkplaceLocale(cms)).key(
1364                org.opencms.workplace.commons.Messages.GUI_LABEL_USER_LAST_MODIFIED_0);
1365        String userLastModified = "" + resource.getUserLastModified();
1366        try {
1367            userLastModified = cms.readUser(resource.getUserLastModified()).getName();
1368        } catch (CmsException e) {
1369            LOG.error(e.getLocalizedMessage(), e);
1370        }
1371
1372        result.addInfo(dateLastModifiedLabel, dateLastModified);
1373        result.addInfo(userLastModifiedLabel, userLastModified);
1374    }
1375
1376    /**
1377     * Creates a bean representing a historical resource version.<p>
1378     *
1379     * @param cms the current CMS context
1380     * @param historyRes the historical resource
1381     * @param offline true if this resource was read from the offline project
1382     * @param maxVersion the largest version number found
1383     *
1384     * @return the bean representing the historical resource
1385     * @throws CmsException if something goes wrong
1386     */
1387    private CmsHistoryResourceBean createHistoryResourceBean(
1388        CmsObject cms,
1389        CmsResource historyRes,
1390        boolean offline,
1391        int maxVersion) throws CmsException {
1392
1393        CmsHistoryResourceBean result = new CmsHistoryResourceBean();
1394
1395        Locale locale = OpenCms.getWorkplaceManager().getWorkplaceLocale(cms);
1396        result.setStructureId(historyRes.getStructureId());
1397        result.setRootPath(historyRes.getRootPath());
1398        result.setDateLastModified(formatDate(historyRes.getDateLastModified(), locale));
1399        CmsUUID userId = historyRes.getUserLastModified();
1400        String userName = userId.toString();
1401        try {
1402            CmsUser user = cms.readUser(userId);
1403            userName = user.getName();
1404        } catch (CmsException e) {
1405            LOG.warn(e.getLocalizedMessage(), e);
1406        }
1407        result.setUserLastModified(userName);
1408        result.setSize(historyRes.getLength());
1409        if (historyRes instanceof I_CmsHistoryResource) {
1410            int publishTag = ((I_CmsHistoryResource)historyRes).getPublishTag();
1411            CmsHistoryProject project = cms.readHistoryProject(publishTag);
1412            long publishDate = project.getPublishingDate();
1413            result.setDatePublished(formatDate(publishDate, locale));
1414            int version = ((I_CmsHistoryResource)historyRes).getVersion();
1415            result.setVersion(
1416                new CmsHistoryVersion(
1417                    Integer.valueOf(historyRes.getVersion()),
1418                    maxVersion == version ? OfflineOnline.online : null));
1419
1420            List<CmsProperty> historyProperties = cms.readHistoryPropertyObjects((I_CmsHistoryResource)historyRes);
1421            Map<String, CmsProperty> historyPropertyMap = CmsProperty.toObjectMap(historyProperties);
1422            CmsProperty titleProp = CmsProperty.wrapIfNull(
1423                historyPropertyMap.get(CmsPropertyDefinition.PROPERTY_TITLE));
1424            CmsProperty descProp = CmsProperty.wrapIfNull(
1425                historyPropertyMap.get(CmsPropertyDefinition.PROPERTY_DESCRIPTION));
1426            result.setTitle(titleProp.getValue());
1427            result.setDescription(descProp.getValue());
1428        } else {
1429            if (offline) {
1430                result.setVersion(new CmsHistoryVersion(null, OfflineOnline.offline));
1431            } else {
1432                result.setVersion(new CmsHistoryVersion(null, OfflineOnline.online));
1433            }
1434        }
1435        return result;
1436    }
1437
1438    /**
1439     * Internal method to delete the given resource.<p>
1440     *
1441     * @param resource the resource to delete
1442     *
1443     * @throws CmsException if something goes wrong
1444     */
1445    private void deleteResource(CmsResource resource) throws CmsException {
1446
1447        String path = null;
1448        CmsObject cms = getCmsObject();
1449        try {
1450            path = cms.getSitePath(resource);
1451            cms.lockResource(path);
1452            cms.deleteResource(path, CmsResource.DELETE_PRESERVE_SIBLINGS);
1453
1454            // check if any detail container page resource exists to this resource
1455            String detailContainers = CmsJspTagContainer.getDetailOnlyPageName(path);
1456            if (cms.existsResource(detailContainers, CmsResourceFilter.IGNORE_EXPIRATION)) {
1457                deleteResource(cms.readResource(detailContainers, CmsResourceFilter.IGNORE_EXPIRATION));
1458            }
1459        } finally {
1460            try {
1461                if (path != null) {
1462                    getCmsObject().unlockResource(path);
1463                }
1464            } catch (Exception e) {
1465                // should really never happen
1466                LOG.debug(e.getLocalizedMessage(), e);
1467            }
1468        }
1469    }
1470
1471    /**
1472     * Converts a date to a date bean.<p>
1473     *
1474     * @param date the date to convert
1475     * @param locale the locale to use for the conversion
1476     *
1477     * @return the date bean
1478     */
1479    private CmsClientDateBean formatDate(long date, Locale locale) {
1480
1481        return new CmsClientDateBean(date, formatDateTime(date));
1482    }
1483
1484    /**
1485     * Formats the date for the current user's locale.<p>
1486     *
1487     * @param date the date to format
1488     *
1489     * @return the formatted date for the current user's locale
1490     */
1491    private String formatDateTime(long date) {
1492
1493        CmsObject cms = getCmsObject();
1494        return formatDateTime(cms, date);
1495    }
1496
1497    /**
1498     * Returns a bean that contains the infos for the {@link org.opencms.gwt.client.ui.contextmenu.CmsAvailabilityDialog}.<p>
1499     *
1500     * @param res the resource to get the availability infos for
1501     *
1502     * @return a bean for the {@link org.opencms.gwt.client.ui.contextmenu.CmsAvailabilityDialog}
1503     *
1504     * @throws CmsRpcException if something goes wrong
1505     */
1506    private CmsAvailabilityInfoBean getAvailabilityInfo(CmsResource res) throws CmsRpcException {
1507
1508        CmsObject cms = getCmsObject();
1509        try {
1510            CmsAvailabilityInfoBean avail = getAvailabilityInfoStatic(cms, res);
1511            avail.setPageInfo(getPageInfo(res));
1512            return avail;
1513        } catch (CmsException e) {
1514            error(e);
1515            return null; // will never be reached
1516        }
1517    }
1518
1519    /**
1520     * Returns the available locales mapped to there display name for the given resource
1521     * or <code>null</code> in case of non xml-content/xml-page resources.<p>
1522     *
1523     * @param resource the resource
1524     *
1525     * @return the available locales
1526     */
1527    private LinkedHashMap<String, String> getAvailableLocales(CmsResource resource) {
1528
1529        LinkedHashMap<String, String> result = null;
1530        List<Locale> locales = null;
1531        try {
1532            if (CmsResourceTypeXmlPage.isXmlPage(resource)) {
1533                locales = CmsXmlPageFactory.unmarshal(getCmsObject(), resource, getRequest()).getLocales();
1534            } else if (CmsResourceTypeXmlContent.isXmlContent(resource)) {
1535                locales = CmsXmlContentFactory.unmarshal(getCmsObject(), resource, getRequest()).getLocales();
1536            } else if (CmsResourceTypeXmlContainerPage.isContainerPage(resource)) {
1537                locales = CmsXmlContainerPageFactory.unmarshal(getCmsObject(), resource).getLocales();
1538            }
1539        } catch (CmsException e) {
1540            LOG.warn(e.getLocalizedMessage(), e);
1541        }
1542        if (locales != null) {
1543            Locale wpLocale = OpenCms.getWorkplaceManager().getWorkplaceLocale(getCmsObject());
1544            result = new LinkedHashMap<String, String>();
1545            for (Locale locale : locales) {
1546                result.put(locale.toString(), locale.getDisplayName(wpLocale));
1547            }
1548        }
1549        return result;
1550    }
1551
1552    /**
1553     * Helper method for converting a map which maps resources to resources to a list of "broken link" beans,
1554     * which have beans representing the source of the corresponding link as children.<p>
1555     *
1556     * @param linkMap a multimap from resource to resources
1557     *
1558     * @return a list of beans representing links which will be broken
1559     *
1560     * @throws CmsException if something goes wrong
1561     */
1562    private List<CmsBrokenLinkBean> getBrokenLinkBeans(Multimap<CmsResource, CmsResource> linkMap) throws CmsException {
1563
1564        CmsBrokenLinkRenderer brokenLinkRenderer = new CmsBrokenLinkRenderer(getCmsObject());
1565
1566        Multimap<CmsBrokenLinkBean, CmsBrokenLinkBean> resultMap = HashMultimap.create();
1567
1568        for (CmsResource source : linkMap.keySet()) {
1569
1570            for (CmsResource target : linkMap.get(source)) {
1571                CmsBrokenLinkBean targetBean = createSitemapBrokenLinkBean(target);
1572                addBrokenLinkAdditionalInfo(getCmsObject(), target, targetBean);
1573                List<CmsBrokenLinkBean> brokenLinkBeans = brokenLinkRenderer.renderBrokenLink(target, source);
1574                for (CmsBrokenLinkBean childBean : brokenLinkBeans) {
1575                    addBrokenLinkAdditionalInfo(getCmsObject(), source, childBean);
1576                    resultMap.put(childBean, targetBean);
1577                }
1578            }
1579        }
1580
1581        // now convert multimap representation to parent/child representation
1582        for (CmsBrokenLinkBean parent : resultMap.keySet()) {
1583            for (CmsBrokenLinkBean child : resultMap.get(parent)) {
1584                parent.addChild(child);
1585            }
1586        }
1587        return Lists.newArrayList(resultMap.keySet());
1588    }
1589
1590    /**
1591     * Internal method to get the broken links information for the given resource.<p>
1592     *
1593     * @param entryResource the resource
1594     *
1595     * @return the broken links information
1596     *
1597     * @throws CmsException if something goes wrong
1598     */
1599    private CmsDeleteResourceBean getBrokenLinks(CmsResource entryResource) throws CmsException {
1600
1601        CmsDeleteResourceBean result = null;
1602
1603        CmsListInfoBean info = null;
1604        List<CmsBrokenLinkBean> brokenLinks = null;
1605
1606        CmsObject cms = getCmsObject();
1607        String resourceSitePath = cms.getSitePath(entryResource);
1608
1609        ensureSession();
1610
1611        List<CmsResource> descendants = new ArrayList<CmsResource>();
1612        HashSet<CmsUUID> deleteIds = new HashSet<CmsUUID>();
1613
1614        descendants.add(entryResource);
1615        if (entryResource.isFolder()) {
1616            descendants.addAll(cms.readResources(resourceSitePath, CmsResourceFilter.IGNORE_EXPIRATION));
1617        }
1618
1619        for (CmsResource deleteRes : descendants) {
1620            deleteIds.add(deleteRes.getStructureId());
1621        }
1622        Multimap<CmsResource, CmsResource> linkMap = HashMultimap.create();
1623        for (CmsResource resource : descendants) {
1624            List<CmsRelation> relations = cms.getRelationsForResource(resource, CmsRelationFilter.SOURCES);
1625            List<CmsResource> result1 = new ArrayList<CmsResource>();
1626            for (CmsRelation relation : relations) {
1627                // only add related resources that are not going to be deleted
1628                if (!deleteIds.contains(relation.getSourceId())) {
1629                    CmsResource source1 = relation.getSource(cms, CmsResourceFilter.ALL);
1630                    if (!source1.getState().isDeleted()) {
1631                        result1.add(source1);
1632                    }
1633                }
1634            }
1635            List<CmsResource> linkSources = result1;
1636            for (CmsResource source : linkSources) {
1637                linkMap.put(source, resource);
1638            }
1639        }
1640
1641        brokenLinks = getBrokenLinkBeans(linkMap);
1642        info = getPageInfo(entryResource);
1643
1644        result = new CmsDeleteResourceBean(resourceSitePath, info, brokenLinks);
1645
1646        return result;
1647    }
1648
1649    /**
1650     * Gets the resources which link to a given structure id.<p>
1651     *
1652     * @param cms the current CMS context
1653     * @param resource the relation target resource
1654     * @param deleteIds set of resources to delete
1655     *
1656     * @return the list of resources which link to the given id
1657     *
1658     * @throws CmsException if something goes wrong
1659     */
1660    @SuppressWarnings("unused")
1661    private List<CmsResource> getLinkSources(CmsObject cms, CmsResource resource, HashSet<CmsUUID> deleteIds)
1662    throws CmsException {
1663
1664        List<CmsRelation> relations = cms.getRelationsForResource(resource, CmsRelationFilter.SOURCES);
1665        List<CmsResource> result = new ArrayList<CmsResource>();
1666        for (CmsRelation relation : relations) {
1667            // only add related resources that are not going to be deleted
1668            if (!deleteIds.contains(relation.getSourceId())) {
1669                CmsResource source = relation.getSource(cms, CmsResourceFilter.ALL);
1670                if (!source.getState().isDeleted()) {
1671                    result.add(source);
1672                }
1673            }
1674        }
1675        return result;
1676    }
1677
1678    /**
1679     * Returns a bean to display the {@link org.opencms.gwt.client.ui.CmsListItemWidget}.<p>
1680     *
1681     * @param res the resource to get the page info for
1682     *
1683     * @return a bean to display the {@link org.opencms.gwt.client.ui.CmsListItemWidget}.<p>
1684     *
1685     * @throws CmsLoaderException if the resource type could not be found
1686     * @throws CmsException if something else goes wrong
1687     */
1688    private CmsListInfoBean getPageInfo(CmsResource res) throws CmsException, CmsLoaderException {
1689
1690        CmsObject cms = getCmsObject();
1691        return getPageInfo(cms, res);
1692    }
1693
1694    /**
1695     * Returns the preview info for the given resource.<p>
1696     *
1697     *@param cms the CMS context
1698     * @param resource the resource
1699     * @param locale the requested locale
1700     *
1701     * @return the preview info
1702     */
1703    private CmsPreviewInfo getPreviewInfo(CmsObject cms, CmsResource resource, Locale locale) {
1704
1705        String title = "";
1706        try {
1707            CmsProperty titleProperty = cms.readPropertyObject(resource, CmsPropertyDefinition.PROPERTY_TITLE, false);
1708            title = titleProperty.getValue("");
1709        } catch (CmsException e) {
1710            LOG.warn(e.getLocalizedMessage(), e);
1711        }
1712        String noPreviewReason = getNoPreviewReason(cms, resource);
1713        String previewContent = null;
1714        int height = 0;
1715        int width = 0;
1716        LinkedHashMap<String, String> locales = getAvailableLocales(resource);
1717        if (noPreviewReason != null) {
1718            previewContent = "<div>" + noPreviewReason + "</div>";
1719            return new CmsPreviewInfo(
1720                "<div>" + noPreviewReason + "</div>",
1721                null,
1722                false,
1723                title,
1724                cms.getSitePath(resource),
1725                locale.toString());
1726        } else if (OpenCms.getResourceManager().matchResourceType(
1727            CmsResourceTypeImage.getStaticTypeName(),
1728            resource.getTypeId())) {
1729            CmsImageScaler scaler = new CmsImageScaler(cms, resource);
1730            String imageLink = null;
1731            if (resource instanceof I_CmsHistoryResource) {
1732                int version = ((I_CmsHistoryResource)resource).getVersion();
1733                imageLink = OpenCms.getLinkManager().substituteLinkForUnknownTarget(
1734                    cms,
1735                    CmsHistoryListUtil.getHistoryLink(cms, resource.getStructureId(), "" + version));
1736            } else {
1737                imageLink = OpenCms.getLinkManager().substituteLinkForUnknownTarget(cms, resource.getRootPath());
1738            }
1739            imageLink = CmsRequestUtil.appendParameter(imageLink, "random", "" + Math.random());
1740            previewContent = "<img src=\"" + imageLink + "\" title=\"" + title + "\" style=\"display:block\" />";
1741            height = scaler.getHeight();
1742            width = scaler.getWidth();
1743        } else if (CmsResourceTypeXmlContent.isXmlContent(resource)) {
1744            if (!locales.containsKey(locale.toString())) {
1745                locale = CmsLocaleManager.getMainLocale(cms, resource);
1746            }
1747            previewContent = CmsPreviewService.getPreviewContent(getRequest(), getResponse(), cms, resource, locale);
1748
1749        } else if (CmsResourceTypePlain.getStaticTypeId() == resource.getTypeId()) {
1750            try {
1751                previewContent = "<pre><code>" + new String(cms.readFile(resource).getContents()) + "</code></pre>";
1752            } catch (CmsException e) {
1753                LOG.warn(e.getLocalizedMessage(), e);
1754                previewContent = "<div>"
1755                    + Messages.get().getBundle(OpenCms.getWorkplaceManager().getWorkplaceLocale(cms)).key(
1756                        Messages.GUI_NO_PREVIEW_CAN_T_READ_CONTENT_0)
1757                    + "</div>";
1758            }
1759        }
1760        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(previewContent)) {
1761            CmsPreviewInfo result = new CmsPreviewInfo(
1762                previewContent,
1763                null,
1764                false,
1765                title,
1766                cms.getSitePath(resource),
1767                locale.toString());
1768            result.setHeight(height);
1769            result.setWidth(width);
1770            result.setLocales(locales);
1771            return result;
1772        }
1773        if (CmsResourceTypeXmlContainerPage.isContainerPage(resource) || CmsResourceTypeXmlPage.isXmlPage(resource)) {
1774            CmsPreviewInfo result = new CmsPreviewInfo(
1775                null,
1776                OpenCms.getLinkManager().substituteLinkForUnknownTarget(cms, resource.getRootPath())
1777                    + "?"
1778                    + CmsGwtConstants.PARAM_DISABLE_DIRECT_EDIT
1779                    + "=true"
1780                    + "&__locale="
1781                    + locale.toString(),
1782                false,
1783                title,
1784                cms.getSitePath(resource),
1785                locale.toString());
1786            result.setLocales(locales);
1787            return result;
1788        }
1789        return new CmsPreviewInfo(
1790            null,
1791            OpenCms.getLinkManager().substituteLinkForUnknownTarget(cms, resource.getRootPath())
1792                + "?"
1793                + CmsGwtConstants.PARAM_DISABLE_DIRECT_EDIT
1794                + "=true",
1795            true,
1796            title,
1797            cms.getSitePath(resource),
1798            locale.toString());
1799    }
1800
1801}