001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.jsp.util;
029
030import org.opencms.file.CmsObject;
031import org.opencms.file.CmsProject;
032import org.opencms.file.CmsRequestContext;
033import org.opencms.file.CmsResource;
034import org.opencms.file.CmsUser;
035import org.opencms.file.types.CmsResourceTypeXmlContent;
036import org.opencms.file.types.CmsResourceTypeXmlPage;
037import org.opencms.i18n.CmsLocaleGroup;
038import org.opencms.jsp.CmsJspResourceWrapper;
039import org.opencms.jsp.util.CmsJspValueTransformers.CmsLocalePropertyLoaderTransformer;
040import org.opencms.jsp.util.CmsJspValueTransformers.CmsPropertyLoaderTransformer;
041import org.opencms.main.CmsException;
042import org.opencms.main.CmsLog;
043import org.opencms.main.OpenCms;
044import org.opencms.security.CmsPermissionSet;
045import org.opencms.staticexport.CmsLinkManager;
046import org.opencms.util.CmsCollectionsGenericWrapper;
047
048import java.util.Collections;
049import java.util.HashMap;
050import java.util.List;
051import java.util.Locale;
052import java.util.Map;
053
054import org.apache.commons.collections.Transformer;
055import org.apache.commons.logging.Log;
056
057/**
058 * Provides utility methods that allow convenient access to the OpenCms VFS,
059 * indented to be used from a JSP with the JSTL or EL.<p>
060 *
061 * @since 7.0.2
062 *
063 * @see CmsJspContentAccessBean
064 */
065public final class CmsJspVfsAccessBean {
066
067    /**
068     * Transformer that loads a resource from the OpenCms VFS,
069     * the input is used as String for the resource name to read.<p>
070     */
071    public class CmsAvailableLocaleLoaderTransformer implements Transformer {
072
073        /**
074         * @see org.apache.commons.collections.Transformer#transform(java.lang.Object)
075         */
076        public Object transform(Object input) {
077
078            List<Locale> result;
079            // read the available locales
080            result = OpenCms.getLocaleManager().getAvailableLocales(getCmsObject(), String.valueOf(input));
081            return result;
082        }
083    }
084
085    /**
086     * Provides Booleans that indicate if a specified resource exists in the OpenCms VFS,
087     * the input is used as String for the resource name to read.<p>
088     */
089    public class CmsExistsResourceTransformer implements Transformer {
090
091        /**
092         * @see org.apache.commons.collections.Transformer#transform(java.lang.Object)
093         */
094        public Object transform(Object input) {
095
096            return Boolean.valueOf(getReadResource().get(input) != null);
097        }
098    }
099
100    /**
101     * Provides Booleans that indicate if a specified resource exists in the OpenCms VFS
102     * and is of type XML content or XML page,
103     * the input is used as String for the resource name to read.<p>
104     */
105    public class CmsExistsXmlTransformer implements Transformer {
106
107        /**
108         * @see org.apache.commons.collections.Transformer#transform(java.lang.Object)
109         */
110        public Object transform(Object input) {
111
112            // first read the resource using the lazy map
113            CmsResource resource = getReadResource().get(input);
114            return Boolean.valueOf(
115                (resource != null)
116                    && (CmsResourceTypeXmlPage.isXmlPage(resource)
117                        || CmsResourceTypeXmlContent.isXmlContent(resource)));
118        }
119    }
120
121    /**
122     * Transformer that loads a resource permission from the OpenCms VFS,
123     * the input is used as String for the resource name to read the permissions for.<p>
124     */
125    public class CmsPermissionsLoaderTransformer implements Transformer {
126
127        /**
128         * @see org.apache.commons.collections.Transformer#transform(java.lang.Object)
129         */
130        public Object transform(Object input) {
131
132            CmsPermissionSet result;
133            try {
134                // read the requested resource permissions
135                result = getCmsObject().getPermissions((String)input);
136            } catch (CmsException e) {
137                // unable to read resource, return null
138                result = null;
139            }
140            return result;
141        }
142    }
143
144    /**
145     * Transformer that a properties of a resource from the OpenCms VFS,
146     * the input is used as String for the property name to read.<p>
147     */
148    public class CmsPropertyLoaderSingleTransformer implements Transformer {
149
150        /** The resource where the properties are read from. */
151        private CmsResource m_resource;
152
153        /** Indicates if properties should be searched when loaded. */
154        private boolean m_search;
155
156        /**
157         * Creates a new property loading Transformer.<p>
158         *
159         * @param resource the resource where the properties are read from
160         * @param search indicates if properties should be searched when loaded
161         */
162        public CmsPropertyLoaderSingleTransformer(CmsResource resource, boolean search) {
163
164            m_resource = resource;
165            m_search = search;
166        }
167
168        /**
169         * @see org.apache.commons.collections.Transformer#transform(java.lang.Object)
170         */
171        public Object transform(Object input) {
172
173            String result;
174            try {
175                // read the properties of the requested resource
176                result = getCmsObject().readPropertyObject(m_resource, String.valueOf(input), m_search).getValue();
177            } catch (CmsException e) {
178                // in case of any error we assume the property does not exist
179                result = null;
180            }
181            return result;
182        }
183    }
184
185    /**
186     * Transformer that loads a resource from the OpenCms VFS,
187     * the input is used as String for the resource name to read.<p>
188     */
189    public class CmsResourceLoaderTransformer implements Transformer {
190
191        /**
192         * @see org.apache.commons.collections.Transformer#transform(java.lang.Object)
193         */
194        public Object transform(Object input) {
195
196            CmsResource result;
197            try {
198                // read the requested resource
199                result = CmsJspElFunctions.convertResource(getCmsObject(), input);
200            } catch (CmsException e) {
201                // unable to read resource, return null
202                result = null;
203            }
204            return result;
205        }
206    }
207
208    /**
209     * Transformer that loads properties of a resource from the OpenCms VFS with another lazy map,
210     * the input is used as String for the resource name to read.<p>
211     */
212    public class CmsResourceLocalePropertyLoaderTransformer implements Transformer {
213
214        /** Indicates if properties should be searched when loaded. */
215        private boolean m_search;
216
217        /**
218         * Creates a new property loading Transformer.<p>
219         *
220         * @param search indicates if properties should be searched when loaded
221         */
222        public CmsResourceLocalePropertyLoaderTransformer(boolean search) {
223
224            m_search = search;
225        }
226
227        /**
228         * @see org.apache.commons.collections.Transformer#transform(java.lang.Object)
229         */
230        public Object transform(Object input) {
231
232            Map<String, String> result = null;
233            // first read the resource using the lazy map
234            CmsResource resource = getReadResource().get(input);
235            if (resource != null) {
236                result = CmsCollectionsGenericWrapper.createLazyMap(
237                    new CmsLocalePropertyLoaderTransformer(getCmsObject(), resource, m_search));
238            }
239            // result may still be null
240            return (result == null) ? Collections.EMPTY_MAP : result;
241        }
242    }
243
244    /**
245     * Transformer that loads properties of a resource from the OpenCms VFS with another lazy map,
246     * the input is used as String for the resource name to read.<p>
247     */
248    public class CmsResourcePropertyLoaderTransformer implements Transformer {
249
250        /** Indicates if properties should be searched when loaded. */
251        private boolean m_search;
252
253        /**
254         * Creates a new property loading Transformer.<p>
255         *
256         * @param search indicates if properties should be searched when loaded
257         */
258        public CmsResourcePropertyLoaderTransformer(boolean search) {
259
260            m_search = search;
261        }
262
263        /**
264         * @see org.apache.commons.collections.Transformer#transform(java.lang.Object)
265         */
266        public Object transform(Object input) {
267
268            Map<String, String> result = null;
269            // first read the resource using the lazy map
270            CmsResource resource = getReadResource().get(input);
271            if (resource != null) {
272                result = CmsCollectionsGenericWrapper.createLazyMap(
273                    new CmsPropertyLoaderTransformer(getCmsObject(), resource, m_search));
274            }
275            // result may still be null
276            return (result == null) ? Collections.EMPTY_MAP : result;
277        }
278    }
279
280    /**
281     * Transformer that calculates links to resources in the OpenCms VFS,
282     * the input is used as String for the resource name to use as link target.<p>
283     *
284     * This is using the same logic as
285     * {@link org.opencms.jsp.CmsJspTagLink#linkTagAction(String, javax.servlet.ServletRequest)}.<p>
286     */
287    public class CmsVfsLinkTransformer implements Transformer {
288
289        /**
290         * @see org.apache.commons.collections.Transformer#transform(java.lang.Object)
291         */
292        public Object transform(Object input) {
293
294            return OpenCms.getLinkManager().substituteLink(
295                getCmsObject(),
296                CmsLinkManager.getAbsoluteUri(String.valueOf(input), getCmsObject().getRequestContext().getUri()));
297        }
298    }
299
300    /**
301     * Provides XML content access beans for VFS resources.<p>
302     */
303    public class CmsXmlContentAccessTransformer implements Transformer {
304
305        /**
306         * @see org.apache.commons.collections.Transformer#transform(java.lang.Object)
307         */
308        public Object transform(Object input) {
309
310            CmsJspContentAccessBean result = null;
311            // first read the resource using the lazy map
312            CmsResource resource = getReadResource().get(input);
313            if ((resource != null)
314                && (CmsResourceTypeXmlPage.isXmlPage(resource) || CmsResourceTypeXmlContent.isXmlContent(resource))) {
315                // make sure we have a resource that really is an XML content
316                result = new CmsJspContentAccessBean(getCmsObject(), resource);
317            }
318            return result;
319        }
320    }
321
322    /** Request context attribute for indicating the model file for a create resource operation. */
323    public static final String ATTRIBUTE_VFS_ACCESS_BEAN = CmsJspVfsAccessBean.class.getName() + ".VFS_ACCESS_BEAN";
324
325    /** Logger instance for this class. */
326    private static final Log LOG = CmsLog.getLog(CmsJspVfsAccessBean.class);
327
328    /** The OpenCms context of the current user. */
329    protected CmsObject m_cms;
330
331    /** Contains booleans that indicate if a resource exists in the VFS. */
332    private Map<String, Boolean> m_existsResource;
333
334    /** Contains booleans that indicate if a resource exists and is an XML content. */
335    private Map<String, Boolean> m_existsXml;
336
337    /** Links calculated for the OpenCms VFS. */
338    private Map<String, String> m_links;
339
340    /** Resource permissions loaded from the OpenCms VFS. */
341    private Map<String, CmsPermissionSet> m_permissions;
342
343    /** Properties loaded from the OpenCms VFS. */
344    private Map<String, Map<String, String>> m_properties;
345
346    /** Properties loaded locale specific from the OpenCms VFS. */
347    private Map<String, Map<String, Map<String, String>>> m_propertiesLocale;
348
349    /** Properties loaded from the OpenCms VFS with search. */
350    private Map<String, Map<String, String>> m_propertiesSearch;
351
352    /** Properties loaded locale specific from the OpenCms VFS with search. */
353    private Map<String, Map<String, Map<String, String>>> m_propertiesSearchLocale;
354
355    /** Available locales as determined by the {@link org.opencms.i18n.CmsLocaleManager} */
356    private Map<String, List<Locale>> m_availableLocales;
357
358    /** Resources loaded from the OpenCms VFS. */
359    private Map<String, CmsResource> m_resources;
360
361    /** XML contents read from the VFS. */
362    private Map<String, CmsJspContentAccessBean> m_xmlContent;
363
364    /**
365     * Creates a new context bean using the OpenCms context of the current user.<p>
366     *
367     * @param cms the OpenCms context of the current user
368     */
369    private CmsJspVfsAccessBean(CmsObject cms) {
370
371        m_cms = cms;
372    }
373
374    /**
375     * Creates a new instance of the JSP VFS access utility bean.<p>
376     *
377     * To prevent multiple creations of the bean during a request, the OpenCms request context
378     * attributes are used to cache the created VFS access utility bean.<p>
379     *
380     * @param cms the current OpenCms user context
381     *
382     * @return a new instance of the JSP VFS access utility bean
383     */
384    public static CmsJspVfsAccessBean create(CmsObject cms) {
385
386        CmsJspVfsAccessBean result;
387        Object attribute = cms.getRequestContext().getAttribute(ATTRIBUTE_VFS_ACCESS_BEAN);
388        if (attribute != null) {
389            result = (CmsJspVfsAccessBean)attribute;
390        } else {
391            result = new CmsJspVfsAccessBean(cms);
392            cms.getRequestContext().setAttribute(ATTRIBUTE_VFS_ACCESS_BEAN, result);
393        }
394        return result;
395    }
396
397    /**
398     * Returns a lazily generated map from site paths of resources to the available locales for the resource.
399     *
400     * @return a lazily generated map from site paths of resources to the available locales for the resource.
401     */
402    public Map<String, List<Locale>> getAvailableLocales() {
403
404        if (m_availableLocales == null) {
405            // create lazy map only on demand
406            m_availableLocales = CmsCollectionsGenericWrapper.createLazyMap(new CmsAvailableLocaleLoaderTransformer());
407        }
408        return m_availableLocales;
409    }
410
411    /**
412     * Returns the OpenCms user context this bean was initialized with.<p>
413     *
414     * @return the OpenCms user context this bean was initialized with
415     */
416    public CmsObject getCmsObject() {
417
418        return m_cms;
419    }
420
421    /**
422     * Short form for {@link #getRequestContext()}.<p>
423     *
424     * Usage example on a JSP with the EL:<pre>
425     * The current URI is: ${cms:vfs(pageContext).context.uri}
426     * </pre>
427     *
428     * @return the OpenCms request context of the current user this bean was initialized with
429     *
430     * @see #getRequestContext()
431     */
432    public CmsRequestContext getContext() {
433
434        return getRequestContext();
435    }
436
437    /**
438     * Returns the current project from the context.<p>
439     *
440     * Usage example on a JSP with the EL:<pre>
441     * The current project name is: ${cms:vfs(pageContext).currentProject.name}
442     * </pre>
443     *
444     * @return the current project
445     */
446    public CmsProject getCurrentProject() {
447
448        return m_cms.getRequestContext().getCurrentProject();
449    }
450
451    /**
452     * Returns the current user from the context.<p>
453     *
454     * Usage example on a JSP with the EL:<pre>
455     * The current user name is: ${cms:vfs(pageContext).currentUser.name}
456     * </pre>
457     *
458     * @return the current user
459     */
460    public CmsUser getCurrentUser() {
461
462        return m_cms.getRequestContext().getCurrentUser();
463    }
464
465    /**
466     * Short form for {@link #getExistsResource()}.<p>
467     *
468     * Usage example on a JSP with the EL / JSTL:<pre>
469     * &lt;c:if test="${cms:vfs(pageContext).exists['/checkme.html']}" &gt;
470     *     The resource "/checkme.html" exists.
471     * &lt;/c:if&gt;
472     * </pre>
473     *
474     * @return a map that lazily reads resources from the OpenCms VFS
475     *
476     * @see #getExistsResource()
477     */
478    public Map<String, Boolean> getExists() {
479
480        return getExistsResource();
481    }
482
483    /**
484     * Returns a map that lazily checks if a resources exists in the OpenCms VFS.<p>
485     *
486     * Usage example on a JSP with the EL / JSTL:<pre>
487     * &lt;c:if test="${cms:vfs(pageContext).existsResource['/checkme.html']}" &gt;
488     *     The resource "/checkme.html" exists.
489     * &lt;/c:if&gt;
490     * </pre>
491     *
492     * Usage example on a JSP with the <code>&lt;cms:contentaccess&gt;</code> tag:<pre>
493     * &lt;cms:contentload ... &gt;
494     *     &lt;cms:contentaccess var="content" /&gt;
495     *     &lt;c:if test="${content.vfs.existsResource['/checkme.html']}" &gt;
496     *         The resource "/checkme.html" exists.
497     *     &lt;/c:if&gt;
498     * &lt;/cms:contentload&gt;</pre>
499     *
500     * @return a map that lazily checks if a resources exists in the OpenCms VFS
501     *
502     * @see #getExists() for a short form of this method
503     */
504    public Map<String, Boolean> getExistsResource() {
505
506        if (m_existsResource == null) {
507            // create lazy map only on demand
508            m_existsResource = CmsCollectionsGenericWrapper.createLazyMap(new CmsExistsResourceTransformer());
509        }
510        return m_existsResource;
511    }
512
513    /**
514     * Returns a map that lazily checks if a resources exists in the VFS and is of type XML content or XML page.<p>
515     *
516     * Usage example on a JSP with the EL / JSTL:<pre>
517     * &lt;c:if test="${cms:vfs(pageContext).existsXml['/text.xml']}" &gt;
518     *     The resource "/text.xml" exists and is an XML document.
519     * &lt;/c:if&gt;
520     * </pre>
521     *
522     * @return a map that lazily checks if a resources exists in the VFS and is of type XML content or XML page
523     */
524    public Map<String, Boolean> getExistsXml() {
525
526        if (m_existsXml == null) {
527            // create lazy map only on demand
528            m_existsXml = CmsCollectionsGenericWrapper.createLazyMap(new CmsExistsXmlTransformer());
529        }
530        return m_existsXml;
531    }
532
533    /**
534     * Flushes the internal caches of this VFS access bean.<p>
535     *
536     * The VFS access bean uses lazy initialized Maps for all access, but once a value has been
537     * read it is cached in the Map and not read again from the VFS. This means the lazy Maps
538     * act as another layer of cache to the VFS.<p>
539     *
540     * The VFS access bean instance itself is cached in the OpenCms request context attributes of the {@link CmsObject},
541     * see {@link #create(CmsObject)}. Normally there is a new {@link CmsObject} created for
542     * all incoming requests, so the live-time of the VFS access bean is short.
543     * In that case the caching of the lazy Maps should improve performance and not be an issue.
544     * However, in rare cases an instance of a {@link CmsObject} may be kept for a long time in
545     * some custom code. In theses cases flushing the caches of the lazy Maps manually may be required, otherwise
546     * the Map caches may be out of sync with the VFS.
547     *
548     * @return always returns <code>true</code>
549     */
550    public boolean getFlushCaches() {
551
552        m_resources = null;
553        m_properties = null;
554        m_propertiesSearch = null;
555
556        return true;
557    }
558
559    /**
560     * Returns a map that lazily calculates links to files in the OpenCms VFS,
561     * which have been adjusted according to the web application path and the
562     * OpenCms static export rules.<p>
563     *
564     * Please note that the target is always assumed to be in the OpenCms VFS, so you can't use
565     * this method for links external to OpenCms.<p>
566     *
567     * Relative links are converted to absolute links, using the current element URI as base.<p>
568     *
569     * Relative links are converted to absolute links, using the current OpenCms request context URI as base.<p>
570     *
571     * Usage example on a JSP with the EL:<pre>
572     * Link to the "/index.html" file: ${cms:vfs(pageContext).link['/index.html']}
573     * </pre>
574     *
575     * Usage example on a JSP with the <code>&lt;cms:contentaccess&gt;</code> tag:<pre>
576     * &lt;cms:contentload ... &gt;
577     *     &lt;cms:contentaccess var="content" /&gt;
578     *     Link to the "/index.html" file: ${content.vfs.link['/index.html']}
579     * &lt;/cms:contentload&gt;</pre>
580     *
581     * @return a map that lazily calculates links to resources in the OpenCms VFS
582     *
583     * @see org.opencms.jsp.CmsJspActionElement#link(String)
584     * @see org.opencms.jsp.CmsJspTagLink#linkTagAction(String, javax.servlet.ServletRequest)
585     */
586    public Map<String, String> getLink() {
587
588        if (m_links == null) {
589            // create lazy map only on demand
590            m_links = CmsCollectionsGenericWrapper.createLazyMap(new CmsVfsLinkTransformer());
591        }
592        return m_links;
593    }
594
595    /**
596     * Gets a lazy loading map used to access locale variants of a resource with a given path.<p>
597     *
598     * Usage in JSP: ${myvfsaccessbeaninstance.localeResource['/foo/bar/index.html']['de']}
599     *
600     * @return the lazy loading map
601     */
602    public Map<String, Map<String, CmsJspResourceWrapper>> getLocaleResource() {
603
604        return CmsCollectionsGenericWrapper.createLazyMap(new Transformer() {
605
606            @SuppressWarnings("synthetic-access")
607            public Object transform(Object arg) {
608
609                if (!(arg instanceof String)) {
610                    return new HashMap<String, CmsJspResourceWrapper>();
611                }
612                String path = (String)arg;
613                try {
614                    CmsResource res = m_cms.readResource(path);
615                    CmsJspResourceWrapper wrapper = new CmsJspResourceWrapper(m_cms, res);
616                    return wrapper.getLocaleResource();
617                } catch (Exception e) {
618                    LOG.warn(e.getLocalizedMessage(), e);
619                    return new HashMap<String, CmsJspResourceWrapper>();
620                }
621            }
622
623        });
624    }
625
626    /**
627     * Returns a lazy loading map used to detect the main locale of a resource which is part of a locale group.<p>
628     *
629     * Usage in JSPs: ${myvfsaccessbeaninstance.mainLocale['/foo/index.html']}
630     *
631     * @return the lazy loading map
632     */
633    public Map<String, Locale> getMainLocale() {
634
635        return CmsCollectionsGenericWrapper.createLazyMap(new Transformer() {
636
637            @SuppressWarnings("synthetic-access")
638            public Object transform(Object arg) {
639
640                if (!(arg instanceof String)) {
641                    return null;
642                }
643                String path = (String)arg;
644                try {
645                    CmsResource res = m_cms.readResource(path);
646                    CmsLocaleGroup localeGroup = m_cms.getLocaleGroupService().readLocaleGroup(res);
647                    return localeGroup.getMainLocale();
648                } catch (Exception e) {
649                    LOG.warn(e.getLocalizedMessage(), e);
650                    return null;
651                }
652            }
653        });
654    }
655
656    /**
657     * Short form for {@link #getReadPermissions()}.<p>
658     *
659     * Usage example on a JSP with the EL:<pre>
660     * Permission string of the "/index.html" resource: ${cms:vfs(pageContext).readPermissions['/index.html'].permissionString}
661     * </pre>
662     *
663     * Usage example on a JSP with the <code>&lt;cms:contentaccess&gt;</code> tag:<pre>
664     * &lt;cms:contentload ... &gt;
665     *     &lt;cms:contentaccess var="content" /&gt;
666     *     Permission string of the "/index.html" resource: ${content.vfs.readPermissions['/index.html'].permissionString}
667     * &lt;/cms:contentload&gt;</pre>
668     *
669     * @return a map that lazily reads resource permissions from the OpenCms VFS
670     *
671     * @see #getReadPermissions()
672     */
673    public Map<String, CmsPermissionSet> getPermissions() {
674
675        return getReadPermissions();
676    }
677
678    /**
679     * Short form for {@link #getReadProperties()}.<p>
680     *
681     * Usage example on a JSP with the EL:<pre>
682     * Title property of the "/index.html" resource: ${cms:vfs(pageContext).property['/index.html']['Title']}
683     * </pre>
684     *
685     * @return a map that lazily reads all resource properties from the OpenCms VFS, without search
686     *
687     * @see #getReadProperties()
688     */
689    public Map<String, Map<String, String>> getProperty() {
690
691        return getReadProperties();
692    }
693
694    /**
695     * Short form for {@link #getReadPropertiesLocale()}.<p>
696     *
697     * Usage example on a JSP with the EL:<pre>
698     * Title property of the "/index.html" resource for locale "de": ${cms:vfs(pageContext).property['/index.html']['de']['Title']}
699     * </pre>
700     *
701     * @return a map that lazily reads all resource properties from the OpenCms VFS, without search
702     *
703     * @see #getReadPropertiesLocale()
704     */
705    public Map<String, Map<String, Map<String, String>>> getPropertyLocale() {
706
707        return getReadPropertiesLocale();
708    }
709
710    /**
711     * Short form for {@link #getReadPropertiesSearch()}.<p>
712     *
713     * Usage example on a JSP with the EL:<pre>
714     * Title property of the "/index.html" resource (searched): ${cms:vfs(pageContext).propertySearch['/index.html']['Title']}
715     * </pre>
716     *
717     * @return a map that lazily reads all resource properties from the OpenCms VFS, with search
718     *
719     * @see #getReadPropertiesSearch()
720     */
721    public Map<String, Map<String, String>> getPropertySearch() {
722
723        return getReadPropertiesSearch();
724    }
725
726    /**
727     * Short form for {@link #getReadPropertiesSearchLocale()}.<p>
728     *
729     * Usage example on a JSP with the EL:<pre>
730     * Title property of the "/index.html" resource (searched) for locale "de": ${cms:vfs(pageContext).propertySearch['/index.html']['de']['Title']}
731     * </pre>
732     *
733     * @return a map that lazily reads all resource properties from the OpenCms VFS, with search
734     *
735     * @see #getReadPropertiesSearchLocale()
736     */
737    public Map<String, Map<String, Map<String, String>>> getPropertySearchLocale() {
738
739        return getReadPropertiesSearchLocale();
740    }
741
742    /**
743     * Returns a map that lazily reads resource permissions from the OpenCms VFS.<p>
744     *
745     * Usage example on a JSP with the EL:<pre>
746     * Permission string of the "/index.html" resource: ${cms:vfs(pageContext).readPermissions['/index.html'].permissionString}
747     * </pre>
748     *
749     * Usage example on a JSP with the <code>&lt;cms:contentaccess&gt;</code> tag:<pre>
750     * &lt;cms:contentload ... &gt;
751     *     &lt;cms:contentaccess var="content" /&gt;
752     *     Permission string of the "/index.html" resource: ${content.vfs.readPermissions['/index.html'].permissionString}
753     * &lt;/cms:contentload&gt;</pre>
754     *
755     * @return a map that lazily reads resource permissions from the OpenCms VFS
756     *
757     * @see #getPermissions() for a short form of this method
758     */
759    public Map<String, CmsPermissionSet> getReadPermissions() {
760
761        if (m_permissions == null) {
762            // create lazy map only on demand
763            m_permissions = CmsCollectionsGenericWrapper.createLazyMap(new CmsPermissionsLoaderTransformer());
764        }
765        return m_permissions;
766    }
767
768    /**
769     * Returns a map that lazily reads all resource properties from the OpenCms VFS, without search.<p>
770     *
771     * Usage example on a JSP with the EL:<pre>
772     * Title property of the "/index.html" resource: ${cms:vfs(pageContext).readProperties['/index.html']['Title']}
773     * </pre>
774     *
775     * Usage example on a JSP with the <code>&lt;cms:contentaccess&gt;</code> tag:<pre>
776     * &lt;cms:contentload ... &gt;
777     *     &lt;cms:contentaccess var="content" /&gt;
778     *     Title property of the "/index.html" resource: ${content.vfs.readProperties['/index.html']['Title']}
779     * &lt;/cms:contentload&gt;</pre>
780     *
781     * @return a map that lazily reads all resource properties from the OpenCms VFS, without search
782     *
783     * @see #getProperty() for a short form of this method
784     */
785    public Map<String, Map<String, String>> getReadProperties() {
786
787        if (m_properties == null) {
788            // create lazy map only on demand
789            m_properties = CmsCollectionsGenericWrapper.createLazyMap(new CmsResourcePropertyLoaderTransformer(false));
790        }
791        return m_properties;
792    }
793
794    /**
795     * Returns a map that lazily reads all resource properties from the OpenCms VFS, without search.<p>
796     *
797     * Usage example on a JSP with the EL:<pre>
798     * Title property of the "/index.html" resource for locale "de": ${cms:vfs(pageContext).readProperties['/index.html']['de']['Title']}
799     * </pre>
800     *
801     * Usage example on a JSP with the <code>&lt;cms:contentaccess&gt;</code> tag:<pre>
802     * &lt;cms:contentload ... &gt;
803     *     &lt;cms:contentaccess var="content" /&gt;
804     *     Title property of the "/index.html" resource: ${content.vfs.readProperties['/index.html']['Title']}
805     * &lt;/cms:contentload&gt;</pre>
806     *
807     * @return a map that lazily reads all resource properties from the OpenCms VFS, without search
808     *
809     * @see #getProperty() for a short form of this method
810     */
811    public Map<String, Map<String, Map<String, String>>> getReadPropertiesLocale() {
812
813        if (m_propertiesLocale == null) {
814            // create lazy map only on demand
815            m_propertiesLocale = CmsCollectionsGenericWrapper.createLazyMap(
816                new CmsResourceLocalePropertyLoaderTransformer(false));
817        }
818        return m_propertiesLocale;
819    }
820
821    /**
822     * Returns a map that lazily reads all resource properties from the OpenCms VFS, with search.<p>
823     *
824     * Usage example on a JSP with the EL:<pre>
825     * Title property of the "/index.html" resource (searched): ${cms:vfs(pageContext).readPropertiesSearch['/index.html']['Title']}
826     * </pre>
827     *
828     * Usage example on a JSP with the <code>&lt;cms:contentaccess&gt;</code> tag:<pre>
829     * &lt;cms:contentload ... &gt;
830     *     &lt;cms:contentaccess var="content" /&gt;
831     *     Title property of the "/index.html" resource (searched): ${content.vfs.readPropertiesSearch['/index.html']['Title']}
832     * &lt;/cms:contentload&gt;</pre>
833     *
834     * @return a map that lazily reads all resource properties from the OpenCms VFS, with search
835     *
836     * @see #getPropertySearch() for a short form of this method
837     */
838    public Map<String, Map<String, String>> getReadPropertiesSearch() {
839
840        if (m_propertiesSearch == null) {
841            // create lazy map only on demand
842            m_propertiesSearch = CmsCollectionsGenericWrapper.createLazyMap(
843                new CmsResourcePropertyLoaderTransformer(true));
844        }
845        return m_propertiesSearch;
846    }
847
848    /**
849     * Returns a map that lazily reads all resource properties from the OpenCms VFS, with search and provides locale specific access to them.<p>
850     *
851     * Usage example on a JSP with the EL:<pre>
852     * Title property of the "/index.html" resource (searched): ${cms:vfs(pageContext).readPropertiesSearch['/index.html']['Title']}
853     * </pre>
854     *
855     * Usage example on a JSP with the <code>&lt;cms:contentaccess&gt;</code> tag:<pre>
856     * &lt;cms:contentload ... &gt;
857     *     &lt;cms:contentaccess var="content" /&gt;
858     *     Title property of the "/index.html" resource (searched) for locale "de": ${content.vfs.readPropertiesSearchLocale['/index.html']['de']['Title']}
859     * &lt;/cms:contentload&gt;</pre>
860     *
861     * @return a map that lazily reads all resource properties from the OpenCms VFS, with search
862     *
863     * @see #getPropertySearch() for a short form of this method
864     */
865    public Map<String, Map<String, Map<String, String>>> getReadPropertiesSearchLocale() {
866
867        if (m_propertiesSearchLocale == null) {
868            // create lazy map only on demand
869            m_propertiesSearchLocale = CmsCollectionsGenericWrapper.createLazyMap(
870                new CmsResourceLocalePropertyLoaderTransformer(true));
871        }
872        return m_propertiesSearchLocale;
873    }
874
875    /**
876     * Returns a map that lazily reads resources from the OpenCms VFS.<p>
877     *
878     * Usage example on a JSP with the EL:<pre>
879     * Root path of the "/index.html" resource: ${cms:vfs(pageContext).readResource['/index.html'].rootPath}
880     * </pre>
881     *
882     * Usage example on a JSP with the <code>&lt;cms:contentaccess&gt;</code> tag:<pre>
883     * &lt;cms:contentload ... &gt;
884     *     &lt;cms:contentaccess var="content" /&gt;
885     *     Root path of the "/index.html" resource: ${content.vfs.readResource['/index.html'].rootPath}
886     * &lt;/cms:contentload&gt;</pre>
887     *
888     * @return a map that lazily reads resources from the OpenCms VFS
889     *
890     * @see #getResource() for a short form of this method
891     */
892    public Map<String, CmsResource> getReadResource() {
893
894        if (m_resources == null) {
895            // create lazy map only on demand
896            m_resources = CmsCollectionsGenericWrapper.createLazyMap(new CmsResourceLoaderTransformer());
897        }
898        return m_resources;
899    }
900
901    /**
902     * Returns a map that lazily reads XML documents from the OpenCms VFS that are wrapped using a
903     * {@link CmsJspContentAccessBean}.<p>
904     *
905     * Usage example on a JSP with the EL:<pre>
906     * Title of "/text.xml": ${cms:vfs(pageContext).readXml['/text.xml'].value['Title']}
907     * </pre>
908     *
909     * @return a map that lazily reads wrapped XML documents from the OpenCms VFS
910     *
911     * @see #getXml() for a short form of this method
912     */
913    public Map<String, CmsJspContentAccessBean> getReadXml() {
914
915        if (m_xmlContent == null) {
916            // create lazy map only on demand
917            m_xmlContent = CmsCollectionsGenericWrapper.createLazyMap(new CmsXmlContentAccessTransformer());
918        }
919        return m_xmlContent;
920    }
921
922    /**
923     * Returns the OpenCms request context the current user this bean was initialized with.<p>
924     *
925     * Usage example on a JSP with the EL:<pre>
926     * The current URI is: ${cms:vfs(pageContext).requestContext.uri}
927     * </pre>
928     *
929     * @return the OpenCms request context the current user this bean was initialized with
930     *
931     * @see #getContext() for a short form of this method
932     */
933    public CmsRequestContext getRequestContext() {
934
935        return m_cms.getRequestContext();
936    }
937
938    /**
939     * Short form for {@link #getReadResource()}.<p>
940     *
941     * Usage example on a JSP with the EL:<pre>
942     * Root path of the "/index.html" resource: ${cms:vfs(pageContext).resource['/index.html'].rootPath}
943     * </pre>
944     *
945     * @return a map that lazily reads resources from the OpenCms VFS
946     *
947     * @see #getReadResource()
948     */
949    public Map<String, CmsResource> getResource() {
950
951        return getReadResource();
952    }
953
954    /**
955     * Short form for {@link #getReadXml()}.<p>
956     *
957     * Usage example on a JSP with the EL:<pre>
958     * Title of "/text.xml": ${cms:vfs(pageContext).xml['/text.xml'].value['Title']}
959     * </pre>
960     *
961     * @return a map that lazily reads wrapped XML documents from the OpenCms VFS
962     *
963     * @see #getReadXml()
964     */
965    public Map<String, CmsJspContentAccessBean> getXml() {
966
967        return getReadXml();
968    }
969}