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, org.opencms.util.CmsUUID)
883     */
884    public CmsResourceStatusBean getResourceStatus(
885        CmsUUID structureId,
886        String contentLocale,
887        boolean includeTargets,
888        CmsUUID detailContentId) throws CmsRpcException {
889
890        try {
891            CmsObject cms = getCmsObject();
892            CmsDefaultResourceStatusProvider provider = new CmsDefaultResourceStatusProvider();
893            return provider.getResourceStatus(
894                cms,
895                structureId,
896                contentLocale,
897                includeTargets,
898                detailContentId,
899                detailContentId != null ? Collections.singletonList(detailContentId) : null);
900        } catch (Throwable e) {
901            error(e);
902            return null;
903        }
904    }
905
906    /**
907     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#getRestoreInfo(org.opencms.util.CmsUUID)
908     */
909    public CmsRestoreInfoBean getRestoreInfo(CmsUUID structureId) throws CmsRpcException {
910
911        try {
912            CmsObject cms = getCmsObject();
913            CmsResource resource = cms.readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION);
914            CmsListInfoBean listInfo = getPageInfo(resource);
915            CmsRestoreInfoBean result = new CmsRestoreInfoBean();
916            result.setListInfoBean(listInfo);
917
918            CmsObject onlineCms = OpenCms.initCmsObject(cms);
919            CmsProject onlineProject = cms.readProject(CmsProject.ONLINE_PROJECT_NAME);
920            onlineCms.getRequestContext().setCurrentProject(onlineProject);
921            CmsResource onlineResource = onlineCms.readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION);
922            result.setOnlinePath(onlineResource.getRootPath());
923            result.setOfflinePath(resource.getRootPath());
924
925            String offlineDate = formatDateTime(resource.getDateLastModified());
926            String onlineDate = formatDateTime(onlineResource.getDateLastModified());
927            result.setOfflineDate(offlineDate);
928            result.setOnlineDate(onlineDate);
929            result.setStructureId(structureId);
930
931            CmsObject offlineRootCms = OpenCms.initCmsObject(cms);
932            offlineRootCms.getRequestContext().setSiteRoot("");
933            CmsObject onlineRootCms = OpenCms.initCmsObject(onlineCms);
934            onlineRootCms.getRequestContext().setSiteRoot("");
935            String parent = CmsResource.getParentFolder(onlineResource.getRootPath());
936            boolean canUndoMove = offlineRootCms.existsResource(parent, CmsResourceFilter.IGNORE_EXPIRATION);
937
938            result.setCanUndoMove(canUndoMove);
939
940            return result;
941        } catch (Throwable e) {
942            error(e);
943            return null;
944        }
945    }
946
947    /**
948     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#getRootEntries()
949     */
950    public List<CmsVfsEntryBean> getRootEntries() throws CmsRpcException {
951
952        try {
953            CmsObject cms = getCmsObject();
954            List<CmsResource> roots = new ArrayList<CmsResource>();
955            roots.add(cms.readResource("/", CmsResourceFilter.IGNORE_EXPIRATION));
956            return makeEntryBeans(roots, true);
957        } catch (CmsException e) {
958            error(e);
959        }
960        return null;
961    }
962
963    /**
964     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#getSitePath(org.opencms.util.CmsUUID)
965     */
966    public String getSitePath(CmsUUID structureId) {
967
968        try {
969            CmsResource resource = getCmsObject().readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION);
970            return getCmsObject().getSitePath(resource);
971        } catch (CmsException e) {
972            if (LOG.isWarnEnabled()) {
973                LOG.warn(e.getMessageContainer(), e);
974            }
975        }
976        return null;
977    }
978
979    /**
980     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#loadLinkInfo(org.opencms.util.CmsUUID)
981     */
982    public CmsExternalLinkInfoBean loadLinkInfo(CmsUUID structureId) throws CmsRpcException {
983
984        CmsExternalLinkInfoBean info = new CmsExternalLinkInfoBean();
985        CmsObject cms = getCmsObject();
986        try {
987            CmsResource linkResource = cms.readResource(structureId, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED);
988            addPageInfo(cms, linkResource, info);
989            CmsFile linkFile = cms.readFile(linkResource);
990            OpenCms.getLocaleManager();
991            String link = new String(linkFile.getContents(), CmsLocaleManager.getResourceEncoding(cms, linkResource));
992            info.setLink(link);
993            info.setSitePath(cms.getSitePath(linkResource));
994        } catch (Exception e) {
995            error(e);
996        }
997        return info;
998    }
999
1000    /**
1001     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#loadPropertyData(org.opencms.util.CmsUUID)
1002     */
1003    public CmsPropertiesBean loadPropertyData(CmsUUID id) throws CmsRpcException {
1004
1005        CmsObject cms = getCmsObject();
1006        try {
1007            CmsPropertyEditorHelper helper = new CmsPropertyEditorHelper(cms);
1008            return helper.loadPropertyData(id);
1009        } catch (Throwable e) {
1010            error(e);
1011        }
1012        return null;
1013    }
1014
1015    /**
1016     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#loadQuickLaunchItems(org.opencms.gwt.shared.CmsQuickLaunchParams)
1017     */
1018    public List<CmsQuickLaunchData> loadQuickLaunchItems(CmsQuickLaunchParams params) throws CmsRpcException {
1019
1020        try {
1021            CmsQuickLaunchProvider provider = new CmsQuickLaunchProvider(getCmsObject());
1022            return provider.getQuickLaunchData(params);
1023        } catch (Exception e) {
1024            error(e);
1025            return null;
1026        }
1027    }
1028
1029    /**
1030     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#prepareEdit(org.opencms.util.CmsUUID, java.lang.String)
1031     */
1032    public CmsPrepareEditResponse prepareEdit(CmsUUID currentPageId, String pathWithMacros) throws CmsRpcException {
1033
1034        try {
1035            CmsObject cms = getCmsObject();
1036            CmsResource resource = null;
1037            if (cms.existsResource(pathWithMacros, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)) {
1038                resource = cms.readResource(pathWithMacros, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED);
1039            } else {
1040                CmsResource currentPage = cms.readResource(currentPageId, CmsResourceFilter.IGNORE_EXPIRATION);
1041                String path = prepareFileNameForEditor(cms, currentPage, pathWithMacros);
1042                resource = cms.readResource(path, CmsResourceFilter.IGNORE_EXPIRATION);
1043            }
1044            ensureLock(resource);
1045            CmsPrepareEditResponse result = new CmsPrepareEditResponse();
1046            result.setRootPath(resource.getRootPath());
1047            result.setSitePath(cms.getSitePath(resource));
1048            result.setStructureId(resource.getStructureId());
1049            return result;
1050        } catch (Throwable e) {
1051            error(e);
1052        }
1053        return null;
1054    }
1055
1056    /**
1057     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#renameResource(org.opencms.util.CmsUUID, java.lang.String)
1058     */
1059    public String renameResource(CmsUUID structureId, String newName) throws CmsRpcException {
1060
1061        try {
1062            return renameResourceInternal(structureId, newName);
1063        } catch (Throwable e) {
1064            error(e);
1065            return null;
1066        }
1067    }
1068
1069    /**
1070     * Internal implementation for renaming a resource.<p>
1071     *
1072     * @param structureId the structure id of the resource to rename
1073     * @param newName the new resource name
1074     * @return either null if the rename was successful, or an error message
1075     *
1076     * @throws CmsException if something goes wrong
1077     */
1078    public String renameResourceInternal(CmsUUID structureId, String newName) throws CmsException {
1079
1080        CmsObject cms = getCmsObject();
1081        Locale locale = OpenCms.getWorkplaceManager().getWorkplaceLocale(cms);
1082        try {
1083            CmsResource.checkResourceName(newName);
1084        } catch (CmsIllegalArgumentException e) {
1085            return e.getLocalizedMessage(locale);
1086        }
1087        CmsResource resource = cms.readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION);
1088        String oldSitePath = cms.getSitePath(resource);
1089        String parentPath = CmsResource.getParentFolder(oldSitePath);
1090        String newSitePath = CmsStringUtil.joinPaths(parentPath, newName);
1091        try {
1092            ensureLock(resource);
1093            cms.moveResource(oldSitePath, newSitePath);
1094            resource = cms.readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION);
1095        } catch (CmsException e) {
1096            return e.getLocalizedMessage(OpenCms.getWorkplaceManager().getWorkplaceLocale(cms));
1097        }
1098        tryUnlock(resource);
1099        return null;
1100    }
1101
1102    /**
1103     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#restoreResource(org.opencms.util.CmsUUID, int)
1104     */
1105    public void restoreResource(CmsUUID structureId, int version) throws CmsRpcException {
1106
1107        CmsObject cms = getCmsObject();
1108        try {
1109            ensureLock(structureId);
1110            cms.restoreResourceVersion(structureId, version);
1111            try {
1112                CmsResource res = cms.readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION);
1113                cms.unlockResource(res);
1114            } catch (Exception e) {
1115                LOG.error(e.getLocalizedMessage(), e);
1116            }
1117
1118        } catch (Exception e) {
1119            error(e);
1120            return; // return stmt  will never be reached
1121        }
1122
1123    }
1124
1125    /**
1126     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#saveAliases(org.opencms.util.CmsUUID, java.util.List)
1127     */
1128    public void saveAliases(CmsUUID structureId, List<CmsAliasBean> aliasBeans) throws CmsRpcException {
1129
1130        try {
1131            m_aliasHelper.saveAliases(structureId, aliasBeans);
1132        } catch (Throwable e) {
1133            error(e);
1134        }
1135    }
1136
1137    /**
1138     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#saveExternalLink(org.opencms.util.CmsUUID, java.lang.String, java.lang.String, java.lang.String)
1139     */
1140    public void saveExternalLink(CmsUUID structureId, String title, String link, String fileName)
1141    throws CmsRpcException {
1142
1143        try {
1144            CmsObject cms = getCmsObject();
1145            CmsResource res = cms.readResource(structureId);
1146            ensureLock(res);
1147            CmsFile file = cms.readFile(res);
1148            String oldLink = new String(file.getContents(), CmsLocaleManager.getResourceEncoding(cms, res));
1149            if (!oldLink.equals(link)) {
1150                file.setContents(link.getBytes(CmsLocaleManager.getResourceEncoding(cms, res)));
1151                cms.writeFile(file);
1152            }
1153            CmsProperty titleProp = cms.readPropertyObject(res, CmsPropertyDefinition.PROPERTY_TITLE, false);
1154            if (titleProp.isNullProperty()) {
1155                titleProp = new CmsProperty(CmsPropertyDefinition.PROPERTY_TITLE, title, null);
1156                cms.writePropertyObject(cms.getSitePath(res), titleProp);
1157            } else if (!titleProp.getValue().equals(title)) {
1158                titleProp.setStructureValue(title);
1159                cms.writePropertyObject(cms.getSitePath(res), titleProp);
1160            }
1161            if (!res.getName().equals(fileName)) {
1162                String oldSitePath = cms.getSitePath(res);
1163                String newSitePath = CmsStringUtil.joinPaths(CmsResource.getParentFolder(oldSitePath), fileName);
1164                getCmsObject().renameResource(oldSitePath, newSitePath);
1165            }
1166            tryUnlock(res);
1167            // update the offline search indices
1168            OpenCms.getSearchManager().updateOfflineIndexes(2 * CmsSearchManager.DEFAULT_OFFLINE_UPDATE_FREQNENCY);
1169        } catch (Exception e) {
1170            error(e);
1171        }
1172    }
1173
1174    /**
1175     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#saveProperties(org.opencms.gwt.shared.property.CmsPropertyChangeSet)
1176     */
1177    public void saveProperties(CmsPropertyChangeSet changes) throws CmsRpcException {
1178
1179        String origSiteRoot = getCmsObject().getRequestContext().getSiteRoot();
1180        try {
1181            getCmsObject().getRequestContext().setSiteRoot("");
1182            CmsPropertyEditorHelper helper = new CmsPropertyEditorHelper(getCmsObject());
1183            helper.saveProperties(changes);
1184        } catch (Throwable t) {
1185            error(t);
1186        } finally {
1187            getCmsObject().getRequestContext().setSiteRoot(origSiteRoot);
1188        }
1189    }
1190
1191    /**
1192     * Sets the current cms context.<p>
1193     *
1194     * @param cms the current cms context to set
1195     */
1196    @Override
1197    public synchronized void setCms(CmsObject cms) {
1198
1199        super.setCms(cms);
1200        m_aliasHelper.setCms(cms);
1201    }
1202
1203    /**
1204     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#substituteLinkForRootPath(java.lang.String, java.lang.String)
1205     */
1206    public String substituteLinkForRootPath(String currentSiteRoot, String rootPath) throws CmsRpcException {
1207
1208        String result = null;
1209        try {
1210            CmsObject cms = OpenCms.initCmsObject(getCmsObject());
1211            cms.getRequestContext().setSiteRoot(currentSiteRoot);
1212            result = OpenCms.getLinkManager().substituteLinkForRootPath(cms, rootPath);
1213        } catch (CmsException e) {
1214            error(e);
1215        }
1216        return result;
1217    }
1218
1219    /**
1220     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#syncDeleteResource(org.opencms.util.CmsUUID)
1221     */
1222    public void syncDeleteResource(CmsUUID structureId) throws CmsRpcException {
1223
1224        deleteResource(structureId);
1225    }
1226
1227    /**
1228     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#undelete(org.opencms.util.CmsUUID)
1229     */
1230    public void undelete(CmsUUID structureId) throws CmsRpcException {
1231
1232        try {
1233            CmsObject cms = OpenCms.initCmsObject(getCmsObject());
1234            cms.getRequestContext().setSiteRoot("");
1235            CmsResource resource = cms.readResource(structureId, CmsResourceFilter.ALL);
1236            ensureLock(resource);
1237            cms.undeleteResource(resource.getRootPath(), true);
1238        } catch (Exception e) {
1239            error(e);
1240        }
1241    }
1242
1243    /**
1244     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#undoChanges(org.opencms.util.CmsUUID, boolean)
1245     */
1246    public void undoChanges(CmsUUID structureId, boolean undoMove) throws CmsRpcException {
1247
1248        try {
1249            CmsObject cms = getCmsObject();
1250            CmsResource resource = cms.readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION);
1251            ensureLock(resource);
1252            CmsResourceUndoMode mode = undoMove ? CmsResource.UNDO_MOVE_CONTENT : CmsResource.UNDO_CONTENT;
1253            String path = cms.getSitePath(resource);
1254            cms.undoChanges(path, mode);
1255            try {
1256                resource = cms.readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION);
1257                path = cms.getSitePath(resource);
1258                cms.unlockResource(path);
1259            } catch (CmsException e) {
1260                LOG.info("Could not unlock resource after undoing changes: " + e.getLocalizedMessage(), e);
1261            }
1262        } catch (Throwable e) {
1263            error(e);
1264        }
1265    }
1266
1267    /**
1268     * @see org.opencms.gwt.shared.rpc.I_CmsVfsService#validateAliases(org.opencms.util.CmsUUID, java.util.Map)
1269     */
1270    public Map<String, String> validateAliases(CmsUUID uuid, Map<String, String> aliasPaths) throws CmsRpcException {
1271
1272        try {
1273            return m_aliasHelper.validateAliases(uuid, aliasPaths);
1274        } catch (Throwable e) {
1275            error(e);
1276        }
1277        return null;
1278
1279    }
1280
1281    /**
1282     * Creates a "broken link" bean based on a resource.<p>
1283     *
1284     * @param resource the resource
1285     *
1286     * @return the "broken link" bean with the data from the resource
1287     *
1288     * @throws CmsException if something goes wrong
1289     */
1290    protected CmsBrokenLinkBean createSitemapBrokenLinkBean(CmsResource resource) throws CmsException {
1291
1292        CmsObject cms = getCmsObject();
1293        CmsProperty titleProp = cms.readPropertyObject(resource, CmsPropertyDefinition.PROPERTY_TITLE, true);
1294        String typeName = OpenCms.getResourceManager().getResourceType(resource).getTypeName();
1295        String defaultTitle = "";
1296        String title = titleProp.getValue(defaultTitle);
1297        String path = cms.getSitePath(resource);
1298        String subtitle = path;
1299
1300        CmsBrokenLinkBean result = new CmsBrokenLinkBean(resource.getStructureId(), title, subtitle, typeName);
1301
1302        return result;
1303    }
1304
1305    /**
1306     * Helper method for creating a VFS entry bean from a resource.<p>
1307     *
1308     * @param resource the resource whose data should be stored in the bean
1309     * @param root true if the resource is a root resource
1310     *
1311     * @return the data bean representing the resource
1312     *
1313     * @throws CmsException if something goes wrong
1314     */
1315    protected CmsVfsEntryBean makeEntryBean(CmsResource resource, boolean root) throws CmsException {
1316
1317        CmsObject cms = getCmsObject();
1318        boolean isFolder = resource.isFolder();
1319        String name = root ? "/" : resource.getName();
1320        String path = cms.getSitePath(resource);
1321        boolean hasChildren = false;
1322        if (isFolder) {
1323            List<CmsResource> children = cms.getResourcesInFolder(
1324                cms.getRequestContext().getSitePath(resource),
1325                CmsResourceFilter.DEFAULT);
1326            if (!children.isEmpty()) {
1327                hasChildren = true;
1328            }
1329        }
1330        String resourceType = OpenCms.getResourceManager().getResourceType(resource.getTypeId()).getTypeName();
1331
1332        return new CmsVfsEntryBean(path, name, resourceType, isFolder, hasChildren);
1333    }
1334
1335    /**
1336     * Helper method for creating a list of VFS entry beans from a list of the corresponding resources.<p>
1337     *
1338     * @param resources the list of resources which should be converted to entry beans
1339     * @param root true if the resources in the list are root resources
1340     *
1341     * @return the list of VFS entry beans for the resources
1342     *
1343     * @throws CmsException if something goes wrong
1344     */
1345    protected List<CmsVfsEntryBean> makeEntryBeans(List<CmsResource> resources, boolean root) throws CmsException {
1346
1347        List<CmsVfsEntryBean> result = new ArrayList<CmsVfsEntryBean>();
1348        for (CmsResource res : resources) {
1349            result.add(makeEntryBean(res, root));
1350        }
1351        return result;
1352    }
1353
1354    /**
1355     * Adds additional info items for broken links.<p>
1356     *
1357     * @param cms the CMS context to use
1358     * @param resource the resource from which the additional infos should be read
1359     * @param result the result in which to store the additional info
1360     */
1361    private void addBrokenLinkAdditionalInfo(CmsObject cms, CmsResource resource, CmsBrokenLinkBean result) {
1362
1363        String dateLastModifiedLabel = org.opencms.workplace.commons.Messages.get().getBundle(
1364            OpenCms.getWorkplaceManager().getWorkplaceLocale(cms)).key(
1365                org.opencms.workplace.commons.Messages.GUI_LABEL_DATE_LAST_MODIFIED_0);
1366        String dateLastModified = CmsVfsService.formatDateTime(cms, resource.getDateLastModified());
1367
1368        String userLastModifiedLabel = org.opencms.workplace.commons.Messages.get().getBundle(
1369            OpenCms.getWorkplaceManager().getWorkplaceLocale(cms)).key(
1370                org.opencms.workplace.commons.Messages.GUI_LABEL_USER_LAST_MODIFIED_0);
1371        String userLastModified = "" + resource.getUserLastModified();
1372        try {
1373            userLastModified = cms.readUser(resource.getUserLastModified()).getName();
1374        } catch (CmsException e) {
1375            LOG.error(e.getLocalizedMessage(), e);
1376        }
1377
1378        result.addInfo(dateLastModifiedLabel, dateLastModified);
1379        result.addInfo(userLastModifiedLabel, userLastModified);
1380    }
1381
1382    /**
1383     * Creates a bean representing a historical resource version.<p>
1384     *
1385     * @param cms the current CMS context
1386     * @param historyRes the historical resource
1387     * @param offline true if this resource was read from the offline project
1388     * @param maxVersion the largest version number found
1389     *
1390     * @return the bean representing the historical resource
1391     * @throws CmsException if something goes wrong
1392     */
1393    private CmsHistoryResourceBean createHistoryResourceBean(
1394        CmsObject cms,
1395        CmsResource historyRes,
1396        boolean offline,
1397        int maxVersion) throws CmsException {
1398
1399        CmsHistoryResourceBean result = new CmsHistoryResourceBean();
1400
1401        Locale locale = OpenCms.getWorkplaceManager().getWorkplaceLocale(cms);
1402        result.setStructureId(historyRes.getStructureId());
1403        result.setRootPath(historyRes.getRootPath());
1404        result.setDateLastModified(formatDate(historyRes.getDateLastModified(), locale));
1405        CmsUUID userId = historyRes.getUserLastModified();
1406        String userName = userId.toString();
1407        try {
1408            CmsUser user = cms.readUser(userId);
1409            userName = user.getName();
1410        } catch (CmsException e) {
1411            LOG.warn(e.getLocalizedMessage(), e);
1412        }
1413        result.setUserLastModified(userName);
1414        result.setSize(historyRes.getLength());
1415        if (historyRes instanceof I_CmsHistoryResource) {
1416            int publishTag = ((I_CmsHistoryResource)historyRes).getPublishTag();
1417            CmsHistoryProject project = cms.readHistoryProject(publishTag);
1418            long publishDate = project.getPublishingDate();
1419            result.setDatePublished(formatDate(publishDate, locale));
1420            int version = ((I_CmsHistoryResource)historyRes).getVersion();
1421            result.setVersion(
1422                new CmsHistoryVersion(
1423                    Integer.valueOf(historyRes.getVersion()),
1424                    maxVersion == version ? OfflineOnline.online : null));
1425
1426            List<CmsProperty> historyProperties = cms.readHistoryPropertyObjects((I_CmsHistoryResource)historyRes);
1427            Map<String, CmsProperty> historyPropertyMap = CmsProperty.toObjectMap(historyProperties);
1428            CmsProperty titleProp = CmsProperty.wrapIfNull(
1429                historyPropertyMap.get(CmsPropertyDefinition.PROPERTY_TITLE));
1430            CmsProperty descProp = CmsProperty.wrapIfNull(
1431                historyPropertyMap.get(CmsPropertyDefinition.PROPERTY_DESCRIPTION));
1432            result.setTitle(titleProp.getValue());
1433            result.setDescription(descProp.getValue());
1434        } else {
1435            if (offline) {
1436                result.setVersion(new CmsHistoryVersion(null, OfflineOnline.offline));
1437            } else {
1438                result.setVersion(new CmsHistoryVersion(null, OfflineOnline.online));
1439            }
1440        }
1441        return result;
1442    }
1443
1444    /**
1445     * Internal method to delete the given resource.<p>
1446     *
1447     * @param resource the resource to delete
1448     *
1449     * @throws CmsException if something goes wrong
1450     */
1451    private void deleteResource(CmsResource resource) throws CmsException {
1452
1453        String path = null;
1454        CmsObject cms = getCmsObject();
1455        try {
1456            path = cms.getSitePath(resource);
1457            cms.lockResource(path);
1458            cms.deleteResource(path, CmsResource.DELETE_PRESERVE_SIBLINGS);
1459
1460            // check if any detail container page resource exists to this resource
1461            String detailContainers = CmsJspTagContainer.getDetailOnlyPageName(path);
1462            if (cms.existsResource(detailContainers, CmsResourceFilter.IGNORE_EXPIRATION)) {
1463                deleteResource(cms.readResource(detailContainers, CmsResourceFilter.IGNORE_EXPIRATION));
1464            }
1465        } finally {
1466            try {
1467                if (path != null) {
1468                    getCmsObject().unlockResource(path);
1469                }
1470            } catch (Exception e) {
1471                // should really never happen
1472                LOG.debug(e.getLocalizedMessage(), e);
1473            }
1474        }
1475    }
1476
1477    /**
1478     * Converts a date to a date bean.<p>
1479     *
1480     * @param date the date to convert
1481     * @param locale the locale to use for the conversion
1482     *
1483     * @return the date bean
1484     */
1485    private CmsClientDateBean formatDate(long date, Locale locale) {
1486
1487        return new CmsClientDateBean(date, formatDateTime(date));
1488    }
1489
1490    /**
1491     * Formats the date for the current user's locale.<p>
1492     *
1493     * @param date the date to format
1494     *
1495     * @return the formatted date for the current user's locale
1496     */
1497    private String formatDateTime(long date) {
1498
1499        CmsObject cms = getCmsObject();
1500        return formatDateTime(cms, date);
1501    }
1502
1503    /**
1504     * Returns a bean that contains the infos for the {@link org.opencms.gwt.client.ui.contextmenu.CmsAvailabilityDialog}.<p>
1505     *
1506     * @param res the resource to get the availability infos for
1507     *
1508     * @return a bean for the {@link org.opencms.gwt.client.ui.contextmenu.CmsAvailabilityDialog}
1509     *
1510     * @throws CmsRpcException if something goes wrong
1511     */
1512    private CmsAvailabilityInfoBean getAvailabilityInfo(CmsResource res) throws CmsRpcException {
1513
1514        CmsObject cms = getCmsObject();
1515        try {
1516            CmsAvailabilityInfoBean avail = getAvailabilityInfoStatic(cms, res);
1517            avail.setPageInfo(getPageInfo(res));
1518            return avail;
1519        } catch (CmsException e) {
1520            error(e);
1521            return null; // will never be reached
1522        }
1523    }
1524
1525    /**
1526     * Returns the available locales mapped to there display name for the given resource
1527     * or <code>null</code> in case of non xml-content/xml-page resources.<p>
1528     *
1529     * @param resource the resource
1530     *
1531     * @return the available locales
1532     */
1533    private LinkedHashMap<String, String> getAvailableLocales(CmsResource resource) {
1534
1535        LinkedHashMap<String, String> result = null;
1536        List<Locale> locales = null;
1537        try {
1538            if (CmsResourceTypeXmlPage.isXmlPage(resource)) {
1539                locales = CmsXmlPageFactory.unmarshal(getCmsObject(), resource, getRequest()).getLocales();
1540            } else if (CmsResourceTypeXmlContent.isXmlContent(resource)) {
1541                locales = CmsXmlContentFactory.unmarshal(getCmsObject(), resource, getRequest()).getLocales();
1542            } else if (CmsResourceTypeXmlContainerPage.isContainerPage(resource)) {
1543                locales = CmsXmlContainerPageFactory.unmarshal(getCmsObject(), resource).getLocales();
1544            }
1545        } catch (CmsException e) {
1546            LOG.warn(e.getLocalizedMessage(), e);
1547        }
1548        if (locales != null) {
1549            Locale wpLocale = OpenCms.getWorkplaceManager().getWorkplaceLocale(getCmsObject());
1550            result = new LinkedHashMap<String, String>();
1551            for (Locale locale : locales) {
1552                result.put(locale.toString(), locale.getDisplayName(wpLocale));
1553            }
1554        }
1555        return result;
1556    }
1557
1558    /**
1559     * Helper method for converting a map which maps resources to resources to a list of "broken link" beans,
1560     * which have beans representing the source of the corresponding link as children.<p>
1561     *
1562     * @param linkMap a multimap from resource to resources
1563     *
1564     * @return a list of beans representing links which will be broken
1565     *
1566     * @throws CmsException if something goes wrong
1567     */
1568    private List<CmsBrokenLinkBean> getBrokenLinkBeans(Multimap<CmsResource, CmsResource> linkMap) throws CmsException {
1569
1570        CmsBrokenLinkRenderer brokenLinkRenderer = new CmsBrokenLinkRenderer(getCmsObject());
1571
1572        Multimap<CmsBrokenLinkBean, CmsBrokenLinkBean> resultMap = HashMultimap.create();
1573
1574        for (CmsResource source : linkMap.keySet()) {
1575
1576            for (CmsResource target : linkMap.get(source)) {
1577                CmsBrokenLinkBean targetBean = createSitemapBrokenLinkBean(target);
1578                addBrokenLinkAdditionalInfo(getCmsObject(), target, targetBean);
1579                List<CmsBrokenLinkBean> brokenLinkBeans = brokenLinkRenderer.renderBrokenLink(target, source);
1580                for (CmsBrokenLinkBean childBean : brokenLinkBeans) {
1581                    addBrokenLinkAdditionalInfo(getCmsObject(), source, childBean);
1582                    resultMap.put(childBean, targetBean);
1583                }
1584            }
1585        }
1586
1587        // now convert multimap representation to parent/child representation
1588        for (CmsBrokenLinkBean parent : resultMap.keySet()) {
1589            for (CmsBrokenLinkBean child : resultMap.get(parent)) {
1590                parent.addChild(child);
1591            }
1592        }
1593        return Lists.newArrayList(resultMap.keySet());
1594    }
1595
1596    /**
1597     * Internal method to get the broken links information for the given resource.<p>
1598     *
1599     * @param entryResource the resource
1600     *
1601     * @return the broken links information
1602     *
1603     * @throws CmsException if something goes wrong
1604     */
1605    private CmsDeleteResourceBean getBrokenLinks(CmsResource entryResource) throws CmsException {
1606
1607        CmsDeleteResourceBean result = null;
1608
1609        CmsListInfoBean info = null;
1610        List<CmsBrokenLinkBean> brokenLinks = null;
1611
1612        CmsObject cms = getCmsObject();
1613        String resourceSitePath = cms.getSitePath(entryResource);
1614
1615        ensureSession();
1616
1617        List<CmsResource> descendants = new ArrayList<CmsResource>();
1618        HashSet<CmsUUID> deleteIds = new HashSet<CmsUUID>();
1619
1620        descendants.add(entryResource);
1621        if (entryResource.isFolder()) {
1622            descendants.addAll(cms.readResources(resourceSitePath, CmsResourceFilter.IGNORE_EXPIRATION));
1623        }
1624
1625        for (CmsResource deleteRes : descendants) {
1626            deleteIds.add(deleteRes.getStructureId());
1627        }
1628        Multimap<CmsResource, CmsResource> linkMap = HashMultimap.create();
1629        for (CmsResource resource : descendants) {
1630            List<CmsRelation> relations = cms.getRelationsForResource(resource, CmsRelationFilter.SOURCES);
1631            List<CmsResource> result1 = new ArrayList<CmsResource>();
1632            for (CmsRelation relation : relations) {
1633                // only add related resources that are not going to be deleted
1634                if (!deleteIds.contains(relation.getSourceId())) {
1635                    CmsResource source1 = relation.getSource(cms, CmsResourceFilter.ALL);
1636                    if (!source1.getState().isDeleted()) {
1637                        result1.add(source1);
1638                    }
1639                }
1640            }
1641            List<CmsResource> linkSources = result1;
1642            for (CmsResource source : linkSources) {
1643                linkMap.put(source, resource);
1644            }
1645        }
1646
1647        brokenLinks = getBrokenLinkBeans(linkMap);
1648        info = getPageInfo(entryResource);
1649
1650        result = new CmsDeleteResourceBean(resourceSitePath, info, brokenLinks);
1651
1652        return result;
1653    }
1654
1655    /**
1656     * Gets the resources which link to a given structure id.<p>
1657     *
1658     * @param cms the current CMS context
1659     * @param resource the relation target resource
1660     * @param deleteIds set of resources to delete
1661     *
1662     * @return the list of resources which link to the given id
1663     *
1664     * @throws CmsException if something goes wrong
1665     */
1666    @SuppressWarnings("unused")
1667    private List<CmsResource> getLinkSources(CmsObject cms, CmsResource resource, HashSet<CmsUUID> deleteIds)
1668    throws CmsException {
1669
1670        List<CmsRelation> relations = cms.getRelationsForResource(resource, CmsRelationFilter.SOURCES);
1671        List<CmsResource> result = new ArrayList<CmsResource>();
1672        for (CmsRelation relation : relations) {
1673            // only add related resources that are not going to be deleted
1674            if (!deleteIds.contains(relation.getSourceId())) {
1675                CmsResource source = relation.getSource(cms, CmsResourceFilter.ALL);
1676                if (!source.getState().isDeleted()) {
1677                    result.add(source);
1678                }
1679            }
1680        }
1681        return result;
1682    }
1683
1684    /**
1685     * Returns a bean to display the {@link org.opencms.gwt.client.ui.CmsListItemWidget}.<p>
1686     *
1687     * @param res the resource to get the page info for
1688     *
1689     * @return a bean to display the {@link org.opencms.gwt.client.ui.CmsListItemWidget}.<p>
1690     *
1691     * @throws CmsLoaderException if the resource type could not be found
1692     * @throws CmsException if something else goes wrong
1693     */
1694    private CmsListInfoBean getPageInfo(CmsResource res) throws CmsException, CmsLoaderException {
1695
1696        CmsObject cms = getCmsObject();
1697        return getPageInfo(cms, res);
1698    }
1699
1700    /**
1701     * Returns the preview info for the given resource.<p>
1702     *
1703     *@param cms the CMS context
1704     * @param resource the resource
1705     * @param locale the requested locale
1706     *
1707     * @return the preview info
1708     */
1709    private CmsPreviewInfo getPreviewInfo(CmsObject cms, CmsResource resource, Locale locale) {
1710
1711        String title = "";
1712        try {
1713            CmsProperty titleProperty = cms.readPropertyObject(resource, CmsPropertyDefinition.PROPERTY_TITLE, false);
1714            title = titleProperty.getValue("");
1715        } catch (CmsException e) {
1716            LOG.warn(e.getLocalizedMessage(), e);
1717        }
1718        String noPreviewReason = getNoPreviewReason(cms, resource);
1719        String previewContent = null;
1720        int height = 0;
1721        int width = 0;
1722        LinkedHashMap<String, String> locales = getAvailableLocales(resource);
1723        if (noPreviewReason != null) {
1724            previewContent = "<div>" + noPreviewReason + "</div>";
1725            return new CmsPreviewInfo(
1726                "<div>" + noPreviewReason + "</div>",
1727                null,
1728                false,
1729                title,
1730                cms.getSitePath(resource),
1731                locale.toString());
1732        } else if (OpenCms.getResourceManager().matchResourceType(
1733            CmsResourceTypeImage.getStaticTypeName(),
1734            resource.getTypeId())) {
1735            CmsImageScaler scaler = new CmsImageScaler(cms, resource);
1736            String imageLink = null;
1737            if (resource instanceof I_CmsHistoryResource) {
1738                int version = ((I_CmsHistoryResource)resource).getVersion();
1739                imageLink = OpenCms.getLinkManager().substituteLinkForUnknownTarget(
1740                    cms,
1741                    CmsHistoryListUtil.getHistoryLink(cms, resource.getStructureId(), "" + version));
1742            } else {
1743                imageLink = OpenCms.getLinkManager().substituteLinkForUnknownTarget(cms, resource.getRootPath());
1744            }
1745            imageLink = CmsRequestUtil.appendParameter(imageLink, "random", "" + Math.random());
1746            previewContent = "<img src=\"" + imageLink + "\" title=\"" + title + "\" style=\"display:block\" />";
1747            height = scaler.getHeight();
1748            width = scaler.getWidth();
1749        } else if (CmsResourceTypeXmlContent.isXmlContent(resource)) {
1750            if (!locales.containsKey(locale.toString())) {
1751                locale = CmsLocaleManager.getMainLocale(cms, resource);
1752            }
1753            previewContent = CmsPreviewService.getPreviewContent(getRequest(), getResponse(), cms, resource, locale);
1754
1755        } else if (CmsResourceTypePlain.getStaticTypeId() == resource.getTypeId()) {
1756            try {
1757                previewContent = "<pre><code>" + new String(cms.readFile(resource).getContents()) + "</code></pre>";
1758            } catch (CmsException e) {
1759                LOG.warn(e.getLocalizedMessage(), e);
1760                previewContent = "<div>"
1761                    + Messages.get().getBundle(OpenCms.getWorkplaceManager().getWorkplaceLocale(cms)).key(
1762                        Messages.GUI_NO_PREVIEW_CAN_T_READ_CONTENT_0)
1763                    + "</div>";
1764            }
1765        }
1766        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(previewContent)) {
1767            CmsPreviewInfo result = new CmsPreviewInfo(
1768                previewContent,
1769                null,
1770                false,
1771                title,
1772                cms.getSitePath(resource),
1773                locale.toString());
1774            result.setHeight(height);
1775            result.setWidth(width);
1776            result.setLocales(locales);
1777            return result;
1778        }
1779        if (CmsResourceTypeXmlContainerPage.isContainerPage(resource) || CmsResourceTypeXmlPage.isXmlPage(resource)) {
1780            CmsPreviewInfo result = new CmsPreviewInfo(
1781                null,
1782                OpenCms.getLinkManager().substituteLinkForUnknownTarget(cms, resource.getRootPath())
1783                    + "?"
1784                    + CmsGwtConstants.PARAM_DISABLE_DIRECT_EDIT
1785                    + "=true"
1786                    + "&__locale="
1787                    + locale.toString(),
1788                false,
1789                title,
1790                cms.getSitePath(resource),
1791                locale.toString());
1792            result.setLocales(locales);
1793            return result;
1794        }
1795        return new CmsPreviewInfo(
1796            null,
1797            OpenCms.getLinkManager().substituteLinkForUnknownTarget(cms, resource.getRootPath())
1798                + "?"
1799                + CmsGwtConstants.PARAM_DISABLE_DIRECT_EDIT
1800                + "=true",
1801            true,
1802            title,
1803            cms.getSitePath(resource),
1804            locale.toString());
1805    }
1806
1807}