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