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