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 GmbH & Co. KG, 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.workplace.explorer;
029
030import org.opencms.db.CmsUserSettings;
031import org.opencms.file.CmsFolder;
032import org.opencms.file.CmsObject;
033import org.opencms.file.CmsProject;
034import org.opencms.file.CmsResource;
035import org.opencms.file.CmsResourceFilter;
036import org.opencms.file.collectors.I_CmsResourceCollector;
037import org.opencms.file.types.CmsResourceTypePlain;
038import org.opencms.i18n.CmsEncoder;
039import org.opencms.jsp.CmsJspActionElement;
040import org.opencms.loader.CmsLoaderException;
041import org.opencms.main.CmsException;
042import org.opencms.main.CmsLog;
043import org.opencms.main.CmsRuntimeException;
044import org.opencms.main.OpenCms;
045import org.opencms.util.CmsRequestUtil;
046import org.opencms.util.CmsStringUtil;
047import org.opencms.workplace.CmsFrameset;
048import org.opencms.workplace.CmsWorkplace;
049import org.opencms.workplace.CmsWorkplaceSettings;
050import org.opencms.workplace.galleries.A_CmsAjaxGallery;
051import org.opencms.workplace.list.I_CmsListResourceCollector;
052import org.opencms.workplace.tools.CmsToolManager;
053
054import java.util.Collections;
055import java.util.List;
056import java.util.Scanner;
057
058import javax.servlet.http.HttpServletRequest;
059
060import org.apache.commons.logging.Log;
061
062/**
063 * Provides methods for building the main frame sets of the OpenCms Workplace.<p>
064 *
065 * The following files use this class:
066 * <ul>
067 * <li>/views/explorer/explorer_fs.jsp
068 * <li>/views/explorer/explorer_files.jsp
069 * <li>/views/explorer/explorer_body_fs.jsp
070 * </ul>
071 * <p>
072 *
073 * @since 6.0.0
074 */
075public class CmsExplorer extends CmsWorkplace {
076
077    /** The 'ctxmenuparams' parameter. */
078    public static final String PARAMETER_CONTEXTMENUPARAMS = "ctxmenuparams";
079
080    /** The "mode" parameter. */
081    public static final String PARAMETER_MODE = "mode";
082
083    /** The "explorerview" view selection. */
084    public static final String VIEW_EXPLORER = "explorerview";
085
086    /** The "galleryview" view selection. */
087    public static final String VIEW_GALLERY = "galleryview";
088
089    /** The "list" view selection. */
090    public static final String VIEW_LIST = "listview";
091
092    /** The log object for this class. */
093    private static final Log LOG = CmsLog.getLog(CmsExplorer.class);
094
095    /** The "flaturl" parameter. */
096    private static final String PARAMETER_FLATURL = "flaturl";
097
098    /** The "page" parameter. */
099    private static final String PARAMETER_PAGE = "page";
100
101    /** The "resource" parameter. */
102    private static final String PARAMETER_RESOURCE = "resource";
103
104    /** The "uri" parameter. */
105    private static final String PARAMETER_URI = "uri";
106
107    /** The 'uri' parameter value. */
108    private String m_uri;
109
110    /**
111     * Public constructor.<p>
112     *
113     * @param jsp an initialized JSP action element
114     */
115    public CmsExplorer(CmsJspActionElement jsp) {
116
117        super(jsp);
118    }
119
120    /**
121     * Creates a link for the OpenCms workplace that will reload the whole workplace, switch to the explorer view, the
122     * site of the given explorerRootPath and show the folder given in the explorerRootPath.
123     * <p>
124     *
125     * @param jsp
126     *            needed for link functionality.
127     *
128     * @param explorerRootPath
129     *            a root relative folder link (has to end with '/').
130     *
131     * @return a link for the OpenCms workplace that will reload the whole workplace, switch to the explorer view, the
132     *         site of the given explorerRootPath and show the folder given in the explorerRootPath.
133     */
134    public static String getWorkplaceExplorerLink(final CmsJspActionElement jsp, final String explorerRootPath) {
135
136        return getWorkplaceExplorerLink(jsp.getCmsObject(), explorerRootPath);
137
138    }
139
140    /**
141     * Creates a link for the OpenCms workplace that will reload the whole workplace, switch to the explorer view, the
142     * site of the given explorerRootPath and show the folder given in the explorerRootPath.
143     * <p>
144     *
145     * @param cms
146     *            the cms object
147     *
148     * @param explorerRootPath
149     *            a root relative folder link (has to end with '/').
150     *
151     * @return a link for the OpenCms workplace that will reload the whole workplace, switch to the explorer view, the
152     *         site of the given explorerRootPath and show the folder given in the explorerRootPath.
153     */
154    public static String getWorkplaceExplorerLink(final CmsObject cms, final String explorerRootPath) {
155
156        // split the root site:
157        StringBuffer siteRoot = new StringBuffer();
158        StringBuffer path = new StringBuffer('/');
159        Scanner scanner = new Scanner(explorerRootPath);
160        scanner.useDelimiter("/");
161        int count = 0;
162        while (scanner.hasNext()) {
163            if (count < 2) {
164                siteRoot.append('/').append(scanner.next());
165            } else {
166                if (count == 2) {
167                    path.append('/');
168                }
169                path.append(scanner.next());
170                path.append('/');
171            }
172            count++;
173        }
174        String targetSiteRoot = siteRoot.toString();
175        String targetVfsFolder = path.toString();
176        // build the link
177        StringBuilder link2Source = new StringBuilder();
178        link2Source.append("/system/workplace/views/workplace.jsp?");
179        link2Source.append(CmsWorkplace.PARAM_WP_EXPLORER_RESOURCE);
180        link2Source.append("=");
181        link2Source.append(targetVfsFolder);
182        link2Source.append("&");
183        link2Source.append(CmsFrameset.PARAM_WP_VIEW);
184        link2Source.append("=");
185        link2Source.append(
186            OpenCms.getLinkManager().substituteLinkForUnknownTarget(
187                cms,
188                "/system/workplace/views/explorer/explorer_fs.jsp"));
189        link2Source.append("&");
190        link2Source.append(CmsWorkplace.PARAM_WP_SITE);
191        link2Source.append("=");
192        link2Source.append(targetSiteRoot);
193
194        String result = link2Source.toString();
195        result = OpenCms.getLinkManager().substituteLinkForUnknownTarget(cms, result);
196        return result;
197    }
198
199    /**
200     * Returns the explorer body frame content uri.<p>
201     *
202     * Used by the explorer_fs.jsp.<p>
203     *
204     * @return the explorer body frame content uri
205     */
206    public String getExplorerBodyUri() {
207
208        String body = CmsWorkplace.VFS_PATH_VIEWS + "explorer/explorer_body_fs.jsp";
209        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(m_uri)) {
210            body += "?" + PARAMETER_URI + "=" + m_uri;
211        }
212        return getJsp().link(body);
213    }
214
215    /**
216     * Returns the explorer files frame content uri.<p>
217     *
218     * Used by the explorer_body_fs.jsp.<p>
219     *
220     * @return the explorer files frame content uri
221     */
222    public String getExplorerFilesUri() {
223
224        String body = "explorer_files.jsp?mode=explorerview";
225        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(m_uri)) {
226            body = m_uri;
227        }
228        return getJsp().link(body);
229    }
230
231    /**
232     * Returns the html for the explorer file list.<p>
233     *
234     * @return the html for the explorer file list
235     */
236    public String getFileList() {
237
238        // if mode is "listonly", only the list will be shown
239        boolean galleryView = VIEW_GALLERY.equals(getSettings().getExplorerMode());
240        // if mode is "listview", all file in the set collector will be shown
241        boolean listView = VIEW_LIST.equals(getSettings().getExplorerMode());
242
243        String currentFolder = getSettings().getExplorerResource();
244        try {
245            getCms().readResource(currentFolder, CmsResourceFilter.ALL);
246        } catch (CmsException e) {
247            // file was not readable
248            currentFolder = "/";
249        }
250
251        // start creating content
252        StringBuffer content = new StringBuffer(2048);
253        content.append(getInitializationHeader());
254
255        // now get the entries for the file list
256        List<CmsResource> resources = getResources(getSettings().getExplorerResource());
257
258        // if a folder contains to much entries we split them to pages of C_ENTRYS_PER_PAGE length
259        int startat = 0;
260        int stopat = resources.size();
261        int selectedPage = 1;
262        int numberOfPages = 0;
263        int maxEntrys = getSettings().getUserSettings().getExplorerFileEntries();
264
265        if (!galleryView) {
266            selectedPage = getSettings().getExplorerPage();
267            if (stopat > maxEntrys) {
268                // we have to split
269                numberOfPages = ((stopat - 1) / maxEntrys) + 1;
270                if (selectedPage > numberOfPages) {
271                    // the user has changed the folder and then selected a page for the old folder
272                    selectedPage = 1;
273                }
274                startat = (selectedPage - 1) * maxEntrys;
275                if ((startat + maxEntrys) < stopat) {
276                    stopat = startat + maxEntrys;
277                }
278            }
279        }
280        // now check which file list columns we want to show
281        int preferences = getUserPreferences();
282
283        boolean showTitle = (preferences & CmsUserSettings.FILELIST_TITLE) > 0;
284        boolean showNavText = (preferences & CmsUserSettings.FILELIST_NAVTEXT) > 0;
285        boolean showPermissions = (preferences & CmsUserSettings.FILELIST_PERMISSIONS) > 0;
286        boolean showDateLastModified = (preferences & CmsUserSettings.FILELIST_DATE_LASTMODIFIED) > 0;
287        boolean showUserWhoLastModified = (preferences & CmsUserSettings.FILELIST_USER_LASTMODIFIED) > 0;
288        boolean showDateCreated = (preferences & CmsUserSettings.FILELIST_DATE_CREATED) > 0;
289        boolean showUserWhoCreated = (preferences & CmsUserSettings.FILELIST_USER_CREATED) > 0;
290        boolean showDateReleased = (preferences & CmsUserSettings.FILELIST_DATE_RELEASED) > 0;
291        boolean showDateExpired = (preferences & CmsUserSettings.FILELIST_DATE_EXPIRED) > 0;
292
293        boolean fullPath = galleryView || listView;
294
295        // set the right reference project
296        CmsProject referenceProject;
297        try {
298            if (!listView) {
299                referenceProject = getCms().readProject(getSettings().getProject());
300            } else {
301                referenceProject = getCms().readProject(getSettings().getExplorerProjectId());
302            }
303        } catch (CmsException ex) {
304            referenceProject = getCms().getRequestContext().getCurrentProject();
305        }
306
307        CmsResourceUtil resUtil = new CmsResourceUtil(getCms());
308        resUtil.setReferenceProject(referenceProject);
309
310        for (int i = startat; i < stopat; i++) {
311            CmsResource res = resources.get(i);
312            resUtil.setResource(res);
313            content.append(
314                getInitializationEntry(
315                    resUtil,
316                    fullPath,
317                    showTitle,
318                    showNavText,
319                    showPermissions,
320                    showDateLastModified,
321                    showUserWhoLastModified,
322                    showDateCreated,
323                    showUserWhoCreated,
324                    showDateReleased,
325                    showDateExpired));
326        }
327
328        content.append(getInitializationFooter(numberOfPages, selectedPage));
329        return content.toString();
330    }
331
332    /**
333     * Generates a resource entry for the explorer initialization code.<p>
334     *
335     * @param resUtil the resource util object to generate the entry for
336     * @param showPath if the path should be given or taken from <code>top.setDirectory</code>
337     * @param showTitle if the title should be shown
338     * @param showNavText if the navtext should be shown
339     * @param showPermissions if the permissions should be shown
340     * @param showDateLastModified if the date of modification should be shown
341     * @param showUserWhoLastModified if the user who last modified the resource should be shown
342     * @param showDateCreated if the date of creation should be shown
343     * @param showUserWhoCreated if the user who created the resource should be shown
344     * @param showDateReleased if the date of release should be shown
345     * @param showDateExpired if the date of expiration should be shown
346     *
347     * @return js code for initializing the explorer view
348     *
349     * @see #getInitializationHeader()
350     * @see #getInitializationFooter(int, int)
351     */
352    public String getInitializationEntry(
353        CmsResourceUtil resUtil,
354        boolean showPath,
355        boolean showTitle,
356        boolean showNavText,
357        boolean showPermissions,
358        boolean showDateLastModified,
359        boolean showUserWhoLastModified,
360        boolean showDateCreated,
361        boolean showUserWhoCreated,
362        boolean showDateReleased,
363        boolean showDateExpired) {
364
365        CmsResource resource = resUtil.getResource();
366        String path = getCms().getSitePath(resource);
367
368        StringBuffer content = new StringBuffer(2048);
369        content.append("top.aF(");
370
371        // position 1: name
372        content.append("\"");
373        content.append(resource.getName());
374        content.append("\",");
375
376        // position 2: path
377        if (showPath) {
378            content.append("\"");
379            content.append(path);
380            content.append("\",");
381        } else {
382            //is taken from top.setDirectory
383            content.append("\"\",");
384        }
385
386        // position 3: title
387        if (showTitle) {
388            String title = resUtil.getTitle();
389            content.append("\"");
390            content.append(CmsEncoder.escapeWBlanks(CmsEncoder.escapeXml(title), CmsEncoder.ENCODING_UTF_8));
391            content.append("\",");
392        } else {
393            content.append("\"\",");
394        }
395
396        // position 4: navigation text
397        if (showNavText) {
398            String navText = resUtil.getNavText();
399            content.append("\"");
400            content.append(CmsEncoder.escapeWBlanks(CmsEncoder.escapeXml(navText), CmsEncoder.ENCODING_UTF_8));
401            content.append("\",");
402        } else {
403            content.append("\"\",");
404        }
405
406        // position 5: type
407        content.append(resUtil.getResourceTypeId());
408        content.append(",");
409
410        // position 6: link type
411        content.append(resUtil.getLinkType());
412        content.append(",");
413
414        // position 7: size
415        content.append(resource.getLength());
416        content.append(",");
417
418        // position 8: state
419        content.append(resource.getState());
420        content.append(",");
421
422        // position 9: layout style
423        content.append(resUtil.getTimeWindowLayoutType());
424        content.append(',');
425
426        // position 10: date of last modification
427        if (showDateLastModified) {
428            content.append("\"");
429            content.append(getMessages().getDateTime(resource.getDateLastModified()));
430            content.append("\",");
431
432        } else {
433            content.append("\"\",");
434        }
435
436        // position 11: user who last modified the resource
437        if (showUserWhoLastModified) {
438            content.append("\"");
439            content.append(resUtil.getUserLastModified());
440            content.append("\",");
441        } else {
442            content.append("\"\",");
443        }
444
445        // position 12: date of creation
446        if (showDateCreated) {
447            content.append("\"");
448            content.append(getMessages().getDateTime(resource.getDateCreated()));
449            content.append("\",");
450        } else {
451            content.append("\"\",");
452        }
453
454        // position 13: user who created the resource
455        if (showUserWhoCreated) {
456            content.append("\"");
457            content.append(resUtil.getUserCreated());
458            content.append("\",");
459        } else {
460            content.append("\"\",");
461        }
462
463        // position 14: date of release
464        if (showDateReleased) {
465            content.append("\"");
466            content.append(resUtil.getDateReleased());
467            content.append("\",");
468        } else {
469            content.append("\"\",");
470        }
471
472        // position 15: date of expiration
473        if (showDateExpired) {
474            content.append("\"");
475            content.append(resUtil.getDateExpired());
476            content.append("\",");
477        } else {
478            content.append("\"\",");
479        }
480
481        // position 16: permissions
482        if (showPermissions) {
483            content.append("\"");
484            content.append(CmsStringUtil.escapeJavaScript(resUtil.getPermissionString()));
485            content.append("\",");
486        } else {
487            content.append("\"\",");
488        }
489
490        // position 17: locked by
491        content.append("\"");
492        content.append(CmsStringUtil.escapeJavaScript(resUtil.getLockedByName()));
493        content.append("\",");
494
495        // position 18: name of project where the resource is locked in
496        content.append("\"");
497        content.append(resUtil.getLockedInProjectName());
498        content.append("\",");
499
500        // position 19: id of project where resource belongs to
501        int lockState = resUtil.getLockState();
502        content.append(lockState);
503        content.append(",\"");
504
505        // position 20: project state, I=resource is inside current project, O=resource is outside current project
506        if (resUtil.isInsideProject()) {
507            content.append("I");
508        } else {
509            content.append("O");
510        }
511        content.append("\",\"");
512
513        // position 21: system lock info, used as text for tool tip
514        content.append(resUtil.getSystemLockInfo(true));
515        content.append("\", ");
516
517        // position 22: project state
518        content.append(resUtil.getProjectState().getMode());
519
520        // finish
521        content.append(");\n");
522        return content.toString();
523    }
524
525    /**
526     * Generates the footer of the explorer initialization code.<p>
527     *
528     * @param numberOfPages the number of pages
529     * @param selectedPage the selected page to display
530     *
531     * @return js code for initializing the explorer view
532     *
533     * @see #getInitializationHeader()
534     * @see #getInitializationEntry(CmsResourceUtil, boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean)
535     */
536    public String getInitializationFooter(int numberOfPages, int selectedPage) {
537
538        StringBuffer content = new StringBuffer(1024);
539        content.append("top.dU(document,");
540        content.append(numberOfPages);
541        content.append(",");
542        content.append(selectedPage);
543        content.append("); \n");
544
545        // display eventual error message
546        if (getSettings().getErrorMessage() != null) {
547            // display error message as JavaScript alert
548            content.append("alert(\"");
549            content.append(CmsStringUtil.escapeJavaScript(getSettings().getErrorMessage().key(getLocale())));
550            content.append("\");\n");
551            // delete error message container in settings
552            getSettings().setErrorMessage(null);
553        }
554
555        // display eventual broadcast message(s)
556        String message = getBroadcastMessageString();
557        if (CmsStringUtil.isNotEmpty(message)) {
558            // display broadcast as JavaScript alert
559            content.append("alert(decodeURIComponent(\"");
560            // the user has pending messages, display them all
561            content.append(CmsEncoder.escapeWBlanks(message, CmsEncoder.ENCODING_UTF_8));
562            content.append("\"));\n");
563        }
564
565        content.append("}\n");
566        return content.toString();
567    }
568
569    /**
570     * Generates the header of the initialization code.<p>
571     *
572     * @return js code for initializing the explorer view
573     *
574     * @see #getInitializationFooter(int, int)
575     * @see #getInitializationEntry(CmsResourceUtil, boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean)
576     */
577    public String getInitializationHeader() {
578
579        // if mode is "listview", all file in the set collector will be shown
580        boolean listView = VIEW_LIST.equals(getSettings().getExplorerMode());
581
582        String currentResourceName = getSettings().getExplorerResource();
583
584        CmsResource currentResource = null;
585        try {
586            currentResource = getCms().readResource(currentResourceName, CmsResourceFilter.ALL);
587        } catch (CmsException e) {
588            // file was not readable
589        }
590        if (currentResource == null) {
591            // show the root folder in case of an error and reset the state
592            currentResourceName = "/";
593            try {
594                currentResource = getCms().readResource(currentResourceName, CmsResourceFilter.ALL);
595            } catch (CmsException e) {
596                // should usually never happen
597                LOG.error(e.getLocalizedMessage(), e);
598                throw new CmsRuntimeException(e.getMessageContainer(), e);
599            }
600        }
601
602        StringBuffer content = new StringBuffer(1024);
603
604        content.append("function initialize() {\n");
605        content.append("top.setRootFolder(\"");
606        String rootFolder = getRootFolder();
607        content.append(CmsEncoder.escapeXml(rootFolder));
608        content.append("\");\n");
609
610        content.append("top.mode=\"");
611        content.append(CmsEncoder.escapeXml(getSettings().getExplorerMode()));
612        content.append("\";\n");
613        String additionalParams = getJsp().getRequest().getParameter(CmsExplorer.PARAMETER_CONTEXTMENUPARAMS);
614        if (additionalParams != null) {
615            content.append(
616                "document.additionalContextMenuParams = \""
617                    + CmsStringUtil.escapeJavaScript(additionalParams)
618                    + "\";\n");
619        }
620        // the resource id of plain resources
621        content.append("top.plainresid=");
622        int plainId;
623        try {
624            plainId = OpenCms.getResourceManager().getResourceType(
625                CmsResourceTypePlain.getStaticTypeName()).getTypeId();
626        } catch (CmsLoaderException e) {
627            // this should really never happen
628            plainId = CmsResourceTypePlain.getStaticTypeId();
629        }
630        content.append(plainId);
631        content.append(";\n");
632
633        // the auto lock setting
634        content.append("top.autolock=");
635        content.append(OpenCms.getWorkplaceManager().autoLockResources());
636        content.append(";\n");
637
638        // the button type setting
639        content.append("top.buttonType=");
640        content.append(getSettings().getUserSettings().getExplorerButtonStyle());
641        content.append(";\n");
642
643        // the help_url
644        content.append("top.head.helpUrl='explorer/index.html';\n");
645        // the project
646        content.append("top.setProject('");
647        if (!listView) {
648            content.append(getSettings().getProject());
649        } else {
650            content.append(getSettings().getExplorerProjectId());
651        }
652        content.append("');\n");
653        // the onlineProject
654        content.append("top.setOnlineProject('");
655        content.append(CmsProject.ONLINE_PROJECT_ID);
656        content.append("');\n");
657        // set the writeAccess for the current Folder
658        boolean writeAccess = VIEW_EXPLORER.equals(getSettings().getExplorerMode());
659        if (writeAccess) {
660            writeAccess = getCms().isInsideCurrentProject(currentResourceName);
661        }
662        content.append("top.enableNewButton(");
663        content.append(writeAccess);
664        content.append(");\n");
665
666        // the folder
667        String siteFolderPath = CmsResource.getFolderPath(
668            getCms().getRequestContext().removeSiteRoot(currentResource.getRootPath()));
669        if (OpenCms.getSiteManager().startsWithShared(siteFolderPath)
670            && OpenCms.getSiteManager().startsWithShared(getCms().getRequestContext().getSiteRoot())) {
671            siteFolderPath = siteFolderPath.substring(OpenCms.getSiteManager().getSharedFolder().length() - 1);
672        }
673
674        content.append("top.setDirectory(\"");
675        content.append(CmsResource.getFolderPath(currentResource.getRootPath()));
676        content.append("\",\"");
677        content.append(siteFolderPath);
678
679        content.append("\");\n");
680        content.append("top.rD();\n");
681
682        //unchecked cast to List<String>
683        @SuppressWarnings("unchecked")
684        List<String> reloadTreeFolders = (List<String>)getJsp().getRequest().getAttribute(REQUEST_ATTRIBUTE_RELOADTREE);
685
686        if (reloadTreeFolders != null) {
687            // folder tree has to be reloaded after copy, delete, move, rename operation
688            String reloadFolder = "";
689            for (int i = 0; i < reloadTreeFolders.size(); i++) {
690                reloadFolder = reloadTreeFolders.get(i);
691                if (getSettings().getUserSettings().getRestrictExplorerView()) {
692                    // in restricted view, adjust folder path to reload: remove restricted folder name
693                    if (reloadFolder.length() >= rootFolder.length()) {
694                        reloadFolder = reloadFolder.substring(rootFolder.length() - 1);
695                    }
696                }
697                content.append("top.addNodeToLoad(\"" + reloadFolder + "\");\n");
698            }
699            content.append("top.reloadNodeList();\n");
700        }
701        content.append("\n");
702        return content.toString();
703    }
704
705    /**
706     * Determines the root folder of the current tree dependent on users setting of explorer view restriction.<p>
707     *
708     * @return the root folder resource name to display
709     */
710    public String getRootFolder() {
711
712        String folder = "/";
713        if (getSettings().getUserSettings().getRestrictExplorerView()) {
714            folder = getSettings().getUserSettings().getStartFolder();
715        }
716        try {
717            getCms().readFolder(folder, CmsResourceFilter.IGNORE_EXPIRATION);
718            return folder;
719        } catch (CmsException e) {
720            // should usually never happen
721            if (LOG.isInfoEnabled()) {
722                LOG.info(e.getLocalizedMessage(), e);
723            }
724            return "/";
725        }
726    }
727
728    /**
729     * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, javax.servlet.http.HttpServletRequest)
730     */
731    @Override
732    protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request) {
733
734        String currentResource = request.getParameter(PARAMETER_RESOURCE);
735        String mode = request.getParameter(PARAMETER_MODE);
736        if (CmsStringUtil.isNotEmpty(mode)) {
737            settings.setExplorerMode(mode);
738        } else {
739            // null argument, use explorer view if no other view currently specified
740            if (!(VIEW_GALLERY.equals(settings.getExplorerMode()) || VIEW_LIST.equals(settings.getExplorerMode()))) {
741                settings.setExplorerMode(VIEW_EXPLORER);
742            }
743        }
744
745        m_uri = request.getParameter(PARAMETER_URI);
746
747        if (CmsStringUtil.isNotEmpty(currentResource) && folderExists(getCms(), currentResource)) {
748            // resource is a folder, set resource name
749            settings.setExplorerResource(currentResource, getCms());
750        } else {
751            // other cases (resource null, no folder), first get the resource name from settings
752            currentResource = settings.getExplorerResource();
753            if (!resourceExists(getCms(), currentResource)) {
754                // resource does not exist, display root folder
755                settings.setExplorerResource("/", getCms());
756            }
757        }
758
759        String selectedPage = request.getParameter(PARAMETER_PAGE);
760        if (selectedPage != null) {
761            int page = 1;
762            try {
763                page = Integer.parseInt(selectedPage);
764            } catch (NumberFormatException e) {
765                // default is 1
766                if (LOG.isInfoEnabled()) {
767                    LOG.info(e.getLocalizedMessage(), e);
768                }
769            }
770            settings.setExplorerPage(page);
771        }
772        if (getSettings().getExplorerMode().equals(CmsExplorer.VIEW_EXPLORER)) {
773            // reset the startup URI, so that it is not displayed again on reload of the frame set
774            getSettings().setViewStartup(null);
775        }
776
777        // if in explorer list view
778        if (getSettings().getExplorerMode().equals(CmsExplorer.VIEW_LIST)) {
779            // if no other view startup url has been set
780            if (getSettings().getViewStartup() == null) {
781                // if not in the admin view
782                if (getSettings().getViewUri().indexOf(CmsToolManager.ADMINVIEW_ROOT_LOCATION) < 0) {
783                    // set the view startup url as editor close link!
784                    String uri = CmsToolManager.VIEW_JSPPAGE_LOCATION;
785                    uri = CmsRequestUtil.appendParameter(
786                        CmsWorkplace.VFS_PATH_VIEWS + "explorer/explorer_fs.jsp",
787                        "uri",
788                        CmsEncoder.encode(CmsEncoder.encode(uri)));
789                    getSettings().setViewStartup(getJsp().link(uri));
790                }
791            }
792        }
793
794        // the flat url
795        settings.setExplorerFlaturl(request.getParameter(PARAMETER_FLATURL));
796    }
797
798    /**
799     * Checks if a folder with a given name exits in the VFS.<p>
800     *
801     * @param cms the current cms context
802     * @param folder the folder to check for
803     * @return true if the folder exists in the VFS
804     */
805    private boolean folderExists(CmsObject cms, String folder) {
806
807        try {
808            CmsFolder test = cms.readFolder(folder, CmsResourceFilter.IGNORE_EXPIRATION);
809            if (test.isFile()) {
810                return false;
811            }
812            return true;
813        } catch (Exception e) {
814            return false;
815        }
816    }
817
818    /**
819     * Returns a list resources that should be displayed in the
820     * OpenCms Explorer.<p>
821     *
822     * How the list is build depends on the current Workplace settings
823     * of the user.
824     *
825     * @param resource the resource to read the files from (usually a folder)
826     * @return a list of resources to display
827     */
828    private List<CmsResource> getResources(String resource) {
829
830        if (VIEW_LIST.equals(getSettings().getExplorerMode())) {
831            // check if the list must show the list view or the check content view
832            I_CmsResourceCollector collector = getSettings().getCollector();
833            if (collector != null) {
834                // is this the collector for the list view
835                if (collector instanceof I_CmsListResourceCollector) {
836                    ((I_CmsListResourceCollector)collector).setPage(getSettings().getExplorerPage());
837                }
838                try {
839                    return collector.getResults(getCms());
840                } catch (CmsException e) {
841                    if (LOG.isInfoEnabled()) {
842                        LOG.info(e.getLocalizedMessage(), e);
843                    }
844                }
845            }
846            return Collections.emptyList();
847        } else if (VIEW_GALLERY.equals(getSettings().getExplorerMode())) {
848            // select galleries
849            A_CmsAjaxGallery gallery = A_CmsAjaxGallery.createInstance(getSettings().getGalleryType(), getJsp());
850            return gallery.getGalleries();
851        } else {
852            // default is to return a list of all files in the folder
853            try {
854                return getCms().getResourcesInFolder(resource, CmsResourceFilter.ONLY_VISIBLE);
855            } catch (CmsException e) {
856                // should usually never happen
857                if (LOG.isInfoEnabled()) {
858                    LOG.info(e.getLocalizedMessage(), e);
859                }
860                return Collections.emptyList();
861            }
862        }
863    }
864
865    /**
866     * Sets the default preferences for the current user if those values are not available.<p>
867     *
868     * @return the integer value of the default preferences
869     */
870    private int getUserPreferences() {
871
872        CmsUserSettings settings = new CmsUserSettings(getCms());
873        return settings.getExplorerSettings();
874    }
875
876    /**
877     * Checks if a resource with a given name exits in the VFS.<p>
878     *
879     * @param cms the current cms context
880     * @param resource the resource to check for
881     *
882     * @return true if the resource exists in the VFS
883     */
884    private boolean resourceExists(CmsObject cms, String resource) {
885
886        try {
887            cms.readResource(resource, CmsResourceFilter.ALL);
888            return true;
889        } catch (CmsException e) {
890            return false;
891        }
892    }
893}