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