001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH (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, 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.file;
029
030import org.opencms.db.CmsDbEntryNotFoundException;
031import org.opencms.db.CmsPublishedResource;
032import org.opencms.db.CmsResourceState;
033import org.opencms.db.CmsSecurityManager;
034import org.opencms.db.log.CmsLogEntry;
035import org.opencms.db.log.CmsLogFilter;
036import org.opencms.db.urlname.CmsUrlNameMappingEntry;
037import org.opencms.db.urlname.CmsUrlNameMappingFilter;
038import org.opencms.file.history.CmsHistoryPrincipal;
039import org.opencms.file.history.CmsHistoryProject;
040import org.opencms.file.history.I_CmsHistoryResource;
041import org.opencms.file.types.I_CmsResourceType;
042import org.opencms.lock.CmsLock;
043import org.opencms.lock.CmsLockFilter;
044import org.opencms.lock.CmsLockType;
045import org.opencms.main.CmsException;
046import org.opencms.main.CmsIllegalArgumentException;
047import org.opencms.main.I_CmsEventListener;
048import org.opencms.main.OpenCms;
049import org.opencms.relations.CmsRelation;
050import org.opencms.relations.CmsRelationFilter;
051import org.opencms.relations.CmsRelationType;
052import org.opencms.report.I_CmsReport;
053import org.opencms.security.CmsAccessControlEntry;
054import org.opencms.security.CmsAccessControlList;
055import org.opencms.security.CmsOrganizationalUnit;
056import org.opencms.security.CmsPermissionSet;
057import org.opencms.security.CmsPrincipal;
058import org.opencms.security.CmsRole;
059import org.opencms.security.CmsSecurityException;
060import org.opencms.security.I_CmsPermissionHandler;
061import org.opencms.security.I_CmsPrincipal;
062import org.opencms.util.CmsPair;
063import org.opencms.util.CmsStringUtil;
064import org.opencms.util.CmsUUID;
065import org.opencms.workplace.CmsWorkplace;
066import org.opencms.xml.content.CmsNumberSuffixNameSequence;
067
068import java.util.ArrayList;
069import java.util.Collections;
070import java.util.Iterator;
071import java.util.List;
072import java.util.Locale;
073import java.util.Map;
074import java.util.Set;
075
076/**
077 * This pivotal class provides all authorized access to the OpenCms VFS resources.<p>
078 * 
079 * It encapsulates user identification and permissions.
080 * Think of it as an initialized "shell" to access the OpenCms VFS.
081 * Every call to a method here will be checked for user permissions
082 * according to the <code>{@link org.opencms.file.CmsRequestContext}</code> this CmsObject instance was created with.<p>
083 * 
084 * From a JSP page running in OpenCms, use <code>{@link org.opencms.jsp.CmsJspBean#getCmsObject()}</code> to gain 
085 * access to the current users CmsObject. Usually this is done with a <code>{@link org.opencms.jsp.CmsJspActionElement}</code>.<p>
086 * 
087 * To generate a new instance of this class in your application, use 
088 * <code>{@link org.opencms.main.OpenCms#initCmsObject(String)}</code>. The argument String should be 
089 * the name of the guest user, usually "Guest" and more formally obtained by <code>{@link org.opencms.db.CmsDefaultUsers#getUserGuest()}</code>.
090 * This will give you an initialized context with guest user permissions.
091 * Then use <code>{@link CmsObject#loginUser(String, String)}</code> to log in the user you want.
092 * Obviously you need the password for the new user.
093 * You should never try to create an instance of this class using the constructor, 
094 * this is reserved for internal operation only.<p> 
095 * 
096 * @since 6.0.0 
097 */
098public final class CmsObject {
099
100    /** The request context. */
101    protected CmsRequestContext m_context;
102
103    /** The security manager to access the cms. */
104    protected CmsSecurityManager m_securityManager;
105
106    /**
107     * Connects an OpenCms user context to a running database.<p>
108     * 
109     * <b>Please note:</b> This constructor is internal to OpenCms and not for public use.
110     * If you want to create a new instance of a <code>{@link CmsObject}</code> in your application,
111     * use <code>{@link org.opencms.main.OpenCms#initCmsObject(String)}</code>.<p>
112     * 
113     * @param securityManager the security manager
114     * @param context the request context that contains the user authentication
115     */
116    public CmsObject(CmsSecurityManager securityManager, CmsRequestContext context) {
117
118        init(securityManager, context);
119    }
120
121    /**
122     * Adds a new relation to the given resource.<p>
123     * 
124     * @param resourceName the name of the source resource
125     * @param targetPath the path of the target resource
126     * @param type the type of the relation
127     * 
128     * @throws CmsException if something goes wrong
129     */
130    public void addRelationToResource(String resourceName, String targetPath, String type) throws CmsException {
131
132        createRelation(resourceName, targetPath, type, false);
133    }
134
135    /**
136     * Convenience method to add the site root from the current user's 
137     * request context to the given resource name.<p>
138     *
139     * @param resourcename the resource name
140     * 
141     * @return the resource name with the site root added
142     * 
143     * @see CmsRequestContext#addSiteRoot(String)
144     */
145    public String addSiteRoot(String resourcename) {
146
147        return m_context.addSiteRoot(resourcename);
148    }
149
150    /**
151     * Adds a user to a group.<p>
152     * 
153     * @param username the name of the user that is to be added to the group
154     * @param groupname the name of the group
155     * 
156     * @throws CmsException if something goes wrong
157     */
158    public void addUserToGroup(String username, String groupname) throws CmsException {
159
160        m_securityManager.addUserToGroup(m_context, username, groupname, false);
161    }
162
163    /**
164     * This method works just like {@link CmsObject#adjustLinks(String, String)}, but you can specify multiple source
165     * files, and the target folder is interpreted as the folder into which the source files have been copied.<p>
166     * 
167     * @param sourceFiles the list of source files 
168     * @param targetParentFolder the folder into which the source files have been copied
169     *  
170     * @throws CmsException if something goes wrong 
171     */
172    public void adjustLinks(List<String> sourceFiles, String targetParentFolder) throws CmsException {
173
174        CmsObject cms = OpenCms.initCmsObject(this);
175        cms.getRequestContext().setSiteRoot("");
176        List<String> rootSourceFiles = new ArrayList<String>();
177        for (String sourceFile : sourceFiles) {
178            rootSourceFiles.add(addSiteRoot(sourceFile));
179        }
180        String rootTargetParentFolder = addSiteRoot(targetParentFolder);
181
182        CmsLinkRewriter rewriter = new CmsLinkRewriter(cms, rootSourceFiles, rootTargetParentFolder);
183        rewriter.rewriteLinks();
184    }
185
186    /**
187     * This method works just like {@link CmsObject#adjustLinks(String, String)}, but instead of specifying 
188     * a single source and target folder, you can specify multiple sources and the corresponding targets in 
189     * a map of strings.
190     * 
191     * @param sourceTargetMap a map with the source files as keys and the corresponding targets as values
192     * @param targetParentFolder the folder into which the source files have been copied
193     *  
194     * @throws CmsException if something goes wrong 
195     */
196    public void adjustLinks(Map<String, String> sourceTargetMap, String targetParentFolder) throws CmsException {
197
198        CmsObject cms = OpenCms.initCmsObject(this);
199        cms.getRequestContext().setSiteRoot("");
200        List<CmsPair<String, String>> sourcesAndTargets = new ArrayList<CmsPair<String, String>>();
201        for (Map.Entry<String, String> entry : sourceTargetMap.entrySet()) {
202            String rootSource = addSiteRoot(entry.getKey());
203            String rootTarget = addSiteRoot(entry.getValue());
204            sourcesAndTargets.add(CmsPair.create(rootSource, rootTarget));
205        }
206        String rootTargetParentFolder = addSiteRoot(targetParentFolder);
207        CmsLinkRewriter rewriter = new CmsLinkRewriter(cms, rootTargetParentFolder, sourcesAndTargets);
208        rewriter.rewriteLinks();
209    }
210
211    /**
212     * Adjusts all links in the target folder that point to the source folder 
213     * so that they are kept "relative" in the target folder where possible.
214     * 
215     * If a link is found from the target folder to the source folder, 
216     * then the target folder is checked if a target of the same name 
217     * is found also "relative" inside the target Folder, and if so,
218     * the link is changed to that "relative" target. This is mainly used to keep 
219     * relative links inside a copied folder structure intact. 
220     * 
221     * Example: Image we have folder /folderA/ that contains files 
222     * /folderA/x1 and /folderA/y1. x1 has a link to y1 and y1 to x1. 
223     * Now someone copies /folderA/ to /folderB/. So we end up with 
224     * /folderB/x2 and /folderB/y2. Because of the link mechanism in OpenCms, 
225     * x2 will have a link to y1 and y2 to x1. By using this method, 
226     * the links from x2 to y1 will be replaced by a link x2 to y2, 
227     * and y2 to x1 with y2 to x2.
228     * 
229     * Link replacement works for links in XML files as well as relation only
230     * type links.
231     * 
232     * @param sourceFolder the source folder
233     * @param targetFolder the target folder
234     * 
235     * @throws CmsException if something goes wrong 
236     */
237    public void adjustLinks(String sourceFolder, String targetFolder) throws CmsException {
238
239        String rootSourceFolder = addSiteRoot(sourceFolder);
240        String rootTargetFolder = addSiteRoot(targetFolder);
241        String siteRoot = getRequestContext().getSiteRoot();
242        getRequestContext().setSiteRoot("");
243        try {
244            CmsLinkRewriter linkRewriter = new CmsLinkRewriter(this, rootSourceFolder, rootTargetFolder);
245            linkRewriter.rewriteLinks();
246        } finally {
247            getRequestContext().setSiteRoot(siteRoot);
248        }
249    }
250
251    /**
252     * Changes the access control for a given resource and a given principal(user/group).<p>
253     * 
254     * @param resourceName name of the resource
255     * @param principalType the type of the principal (currently group or user):
256     *      <ul>
257     *          <li><code>{@link I_CmsPrincipal#PRINCIPAL_USER}</code></li>
258     *          <li><code>{@link I_CmsPrincipal#PRINCIPAL_GROUP}</code></li>
259     *      </ul>
260     * @param principalName name of the principal
261     * @param allowedPermissions bit set of allowed permissions
262     * @param deniedPermissions bit set of denied permissions
263     * @param flags additional flags of the access control entry
264     * 
265     * @throws CmsException if something goes wrong
266     */
267    public void chacc(
268        String resourceName,
269        String principalType,
270        String principalName,
271        int allowedPermissions,
272        int deniedPermissions,
273        int flags) throws CmsException {
274
275        CmsResource res = readResource(resourceName, CmsResourceFilter.ALL);
276
277        CmsAccessControlEntry acEntry = null;
278        try {
279            I_CmsPrincipal principal = CmsPrincipal.readPrincipal(this, principalType, principalName);
280            acEntry = new CmsAccessControlEntry(
281                res.getResourceId(),
282                principal.getId(),
283                allowedPermissions,
284                deniedPermissions,
285                flags);
286            acEntry.setFlagsForPrincipal(principal);
287        } catch (CmsDbEntryNotFoundException e) {
288            // check for special ids
289            if (principalName.equalsIgnoreCase(CmsAccessControlEntry.PRINCIPAL_ALL_OTHERS_NAME)) {
290                acEntry = new CmsAccessControlEntry(
291                    res.getResourceId(),
292                    CmsAccessControlEntry.PRINCIPAL_ALL_OTHERS_ID,
293                    allowedPermissions,
294                    deniedPermissions,
295                    flags);
296                acEntry.setFlags(CmsAccessControlEntry.ACCESS_FLAGS_ALLOTHERS);
297            } else if (principalName.equalsIgnoreCase(CmsAccessControlEntry.PRINCIPAL_OVERWRITE_ALL_NAME)) {
298                acEntry = new CmsAccessControlEntry(
299                    res.getResourceId(),
300                    CmsAccessControlEntry.PRINCIPAL_OVERWRITE_ALL_ID,
301                    allowedPermissions,
302                    deniedPermissions,
303                    flags);
304                acEntry.setFlags(CmsAccessControlEntry.ACCESS_FLAGS_OVERWRITE_ALL);
305            } else if (principalType.equalsIgnoreCase(CmsRole.PRINCIPAL_ROLE)) {
306                // only vfs managers can set role based permissions
307                m_securityManager.checkRoleForResource(m_context, CmsRole.VFS_MANAGER, res);
308                // check for role
309                CmsRole role = CmsRole.valueOfRoleName(principalName);
310                // role based permissions can only be set in the system folder
311                if ((role == null) || (!res.getRootPath().startsWith(CmsWorkplace.VFS_PATH_SYSTEM))) {
312                    throw e;
313                }
314                acEntry = new CmsAccessControlEntry(
315                    res.getResourceId(),
316                    role.getId(),
317                    allowedPermissions,
318                    deniedPermissions,
319                    flags);
320                acEntry.setFlags(CmsAccessControlEntry.ACCESS_FLAGS_ROLE);
321            } else {
322                throw e;
323            }
324        }
325
326        m_securityManager.writeAccessControlEntry(m_context, res, acEntry);
327    }
328
329    /**
330     * Changes the access control for a given resource and a given principal(user/group).<p>
331     * 
332     * @param resourceName name of the resource
333     * @param principalType the type of the principal (group or user):
334     *      <ul>
335     *          <li><code>{@link I_CmsPrincipal#PRINCIPAL_USER}</code></li>
336     *          <li><code>{@link I_CmsPrincipal#PRINCIPAL_GROUP}</code></li>
337     *      </ul>
338     * @param principalName name of the principal
339     * @param permissionString the permissions in the format ((+|-)(r|w|v|c|i|o))*
340     * 
341     * @throws CmsException if something goes wrong
342     */
343    public void chacc(String resourceName, String principalType, String principalName, String permissionString)
344    throws CmsException {
345
346        CmsResource res = readResource(resourceName, CmsResourceFilter.ALL);
347
348        CmsAccessControlEntry acEntry = null;
349        try {
350            I_CmsPrincipal principal = CmsPrincipal.readPrincipal(this, principalType, principalName);
351            acEntry = new CmsAccessControlEntry(res.getResourceId(), principal.getId(), permissionString);
352            acEntry.setFlagsForPrincipal(principal);
353        } catch (CmsDbEntryNotFoundException e) {
354            // check for special ids
355            if (principalName.equalsIgnoreCase(CmsAccessControlEntry.PRINCIPAL_ALL_OTHERS_NAME)) {
356                acEntry = new CmsAccessControlEntry(
357                    res.getResourceId(),
358                    CmsAccessControlEntry.PRINCIPAL_ALL_OTHERS_ID,
359                    permissionString);
360                acEntry.setFlags(CmsAccessControlEntry.ACCESS_FLAGS_ALLOTHERS);
361            } else if (principalName.equalsIgnoreCase(CmsAccessControlEntry.PRINCIPAL_OVERWRITE_ALL_NAME)) {
362                acEntry = new CmsAccessControlEntry(
363                    res.getResourceId(),
364                    CmsAccessControlEntry.PRINCIPAL_OVERWRITE_ALL_ID,
365                    permissionString);
366                acEntry.setFlags(CmsAccessControlEntry.ACCESS_FLAGS_OVERWRITE_ALL);
367            } else if (principalType.equalsIgnoreCase(CmsRole.PRINCIPAL_ROLE)) {
368                // only vfs managers can set role based permissions
369                m_securityManager.checkRoleForResource(m_context, CmsRole.VFS_MANAGER, res);
370                // check for role
371                CmsRole role = CmsRole.valueOfRoleName(principalName);
372                // role based permissions can only be set in the system folder
373                if ((role == null)
374                    || (!res.getRootPath().startsWith(CmsWorkplace.VFS_PATH_SYSTEM) && !res.getRootPath().equals("/") && !res.getRootPath().equals(
375                        "/system"))) {
376                    throw e;
377                }
378                acEntry = new CmsAccessControlEntry(res.getResourceId(), role.getId(), permissionString);
379                acEntry.setFlags(CmsAccessControlEntry.ACCESS_FLAGS_ROLE);
380            } else {
381                throw e;
382            }
383        }
384
385        m_securityManager.writeAccessControlEntry(m_context, res, acEntry);
386    }
387
388    /**
389     * Changes the lock of a resource to the current user,
390     * that is "steals" the lock from another user.<p>
391     * 
392     * This is the "steal lock" operation.<p>
393     * 
394     * @param resource the resource to change the lock
395     * 
396     * @throws CmsException if something goes wrong
397     */
398    public void changeLock(CmsResource resource) throws CmsException {
399
400        getResourceType(resource).changeLock(this, m_securityManager, resource);
401    }
402
403    /**
404     * Changes the lock of a resource to the current user,
405     * that is "steals" the lock from another user.<p>
406     * 
407     * This is the "steal lock" operation.<p>
408     * 
409     * @param resourcename the name of the resource to change the lock with complete path
410     * 
411     * @throws CmsException if something goes wrong
412     */
413    public void changeLock(String resourcename) throws CmsException {
414
415        CmsResource resource = readResource(resourcename, CmsResourceFilter.ALL);
416        changeLock(resource);
417    }
418
419    /**
420     * Returns a list with all sub resources of a given folder that have set the given property, 
421     * matching the current property's value with the given old value and replacing it by a given new value.<p>
422     *
423     * @param resourcename the name of the resource to change the property value
424     * @param property the name of the property to change the value
425     * @param oldValue the old value of the property, can be a regular expression
426     * @param newValue the new value of the property
427     * @param recursive if true, change recursively all property values on sub-resources (only for folders)
428     *
429     * @return a list with the <code>{@link CmsResource}</code>'s where the property value has been changed
430     *
431     * @throws CmsException if operation was not successful
432     */
433    public List<CmsResource> changeResourcesInFolderWithProperty(
434        String resourcename,
435        String property,
436        String oldValue,
437        String newValue,
438        boolean recursive) throws CmsException {
439
440        CmsResource resource = readResource(resourcename, CmsResourceFilter.IGNORE_EXPIRATION);
441        return m_securityManager.changeResourcesInFolderWithProperty(
442            m_context,
443            resource,
444            property,
445            oldValue,
446            newValue,
447            recursive);
448    }
449
450    /**
451     * Changes the resource flags of a resource.<p>
452     * 
453     * The resource flags are used to indicate various "special" conditions
454     * for a resource. Most notably, the "internal only" setting which signals 
455     * that a resource can not be directly requested with it's URL.<p>
456     *
457     * @param resourcename the name of the resource to change the flags for (full current site relative path)
458     * @param flags the new flags for this resource
459     *
460     * @throws CmsException if something goes wrong
461     */
462    public void chflags(String resourcename, int flags) throws CmsException {
463
464        CmsResource resource = readResource(resourcename, CmsResourceFilter.IGNORE_EXPIRATION);
465        getResourceType(resource).chflags(this, m_securityManager, resource, flags);
466    }
467
468    /**
469     * Changes the resource type of a resource.<p>
470     * 
471     * OpenCms handles resources according to the resource type,
472     * not the file suffix. This is e.g. why a JSP in OpenCms can have the 
473     * suffix ".html" instead of ".jsp" only. Changing the resource type
474     * makes sense e.g. if you want to make a plain text file a JSP resource,
475     * or a binary file an image, etc.<p> 
476     *
477     * @param resourcename the name of the resource to change the type for (full current site relative path)
478     * @param type the new resource type for this resource
479     *
480     * @throws CmsException if something goes wrong
481     */
482    public void chtype(String resourcename, int type) throws CmsException {
483
484        CmsResource resource = readResource(resourcename, CmsResourceFilter.IGNORE_EXPIRATION);
485        getResourceType(resource).chtype(this, m_securityManager, resource, type);
486    }
487
488    /**
489     * Copies a resource.<p>
490     * 
491     * The copied resource will always be locked to the current user
492     * after the copy operation.<p>
493     * 
494     * Siblings will be treated according to the
495     * <code>{@link org.opencms.file.CmsResource#COPY_PRESERVE_SIBLING}</code> mode.<p>
496     * 
497     * @param source the name of the resource to copy (full current site relative path)
498     * @param destination the name of the copy destination (full current site relative path)
499     * 
500     * @throws CmsException if something goes wrong
501     * @throws CmsIllegalArgumentException if the <code>destination</code> argument is null or of length 0
502     * 
503     * @see #copyResource(String, String, CmsResource.CmsResourceCopyMode)
504     */
505    public void copyResource(String source, String destination) throws CmsException, CmsIllegalArgumentException {
506
507        copyResource(source, destination, CmsResource.COPY_PRESERVE_SIBLING);
508    }
509
510    /**
511     * Copies a resource.<p>
512     * 
513     * The copied resource will always be locked to the current user
514     * after the copy operation.<p>
515     * 
516     * The <code>siblingMode</code> parameter controls how to handle siblings 
517     * during the copy operation.<br>
518     * Possible values for this parameter are: <br>
519     * <ul>
520     * <li><code>{@link CmsResource#COPY_AS_NEW}</code></li>
521     * <li><code>{@link CmsResource#COPY_AS_SIBLING}</code></li>
522     * <li><code>{@link CmsResource#COPY_PRESERVE_SIBLING}</code></li>
523     * </ul><p>
524     * 
525     * @param source the name of the resource to copy (full current site relative path)
526     * @param destination the name of the copy destination (full current site relative path)
527     * @param siblingMode indicates how to handle siblings during copy
528     * 
529     * @throws CmsException if something goes wrong
530     * @throws CmsIllegalArgumentException if the <code>destination</code> argument is null or of length 0
531     */
532    public void copyResource(String source, String destination, CmsResource.CmsResourceCopyMode siblingMode)
533    throws CmsException, CmsIllegalArgumentException {
534
535        CmsResource resource = readResource(source, CmsResourceFilter.IGNORE_EXPIRATION);
536        getResourceType(resource).copyResource(this, m_securityManager, resource, destination, siblingMode);
537    }
538
539    /**
540     * Copies a resource to the current project of the user.<p>
541     * 
542     * This is used to extend the current users project with the
543     * specified resource, in case that the resource is not yet part of the project.
544     * The resource is not really copied like in a regular copy operation, 
545     * it is in fact only "enabled" in the current users project.<p>   
546     * 
547     * @param resource the resource to copy to the current project
548     * 
549     * @throws CmsException if something goes wrong
550     */
551    public void copyResourceToProject(CmsResource resource) throws CmsException {
552
553        getResourceType(resource).copyResourceToProject(this, m_securityManager, resource);
554    }
555
556    /**
557     * Copies a resource to the current project of the user.<p>
558     * 
559     * This is used to extend the current users project with the
560     * specified resource, in case that the resource is not yet part of the project.
561     * The resource is not really copied like in a regular copy operation, 
562     * it is in fact only "enabled" in the current users project.<p>   
563     * 
564     * @param resourcename the name of the resource to copy to the current project (full current site relative path)
565     * 
566     * @throws CmsException if something goes wrong
567     */
568    public void copyResourceToProject(String resourcename) throws CmsException {
569
570        CmsResource resource = readResource(resourcename, CmsResourceFilter.ALL);
571        copyResourceToProject(resource);
572    }
573
574    /**
575     * Counts the locked resources in a project.<p>
576     *
577     * @param id the id of the project
578     * 
579     * @return the number of locked resources in this project
580     *
581     * @throws CmsException if operation was not successful
582     */
583    public int countLockedResources(CmsUUID id) throws CmsException {
584
585        return m_securityManager.countLockedResources(m_context, id);
586    }
587
588    /**
589     * Copies access control entries of a given resource to another resource.<p>
590     * 
591     * Already existing access control entries of the destination resource are removed.<p>
592     * 
593     * @param sourceName the name of the resource of which the access control entries are copied
594     * @param destName the name of the resource to which the access control entries are applied
595     * 
596     * @throws CmsException if something goes wrong
597     */
598    public void cpacc(String sourceName, String destName) throws CmsException {
599
600        CmsResource source = readResource(sourceName);
601        CmsResource dest = readResource(destName);
602        m_securityManager.copyAccessControlEntries(m_context, source, dest);
603    }
604
605    /**
606     * Creates a new user group.<p>
607     * 
608     * @param groupFqn the name of the new group
609     * @param description the description of the new group
610     * @param flags the flags for the new group
611     * @param parent the parent group (or <code>null</code>)
612     *
613     * @return a <code>{@link CmsGroup}</code> object representing the newly created group
614     *
615     * @throws CmsException if operation was not successful
616     */
617    public CmsGroup createGroup(String groupFqn, String description, int flags, String parent) throws CmsException {
618
619        return m_securityManager.createGroup(m_context, groupFqn, description, flags, parent);
620    }
621
622    /**
623     * Creates a new project.<p>
624     *
625     * @param name the name of the project to create
626     * @param description the description for the new project
627     * @param groupname the name of the project user group
628     * @param managergroupname the name of the project manager group
629     * 
630     * @return the created project
631     * 
632     * @throws CmsException if something goes wrong
633     */
634    public CmsProject createProject(String name, String description, String groupname, String managergroupname)
635    throws CmsException {
636
637        return m_securityManager.createProject(
638            m_context,
639            name,
640            description,
641            groupname,
642            managergroupname,
643            CmsProject.PROJECT_TYPE_NORMAL);
644    }
645
646    /**
647     * Creates a new project.<p>
648     *
649     * @param name the name of the project to create
650     * @param description the description for the new project
651     * @param groupname the name of the project user group
652     * @param managergroupname the name of the project manager group
653     * @param projecttype the type of the project (normal or temporary)
654     * 
655     * @return the created project
656     * 
657     * @throws CmsException if operation was not successful
658     */
659    public CmsProject createProject(
660        String name,
661        String description,
662        String groupname,
663        String managergroupname,
664        CmsProject.CmsProjectType projecttype) throws CmsException {
665
666        return m_securityManager.createProject(m_context, name, description, groupname, managergroupname, projecttype);
667    }
668
669    /**
670     * Creates a property definition.<p>
671     *
672     * Property definitions are valid for all resource types.<p>
673     * 
674     * @param name the name of the property definition to create
675     * 
676     * @return the created property definition
677     * 
678     * @throws CmsException if something goes wrong
679     */
680    public CmsPropertyDefinition createPropertyDefinition(String name) throws CmsException {
681
682        return (m_securityManager.createPropertyDefinition(m_context, name));
683    }
684
685    /**
686     * Creates a resource with the given properties and content.
687     * Will throw an exception, if a resource with the given name already exists.<p>
688     *
689     * @param sitePath the site path for the resource
690     * @param resource the resource object to be imported
691     * @param content the content of the resource
692     * @param properties the properties of the resource
693     * 
694     * @return the imported resource
695     * 
696     * @throws CmsException if something goes wrong
697     */
698    public CmsResource createResource(
699        String sitePath,
700        CmsResource resource,
701        byte[] content,
702        List<CmsProperty> properties) throws CmsException {
703
704        resource.setUserLastModified(getRequestContext().getCurrentUser().getId());
705        resource.setDateLastModified(System.currentTimeMillis());
706        // ensure resource record is updated
707        resource.setState(CmsResource.STATE_NEW);
708        return m_securityManager.createResource(
709            m_context,
710            m_context.addSiteRoot(sitePath),
711            resource,
712            content,
713            properties);
714    }
715
716    /**
717     * Creates a new resource of the given resource type with 
718     * empty content and no properties.<p>
719     * 
720     * @param resourcename the name of the resource to create (full current site relative path)
721     * @param type the type of the resource to create
722     * 
723     * @return the created resource
724     * 
725     * @throws CmsException if something goes wrong
726     * @throws CmsIllegalArgumentException if the given <code>resourcename</code> is null or of length 0
727     * 
728     * @see #createResource(String, int, byte[], List)
729     */
730    public CmsResource createResource(String resourcename, int type) throws CmsException, CmsIllegalArgumentException {
731
732        return createResource(resourcename, type, new byte[0], new ArrayList<CmsProperty>(0));
733    }
734
735    /**
736     * Creates a new resource of the given resource type
737     * with the provided content and properties.<p>
738     * 
739     * @param resourcename the name of the resource to create (full current site relative path)
740     * @param type the type of the resource to create
741     * @param content the contents for the new resource
742     * @param properties the properties for the new resource
743     * 
744     * @return the created resource
745     * 
746     * @throws CmsException if something goes wrong
747     * @throws CmsIllegalArgumentException if the <code>resourcename</code> argument is null or of length 0
748     */
749    public CmsResource createResource(String resourcename, int type, byte[] content, List<CmsProperty> properties)
750    throws CmsException, CmsIllegalArgumentException {
751
752        return getResourceType(type).createResource(this, m_securityManager, resourcename, content, properties);
753    }
754
755    /**
756     * Creates a new sibling of the source resource.<p>
757     * 
758     * @param source the name of the resource to create a sibling for with complete path
759     * @param destination the name of the sibling to create with complete path
760     * @param properties the individual properties for the new sibling
761     * 
762     * @return the new created sibling
763     * 
764     * @throws CmsException if something goes wrong
765     */
766    public CmsResource createSibling(String source, String destination, List<CmsProperty> properties)
767    throws CmsException {
768
769        CmsResource resource = readResource(source, CmsResourceFilter.IGNORE_EXPIRATION);
770        return getResourceType(resource).createSibling(this, m_securityManager, resource, destination, properties);
771    }
772
773    /**
774     * Creates the project for the temporary workplace files.<p>
775     *
776     * @return the created project for the temporary workplace files
777     * 
778     * @throws CmsException if something goes wrong
779     */
780    public CmsProject createTempfileProject() throws CmsException {
781
782        return m_securityManager.createTempfileProject(m_context);
783    }
784
785    /**
786     * Creates a new user.<p>
787     * 
788     * @param userFqn the name for the new user
789     * @param password the password for the new user
790     * @param description the description for the new user
791     * @param additionalInfos the additional infos for the user
792     *
793     * @return the created user
794     * 
795     * @throws CmsException if something goes wrong
796     */
797    public CmsUser createUser(String userFqn, String password, String description, Map<String, Object> additionalInfos)
798    throws CmsException {
799
800        return m_securityManager.createUser(m_context, userFqn, password, description, additionalInfos);
801    }
802
803    /**
804     * Deletes all published resource entries.<p>
805     * 
806     * @param linkType the type of resource deleted (0= non-parameter, 1=parameter)
807     * 
808     * @throws CmsException if something goes wrong
809     */
810    public void deleteAllStaticExportPublishedResources(int linkType) throws CmsException {
811
812        m_securityManager.deleteAllStaticExportPublishedResources(m_context, linkType);
813    }
814
815    /**
816     * Deletes a group, where all permissions, users and children of the group
817     * are transfered to a replacement group.<p>
818     * 
819     * @param groupId the id of the group to be deleted
820     * @param replacementId the id of the group to be transfered, can be <code>null</code>
821     *
822     * @throws CmsException if operation was not successful
823     */
824    public void deleteGroup(CmsUUID groupId, CmsUUID replacementId) throws CmsException {
825
826        m_securityManager.deleteGroup(m_context, groupId, replacementId);
827    }
828
829    /**
830     * Deletes a user group.<p>
831     *
832     * Only groups that contain no subgroups can be deleted.<p>
833     * 
834     * @param group the name of the group
835     * 
836     * @throws CmsException if operation was not successful
837     */
838    public void deleteGroup(String group) throws CmsException {
839
840        m_securityManager.deleteGroup(m_context, group);
841    }
842
843    /**
844     * Deletes the versions from the history tables, keeping the given number of versions per resource.<p>
845     * 
846     * @param versionsToKeep number of versions to keep, is ignored if negative 
847     * @param versionsDeleted number of versions to keep for deleted resources, is ignored if negative
848     * @param timeDeleted deleted resources older than this will also be deleted, is ignored if negative
849     * @param report the report for output logging
850     * 
851     * @throws CmsException if operation was not successful
852     */
853    public void deleteHistoricalVersions(int versionsToKeep, int versionsDeleted, long timeDeleted, I_CmsReport report)
854    throws CmsException {
855
856        m_securityManager.deleteHistoricalVersions(m_context, versionsToKeep, versionsDeleted, timeDeleted, report);
857    }
858
859    /**
860     * Deletes the log entries matching the given filter.<p>
861     *
862     * @param filter the filter to use for deleting the log entries
863     *
864     * @throws CmsException if something goes wrong
865     * 
866     * @see CmsSecurityManager#deleteLogEntries(CmsRequestContext, CmsLogFilter)
867     * @see #getLogEntries(CmsLogFilter)
868     */
869    public void deleteLogEntries(CmsLogFilter filter) throws CmsException {
870
871        m_securityManager.deleteLogEntries(m_context, filter);
872    }
873
874    /**
875     * Deletes a project.<p>
876     *
877     * All resources inside the project have to be be reset to their online state.<p>
878     * 
879     * @param id the id of the project to delete
880     *
881     * @throws CmsException if operation was not successful
882     */
883    public void deleteProject(CmsUUID id) throws CmsException {
884
885        m_securityManager.deleteProject(m_context, id);
886    }
887
888    /**
889     * Deletes a property definition.<p>
890     *
891     * @param name the name of the property definition to delete
892     *
893     * @throws CmsException if something goes wrong
894     */
895    public void deletePropertyDefinition(String name) throws CmsException {
896
897        m_securityManager.deletePropertyDefinition(m_context, name);
898    }
899
900    /**
901     * Deletes the relations to a given resource.<p>
902     *
903     * @param resourceName the resource to delete the relations from
904     * @param filter the filter to use for deleting the relations
905     *
906     * @throws CmsException if something goes wrong
907     */
908    public void deleteRelationsFromResource(String resourceName, CmsRelationFilter filter) throws CmsException {
909
910        CmsResource resource = readResource(resourceName, CmsResourceFilter.ALL);
911        m_securityManager.deleteRelationsForResource(m_context, resource, filter);
912    }
913
914    /**
915     * Deletes a resource given its name.<p>
916     * 
917     * The <code>siblingMode</code> parameter controls how to handle siblings 
918     * during the delete operation.<br>
919     * Possible values for this parameter are: <br>
920     * <ul>
921     * <li><code>{@link CmsResource#DELETE_REMOVE_SIBLINGS}</code></li>
922     * <li><code>{@link CmsResource#DELETE_PRESERVE_SIBLINGS}</code></li>
923     * </ul><p>
924     * 
925     * @param resourcename the name of the resource to delete (full current site relative path)
926     * @param siblingMode indicates how to handle siblings of the deleted resource
927     *
928     * @throws CmsException if something goes wrong
929     */
930    public void deleteResource(String resourcename, CmsResource.CmsResourceDeleteMode siblingMode) throws CmsException {
931
932        // throw the exception if resource name is an empty string
933        if (CmsStringUtil.isEmptyOrWhitespaceOnly(resourcename)) {
934            throw new CmsVfsResourceNotFoundException(Messages.get().container(
935                Messages.ERR_DELETE_RESOURCE_1,
936                resourcename));
937        }
938
939        CmsResource resource = readResource(resourcename, CmsResourceFilter.IGNORE_EXPIRATION);
940        getResourceType(resource).deleteResource(this, m_securityManager, resource, siblingMode);
941    }
942
943    /**
944     * Deletes a published resource entry.<p>
945     * 
946     * @param resourceName The name of the resource to be deleted in the static export
947     * @param linkType the type of resource deleted (0= non-parameter, 1=parameter)
948     * @param linkParameter the parameters of the resource
949     * 
950     * @throws CmsException if something goes wrong
951     */
952    public void deleteStaticExportPublishedResource(String resourceName, int linkType, String linkParameter)
953    throws CmsException {
954
955        m_securityManager.deleteStaticExportPublishedResource(m_context, resourceName, linkType, linkParameter);
956    }
957
958    /**
959     * Deletes a user.<p>
960     *
961     * @param userId the id of the user to be deleted
962     *
963     * @throws CmsException if operation was not successful
964     */
965    public void deleteUser(CmsUUID userId) throws CmsException {
966
967        m_securityManager.deleteUser(m_context, userId);
968    }
969
970    /**
971     * Deletes a user, where all permissions and resources attributes of the user
972     * were transfered to a replacement user.<p>
973     *
974     * @param userId the id of the user to be deleted
975     * @param replacementId the id of the user to be transfered, can be <code>null</code>
976     *
977     * @throws CmsException if operation was not successful
978     */
979    public void deleteUser(CmsUUID userId, CmsUUID replacementId) throws CmsException {
980
981        m_securityManager.deleteUser(m_context, userId, replacementId);
982    }
983
984    /**
985     * Deletes a user.<p>
986     * 
987     * @param username the name of the user to be deleted
988     *
989     * @throws CmsException if operation was not successful
990     */
991    public void deleteUser(String username) throws CmsException {
992
993        m_securityManager.deleteUser(m_context, username);
994    }
995
996    /**
997     * Checks the availability of a resource in the VFS,
998     * using the <code>{@link CmsResourceFilter#DEFAULT}</code> filter.<p> 
999     *
1000     * A resource may be of type <code>{@link CmsFile}</code> or 
1001     * <code>{@link CmsFolder}</code>.<p>
1002     * 
1003     * This method also takes into account the user permissions, so if 
1004     * the given resource exists, but the current user has not the required 
1005     * permissions, then this method will return <code>false</code>.<p>
1006     *
1007     * @param structureId the structure id of the resource to check
1008     *
1009     * @return <code>true</code> if the resource is available
1010     *
1011     * @see #readResource(CmsUUID)
1012     * @see #existsResource(CmsUUID, CmsResourceFilter)
1013     */
1014    public boolean existsResource(CmsUUID structureId) {
1015
1016        return existsResource(structureId, CmsResourceFilter.DEFAULT);
1017    }
1018
1019    /**
1020     * Checks the availability of a resource in the VFS,
1021     * using the <code>{@link CmsResourceFilter#DEFAULT}</code> filter.<p> 
1022     *
1023     * A resource may be of type <code>{@link CmsFile}</code> or 
1024     * <code>{@link CmsFolder}</code>.<p>  
1025     *
1026     * The specified filter controls what kind of resources should be "found" 
1027     * during the read operation. This will depend on the application. For example, 
1028     * using <code>{@link CmsResourceFilter#DEFAULT}</code> will only return currently
1029     * "valid" resources, while using <code>{@link CmsResourceFilter#IGNORE_EXPIRATION}</code>
1030     * will ignore the date release / date expired information of the resource.<p>
1031     * 
1032     * This method also takes into account the user permissions, so if 
1033     * the given resource exists, but the current user has not the required 
1034     * permissions, then this method will return <code>false</code>.<p>
1035     *
1036     * @param structureId the structure id of the resource to check
1037     * @param filter the resource filter to use while checking
1038     *
1039     * @return <code>true</code> if the resource is available
1040     * 
1041     * @see #readResource(CmsUUID)
1042     * @see #readResource(CmsUUID, CmsResourceFilter)
1043     */
1044    public boolean existsResource(CmsUUID structureId, CmsResourceFilter filter) {
1045
1046        return m_securityManager.existsResource(m_context, structureId, filter);
1047    }
1048
1049    /**
1050     * Checks the availability of a resource in the VFS,
1051     * using the <code>{@link CmsResourceFilter#DEFAULT}</code> filter.<p> 
1052     *
1053     * A resource may be of type <code>{@link CmsFile}</code> or 
1054     * <code>{@link CmsFolder}</code>.<p>
1055     * 
1056     * This method also takes into account the user permissions, so if 
1057     * the given resource exists, but the current user has not the required 
1058     * permissions, then this method will return <code>false</code>.<p>
1059     *
1060     * @param resourcename the name of the resource to check (full current site relative path)
1061     *
1062     * @return <code>true</code> if the resource is available
1063     *
1064     * @see #readResource(String)
1065     * @see #existsResource(String, CmsResourceFilter)
1066     */
1067    public boolean existsResource(String resourcename) {
1068
1069        return existsResource(resourcename, CmsResourceFilter.DEFAULT);
1070    }
1071
1072    /**
1073     * Checks the availability of a resource in the VFS,
1074     * using the provided filter.<p> 
1075     *
1076     * A resource may be of type <code>{@link CmsFile}</code> or 
1077     * <code>{@link CmsFolder}</code>.<p>  
1078     *
1079     * The specified filter controls what kind of resources should be "found" 
1080     * during the read operation. This will depend on the application. For example, 
1081     * using <code>{@link CmsResourceFilter#DEFAULT}</code> will only return currently
1082     * "valid" resources, while using <code>{@link CmsResourceFilter#IGNORE_EXPIRATION}</code>
1083     * will ignore the date release / date expired information of the resource.<p>
1084     * 
1085     * This method also takes into account the user permissions, so if 
1086     * the given resource exists, but the current user has not the required 
1087     * permissions, then this method will return <code>false</code>.<p>
1088     *
1089     * @param resourcename the name of the resource to check (full current site relative path)
1090     * @param filter the resource filter to use while checking
1091     *
1092     * @return <code>true</code> if the resource is available
1093     * 
1094     * @see #readResource(String)
1095     * @see #readResource(String, CmsResourceFilter)
1096     */
1097    public boolean existsResource(String resourcename, CmsResourceFilter filter) {
1098
1099        return m_securityManager.existsResource(m_context, addSiteRoot(resourcename), filter);
1100    }
1101
1102    /**
1103     * Returns the list of access control entries of a resource given its name.<p>
1104     * 
1105     * @param resourceName the name of the resource
1106     * 
1107     * @return a list of <code>{@link CmsAccessControlEntry}</code> objects
1108     * 
1109     * @throws CmsException if something goes wrong
1110     */
1111    public List<CmsAccessControlEntry> getAccessControlEntries(String resourceName) throws CmsException {
1112
1113        return getAccessControlEntries(resourceName, true);
1114    }
1115
1116    /**
1117     * Returns the list of access control entries of a resource given its name.<p>
1118     * 
1119     * @param resourceName the name of the resource
1120     * @param getInherited <code>true</code>, if inherited access control entries should be returned, too
1121     * 
1122     * @return a list of <code>{@link CmsAccessControlEntry}</code> objects defining all permissions for the given resource
1123     * 
1124     * @throws CmsException if something goes wrong
1125     */
1126    public List<CmsAccessControlEntry> getAccessControlEntries(String resourceName, boolean getInherited)
1127    throws CmsException {
1128
1129        CmsResource res = readResource(resourceName, CmsResourceFilter.ALL);
1130        return m_securityManager.getAccessControlEntries(m_context, res, getInherited);
1131    }
1132
1133    /**
1134     * Returns the access control list (summarized access control entries) of a given resource.<p>
1135     * 
1136     * @param resourceName the name of the resource
1137     * 
1138     * @return the access control list of the resource
1139     * 
1140     * @throws CmsException if something goes wrong
1141     */
1142    public CmsAccessControlList getAccessControlList(String resourceName) throws CmsException {
1143
1144        return getAccessControlList(resourceName, false);
1145    }
1146
1147    /**
1148     * Returns the access control list (summarized access control entries) of a given resource.<p>
1149     * 
1150     * If <code>inheritedOnly</code> is set, only inherited access control entries are returned.<p>
1151     * 
1152     * @param resourceName the name of the resource
1153     * @param inheritedOnly if set, the non-inherited entries are skipped
1154     * 
1155     * @return the access control list of the resource
1156     * 
1157     * @throws CmsException if something goes wrong
1158     */
1159    public CmsAccessControlList getAccessControlList(String resourceName, boolean inheritedOnly) throws CmsException {
1160
1161        CmsResource res = readResource(resourceName, CmsResourceFilter.ALL);
1162        return m_securityManager.getAccessControlList(m_context, res, inheritedOnly);
1163    }
1164
1165    /**
1166     * Gets all access control entries for the current project.<p>
1167     * 
1168     * @return the list of all access control entries
1169     * 
1170     * @throws CmsException if something goes wrong 
1171     */
1172    public List<CmsAccessControlEntry> getAllAccessControlEntries() throws CmsException {
1173
1174        return m_securityManager.getAllAccessControlEntries(m_context);
1175    }
1176
1177    /**
1178     * Returns a list with all projects from history.<p>
1179     *
1180     * @return list of <code>{@link CmsHistoryProject}</code> objects 
1181     *           with all projects from history
1182     *
1183     * @throws CmsException  if operation was not successful
1184     */
1185    public List<CmsHistoryProject> getAllHistoricalProjects() throws CmsException {
1186
1187        return m_securityManager.getAllHistoricalProjects(m_context);
1188    }
1189
1190    /**
1191     * Gets all URL names for a given structure id.<p>
1192     * 
1193     * @param id the structure id 
1194     * @return the list of all URL names for that structure id 
1195     * 
1196     * @throws CmsException if something goes wrong 
1197     */
1198    public List<String> getAllUrlNames(CmsUUID id) throws CmsException {
1199
1200        return m_securityManager.readAllUrlNameMappingEntries(m_context, id);
1201    }
1202
1203    /**
1204     * Returns a list of child resources to the given resource that can not be locked by the current user.<p>
1205     * 
1206     * @param resource the resource
1207     * 
1208     * @return a list of child resources to the given resource that can not be locked by the current user
1209     * 
1210     * @throws CmsException if something goes wrong reading the resources
1211     */
1212    public List<CmsResource> getBlockingLockedResources(CmsResource resource) throws CmsException {
1213
1214        if (resource.isFolder()) {
1215            CmsLockFilter blockingFilter = CmsLockFilter.FILTER_ALL;
1216            blockingFilter = blockingFilter.filterNotLockableByUser(getRequestContext().getCurrentUser());
1217            return getLockedResources(resource, blockingFilter);
1218        }
1219        return Collections.<CmsResource> emptyList();
1220    }
1221
1222    /**
1223     * Returns a list of child resources to the given resource that can not be locked by the current user.<p>
1224     * 
1225     * @param resourceName the resource site path
1226     * 
1227     * @return a list of child resources to the given resource that can not be locked by the current user
1228     * 
1229     * @throws CmsException if something goes wrong reading the resources
1230     */
1231    public List<CmsResource> getBlockingLockedResources(String resourceName) throws CmsException {
1232
1233        CmsResource resource = readResource(resourceName);
1234        return getBlockingLockedResources(resource);
1235    }
1236
1237    /**
1238     * Returns all child groups of a group.<p>
1239     * 
1240     * @param groupname the name of the group
1241     * @param includeSubChildren if set also returns all sub-child groups of the given group
1242     *
1243     * @return a list of all child <code>{@link CmsGroup}</code> objects or <code>null</code>
1244     * 
1245     * @throws CmsException if operation was not successful
1246     */
1247    public List<CmsGroup> getChildren(String groupname, boolean includeSubChildren) throws CmsException {
1248
1249        return m_securityManager.getChildren(m_context, groupname, includeSubChildren);
1250    }
1251
1252    /**
1253     * Returns the detail name of a resource.<p>
1254     * 
1255     * The detail view URI of a content element consists of its detail page URI and the detail name returned by this 
1256     * method.<p>
1257     * 
1258     * @param res the resource for which the detail name should be retrieved
1259     * @param locale the locale for the detail name 
1260     * @param defaultLocales the default locales for the detail name 
1261     *   
1262     * @return the detail name 
1263     * @throws CmsException if something goes wrong 
1264     */
1265    public String getDetailName(CmsResource res, Locale locale, List<Locale> defaultLocales) throws CmsException {
1266
1267        String urlName = readBestUrlName(res.getStructureId(), locale, defaultLocales);
1268        if (urlName == null) {
1269            urlName = res.getStructureId().toString();
1270        }
1271        return urlName;
1272    }
1273
1274    /**
1275     * Returns all file resources contained in a folder.<p>
1276     * 
1277     * The result is filtered according to the rules of 
1278     * the <code>{@link CmsResourceFilter#DEFAULT}</code> filter.<p>
1279     * 
1280     * @param resourcename the full current site relative path of the resource to return the child resources for
1281     * 
1282     * @return a list of all child files as <code>{@link CmsResource}</code> objects
1283     * 
1284     * @throws CmsException if something goes wrong
1285     * 
1286     * @see #getFilesInFolder(String, CmsResourceFilter)
1287     */
1288    public List<CmsResource> getFilesInFolder(String resourcename) throws CmsException {
1289
1290        return getFilesInFolder(resourcename, CmsResourceFilter.DEFAULT);
1291    }
1292
1293    /**
1294     * Returns all file resources contained in a folder.<p>
1295     * 
1296     * With the <code>{@link CmsResourceFilter}</code> provided as parameter
1297     * you can control if you want to include deleted, invisible or 
1298     * time-invalid resources in the result.<p>
1299     * 
1300     * @param resourcename the full path of the resource to return the child resources for
1301     * @param filter the resource filter to use
1302     * 
1303     * @return a list of all child file as <code>{@link CmsResource}</code> objects
1304     * 
1305     * @throws CmsException if something goes wrong
1306     */
1307    public List<CmsResource> getFilesInFolder(String resourcename, CmsResourceFilter filter) throws CmsException {
1308
1309        CmsResource resource = readResource(resourcename, CmsResourceFilter.ALL);
1310        return m_securityManager.readChildResources(m_context, resource, filter, false, true);
1311    }
1312
1313    /**
1314     * Returns all the groups the given user belongs to.<p>
1315     *
1316     * @param username the name of the user
1317     * @param directGroupsOnly if set only the direct assigned groups will be returned, if not also indirect roles
1318     * 
1319     * @return a list of <code>{@link CmsGroup}</code> objects
1320     * 
1321     * @throws CmsException if operation was not successful
1322     */
1323    public List<CmsGroup> getGroupsOfUser(String username, boolean directGroupsOnly) throws CmsException {
1324
1325        return getGroupsOfUser(username, directGroupsOnly, true);
1326    }
1327
1328    /**
1329     * Returns all the groups the given user belongs to.<p>
1330     *
1331     * @param username the name of the user
1332     * @param directGroupsOnly if set only the direct assigned groups will be returned, if not also indirect roles
1333     * @param includeOtherOus if to include groups of other organizational units
1334     * 
1335     * @return a list of <code>{@link CmsGroup}</code> objects
1336     * 
1337     * @throws CmsException if operation was not successful
1338     */
1339    public List<CmsGroup> getGroupsOfUser(String username, boolean directGroupsOnly, boolean includeOtherOus)
1340    throws CmsException {
1341
1342        return getGroupsOfUser(username, directGroupsOnly, includeOtherOus, m_context.getRemoteAddress());
1343    }
1344
1345    /**
1346     * Returns the groups of a user filtered by the specified IP address.<p>
1347     *
1348     * @param username the name of the user
1349     * @param directGroupsOnly if set only the direct assigned groups will be returned, if not also indirect roles
1350     * @param remoteAddress the IP address to filter the groups in the result list
1351     * @param includeOtherOus if to include groups of other organizational units
1352     * 
1353     * @return a list of <code>{@link CmsGroup}</code> objects filtered by the specified IP address
1354     * 
1355     * @throws CmsException if operation was not successful
1356     */
1357    public List<CmsGroup> getGroupsOfUser(
1358        String username,
1359        boolean directGroupsOnly,
1360        boolean includeOtherOus,
1361        String remoteAddress) throws CmsException {
1362
1363        return m_securityManager.getGroupsOfUser(
1364            m_context,
1365            username,
1366            (includeOtherOus ? "" : CmsOrganizationalUnit.getParentFqn(username)),
1367            includeOtherOus,
1368            false,
1369            directGroupsOnly,
1370            remoteAddress);
1371    }
1372
1373    /**
1374     * Returns the edition lock state for a specified resource.<p>
1375     * 
1376     * If the resource is waiting to be publish you might get a lock of type {@link CmsLockType#PUBLISH}.<p>
1377     * 
1378     * @param resource the resource to return the edition lock state for
1379     * 
1380     * @return the edition lock state for the specified resource
1381     * 
1382     * @throws CmsException if something goes wrong
1383     */
1384    public CmsLock getLock(CmsResource resource) throws CmsException {
1385
1386        return m_securityManager.getLock(m_context, resource);
1387    }
1388
1389    /**
1390     * Returns the lock state for a specified resource name.<p>
1391     * 
1392     * If the resource is waiting to be publish you might get a lock of type {@link CmsLockType#PUBLISH}.<p>
1393     * 
1394     * @param resourcename the name if the resource to get the lock state for (full current site relative path)
1395     * 
1396     * @return the lock state for the specified resource
1397     * 
1398     * @throws CmsException if something goes wrong
1399     */
1400    public CmsLock getLock(String resourcename) throws CmsException {
1401
1402        CmsResource resource = readResource(resourcename, CmsResourceFilter.ALL);
1403        return getLock(resource);
1404    }
1405
1406    /**
1407     * Returns all locked resources within a folder or matches the lock of the given resource.<p>
1408     *
1409     * @param resource the resource to check
1410     * @param filter the lock filter
1411     * 
1412     * @return a list of locked resources
1413     *
1414     * @throws CmsException if operation was not successful
1415     */
1416    public List<CmsResource> getLockedResources(CmsResource resource, CmsLockFilter filter) throws CmsException {
1417
1418        return m_securityManager.getLockedResourcesObjects(m_context, resource, filter);
1419    }
1420
1421    /**
1422     * Returns all locked resources within a folder or matches the lock of the given resource.<p>
1423     *
1424     * @param resourceName the name of the resource to check
1425     * @param filter the lock filter
1426     * 
1427     * @return a list of locked resource paths (relative to current site)
1428     *
1429     * @throws CmsException if operation was not successful
1430     */
1431    public List<String> getLockedResources(String resourceName, CmsLockFilter filter) throws CmsException {
1432
1433        CmsResource resource = readResource(resourceName, CmsResourceFilter.ALL);
1434        return m_securityManager.getLockedResources(m_context, resource, filter);
1435    }
1436
1437    /**
1438     * Returns all locked resources within a folder or matches the lock of the given resource, but uses a cache for resource lookup.<p>
1439     *
1440     * @param resource the resource to check
1441     * @param filter the lock filter
1442     * @param cache the cache to use for resource lookups 
1443     * 
1444     * @return a list of locked resources
1445     *
1446     * @throws CmsException if operation was not successful
1447     */
1448    public List<CmsResource> getLockedResourcesWithCache(
1449        CmsResource resource,
1450        CmsLockFilter filter,
1451        Map<String, CmsResource> cache) throws CmsException {
1452
1453        return m_securityManager.getLockedResourcesObjectsWithCache(m_context, resource, filter, cache);
1454    }
1455
1456    /**
1457     * Returns all log entries matching the given filter.<p> 
1458     * 
1459     * @param filter the filter to match the relation 
1460     * 
1461     * @return a list containing all log entries matching the given filter
1462     * 
1463     * @throws CmsException if something goes wrong
1464     * 
1465     * @see CmsSecurityManager#getLogEntries(CmsRequestContext, CmsLogFilter)
1466     * @see #deleteLogEntries(CmsLogFilter)
1467     */
1468    public List<CmsLogEntry> getLogEntries(CmsLogFilter filter) throws CmsException {
1469
1470        return m_securityManager.getLogEntries(m_context, filter);
1471    }
1472
1473    /**
1474     * Returns the name a resource would have if it were moved to the
1475     * "lost and found" folder. <p>
1476     * 
1477     * In general, it is the same name as the given resource has, the only exception is
1478     * if a resource in the "lost and found" folder with the same name already exists. 
1479     * In such case, a counter is added to the resource name.<p>
1480     * 
1481     * @param resourcename the name of the resource to get the "lost and found" name for (full current site relative path)
1482     *
1483     * @return the tentative name of the resource inside the "lost and found" folder
1484     * 
1485     * @throws CmsException if something goes wrong
1486     * 
1487     * @see #moveToLostAndFound(String)
1488     */
1489    public String getLostAndFoundName(String resourcename) throws CmsException {
1490
1491        CmsResource resource = readResource(resourcename, CmsResourceFilter.ALL);
1492        return m_securityManager.moveToLostAndFound(m_context, resource, true);
1493    }
1494
1495    /**
1496     * Returns the parent group of a group.<p>
1497     *
1498     * @param groupname the name of the group
1499     * 
1500     * @return group the parent group or <code>null</code>
1501     * 
1502     * @throws CmsException if operation was not successful
1503     */
1504    public CmsGroup getParent(String groupname) throws CmsException {
1505
1506        return m_securityManager.getParent(m_context, groupname);
1507    }
1508
1509    /**
1510     * Returns the set of permissions of the current user for a given resource.<p>
1511     * 
1512     * @param resourceName the name of the resource
1513     * 
1514     * @return the bit set of the permissions of the current user
1515     * 
1516     * @throws CmsException if something goes wrong
1517     */
1518    public CmsPermissionSet getPermissions(String resourceName) throws CmsException {
1519
1520        return getPermissions(resourceName, m_context.getCurrentUser().getName());
1521    }
1522
1523    /**
1524     * Returns the set of permissions of a given user for a given resource.<p>
1525     * 
1526     * @param resourceName the name of the resource
1527     * @param userName the name of the user
1528     * 
1529     * @return the current permissions on this resource
1530     * 
1531     * @throws CmsException if something goes wrong
1532     */
1533    public CmsPermissionSet getPermissions(String resourceName, String userName) throws CmsException {
1534
1535        // reading permissions is allowed even if the resource is marked as deleted
1536        CmsResource resource = readResource(resourceName, CmsResourceFilter.ALL);
1537        CmsUser user = readUser(userName);
1538        return m_securityManager.getPermissions(m_context, resource, user);
1539    }
1540
1541    /**
1542     * Returns all relations for the given resource matching the given filter.<p> 
1543     * 
1544     * You should have view/read permissions on the given resource.<p>
1545     * 
1546     * You may become source and/or target paths to resource you do not have view/read permissions on.<p> 
1547     * 
1548     * @param resource the resource to retrieve the relations for
1549     * @param filter the filter to match the relation 
1550     * 
1551     * @return a List containing all {@link org.opencms.relations.CmsRelation} 
1552     *          objects for the given resource matching the given filter
1553     * 
1554     * @throws CmsException if something goes wrong
1555     * 
1556     * @see CmsSecurityManager#getRelationsForResource(CmsRequestContext, CmsResource, CmsRelationFilter)
1557     */
1558    public List<CmsRelation> getRelationsForResource(CmsResource resource, CmsRelationFilter filter)
1559    throws CmsException {
1560
1561        return m_securityManager.getRelationsForResource(m_context, resource, filter);
1562    }
1563
1564    /**
1565     * Returns all relations for the given resource matching the given filter.<p> 
1566     * 
1567     * You should have view/read permissions on the given resource.<p>
1568     * 
1569     * You may become source and/or target paths to resource you do not have view/read permissions on.<p> 
1570     * 
1571     * @param resourceName the name of the resource to retrieve the relations for
1572     * @param filter the filter to match the relation 
1573     * 
1574     * @return a List containing all {@link org.opencms.relations.CmsRelation} 
1575     *          objects for the given resource matching the given filter
1576     * 
1577     * @throws CmsException if something goes wrong
1578     * 
1579     * @see CmsSecurityManager#getRelationsForResource(CmsRequestContext, CmsResource, CmsRelationFilter)
1580     */
1581    public List<CmsRelation> getRelationsForResource(String resourceName, CmsRelationFilter filter) throws CmsException {
1582
1583        return getRelationsForResource(readResource(resourceName, CmsResourceFilter.ALL), filter);
1584    }
1585
1586    /**
1587     * Returns the current users request context.<p>
1588     *
1589     * This request context is used to authenticate the user for all 
1590     * OpenCms operations. It also contains the request runtime settings, e.g.
1591     * about the current site this request was made on.<p>
1592     *
1593     * @return the current users request context
1594     */
1595    public CmsRequestContext getRequestContext() {
1596
1597        return m_context;
1598    }
1599
1600    /**
1601     * Returns all resources associated to a given principal via an ACE with the given permissions.<p> 
1602     * 
1603     * If the <code>includeAttr</code> flag is set it returns also all resources associated to 
1604     * a given principal through some of following attributes.<p> 
1605     * 
1606     * <ul>
1607     *    <li>User Created</li>
1608     *    <li>User Last Modified</li>
1609     * </ul><p>
1610     * 
1611     * @param principalId the id of the principal
1612     * @param permissions a set of permissions to match, can be <code>null</code> for all ACEs
1613     * @param includeAttr a flag to include resources associated by attributes
1614     * 
1615     * @return a set of <code>{@link CmsResource}</code> objects
1616     * 
1617     * @throws CmsException if something goes wrong
1618     */
1619    public Set<CmsResource> getResourcesForPrincipal(
1620        CmsUUID principalId,
1621        CmsPermissionSet permissions,
1622        boolean includeAttr) throws CmsException {
1623
1624        return m_securityManager.getResourcesForPrincipal(getRequestContext(), principalId, permissions, includeAttr);
1625    }
1626
1627    /**
1628     * Returns all child resources of a resource, that is the resources
1629     * contained in a folder.<p>
1630     * 
1631     * With the <code>{@link CmsResourceFilter}</code> provided as parameter
1632     * you can control if you want to include deleted, invisible or 
1633     * time-invalid resources in the result.<p>
1634     * 
1635     * This method is mainly used by the workplace explorer.<p>
1636     * 
1637     * @param resourcename the full current site relative path of the resource to return the child resources for
1638     * @param filter the resource filter to use
1639     * 
1640     * @return a list of all child <code>{@link CmsResource}</code>s
1641     * 
1642     * @throws CmsException if something goes wrong
1643     */
1644    public List<CmsResource> getResourcesInFolder(String resourcename, CmsResourceFilter filter) throws CmsException {
1645
1646        CmsResource resource = readResource(resourcename, CmsResourceFilter.ALL);
1647        return m_securityManager.readChildResources(m_context, resource, filter, true, true);
1648    }
1649
1650    /**
1651     * Adjusts the absolute resource root path for the current site.<p> 
1652     * 
1653     * The full root path of a resource is always available using
1654     * <code>{@link CmsResource#getRootPath()}</code>. From this name this method cuts 
1655     * of the current site root using 
1656     * <code>{@link CmsRequestContext#removeSiteRoot(String)}</code>.<p>
1657     * 
1658     * If the resource root path does not start with the current site root,
1659     * it is left untouched.<p>
1660     * 
1661     * @param resource the resource to get the adjusted site root path for
1662     * 
1663     * @return the absolute resource path adjusted for the current site
1664     * 
1665     * @see CmsRequestContext#removeSiteRoot(String)
1666     * @see CmsRequestContext#getSitePath(CmsResource)
1667     * @see CmsResource#getRootPath()
1668     */
1669    public String getSitePath(CmsResource resource) {
1670
1671        return m_context.getSitePath(resource);
1672    }
1673
1674    /**
1675     * Returns all folder resources contained in a folder.<p>
1676     * 
1677     * The result is filtered according to the rules of 
1678     * the <code>{@link CmsResourceFilter#DEFAULT}</code> filter.<p>
1679     * 
1680     * @param resourcename the full current site relative path of the resource to return the child resources for. 
1681     * 
1682     * @return a list of all child file as <code>{@link CmsResource}</code> objects
1683     * 
1684     * @throws CmsException if something goes wrong
1685     * 
1686     * @see #getSubFolders(String, CmsResourceFilter)
1687     */
1688    public List<CmsResource> getSubFolders(String resourcename) throws CmsException {
1689
1690        return getSubFolders(resourcename, CmsResourceFilter.DEFAULT);
1691    }
1692
1693    /**
1694     * Returns all folder resources contained in a folder.<p>
1695     * 
1696     * With the <code>{@link CmsResourceFilter}</code> provided as parameter
1697     * you can control if you want to include deleted, invisible or 
1698     * time-invalid resources in the result.<p>
1699     * 
1700     * @param resourcename the full current site relative path of the resource to return the child resources for. 
1701     * 
1702     * @return a list of all child folder <code>{@link CmsResource}</code>s
1703     * @param filter the resource filter to use
1704     * 
1705     * @throws CmsException if something goes wrong
1706     */
1707    public List<CmsResource> getSubFolders(String resourcename, CmsResourceFilter filter) throws CmsException {
1708
1709        CmsResource resource = readResource(resourcename, CmsResourceFilter.ALL);
1710        return m_securityManager.readChildResources(m_context, resource, filter, true, false);
1711    }
1712
1713    /**
1714     * Returns the newest URL names for the given structure id for each locale.<p>
1715     * 
1716     * @param id the structure id 
1717     * @return the list of URL names for each locale 
1718     * 
1719     * @throws CmsException if something goes wrong 
1720     */
1721    public List<String> getUrlNamesForAllLocales(CmsUUID id) throws CmsException {
1722
1723        return m_securityManager.readUrlNamesForAllLocales(m_context, id);
1724    }
1725
1726    /**
1727     * Returns all direct users of a given group.<p>
1728     *
1729     * Users that are "indirectly" in the group are not returned in the result.<p>
1730     *
1731     * @param groupname the name of the group to get all users for
1732     * 
1733     * @return all <code>{@link CmsUser}</code> objects in the group
1734     *
1735     * @throws CmsException if operation was not successful
1736     */
1737    public List<CmsUser> getUsersOfGroup(String groupname) throws CmsException {
1738
1739        return getUsersOfGroup(groupname, true);
1740    }
1741
1742    /**
1743     * Returns all direct users of a given group.<p>
1744     *
1745     * Users that are "indirectly" in the group are not returned in the result.<p>
1746     *
1747     * @param groupname the name of the group to get all users for
1748     * @param includeOtherOus if the result should include users of other ous
1749     * 
1750     * @return all <code>{@link CmsUser}</code> objects in the group
1751     *
1752     * @throws CmsException if operation was not successful
1753     */
1754    public List<CmsUser> getUsersOfGroup(String groupname, boolean includeOtherOus) throws CmsException {
1755
1756        return m_securityManager.getUsersOfGroup(m_context, groupname, includeOtherOus, true, false);
1757    }
1758
1759    /**
1760     * Checks if the current user has required permissions to access a given resource.<p>
1761     * 
1762     * @param resource the resource to check the permissions for
1763     * @param requiredPermissions the set of permissions to check for
1764     * 
1765     * @return <code>true</code> if the required permissions are satisfied
1766     * 
1767     * @throws CmsException if something goes wrong
1768     */
1769    public boolean hasPermissions(CmsResource resource, CmsPermissionSet requiredPermissions) throws CmsException {
1770
1771        return m_securityManager.hasPermissions(m_context, resource, requiredPermissions, true, CmsResourceFilter.ALL).isAllowed();
1772    }
1773
1774    /**
1775     * Checks if the current user has required permissions to access a given resource.<p>
1776     * 
1777     * @param resource the resource to check the permissions for
1778     * @param requiredPermissions the set of permissions to check for
1779     * @param checkLock if <code>true</code>, a lock for the current user is required for 
1780     *      all write operations, if <code>false</code> it's ok to write as long as the resource
1781     *      is not locked by another user.
1782     * @param filter the resource filter to use
1783     * 
1784     * @return <code>true</code> if the required permissions are satisfied
1785     * 
1786     * @throws CmsException if something goes wrong
1787     */
1788    public boolean hasPermissions(
1789        CmsResource resource,
1790        CmsPermissionSet requiredPermissions,
1791        boolean checkLock,
1792        CmsResourceFilter filter) throws CmsException {
1793
1794        return I_CmsPermissionHandler.PERM_ALLOWED == m_securityManager.hasPermissions(
1795            m_context,
1796            resource,
1797            requiredPermissions,
1798            checkLock,
1799            filter);
1800    }
1801
1802    /**
1803     * Writes a list of access control entries as new access control entries of a given resource.<p>
1804     * 
1805     * Already existing access control entries of this resource are removed before.<p>
1806     * 
1807     * @param resource the resource to attach the control entries to
1808     * @param acEntries a list of <code>{@link CmsAccessControlEntry}</code> objects
1809     * 
1810     * @throws CmsException if something goes wrong
1811     */
1812    public void importAccessControlEntries(CmsResource resource, List<CmsAccessControlEntry> acEntries)
1813    throws CmsException {
1814
1815        m_securityManager.importAccessControlEntries(m_context, resource, acEntries);
1816    }
1817
1818    /**
1819     * Imports a new relation to the given resource.<p>
1820     * 
1821     * @param resourceName the name of the source resource
1822     * @param targetPath the path of the target resource
1823     * @param relationType the type of the relation
1824     * 
1825     * @throws CmsException if something goes wrong
1826     */
1827    public void importRelation(String resourceName, String targetPath, String relationType) throws CmsException {
1828
1829        createRelation(resourceName, targetPath, relationType, true);
1830    }
1831
1832    /**
1833     * Imports a resource to the OpenCms VFS.<p>
1834     * 
1835     * If a resource already exists in the VFS (i.e. has the same name and 
1836     * same id) it is replaced by the imported resource.<p>
1837     * 
1838     * If a resource with the same name but a different id exists, 
1839     * the imported resource is (usually) moved to the "lost and found" folder.<p> 
1840     *
1841     * @param resourcename the name for the resource after import (full current site relative path)
1842     * @param resource the resource object to be imported
1843     * @param content the content of the resource
1844     * @param properties the properties of the resource
1845     * 
1846     * @return the imported resource
1847     * 
1848     * @throws CmsException if something goes wrong
1849     * 
1850     * @see CmsObject#moveToLostAndFound(String)
1851     */
1852    public CmsResource importResource(
1853        String resourcename,
1854        CmsResource resource,
1855        byte[] content,
1856        List<CmsProperty> properties) throws CmsException {
1857
1858        return getResourceType(resource).importResource(
1859            this,
1860            m_securityManager,
1861            resourcename,
1862            resource,
1863            content,
1864            properties);
1865    }
1866
1867    /**
1868     * Creates a new user by import.<p>
1869     * 
1870     * @param id the id of the user
1871     * @param name the new name for the user
1872     * @param password the new password for the user
1873     * @param firstname the first name of the user
1874     * @param lastname the last name of the user
1875     * @param email the email of the user
1876     * @param flags the flags for a user (for example <code>{@link I_CmsPrincipal#FLAG_ENABLED}</code>)
1877     * @param dateCreated the creation date
1878     * @param additionalInfos the additional user infos
1879     * 
1880     * @return the imported user
1881     *
1882     * @throws CmsException if something goes wrong
1883     */
1884    public CmsUser importUser(
1885        String id,
1886        String name,
1887        String password,
1888        String firstname,
1889        String lastname,
1890        String email,
1891        int flags,
1892        long dateCreated,
1893        Map<String, Object> additionalInfos) throws CmsException {
1894
1895        return m_securityManager.importUser(
1896            m_context,
1897            id,
1898            name,
1899            password,
1900            firstname,
1901            lastname,
1902            email,
1903            flags,
1904            dateCreated,
1905            additionalInfos);
1906    }
1907
1908    /**
1909     * Increments a counter and returns its old value.<p>
1910     * 
1911     * @param name the name of the counter 
1912     *  
1913     * @return the value of the counter before incrementing 
1914     *    
1915     * @throws CmsException if something goes wrong 
1916     */
1917    public int incrementCounter(String name) throws CmsException {
1918
1919        return m_securityManager.incrementCounter(m_context, name);
1920    }
1921
1922    /**
1923     * Checks if the specified resource is inside the current project.<p>
1924     * 
1925     * The project "view" is determined by a set of path prefixes. 
1926     * If the resource starts with any one of this prefixes, it is considered to 
1927     * be "inside" the project.<p>
1928     * 
1929     * @param resourcename the specified resource name (full current site relative path)
1930     * 
1931     * @return <code>true</code>, if the specified resource is inside the current project
1932     */
1933    public boolean isInsideCurrentProject(String resourcename) {
1934
1935        return m_securityManager.isInsideCurrentProject(m_context, addSiteRoot(resourcename));
1936    }
1937
1938    /**
1939     * Checks if the current user has management access to the current project.<p>
1940     *
1941     * @return <code>true</code>, if the user has management access to the current project
1942     */
1943
1944    public boolean isManagerOfProject() {
1945
1946        return m_securityManager.isManagerOfProject(m_context);
1947    }
1948
1949    /**
1950     * Locks a resource.<p>
1951     *
1952     * This will be an exclusive, persistent lock that is removed only if the user unlocks it.<p>
1953     *
1954     * @param resource the resource to lock
1955     * 
1956     * @throws CmsException if something goes wrong
1957     */
1958    public void lockResource(CmsResource resource) throws CmsException {
1959
1960        getResourceType(resource).lockResource(this, m_securityManager, resource, CmsLockType.EXCLUSIVE);
1961    }
1962
1963    /**
1964     * Locks a resource.<p>
1965     *
1966     * This will be an exclusive, persistent lock that is removed only if the user unlocks it.<p>
1967     *
1968     * @param resourcename the name of the resource to lock (full current site relative path)
1969     * 
1970     * @throws CmsException if something goes wrong
1971     */
1972    public void lockResource(String resourcename) throws CmsException {
1973
1974        lockResource(resourcename, CmsLockType.EXCLUSIVE);
1975    }
1976
1977    /**
1978     * Locks a resource temporary.<p>
1979     *
1980     * This will be an exclusive, temporary lock valid only for the current users session.
1981     * Usually this should not be used directly, this method is intended for the OpenCms workplace only.<p>
1982     *
1983     * @param resource the resource to lock
1984     * 
1985     * @throws CmsException if something goes wrong
1986     * 
1987     * @see CmsObject#lockResource(String)
1988     */
1989    public void lockResourceTemporary(CmsResource resource) throws CmsException {
1990
1991        getResourceType(resource).lockResource(this, m_securityManager, resource, CmsLockType.TEMPORARY);
1992    }
1993
1994    /**
1995     * Locks a resource temporary.<p>
1996     *
1997     * This will be an exclusive, temporary lock valid only for the current users session.
1998     * Usually this should not be used directly, this method is intended for the OpenCms workplace only.<p>
1999     *
2000     * @param resourcename the name of the resource to lock (full current site relative path)
2001     * 
2002     * @throws CmsException if something goes wrong
2003     * 
2004     * @see CmsObject#lockResource(String)
2005     */
2006    public void lockResourceTemporary(String resourcename) throws CmsException {
2007
2008        lockResource(resourcename, CmsLockType.TEMPORARY);
2009    }
2010
2011    /**
2012     * Logs a user into the Cms, if the password is correct.<p>
2013     *
2014     * @param username the name of the user
2015     * @param password the password of the user
2016     * 
2017     * @return the name of the logged in user
2018     *
2019     * @throws CmsException if the login was not successful
2020     */
2021    public String loginUser(String username, String password) throws CmsException {
2022
2023        return loginUser(username, password, m_context.getRemoteAddress());
2024    }
2025
2026    /**
2027     * Logs a user with a given ip address into the Cms, if the password is correct.<p>
2028     *
2029     * @param username the name of the user
2030     * @param password the password of the user
2031     * @param remoteAddress the ip address
2032     * 
2033     * @return the name of the logged in user
2034     *
2035     * @throws CmsException if the login was not successful
2036     */
2037    public String loginUser(String username, String password, String remoteAddress) throws CmsException {
2038
2039        // login the user
2040        CmsUser newUser = m_securityManager.loginUser(m_context, username, password, remoteAddress);
2041        // set the project back to the "Online" project
2042        CmsProject newProject = m_securityManager.readProject(CmsProject.ONLINE_PROJECT_ID);
2043        // switch the cms context to the new user and project
2044        m_context.switchUser(newUser, newProject, newUser.getOuFqn());
2045        // init this CmsObject with the new user
2046        init(m_securityManager, m_context);
2047        // fire a login event
2048        fireEvent(I_CmsEventListener.EVENT_LOGIN_USER, newUser);
2049        // return the users login name
2050        return newUser.getName();
2051    }
2052
2053    /**
2054     * Lookups and reads the user or group with the given UUID.<p>
2055     *   
2056     * @param principalId the uuid of a user or group
2057     * 
2058     * @return the user or group with the given UUID
2059     */
2060    public I_CmsPrincipal lookupPrincipal(CmsUUID principalId) {
2061
2062        return m_securityManager.lookupPrincipal(m_context, principalId);
2063    }
2064
2065    /**
2066     * Lookups and reads the user or group with the given name.<p>
2067     * 
2068     * @param principalName the name of the user or group
2069     * 
2070     * @return the user or group with the given name
2071     */
2072    public I_CmsPrincipal lookupPrincipal(String principalName) {
2073
2074        return m_securityManager.lookupPrincipal(m_context, principalName);
2075    }
2076
2077    /**
2078     * Moves a resource to the given destination.<p>
2079     * 
2080     * A move operation in OpenCms is always a copy (as sibling) followed by a delete,
2081     * this is a result of the online/offline structure of the 
2082     * OpenCms VFS. This way you can see the deleted files/folders in the offline
2083     * project, and you will be unable to undelete them.<p>
2084     * 
2085     * @param source the name of the resource to move (full current site relative path)
2086     * @param destination the destination resource name (full current site relative path)
2087     *
2088     * @throws CmsException if something goes wrong
2089     * 
2090     * @see #renameResource(String, String)
2091     */
2092    public void moveResource(String source, String destination) throws CmsException {
2093
2094        CmsResource resource = readResource(source, CmsResourceFilter.IGNORE_EXPIRATION);
2095        getResourceType(resource).moveResource(this, m_securityManager, resource, destination);
2096    }
2097
2098    /**
2099     * Moves a resource to the "lost and found" folder.<p>
2100     * 
2101     * The "lost and found" folder is a special system folder. 
2102     * 
2103     * This operation is used e.g. during import of resources
2104     * when a resource with the same name but a different resource ID
2105     * already exists in the VFS. In this case, the imported resource is 
2106     * moved to the "lost and found" folder.<p>
2107     * 
2108     * @param resourcename the name of the resource to move to "lost and found" (full current site relative path)
2109     *
2110     * @return the name of the resource inside the "lost and found" folder
2111     * 
2112     * @throws CmsException if something goes wrong
2113     * 
2114     * @see #getLostAndFoundName(String)
2115     */
2116    public String moveToLostAndFound(String resourcename) throws CmsException {
2117
2118        CmsResource resource = readResource(resourcename, CmsResourceFilter.ALL);
2119        return m_securityManager.moveToLostAndFound(m_context, resource, false);
2120    }
2121
2122    /**
2123     * Reads all historical versions of a resource.<br>
2124     * 
2125     * The reading excludes the file content, if the resource is a file.<p>
2126     *
2127     * @param resourceName the name of the resource to be read
2128     *
2129     * @return a list of historical resources, as <code>{@link I_CmsHistoryResource}</code> objects
2130     *
2131     * @throws CmsException if operation was not successful
2132     */
2133    public List<I_CmsHistoryResource> readAllAvailableVersions(String resourceName) throws CmsException {
2134
2135        CmsResource resource = readResource(resourceName, CmsResourceFilter.ALL);
2136        return m_securityManager.readAllAvailableVersions(m_context, resource);
2137    }
2138
2139    /**
2140     * Reads all property definitions.<p>
2141     *
2142     * @return a list with the <code>{@link CmsPropertyDefinition}</code> objects (may be empty)
2143     *
2144     * @throws CmsException if something goes wrong
2145     */
2146    public List<CmsPropertyDefinition> readAllPropertyDefinitions() throws CmsException {
2147
2148        return m_securityManager.readAllPropertyDefinitions(m_context);
2149    }
2150
2151    /**
2152     * Returns the first ancestor folder matching the filter criteria.<p>
2153     * 
2154     * If no folder matching the filter criteria is found, null is returned.<p>
2155     * 
2156     * @param resourcename the name of the resource to start (full current site relative path)
2157     * @param filter the resource filter to match while reading the ancestors
2158     * 
2159     * @return the first ancestor folder matching the filter criteria or null if no folder was found
2160     * 
2161     * @throws CmsException if something goes wrong
2162     */
2163    public CmsFolder readAncestor(String resourcename, CmsResourceFilter filter) throws CmsException {
2164
2165        CmsResource resource = readResource(resourcename, CmsResourceFilter.ALL);
2166        return m_securityManager.readAncestor(m_context, resource, filter);
2167    }
2168
2169    /**
2170     * Returns the first ancestor folder matching the resource type.<p>
2171     * 
2172     * If no folder with the requested resource type is found, null is returned.<p>
2173     * 
2174     * @param resourcename the name of the resource to start (full current site relative path)
2175     * @param type the resource type of the folder to match
2176     * 
2177     * @return the first ancestor folder matching the filter criteria or null if no folder was found
2178     * 
2179     * @throws CmsException if something goes wrong
2180     */
2181    public CmsFolder readAncestor(String resourcename, int type) throws CmsException {
2182
2183        return readAncestor(resourcename, CmsResourceFilter.requireType(type));
2184    }
2185
2186    /**
2187     * Reads the newest URL name which is mapped to the given structure id.<p>
2188     * 
2189     * If the structure id is not mapped to any name, null will be returned.<p>
2190     * 
2191     * @param id the structure id for which the newest mapped name should be returned
2192     * @param locale the locale for which the URL name should be selected if possible 
2193     * @param defaultLocales the default locales which should be used if the locale is not available
2194     * @return an URL name or null 
2195     * @throws CmsException if something goes wrong 
2196     */
2197    public String readBestUrlName(CmsUUID id, Locale locale, List<Locale> defaultLocales) throws CmsException {
2198
2199        return m_securityManager.readBestUrlName(m_context, id, locale, defaultLocales);
2200    }
2201
2202    /**
2203     * Returns the default resource for the given folder.<p>
2204     * <ol>
2205     *   <li>the {@link CmsPropertyDefinition#PROPERTY_DEFAULT_FILE} is checked, and
2206     *   <li>if still no file could be found, the configured default files in the 
2207     *       <code>opencms-vfs.xml</code> configuration are iterated until a match is 
2208     *       found, and
2209     *   <li>if still no file could be found, <code>null</code> is returned
2210     * </ol>
2211     * 
2212     * @param folderResource the folder
2213     * @param resourceFilter the resource filter
2214     * 
2215     * @return the default file for the given folder
2216     * 
2217     * @throws CmsSecurityException  if the user has no permissions to read the resulting file
2218     */
2219    public CmsResource readDefaultFile(CmsResource folderResource, CmsResourceFilter resourceFilter)
2220    throws CmsSecurityException {
2221
2222        return m_securityManager.readDefaultFile(m_context, folderResource, resourceFilter);
2223    }
2224
2225    /**
2226     * Returns the default resource for the given folder.<p>
2227     * 
2228     * If the given resource name or id identifies a file, then this file is returned.<p>
2229     * 
2230     * Otherwise, in case of a folder:<br> 
2231     * <ol>
2232     *   <li>the {@link CmsPropertyDefinition#PROPERTY_DEFAULT_FILE} is checked, and
2233     *   <li>if still no file could be found, the configured default files in the 
2234     *       <code>opencms-vfs.xml</code> configuration are iterated until a match is 
2235     *       found, and
2236     *   <li>if still no file could be found, <code>null</code> is returned
2237     * </ol>
2238     * 
2239     * @param resourceNameOrID the name or id of the folder to read the default file for
2240     * 
2241     * @return the default file for the given folder
2242     * 
2243     * @throws CmsException if something goes wrong
2244     * @throws CmsSecurityException if the user has no permissions to read the resulting file
2245     */
2246    public CmsResource readDefaultFile(String resourceNameOrID) throws CmsException, CmsSecurityException {
2247
2248        CmsResource resource;
2249        try {
2250            resource = readResource(new CmsUUID(resourceNameOrID));
2251        } catch (NumberFormatException e) {
2252            resource = readResource(resourceNameOrID);
2253        }
2254        return m_securityManager.readDefaultFile(m_context, resource, CmsResourceFilter.DEFAULT);
2255    }
2256
2257    /**
2258     * Reads all deleted (historical) resources below the given path, 
2259     * including the full tree below the path, if required.<p>
2260     * 
2261     * The result list may include resources with the same name of  
2262     * resources (with different id's).<p>
2263     * 
2264     * Use in conjunction with the {@link #restoreDeletedResource(CmsUUID)} 
2265     * method.<p>
2266     * 
2267     * @param resourcename the parent path to read the resources from
2268     * @param readTree <code>true</code> to read all sub resources
2269     * 
2270     * @return a list of <code>{@link I_CmsHistoryResource}</code> objects
2271     * 
2272     * @throws CmsException if something goes wrong
2273     * 
2274     * @see #readResource(CmsUUID, int)
2275     * @see #readResources(String, CmsResourceFilter, boolean)
2276     */
2277    public List<I_CmsHistoryResource> readDeletedResources(String resourcename, boolean readTree) throws CmsException {
2278
2279        CmsResource resource = readResource(resourcename, CmsResourceFilter.ALL);
2280        return m_securityManager.readDeletedResources(m_context, resource, readTree);
2281    }
2282
2283    /**
2284     * Reads a file resource (including it's binary content) from the VFS,
2285     * for the given resource (this may also be an historical version of the resource).<p>
2286     * 
2287     * In case the input {@link CmsResource} object already is a {@link CmsFile} with contents
2288     * available, it is casted to a file and returned unchanged. Otherwise the file is read 
2289     * from the VFS.<p>
2290     * 
2291     * In case you do not need the file content, 
2292     * use <code>{@link #readResource(String)}</code> or
2293     * <code>{@link #readResource(String, CmsResourceFilter)}</code> instead.<p>
2294     * 
2295     * No resource filter is applied when reading the resource, since we already have
2296     * a full resource instance and assume we just want the content for that instance. 
2297     * In case you need to apply a filter, use {@link #readFile(String, CmsResourceFilter)} instead.<p>
2298     * 
2299     * @param resource the resource to read
2300     *
2301     * @return the file resource that was read
2302     *
2303     * @throws CmsException if the file resource could not be read for any reason
2304     * 
2305     * @see #readFile(String)
2306     * @see #readFile(String, CmsResourceFilter)
2307     */
2308    public CmsFile readFile(CmsResource resource) throws CmsException {
2309
2310        // test if we already have a file
2311        if (resource instanceof CmsFile) {
2312            // resource is already a file
2313            CmsFile file = (CmsFile)resource;
2314            if ((file.getContents() != null) && (file.getContents().length > 0)) {
2315                // file has the contents already available
2316                return file;
2317            }
2318        }
2319
2320        return m_securityManager.readFile(m_context, resource);
2321    }
2322
2323    /**
2324     * Reads a file resource (including it's binary content) from the VFS,
2325     * using the <code>{@link CmsResourceFilter#DEFAULT}</code> filter.<p>
2326     *  
2327     * In case you do not need the file content, 
2328     * use <code>{@link #readResource(String)}</code> instead.<p>
2329     *
2330     * @param resourcename the name of the resource to read (full current site relative path)
2331     *
2332     * @return the file resource that was read
2333     *
2334     * @throws CmsException if the file resource could not be read for any reason
2335     * 
2336     * @see #readFile(String, CmsResourceFilter)
2337     * @see #readFile(CmsResource)
2338     * @see #readResource(String)
2339     */
2340    public CmsFile readFile(String resourcename) throws CmsException {
2341
2342        return readFile(resourcename, CmsResourceFilter.DEFAULT);
2343    }
2344
2345    /**
2346     * Reads a file resource (including it's binary content) from the VFS,
2347     * using the specified resource filter.<p>
2348     * 
2349     * In case you do not need the file content, 
2350     * use <code>{@link #readResource(String, CmsResourceFilter)}</code> instead.<p>
2351     * 
2352     * The specified filter controls what kind of resources should be "found" 
2353     * during the read operation. This will depend on the application. For example, 
2354     * using <code>{@link CmsResourceFilter#DEFAULT}</code> will only return currently
2355     * "valid" resources, while using <code>{@link CmsResourceFilter#IGNORE_EXPIRATION}</code>
2356     * will ignore the date release / date expired information of the resource.<p>
2357     *
2358     * @param resourcename the name of the resource to read (full current site relative path)
2359     * @param filter the resource filter to use while reading
2360     *
2361     * @return the file resource that was read
2362     *
2363     * @throws CmsException if the file resource could not be read for any reason
2364     *
2365     * @see #readFile(String)
2366     * @see #readFile(CmsResource)
2367     * @see #readResource(String, CmsResourceFilter)
2368     */
2369    public CmsFile readFile(String resourcename, CmsResourceFilter filter) throws CmsException {
2370
2371        CmsResource resource = readResource(resourcename, filter);
2372        return readFile(resource);
2373    }
2374
2375    /**
2376     * Reads a folder resource from the VFS,
2377     * using the <code>{@link CmsResourceFilter#DEFAULT}</code> filter.<p> 
2378     *
2379     * @param resourcename the name of the folder resource to read (full current site relative path)
2380     *
2381     * @return the folder resource that was read
2382     *
2383     * @throws CmsException if the resource could not be read for any reason
2384     *
2385     * @see #readResource(String, CmsResourceFilter)
2386     * @see #readFolder(String, CmsResourceFilter)
2387     */
2388    public CmsFolder readFolder(String resourcename) throws CmsException {
2389
2390        return readFolder(resourcename, CmsResourceFilter.DEFAULT);
2391    }
2392
2393    /**
2394     * Reads a folder resource from the VFS,
2395     * using the specified resource filter.<p>
2396     *
2397     * The specified filter controls what kind of resources should be "found" 
2398     * during the read operation. This will depend on the application. For example, 
2399     * using <code>{@link CmsResourceFilter#DEFAULT}</code> will only return currently
2400     * "valid" resources, while using <code>{@link CmsResourceFilter#IGNORE_EXPIRATION}</code>
2401     * will ignore the date release / date expired information of the resource.<p>
2402     * 
2403     * @param resourcename the name of the folder resource to read (full current site relative path)
2404     * @param filter the resource filter to use while reading
2405     *
2406     * @return the folder resource that was read
2407     *
2408     * @throws CmsException if the resource could not be read for any reason
2409     * 
2410     * @see #readResource(String, CmsResourceFilter)
2411     */
2412    public CmsFolder readFolder(String resourcename, CmsResourceFilter filter) throws CmsException {
2413
2414        return m_securityManager.readFolder(m_context, addSiteRoot(resourcename), filter);
2415    }
2416
2417    /**
2418     * Reads the group of a project.<p>
2419     *
2420     * @param project the project to read the group from
2421     * 
2422     * @return the group of the given project
2423     */
2424    public CmsGroup readGroup(CmsProject project) {
2425
2426        return m_securityManager.readGroup(m_context, project);
2427    }
2428
2429    /**
2430     * Reads a group based on its id.<p>
2431     *
2432     * @param groupId the id of the group to be read
2433     * 
2434     * @return the group that has the provided id
2435     * 
2436     * @throws CmsException if something goes wrong
2437     * 
2438     * @see #readHistoryPrincipal(CmsUUID) for retrieving deleted groups
2439     */
2440    public CmsGroup readGroup(CmsUUID groupId) throws CmsException {
2441
2442        return m_securityManager.readGroup(m_context, groupId);
2443    }
2444
2445    /**
2446     * Reads a group based on its name.<p>
2447     * 
2448     * @param groupName the name of the group to be read
2449     * 
2450     * @return the group that has the provided name
2451     * 
2452     * @throws CmsException if something goes wrong
2453     */
2454    public CmsGroup readGroup(String groupName) throws CmsException {
2455
2456        return m_securityManager.readGroup(m_context, groupName);
2457    }
2458
2459    /**
2460     * Reads a principal (an user or group) from the historical archive based on its ID.<p>
2461     * 
2462     * @param principalId the id of the principal to read
2463     * 
2464     * @return the historical principal entry with the given id
2465     * 
2466     * @throws CmsException if something goes wrong, ie. {@link org.opencms.db.CmsDbEntryNotFoundException}
2467     * 
2468     * @see #readUser(CmsUUID)
2469     * @see #readGroup(CmsUUID)
2470     */
2471    public CmsHistoryPrincipal readHistoryPrincipal(CmsUUID principalId) throws CmsException {
2472
2473        return m_securityManager.readHistoricalPrincipal(m_context, principalId);
2474    }
2475
2476    /**
2477     * Returns the latest historical project entry with the given id.<p>
2478     *
2479     * @param projectId the project id
2480     * 
2481     * @return the requested historical project entry
2482     * 
2483     * @throws CmsException if operation was not successful
2484     */
2485    public CmsHistoryProject readHistoryProject(CmsUUID projectId) throws CmsException {
2486
2487        return (m_securityManager.readHistoryProject(m_context, projectId));
2488    }
2489
2490    /**
2491     * Returns a historical project entry.<p>
2492     *
2493     * @param publishTag publish tag of the project
2494     * 
2495     * @return the requested historical project entry
2496     * 
2497     * @throws CmsException if operation was not successful
2498     */
2499    public CmsHistoryProject readHistoryProject(int publishTag) throws CmsException {
2500
2501        return (m_securityManager.readHistoryProject(m_context, publishTag));
2502    }
2503
2504    /**
2505     * Reads the list of all <code>{@link CmsProperty}</code> objects that belong to the given historical resource version.<p>
2506     * 
2507     * @param resource the historical resource version to read the properties for
2508     * 
2509     * @return the list of <code>{@link CmsProperty}</code> objects
2510     * 
2511     * @throws CmsException if something goes wrong
2512     */
2513    public List<CmsProperty> readHistoryPropertyObjects(I_CmsHistoryResource resource) throws CmsException {
2514
2515        return m_securityManager.readHistoryPropertyObjects(m_context, resource);
2516    }
2517
2518    /**
2519     * This method retrieves the structure id which is mapped to a given URL name.<p>
2520     * 
2521     * If there is no structure id mapped to the given name, null will be returned.<p>
2522     * 
2523     * However if the parameter is a string which represents a valid uuid, it will be directly returned as a {@link CmsUUID} instance.<p> 
2524     * 
2525     * @param name the url name  
2526     * @return the id which is mapped to the URL name 
2527     * 
2528     * @throws CmsException if something goes wrong 
2529     */
2530    public CmsUUID readIdForUrlName(String name) throws CmsException {
2531
2532        if (CmsUUID.isValidUUID(name)) {
2533            return new CmsUUID(name);
2534        }
2535        return m_securityManager.readIdForUrlName(m_context, name);
2536    }
2537
2538    /**
2539     * Returns the project manager group of a project.<p>
2540     *
2541     * @param project the project
2542     * 
2543     * @return the manager group of the project
2544     */
2545    public CmsGroup readManagerGroup(CmsProject project) {
2546
2547        return m_securityManager.readManagerGroup(m_context, project);
2548    }
2549
2550    /**
2551     * Reads the owner of a project.<p>
2552     *
2553     * @param project the project to read the owner from
2554     * 
2555     * @return the owner of the project
2556     * 
2557     * @throws CmsException if something goes wrong
2558     */
2559    public CmsUser readOwner(CmsProject project) throws CmsException {
2560
2561        return m_securityManager.readOwner(m_context, project);
2562    }
2563
2564    /**
2565     * Returns the parent folder to the given structure id.<p>
2566     * 
2567     * @param structureId the child structure id
2568     * 
2569     * @return the parent folder <code>{@link CmsResource}</code>
2570     * 
2571     * @throws CmsException if something goes wrong
2572     */
2573    public CmsResource readParentFolder(CmsUUID structureId) throws CmsException {
2574
2575        return m_securityManager.readParentFolder(m_context, structureId);
2576    }
2577
2578    /**
2579     * Builds a list of resources for a given path.<p>
2580     * 
2581     * @param path the requested path
2582     * @param filter a filter object (only "includeDeleted" information is used!)
2583     * 
2584     * @return list of <code>{@link CmsResource}</code>s
2585     * 
2586     * @throws CmsException if something goes wrong
2587     */
2588    public List<CmsResource> readPath(String path, CmsResourceFilter filter) throws CmsException {
2589
2590        return m_securityManager.readPath(m_context, addSiteRoot(path), filter);
2591    }
2592
2593    /**
2594     * Reads the project with the given id.<p>
2595     *
2596     * @param id the id of the project
2597     * 
2598     * @return the project with the given id
2599     *
2600     * @throws CmsException if operation was not successful
2601     */
2602    public CmsProject readProject(CmsUUID id) throws CmsException {
2603
2604        return m_securityManager.readProject(id);
2605    }
2606
2607    /**
2608     * Reads the project with the given name.<p>
2609     *
2610     * @param name the name of the project
2611     * 
2612     * @return the project with the given name
2613     * 
2614     * @throws CmsException if operation was not successful
2615     */
2616    public CmsProject readProject(String name) throws CmsException {
2617
2618        return m_securityManager.readProject(name);
2619    }
2620
2621    /**
2622     * Returns the list of all resource names that define the "view" of the given project.<p>
2623     * 
2624     * @param project the project to get the project resources for
2625     * 
2626     * @return the list of all resource names (root paths), as <code>{@link String}</code> 
2627     *              objects that define the "view" of the given project
2628     * 
2629     * @throws CmsException if something goes wrong
2630     */
2631    public List<String> readProjectResources(CmsProject project) throws CmsException {
2632
2633        return m_securityManager.readProjectResources(m_context, project);
2634    }
2635
2636    /**
2637     * Reads all resources of a project that match a given state from the VFS.<p>
2638     * 
2639     * Possible values for the <code>state</code> parameter are:<br>
2640     * <ul>
2641     * <li><code>{@link CmsResource#STATE_CHANGED}</code>: Read all "changed" resources in the project</li>
2642     * <li><code>{@link CmsResource#STATE_NEW}</code>: Read all "new" resources in the project</li>
2643     * <li><code>{@link CmsResource#STATE_DELETED}</code>: Read all "deleted" resources in the project</li>
2644     * <li><code>{@link CmsResource#STATE_KEEP}</code>: Read all resources either "changed", "new" or "deleted" in the project</li>
2645     * </ul><p>
2646     * 
2647     * @param projectId the id of the project to read the file resources for
2648     * @param state the resource state to match
2649     *
2650     * @return all <code>{@link CmsResource}</code>s of a project that match a given criteria from the VFS
2651     * 
2652     * @throws CmsException if something goes wrong
2653     */
2654    public List<CmsResource> readProjectView(CmsUUID projectId, CmsResourceState state) throws CmsException {
2655
2656        return m_securityManager.readProjectView(m_context, projectId, state);
2657    }
2658
2659    /**
2660     * Reads a property definition.<p>
2661     *
2662     * If no property definition with the given name is found, 
2663     * <code>null</code> is returned.<p>
2664     * 
2665     * @param name the name of the property definition to read
2666     * 
2667     * @return the property definition that was read
2668     *
2669     * @throws CmsException a CmsDbEntryNotFoundException is thrown if the property definition does not exist
2670     */
2671    public CmsPropertyDefinition readPropertyDefinition(String name) throws CmsException {
2672
2673        return (m_securityManager.readPropertyDefinition(m_context, name));
2674    }
2675
2676    /**
2677     * Reads a property object from a resource specified by a property name.<p>
2678     * 
2679     * Returns <code>{@link CmsProperty#getNullProperty()}</code> if the property is not found.<p>
2680     * 
2681     * This method is more efficient then using <code>{@link CmsObject#readPropertyObject(String, String, boolean)}</code>
2682     * if you already have an instance of the resource to look up the property from.<p>
2683     * 
2684     * @param resource the resource where the property is attached to
2685     * @param property the property name
2686     * @param search if true, the property is searched on all parent folders of the resource, 
2687     *      if it's not found attached directly to the resource
2688     * 
2689     * @return the required property, or <code>{@link CmsProperty#getNullProperty()}</code> if the property was not found
2690     * 
2691     * @throws CmsException if something goes wrong
2692     */
2693    public CmsProperty readPropertyObject(CmsResource resource, String property, boolean search) throws CmsException {
2694
2695        return m_securityManager.readPropertyObject(m_context, resource, property, search);
2696    }
2697
2698    /**
2699     * Reads a property object from a resource specified by a property name.<p>
2700     * 
2701     * Returns <code>{@link CmsProperty#getNullProperty()}</code> if the property is not found.<p>
2702     * 
2703     * @param resourcePath the name of resource where the property is attached to
2704     * @param property the property name
2705     * @param search if true, the property is searched on all parent folders of the resource, 
2706     *      if it's not found attached directly to the resource
2707     * 
2708     * @return the required property, or <code>{@link CmsProperty#getNullProperty()}</code> if the property was not found
2709     * 
2710     * @throws CmsException if something goes wrong
2711     */
2712    public CmsProperty readPropertyObject(String resourcePath, String property, boolean search) throws CmsException {
2713
2714        CmsResource resource = readResource(resourcePath, CmsResourceFilter.ALL);
2715        return m_securityManager.readPropertyObject(m_context, resource, property, search);
2716    }
2717
2718    /**
2719     * Reads all property objects from a resource.<p>
2720     * 
2721     * Returns an empty list if no properties are found.<p>
2722     * 
2723     * This method is more efficient then using <code>{@link CmsObject#readPropertyObjects(String, boolean)}</code>
2724     * if you already have an instance of the resource to look up the property from.<p>
2725     * 
2726     * If the <code>search</code> parameter is <code>true</code>, the properties of all 
2727     * parent folders of the resource are also read. The results are merged with the 
2728     * properties directly attached to the resource. While merging, a property
2729     * on a parent folder that has already been found will be ignored.
2730     * So e.g. if a resource has a property "Title" attached, and it's parent folder 
2731     * has the same property attached but with a different value, the result list will
2732     * contain only the property with the value from the resource, not form the parent folder(s).<p>
2733     * 
2734     * @param resource the resource where the property is mapped to
2735     * @param search if <code>true</code>, the properties of all parent folders of the resource 
2736     *      are merged with the resource properties.
2737     * 
2738     * @return a list of <code>{@link CmsProperty}</code> objects
2739     * 
2740     * @throws CmsException if something goes wrong
2741     */
2742    public List<CmsProperty> readPropertyObjects(CmsResource resource, boolean search) throws CmsException {
2743
2744        return m_securityManager.readPropertyObjects(m_context, resource, search);
2745    }
2746
2747    /**
2748     * Reads all property objects from a resource.<p>
2749     * 
2750     * Returns an empty list if no properties are found.<p>
2751     * 
2752     * All properties in the result List will be in frozen (read only) state, so you can't change the values.<p>
2753     * 
2754     * If the <code>search</code> parameter is <code>true</code>, the properties of all 
2755     * parent folders of the resource are also read. The results are merged with the 
2756     * properties directly attached to the resource. While merging, a property
2757     * on a parent folder that has already been found will be ignored.
2758     * So e.g. if a resource has a property "Title" attached, and it's parent folder 
2759     * has the same property attached but with a different value, the result list will
2760     * contain only the property with the value from the resource, not form the parent folder(s).<p>
2761     * 
2762     * @param resourcePath the name of resource where the property is mapped to
2763     * @param search if <code>true</code>, the properties of all parent folders of the resource 
2764     *      are merged with the resource properties.
2765     * 
2766     * @return a list of <code>{@link CmsProperty}</code> objects
2767     * 
2768     * @throws CmsException if something goes wrong
2769     */
2770    public List<CmsProperty> readPropertyObjects(String resourcePath, boolean search) throws CmsException {
2771
2772        CmsResource resource = readResource(resourcePath, CmsResourceFilter.ALL);
2773        return m_securityManager.readPropertyObjects(m_context, resource, search);
2774    }
2775
2776    /**
2777     * Reads the resources that were published in a publish task for a given publish history ID.<p>
2778     * 
2779     * @param publishHistoryId unique ID to identify each publish task in the publish history
2780     * 
2781     * @return a list of <code>{@link org.opencms.db.CmsPublishedResource}</code> objects
2782     * 
2783     * @throws CmsException if something goes wrong
2784     */
2785    public List<CmsPublishedResource> readPublishedResources(CmsUUID publishHistoryId) throws CmsException {
2786
2787        return m_securityManager.readPublishedResources(m_context, publishHistoryId);
2788    }
2789
2790    /**
2791     * Returns all relations matching the given filter.<p> 
2792     * 
2793     * @param filter the filter to match the relation 
2794     * 
2795     * @return all relations matching the given filter
2796     * 
2797     * @throws CmsException if something goes wrong
2798     * 
2799     * @see CmsSecurityManager#getRelationsForResource(CmsRequestContext, CmsResource, CmsRelationFilter)
2800     * @see #getRelationsForResource(CmsResource, CmsRelationFilter)
2801     */
2802    public List<CmsRelation> readRelations(CmsRelationFilter filter) throws CmsException {
2803
2804        return m_securityManager.getRelationsForResource(m_context, null, filter);
2805    }
2806
2807    /**
2808     * Reads a resource from the VFS,
2809     * using the <code>{@link CmsResourceFilter#DEFAULT}</code> filter.<p> 
2810     *
2811     * A resource may be of type <code>{@link CmsFile}</code> or 
2812     * <code>{@link CmsFolder}</code>. In case of
2813     * a file, the resource will not contain the binary file content. Since reading 
2814     * the binary content is a cost-expensive database operation, it's recommended 
2815     * to work with resources if possible, and only read the file content when absolutely
2816     * required. To "upgrade" a resource to a file, 
2817     * use <code>{@link #readFile(CmsResource)}</code>.<p> 
2818     *
2819     * @param structureID the structure ID of the resource to read
2820     *
2821     * @return the resource that was read
2822     *
2823     * @throws CmsException if the resource could not be read for any reason
2824     *
2825     * @see #readFile(String) 
2826     * @see #readResource(CmsUUID, CmsResourceFilter)
2827     */
2828    public CmsResource readResource(CmsUUID structureID) throws CmsException {
2829
2830        return readResource(structureID, CmsResourceFilter.DEFAULT);
2831    }
2832
2833    /**
2834     * Reads a resource from the VFS,
2835     * using the specified resource filter.<p>
2836     *
2837     * A resource may be of type <code>{@link CmsFile}</code> or 
2838     * <code>{@link CmsFolder}</code>. In case of
2839     * a file, the resource will not contain the binary file content. Since reading 
2840     * the binary content is a cost-expensive database operation, it's recommended 
2841     * to work with resources if possible, and only read the file content when absolutely
2842     * required. To "upgrade" a resource to a file, 
2843     * use <code>{@link #readFile(CmsResource)}</code>.<p> 
2844     *
2845     * The specified filter controls what kind of resources should be "found" 
2846     * during the read operation. This will depend on the application. For example, 
2847     * using <code>{@link CmsResourceFilter#DEFAULT}</code> will only return currently
2848     * "valid" resources, while using <code>{@link CmsResourceFilter#IGNORE_EXPIRATION}</code>
2849     * will ignore the date release / date expired information of the resource.<p>
2850     * 
2851     * @param structureID the structure ID of the resource to read
2852     * @param filter the resource filter to use while reading
2853     *
2854     * @return the resource that was read
2855     *
2856     * @throws CmsException if the resource could not be read for any reason
2857     * 
2858     * @see #readFile(String, CmsResourceFilter)
2859     * @see #readFolder(String, CmsResourceFilter)
2860     */
2861    public CmsResource readResource(CmsUUID structureID, CmsResourceFilter filter) throws CmsException {
2862
2863        return m_securityManager.readResource(m_context, structureID, filter);
2864    }
2865
2866    /**
2867     * Reads the historical resource with the given version for the resource given 
2868     * the given structure id.<p>
2869     *
2870     * A resource may be of type <code>{@link CmsFile}</code> or 
2871     * <code>{@link CmsFolder}</code>. In case of a file, the resource will not 
2872     * contain the binary file content. Since reading the binary content is a 
2873     * cost-expensive database operation, it's recommended to work with resources 
2874     * if possible, and only read the file content when absolutely required. To 
2875     * "upgrade" a resource to a file, use 
2876     * <code>{@link #readFile(CmsResource)}</code>.<p> 
2877     *
2878     * Please note that historical versions are just generated during publishing, 
2879     * so the first version with version number 1 is generated during publishing 
2880     * of a new resource (exception is a new sibling, that may also contain some 
2881     * relevant versions of already published siblings) and the last version 
2882     * available is the version of the current online resource.<p>
2883     * 
2884     * @param structureID the structure ID of the resource to read
2885     * @param version the version number you want to retrieve
2886     *
2887     * @return the resource that was read
2888     *
2889     * @throws CmsException if the resource could not be read for any reason
2890     * @throws CmsVfsResourceNotFoundException if the version does not exists
2891     * 
2892     * @see #restoreResourceVersion(CmsUUID, int)
2893     */
2894    public I_CmsHistoryResource readResource(CmsUUID structureID, int version)
2895    throws CmsException, CmsVfsResourceNotFoundException {
2896
2897        CmsResource resource = readResource(structureID, CmsResourceFilter.ALL);
2898        return m_securityManager.readResource(m_context, resource, version);
2899    }
2900
2901    /**
2902     * Reads a resource from the VFS,
2903     * using the <code>{@link CmsResourceFilter#DEFAULT}</code> filter.<p> 
2904     *
2905     * A resource may be of type <code>{@link CmsFile}</code> or 
2906     * <code>{@link CmsFolder}</code>. In case of
2907     * a file, the resource will not contain the binary file content. Since reading 
2908     * the binary content is a cost-expensive database operation, it's recommended 
2909     * to work with resources if possible, and only read the file content when absolutely
2910     * required. To "upgrade" a resource to a file, 
2911     * use <code>{@link #readFile(CmsResource)}</code>.<p> 
2912     *
2913     * @param resourcename the name of the resource to read (full current site relative path)
2914     *
2915     * @return the resource that was read
2916     *
2917     * @throws CmsException if the resource could not be read for any reason
2918     *
2919     * @see #readFile(String) 
2920     * @see #readResource(String, CmsResourceFilter)
2921     */
2922    public CmsResource readResource(String resourcename) throws CmsException {
2923
2924        return readResource(resourcename, CmsResourceFilter.DEFAULT);
2925    }
2926
2927    /**
2928     * Reads a resource from the VFS,
2929     * using the specified resource filter.<p>
2930     *
2931     * A resource may be of type <code>{@link CmsFile}</code> or 
2932     * <code>{@link CmsFolder}</code>. In case of
2933     * a file, the resource will not contain the binary file content. Since reading 
2934     * the binary content is a cost-expensive database operation, it's recommended 
2935     * to work with resources if possible, and only read the file content when absolutely
2936     * required. To "upgrade" a resource to a file, 
2937     * use <code>{@link #readFile(CmsResource)}</code>.<p> 
2938     *
2939     * The specified filter controls what kind of resources should be "found" 
2940     * during the read operation. This will depend on the application. For example, 
2941     * using <code>{@link CmsResourceFilter#DEFAULT}</code> will only return currently
2942     * "valid" resources, while using <code>{@link CmsResourceFilter#IGNORE_EXPIRATION}</code>
2943     * will ignore the date release / date expired information of the resource.<p>
2944     * 
2945     * @param resourcename the name of the resource to read (full current site relative path)
2946     * @param filter the resource filter to use while reading
2947     *
2948     * @return the resource that was read
2949     *
2950     * @throws CmsException if the resource could not be read for any reason
2951     * 
2952     * @see #readFile(String, CmsResourceFilter)
2953     * @see #readFolder(String, CmsResourceFilter)
2954     */
2955    public CmsResource readResource(String resourcename, CmsResourceFilter filter) throws CmsException {
2956
2957        return m_securityManager.readResource(m_context, addSiteRoot(resourcename), filter);
2958    }
2959
2960    /**
2961     * Reads all resources below the given path matching the filter criteria, 
2962     * including the full tree below the path.<p>
2963     * 
2964     * @param resourcename the parent path to read the resources from
2965     * @param filter the filter
2966     * 
2967     * @return a list of <code>{@link CmsResource}</code> objects matching the filter criteria
2968     * 
2969     * @throws CmsException if something goes wrong
2970     * 
2971     * @see #readResources(String, CmsResourceFilter, boolean)
2972     */
2973    public List<CmsResource> readResources(String resourcename, CmsResourceFilter filter) throws CmsException {
2974
2975        return readResources(resourcename, filter, true);
2976    }
2977
2978    /**
2979     * Reads all resources below the given path matching the filter criteria,
2980     * including the full tree below the path only in case the <code>readTree</code> 
2981     * parameter is <code>true</code>.<p>
2982     * 
2983     * @param resourcename the parent path to read the resources from
2984     * @param filter the filter
2985     * @param readTree <code>true</code> to read all sub resources
2986     * 
2987     * @return a list of <code>{@link CmsResource}</code> objects matching the filter criteria
2988     * 
2989     * @throws CmsException if something goes wrong
2990     */
2991    public List<CmsResource> readResources(String resourcename, CmsResourceFilter filter, boolean readTree)
2992    throws CmsException {
2993
2994        CmsResource resource = readResource(resourcename, CmsResourceFilter.ALL);
2995        return m_securityManager.readResources(m_context, resource, filter, readTree);
2996    }
2997
2998    /**
2999     * Reads all resources that have a value set for the specified property.<p>
3000     * 
3001     * Both individual and shared properties of a resource are checked.<p>
3002     * 
3003     * Will use the {@link CmsResourceFilter#ALL} resource filter.<p>
3004     *
3005     * @param propertyDefinition the name of the property to check for
3006     * 
3007     * @return a list of all <code>{@link CmsResource}</code> objects 
3008     *          that have a value set for the specified property.
3009     * 
3010     * @throws CmsException if something goes wrong
3011     */
3012    public List<CmsResource> readResourcesWithProperty(String propertyDefinition) throws CmsException {
3013
3014        return readResourcesWithProperty("/", propertyDefinition);
3015    }
3016
3017    /**
3018     * Reads all resources that have a value set for the specified property in the given path.<p>
3019     * 
3020     * Both individual and shared properties of a resource are checked.<p>
3021     * 
3022     * Will use the {@link CmsResourceFilter#ALL} resource filter.<p>
3023     *
3024     * @param path the folder to get the resources with the property from
3025     * @param propertyDefinition the name of the property to check for
3026     * 
3027     * @return all <code>{@link CmsResource}</code> objects 
3028     *          that have a value set for the specified property in the given path.
3029     * 
3030     * @throws CmsException if something goes wrong
3031     */
3032    public List<CmsResource> readResourcesWithProperty(String path, String propertyDefinition) throws CmsException {
3033
3034        return readResourcesWithProperty(path, propertyDefinition, null);
3035    }
3036
3037    /**
3038     * Reads all resources that have a value (containing the specified value) set 
3039     * for the specified property in the given path.<p>
3040     * 
3041     * Both individual and shared properties of a resource are checked.<p>
3042     *
3043     * If the <code>value</code> parameter is <code>null</code>, all resources having the
3044     * given property set are returned.<p>
3045     * 
3046     * Will use the {@link CmsResourceFilter#ALL} resource filter.<p>
3047     * 
3048     * @param path the folder to get the resources with the property from
3049     * @param propertyDefinition the name of the property to check for
3050     * @param value the string to search in the value of the property
3051     * 
3052     * @return all <code>{@link CmsResource}</code> objects 
3053     *          that have a value set for the specified property in the given path.
3054     * 
3055     * @throws CmsException if something goes wrong
3056     */
3057    public List<CmsResource> readResourcesWithProperty(String path, String propertyDefinition, String value)
3058    throws CmsException {
3059
3060        CmsResource resource = readResource(path, CmsResourceFilter.IGNORE_EXPIRATION);
3061        return m_securityManager.readResourcesWithProperty(
3062            m_context,
3063            resource,
3064            propertyDefinition,
3065            value,
3066            CmsResourceFilter.ALL);
3067    }
3068
3069    /**
3070     * Reads all resources that have a value (containing the specified value) set 
3071     * for the specified property in the given path.<p>
3072     * 
3073     * Both individual and shared properties of a resource are checked.<p>
3074     *
3075     * If the <code>value</code> parameter is <code>null</code>, all resources having the
3076     * given property set are returned.<p>
3077     * 
3078     * Will use the given resource filter.<p>
3079     * 
3080     * @param path the folder to get the resources with the property from
3081     * @param propertyDefinition the name of the property to check for
3082     * @param value the string to search in the value of the property
3083     * @param filter the resource filter to apply to the result set
3084     * 
3085     * @return all <code>{@link CmsResource}</code> objects 
3086     *          that have a value set for the specified property in the given path.
3087     * 
3088     * @throws CmsException if something goes wrong
3089     */
3090    public List<CmsResource> readResourcesWithProperty(
3091        String path,
3092        String propertyDefinition,
3093        String value,
3094        CmsResourceFilter filter) throws CmsException {
3095
3096        CmsResource resource = readResource(path, CmsResourceFilter.IGNORE_EXPIRATION);
3097        return m_securityManager.readResourcesWithProperty(m_context, resource, propertyDefinition, value, filter);
3098    }
3099
3100    /**
3101     * Returns a set of principals that are responsible for a specific resource.<p>
3102     * 
3103     * @param resource the resource to get the responsible principals from
3104     * 
3105     * @return the set of principals that are responsible for a specific resource
3106     * 
3107     * @throws CmsException if something goes wrong
3108     */
3109    public Set<I_CmsPrincipal> readResponsiblePrincipals(CmsResource resource) throws CmsException {
3110
3111        return m_securityManager.readResponsiblePrincipals(m_context, resource);
3112    }
3113
3114    /**
3115     * Returns a set of users that are responsible for a specific resource.<p>
3116     * 
3117     * @param resource the resource to get the responsible users from
3118     * 
3119     * @return the set of users that are responsible for a specific resource
3120     * 
3121     * @throws CmsException if something goes wrong
3122     */
3123    public Set<CmsUser> readResponsibleUsers(CmsResource resource) throws CmsException {
3124
3125        return m_securityManager.readResponsibleUsers(m_context, resource);
3126    }
3127
3128    /**
3129     * Returns a list of all siblings of the specified resource,
3130     * the specified resource being always part of the result set.<p>
3131     * 
3132     * @param resource the resource
3133     * @param filter a resource filter
3134     * 
3135     * @return a list of <code>{@link CmsResource}</code>s that 
3136     *          are siblings to the specified resource, 
3137     *          including the specified resource itself.
3138     * 
3139     * @throws CmsException if something goes wrong
3140     */
3141    public List<CmsResource> readSiblings(CmsResource resource, CmsResourceFilter filter) throws CmsException {
3142
3143        return m_securityManager.readSiblings(m_context, resource, filter);
3144    }
3145
3146    /**
3147     * Returns a list of all siblings of the specified resource,
3148     * the specified resource being always part of the result set.<p>
3149     * 
3150     * @param resourcename the name of the specified resource
3151     * @param filter a resource filter
3152     * 
3153     * @return a list of <code>{@link CmsResource}</code>s that 
3154     *          are siblings to the specified resource, 
3155     *          including the specified resource itself.
3156     * 
3157     * @throws CmsException if something goes wrong
3158     */
3159    public List<CmsResource> readSiblings(String resourcename, CmsResourceFilter filter) throws CmsException {
3160
3161        CmsResource resource = readResource(resourcename, filter);
3162        return readSiblings(resource, filter);
3163    }
3164
3165    /**
3166     * Reads all resources with the given resource id.<p>
3167     * 
3168     * @param resourceId the resource id for which we want the siblings 
3169     * @param filter the resource filter used to read the resources 
3170     * @return the siblings which share the given resource id 
3171     * 
3172     * @throws CmsException if something goes wrong 
3173     */
3174    public List<CmsResource> readSiblingsForResourceId(CmsUUID resourceId, CmsResourceFilter filter)
3175    throws CmsException {
3176
3177        CmsResource pseudoResource = new CmsResource(
3178            null,
3179            resourceId,
3180            null,
3181            0,
3182            false,
3183            0,
3184            null,
3185            null,
3186            0,
3187            null,
3188            0,
3189            null,
3190            0,
3191            0,
3192            0,
3193            0,
3194            0,
3195            0);
3196        return readSiblings(pseudoResource, filter);
3197    }
3198
3199    /**
3200     * Returns the parameters of a resource in the list of all published template resources.<p>
3201     * 
3202     * @param rfsName the rfs name of the resource
3203     * 
3204     * @return the parameter string of the requested resource
3205     * 
3206     * @throws CmsException if something goes wrong
3207     */
3208    public String readStaticExportPublishedResourceParameters(String rfsName) throws CmsException {
3209
3210        return m_securityManager.readStaticExportPublishedResourceParameters(m_context, rfsName);
3211    }
3212
3213    /**
3214     * Returns a list of all template resources which must be processed during a static export.<p>
3215     * 
3216     * @param parameterResources flag for reading resources with parameters (1) or without (0)
3217     * 
3218     * @param timestamp a time stamp for reading the data from the db
3219     * 
3220     * @return a list of template resources as <code>{@link String}</code> objects
3221     * 
3222     * @throws CmsException if something goes wrong
3223     */
3224    public List<String> readStaticExportResources(int parameterResources, long timestamp) throws CmsException {
3225
3226        return m_securityManager.readStaticExportResources(m_context, parameterResources, timestamp);
3227    }
3228
3229    /**
3230     * Reads the URL name mappings matching a given filter.<p>
3231     * 
3232     * @param filter the filter to match 
3233     * @return the URL name mappings matching the filter 
3234     * 
3235     * @throws CmsException if something goes wrong 
3236     */
3237    public List<CmsUrlNameMappingEntry> readUrlNameMappings(CmsUrlNameMappingFilter filter) throws CmsException {
3238
3239        return m_securityManager.readUrlNameMappings(m_context, filter);
3240    }
3241
3242    /**
3243     * Reads the URL names for all locales.<p> 
3244     * 
3245     * @param structureId the id of resource for which the URL names should be read 
3246     * @return returns the URL names for the resource 
3247     * 
3248     * @throws CmsException if something goes wrong 
3249     */
3250    public List<String> readUrlNamesForAllLocales(CmsUUID structureId) throws CmsException {
3251
3252        List<String> detailNames = m_securityManager.readUrlNamesForAllLocales(m_context, structureId);
3253        if (detailNames.isEmpty()) {
3254            List<String> result = new ArrayList<String>();
3255            result.add(structureId.toString());
3256            return result;
3257        }
3258        return detailNames;
3259    }
3260
3261    /**
3262     * Reads a user based on its id.<p>
3263     *
3264     * @param userId the id of the user to be read
3265     * 
3266     * @return the user with the given id
3267     * 
3268     * @throws CmsException if something goes wrong
3269     * 
3270     * @see #readHistoryPrincipal(CmsUUID) for retrieving data of deleted users
3271     */
3272    public CmsUser readUser(CmsUUID userId) throws CmsException {
3273
3274        return m_securityManager.readUser(m_context, userId);
3275    }
3276
3277    /**
3278     * Reads a user based on its name.<p>
3279     *
3280     * @param username the name of the user to be read
3281     * 
3282     * @return the user with the given name
3283     * 
3284     * @throws CmsException if something goes wrong
3285     */
3286    public CmsUser readUser(String username) throws CmsException {
3287
3288        return m_securityManager.readUser(m_context, username);
3289    }
3290
3291    /**
3292     * Returns a user, if the password is correct.<p>
3293     * 
3294     * If the user/pwd pair is not valid a <code>{@link CmsException}</code> is thrown.<p>
3295     *
3296     * @param username the name of the user to be returned
3297     * @param password the password of the user to be returned
3298     * 
3299     * @return the validated user
3300     *
3301     * @throws CmsException if operation was not successful
3302     */
3303    public CmsUser readUser(String username, String password) throws CmsException {
3304
3305        return m_securityManager.readUser(m_context, username, password);
3306    }
3307
3308    /**
3309     * Removes a resource from the current project of the user.<p>
3310     * 
3311     * This is used to reduce the current users project with the
3312     * specified resource, in case that the resource is already part of the project.
3313     * The resource is not really removed like in a regular copy operation, 
3314     * it is in fact only "disabled" in the current users project.<p>   
3315     * 
3316     * @param resourcename the name of the resource to remove to the current project (full current site relative path)
3317     * 
3318     * @throws CmsException if something goes wrong
3319     */
3320    public void removeResourceFromProject(String resourcename) throws CmsException {
3321
3322        // TODO: this should be also possible if the resource has been deleted
3323        CmsResource resource = readResource(resourcename, CmsResourceFilter.ALL);
3324        getResourceType(resource).removeResourceFromProject(this, m_securityManager, resource);
3325    }
3326
3327    /**
3328     * Removes a user from a group.<p>
3329     *
3330     * @param username the name of the user that is to be removed from the group
3331     * @param groupname the name of the group
3332     * 
3333     * @throws CmsException if operation was not successful
3334     */
3335    public void removeUserFromGroup(String username, String groupname) throws CmsException {
3336
3337        m_securityManager.removeUserFromGroup(m_context, username, groupname, false);
3338    }
3339
3340    /**
3341     * Renames a resource to the given destination name,
3342     * this is identical to a <code>move</code> operation.<p>
3343     *
3344     * @param source the name of the resource to rename (full current site relative path)
3345     * @param destination the new resource name (full path)
3346     * 
3347     * @throws CmsException if something goes wrong
3348     * 
3349     * @see #moveResource(String, String)
3350     */
3351    public void renameResource(String source, String destination) throws CmsException {
3352
3353        moveResource(source, destination);
3354    }
3355
3356    /**
3357     * Replaces the content, type and properties of a resource.<p>
3358     * 
3359     * @param resourcename the name of the resource to replace (full current site relative path)
3360     * @param type the new type of the resource
3361     * @param content the new content of the resource
3362     * @param properties the new properties of the resource
3363     * 
3364     * @throws CmsException if something goes wrong
3365     */
3366    public void replaceResource(String resourcename, int type, byte[] content, List<CmsProperty> properties)
3367    throws CmsException {
3368
3369        CmsResource resource = readResource(resourcename, CmsResourceFilter.IGNORE_EXPIRATION);
3370        getResourceType(resource).replaceResource(this, m_securityManager, resource, type, content, properties);
3371    }
3372
3373    /**
3374     * Restores a deleted resource identified by its structure id from the historical archive.<p>
3375     * 
3376     * These ids can be obtained from the {@link #readDeletedResources(String, boolean)} method.<p>
3377     * 
3378     * @param structureId the structure id of the resource to restore
3379     * 
3380     * @throws CmsException if something goes wrong
3381     */
3382    public void restoreDeletedResource(CmsUUID structureId) throws CmsException {
3383
3384        m_securityManager.restoreDeletedResource(m_context, structureId);
3385    }
3386
3387    /**
3388     * Restores a resource in the current project with a version from the historical archive.<p>
3389     * 
3390     * @param structureId the structure id of the resource to restore from the archive
3391     * @param version the desired version of the resource to be restored
3392     *
3393     * @throws CmsException if something goes wrong
3394     * 
3395     * @see #readResource(CmsUUID, int)
3396     */
3397    public void restoreResourceVersion(CmsUUID structureId, int version) throws CmsException {
3398
3399        CmsResource resource = readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION);
3400        getResourceType(resource).restoreResource(this, m_securityManager, resource, version);
3401    }
3402
3403    /**
3404     * Removes an access control entry of a given principal from a given resource.<p>
3405     * 
3406     * @param resourceName name of the resource
3407     * @param principalType the type of the principal (currently group or user)
3408     * @param principalName the name of the principal
3409     * 
3410     * @throws CmsException if something goes wrong
3411     */
3412    public void rmacc(String resourceName, String principalType, String principalName) throws CmsException {
3413
3414        CmsResource res = readResource(resourceName, CmsResourceFilter.ALL);
3415
3416        if (CmsUUID.isValidUUID(principalName)) {
3417            // principal name is in fact a UUID, probably the user was already deleted
3418            m_securityManager.removeAccessControlEntry(m_context, res, new CmsUUID(principalName));
3419        } else {
3420            try {
3421                // principal name not a UUID, assume this is a normal group or user name
3422                I_CmsPrincipal principal = CmsPrincipal.readPrincipal(this, principalType, principalName);
3423                m_securityManager.removeAccessControlEntry(m_context, res, principal.getId());
3424            } catch (CmsDbEntryNotFoundException e) {
3425                // role case
3426                CmsRole role = CmsRole.valueOfRoleName(principalName);
3427                if (role == null) {
3428                    throw e;
3429                }
3430                m_securityManager.removeAccessControlEntry(m_context, res, role.getId());
3431            }
3432        }
3433    }
3434
3435    /**
3436     * Changes the "expire" date of a resource.<p>
3437     * 
3438     * @param resource the resource to change
3439     * @param dateExpired the new expire date of the changed resource
3440     * @param recursive if this operation is to be applied recursively to all resources in a folder
3441     * 
3442     * @throws CmsException if something goes wrong
3443     */
3444    public void setDateExpired(CmsResource resource, long dateExpired, boolean recursive) throws CmsException {
3445
3446        getResourceType(resource).setDateExpired(this, m_securityManager, resource, dateExpired, recursive);
3447    }
3448
3449    /**
3450     * Changes the "expire" date of a resource.<p>
3451     * 
3452     * @param resourcename the name of the resource to change (full current site relative path)
3453     * @param dateExpired the new expire date of the changed resource
3454     * @param recursive if this operation is to be applied recursively to all resources in a folder
3455     * 
3456     * @throws CmsException if something goes wrong
3457     */
3458    public void setDateExpired(String resourcename, long dateExpired, boolean recursive) throws CmsException {
3459
3460        CmsResource resource = readResource(resourcename, CmsResourceFilter.IGNORE_EXPIRATION);
3461        setDateExpired(resource, dateExpired, recursive);
3462    }
3463
3464    /**
3465     * Changes the "last modified" time stamp of a resource.<p>
3466     * 
3467     * @param resourcename the name of the resource to change (full current site relative path)
3468     * @param dateLastModified time stamp the new time stamp of the changed resource
3469     * @param recursive if this operation is to be applied recursively to all resources in a folder
3470     * 
3471     * @throws CmsException if something goes wrong
3472     */
3473    public void setDateLastModified(String resourcename, long dateLastModified, boolean recursive) throws CmsException {
3474
3475        CmsResource resource = readResource(resourcename, CmsResourceFilter.IGNORE_EXPIRATION);
3476        getResourceType(resource).setDateLastModified(this, m_securityManager, resource, dateLastModified, recursive);
3477    }
3478
3479    /**
3480     * Changes the "release" date of a resource.<p>
3481     * 
3482     * @param resource the resource to change
3483     * @param dateReleased the new release date of the changed resource
3484     * @param recursive if this operation is to be applied recursively to all resources in a folder
3485     * 
3486     * @throws CmsException if something goes wrong
3487     */
3488    public void setDateReleased(CmsResource resource, long dateReleased, boolean recursive) throws CmsException {
3489
3490        getResourceType(resource).setDateReleased(this, m_securityManager, resource, dateReleased, recursive);
3491    }
3492
3493    /**
3494     * Changes the "release" date of a resource.<p>
3495     * 
3496     * @param resourcename the name of the resource to change (full current site relative path)
3497     * @param dateReleased the new release date of the changed resource
3498     * @param recursive if this operation is to be applied recursively to all resources in a folder
3499     * 
3500     * @throws CmsException if something goes wrong
3501     */
3502    public void setDateReleased(String resourcename, long dateReleased, boolean recursive) throws CmsException {
3503
3504        CmsResource resource = readResource(resourcename, CmsResourceFilter.IGNORE_EXPIRATION);
3505        setDateReleased(resource, dateReleased, recursive);
3506    }
3507
3508    /**
3509     * Sets a new parent-group for an already existing group.<p>
3510     *
3511     * @param groupName the name of the group that should be updated
3512     * @param parentGroupName the name of the parent group to set, 
3513     *                      or <code>null</code> if the parent
3514     *                      group should be deleted.
3515     * 
3516     * @throws CmsException  if operation was not successful
3517     */
3518    public void setParentGroup(String groupName, String parentGroupName) throws CmsException {
3519
3520        m_securityManager.setParentGroup(m_context, groupName, parentGroupName);
3521    }
3522
3523    /**
3524     * Sets the password for a user.<p>
3525     *
3526     * @param username the name of the user
3527     * @param newPassword the new password
3528     *
3529     * @throws CmsException if operation was not successful
3530     */
3531    public void setPassword(String username, String newPassword) throws CmsException {
3532
3533        m_securityManager.setPassword(m_context, username, newPassword);
3534    }
3535
3536    /**
3537     * Sets the password for a specified user.<p>
3538     *
3539     * @param username the name of the user
3540     * @param oldPassword the old password
3541     * @param newPassword the new password
3542     * 
3543     * @throws CmsException if the user data could not be read from the database
3544     */
3545    public void setPassword(String username, String oldPassword, String newPassword) throws CmsException {
3546
3547        m_securityManager.resetPassword(m_context, username, oldPassword, newPassword);
3548    }
3549
3550    /**
3551     * Undeletes a resource.<p>
3552     * 
3553     * Only resources that have already been published once can be undeleted,
3554     * if a "new" resource is deleted it can not be undeleted.<p>
3555     * 
3556     * @param resourcename the name of the resource to undelete
3557     * @param recursive if this operation is to be applied recursively to all resources in a folder
3558     *
3559     * @throws CmsException if something goes wrong
3560     * 
3561     * @see CmsObject#undoChanges(String, CmsResource.CmsResourceUndoMode)
3562     */
3563    public void undeleteResource(String resourcename, boolean recursive) throws CmsException {
3564
3565        CmsResource resource = readResource(resourcename, CmsResourceFilter.ALL);
3566        getResourceType(resource).undelete(this, m_securityManager, resource, recursive);
3567    }
3568
3569    /**
3570     * Undoes all changes to a resource by restoring the version from the 
3571     * online project to the current offline project.<p>
3572     * 
3573     * @param resourcename the name of the resource to undo the changes for
3574     * @param mode the undo mode, one of the <code>{@link CmsResource.CmsResourceUndoMode}#UNDO_XXX</code> constants
3575     *
3576     * @throws CmsException if something goes wrong
3577     * 
3578     * @see CmsResource#UNDO_CONTENT
3579     * @see CmsResource#UNDO_CONTENT_RECURSIVE
3580     * @see CmsResource#UNDO_MOVE_CONTENT
3581     * @see CmsResource#UNDO_MOVE_CONTENT_RECURSIVE
3582     */
3583    public void undoChanges(String resourcename, CmsResource.CmsResourceUndoMode mode) throws CmsException {
3584
3585        CmsResource resource = readResource(resourcename, CmsResourceFilter.ALL);
3586        getResourceType(resource).undoChanges(this, m_securityManager, resource, mode);
3587    }
3588
3589    /**
3590     * Unlocks all resources of a project.
3591     *
3592     * @param id the id of the project to be unlocked
3593     *
3594     * @throws CmsException if operation was not successful
3595     */
3596    public void unlockProject(CmsUUID id) throws CmsException {
3597
3598        m_securityManager.unlockProject(m_context, id);
3599    }
3600
3601    /**
3602     * Unlocks a resource.<p>
3603     * 
3604     * @param resource the resource to unlock
3605     * 
3606     * @throws CmsException if something goes wrong
3607     */
3608    public void unlockResource(CmsResource resource) throws CmsException {
3609
3610        getResourceType(resource).unlockResource(this, m_securityManager, resource);
3611    }
3612
3613    /**
3614     * Unlocks a resource.<p>
3615     * 
3616     * @param resourcename the name of the resource to unlock (full current site relative path)
3617     * 
3618     * @throws CmsException if something goes wrong
3619     */
3620    public void unlockResource(String resourcename) throws CmsException {
3621
3622        CmsResource resource = readResource(resourcename, CmsResourceFilter.ALL);
3623        getResourceType(resource).unlockResource(this, m_securityManager, resource);
3624    }
3625
3626    /**
3627     * Tests if a user is member of the given group.<p>
3628     *
3629     * @param username the name of the user to test
3630     * @param groupname the name of the group to test
3631     * 
3632     * @return <code>true</code>, if the user is in the group; or <code>false</code> otherwise
3633     *
3634     * @throws CmsException if operation was not successful
3635     */
3636    public boolean userInGroup(String username, String groupname) throws CmsException {
3637
3638        return (m_securityManager.userInGroup(m_context, username, groupname));
3639    }
3640
3641    /**
3642     * This method checks if a new password follows the rules for
3643     * new passwords, which are defined by a Class implementing the 
3644     * <code>{@link org.opencms.security.I_CmsPasswordHandler}</code> 
3645     * interface and configured in the opencms.properties file.<p>
3646     * 
3647     * If this method throws no exception the password is valid.<p>
3648     *
3649     * @param password the new password that has to be checked
3650     *
3651     * @throws CmsSecurityException if the password is not valid
3652     */
3653    public void validatePassword(String password) throws CmsSecurityException {
3654
3655        m_securityManager.validatePassword(password);
3656    }
3657
3658    /**
3659     * Writes a resource to the OpenCms VFS, including it's content.<p>
3660     * 
3661     * Applies only to resources of type <code>{@link CmsFile}</code>
3662     * i.e. resources that have a binary content attached.<p>
3663     * 
3664     * Certain resource types might apply content validation or transformation rules 
3665     * before the resource is actually written to the VFS. The returned result
3666     * might therefore be a modified version from the provided original.<p>
3667     *
3668     * @param resource the resource to write
3669     *
3670     * @return the written resource (may have been modified)
3671     *
3672     * @throws CmsException if something goes wrong
3673     */
3674    public CmsFile writeFile(CmsFile resource) throws CmsException {
3675
3676        return getResourceType(resource).writeFile(this, m_securityManager, resource);
3677    }
3678
3679    /**
3680     * Writes an already existing group.<p>
3681     *
3682     * The group has to be a valid OpenCms group.<br>
3683     * 
3684     * The group will be completely overridden by the given data.<p>
3685     *
3686     * @param group the group that should be written
3687     * 
3688     * @throws CmsException if operation was not successful
3689     */
3690    public void writeGroup(CmsGroup group) throws CmsException {
3691
3692        m_securityManager.writeGroup(m_context, group);
3693    }
3694
3695    /**
3696     * Creates a historical entry of the current project.<p>
3697     * 
3698     * @param publishTag the correlative publish tag
3699     * @param publishDate the date of publishing
3700
3701     * @throws CmsException if operation was not successful
3702     */
3703    public void writeHistoryProject(int publishTag, long publishDate) throws CmsException {
3704
3705        m_securityManager.writeHistoryProject(m_context, publishTag, publishDate);
3706    }
3707
3708    /**
3709     * Writes an already existing project.<p>
3710     *
3711     * The project id has to be a valid OpenCms project id.<br>
3712     * 
3713     * The project with the given id will be completely overridden
3714     * by the given data.<p>
3715     *
3716     * @param project the project that should be written
3717     * 
3718     * @throws CmsException if operation was not successful
3719     */
3720    public void writeProject(CmsProject project) throws CmsException {
3721
3722        m_securityManager.writeProject(m_context, project);
3723    }
3724
3725    /**
3726     * Writes the 'projectlastmodified' field of a resource record.<p>
3727     * 
3728     * @param resource the resource which should be modified 
3729     * @param project the project whose id should be written into the resource record
3730     * 
3731     * @throws CmsException if something goes wrong 
3732     */
3733    public void writeProjectLastModified(CmsResource resource, CmsProject project) throws CmsException {
3734
3735        m_securityManager.writeResourceProjectLastModified(getRequestContext(), resource, project);
3736    }
3737
3738    /**
3739     * Writes a property for a specified resource.<p>
3740     * 
3741     * @param resourcename the name of resource with complete path
3742     * @param property the property to write
3743     * 
3744     * @throws CmsException if something goes wrong
3745     */
3746    public void writePropertyObject(String resourcename, CmsProperty property) throws CmsException {
3747
3748        CmsResource resource = readResource(resourcename, CmsResourceFilter.IGNORE_EXPIRATION);
3749        getResourceType(resource).writePropertyObject(this, m_securityManager, resource, property);
3750    }
3751
3752    /**
3753     * Writes a list of properties for a specified resource.<p>
3754     * 
3755     * Code calling this method has to ensure that the no properties 
3756     * <code>a, b</code> are contained in the specified list so that <code>a.equals(b)</code>, 
3757     * otherwise an exception is thrown.<p>
3758     * 
3759     * @param res the resource
3760     * @param properties the list of properties to write
3761     * 
3762     * @throws CmsException if something goes wrong
3763     */
3764    public void writePropertyObjects(CmsResource res, List<CmsProperty> properties) throws CmsException {
3765
3766        getResourceType(res).writePropertyObjects(this, m_securityManager, res, properties);
3767    }
3768
3769    /**
3770     * Writes a list of properties for a specified resource.<p>
3771     * 
3772     * Code calling this method has to ensure that the no properties 
3773     * <code>a, b</code> are contained in the specified list so that <code>a.equals(b)</code>, 
3774     * otherwise an exception is thrown.<p>
3775     * 
3776     * @param resourcename the name of resource with complete path
3777     * @param properties the list of properties to write
3778     * 
3779     * @throws CmsException if something goes wrong
3780     */
3781    public void writePropertyObjects(String resourcename, List<CmsProperty> properties) throws CmsException {
3782
3783        CmsResource resource = readResource(resourcename, CmsResourceFilter.IGNORE_EXPIRATION);
3784        getResourceType(resource).writePropertyObjects(this, m_securityManager, resource, properties);
3785    }
3786
3787    /**
3788     * Writes a resource.<p>
3789     *
3790     * @param resource the file to write
3791     *
3792     * @throws CmsException if resource type is set to folder, or
3793     *                      if the user has not the rights to write the file header.
3794     */
3795    public void writeResource(CmsResource resource) throws CmsException {
3796
3797        m_securityManager.writeResource(m_context, resource);
3798    }
3799
3800    /**
3801     * Writes a published resource entry.<p>
3802     * 
3803     * This is done during static export.<p>
3804     * 
3805     * @param resourceName The name of the resource to be added to the static export
3806     * @param linkType the type of resource exported (0= non-parameter, 1=parameter)
3807     * @param linkParameter the parameters added to the resource
3808     * @param timestamp a time stamp for writing the data into the db
3809     * 
3810     * @throws CmsException if something goes wrong
3811     */
3812    public void writeStaticExportPublishedResource(
3813        String resourceName,
3814        int linkType,
3815        String linkParameter,
3816        long timestamp) throws CmsException {
3817
3818        m_securityManager.writeStaticExportPublishedResource(
3819            m_context,
3820            resourceName,
3821            linkType,
3822            linkParameter,
3823            timestamp);
3824    }
3825
3826    /**
3827     * Writes a new URL name mapping for a given resource.<p>
3828     * 
3829     * The first name from the given name sequence which is not already mapped to another resource will be used
3830     * for the URL name mapping.<p>
3831     * 
3832     * @param nameSeq an iterator for generating names for the mapping   
3833     * @param structureId the structure id to which the name should be mapped
3834     * @param locale the locale of the mapping 
3835     *   
3836     * @return the name which was actually mapped to the structure id
3837     *  
3838     * @throws CmsException if something goes wrong 
3839     */
3840    public String writeUrlNameMapping(Iterator<String> nameSeq, CmsUUID structureId, String locale) throws CmsException {
3841
3842        return m_securityManager.writeUrlNameMapping(m_context, nameSeq, structureId, locale);
3843    }
3844
3845    /**
3846     * Writes a new URL name mapping for a given resource.<p>
3847     * 
3848     * This method uses {@link CmsNumberSuffixNameSequence} to generate a sequence of name candidates 
3849     * from the given base name.<p>
3850     * 
3851     * @param name the base name for the mapping 
3852     * @param structureId the structure id to which the name should be mapped
3853     * @param locale the locale of the mapping 
3854     *  
3855     * @return the URL name that was actually used for the mapping
3856     * 
3857     * @throws CmsException if something goes wrong 
3858     */
3859    public String writeUrlNameMapping(String name, CmsUUID structureId, String locale) throws CmsException {
3860
3861        return writeUrlNameMapping(new CmsNumberSuffixNameSequence(name), structureId, locale);
3862    }
3863
3864    /**
3865     * Updates the user information. <p>
3866     * 
3867     * The user id has to be a valid OpenCms user id.<br>
3868     * 
3869     * The user with the given id will be completely overriden
3870     * by the given data.<p>
3871     *
3872     * @param user the user to be written
3873     *
3874     * @throws CmsException if operation was not successful
3875     */
3876    public void writeUser(CmsUser user) throws CmsException {
3877
3878        m_securityManager.writeUser(m_context, user);
3879    }
3880
3881    /**
3882     * Adds a new relation to the given resource.<p>
3883     * 
3884     * @param resourceName the name of the source resource
3885     * @param targetPath the path of the target resource
3886     * @param relationType the type of the relation
3887     * @param importCase if importing relations
3888     * 
3889     * @throws CmsException if something goes wrong
3890     */
3891    private void createRelation(String resourceName, String targetPath, String relationType, boolean importCase)
3892    throws CmsException {
3893
3894        CmsResource resource = readResource(resourceName, CmsResourceFilter.IGNORE_EXPIRATION);
3895        CmsResource target = readResource(targetPath, CmsResourceFilter.IGNORE_EXPIRATION);
3896        CmsRelationType type = CmsRelationType.valueOf(relationType);
3897        m_securityManager.addRelationToResource(m_context, resource, target, type, importCase);
3898    }
3899
3900    /**
3901     * Notify all event listeners that a particular event has occurred.<p>
3902     * 
3903     * The event will be given to all registered <code>{@link I_CmsEventListener}</code>s.<p>
3904     * 
3905     * @param type the type of the event
3906     * @param data a data object that contains data used by the event listeners
3907     * 
3908     * @see OpenCms#addCmsEventListener(I_CmsEventListener)
3909     * @see OpenCms#addCmsEventListener(I_CmsEventListener, int[])
3910     */
3911    private void fireEvent(int type, Object data) {
3912
3913        OpenCms.fireCmsEvent(type, Collections.singletonMap("data", data));
3914    }
3915
3916    /**
3917     * Convenience method to get the initialized resource type instance for the given resource, 
3918     * with a fall back to special "unknown" resource types in case the resource type is not configured.<p>
3919     * 
3920     * @param resource the resource to get the type for
3921     * 
3922     * @return the initialized resource type instance for the given resource
3923     * 
3924     * @see org.opencms.loader.CmsResourceManager#getResourceType(int)
3925     */
3926    private I_CmsResourceType getResourceType(CmsResource resource) {
3927
3928        return OpenCms.getResourceManager().getResourceType(resource);
3929    }
3930
3931    /**
3932     * Convenience method to return the initialized resource type 
3933     * instance for the given id.<p>
3934     * 
3935     * @param resourceType the id of the resource type to get
3936     * 
3937     * @return the initialized resource type instance for the given id
3938     * 
3939     * @throws CmsException if something goes wrong
3940     * 
3941     * @see org.opencms.loader.CmsResourceManager#getResourceType(int)
3942     */
3943    private I_CmsResourceType getResourceType(int resourceType) throws CmsException {
3944
3945        return OpenCms.getResourceManager().getResourceType(resourceType);
3946    }
3947
3948    /**
3949     * Initializes this <code>{@link CmsObject}</code> with the provided user context and database connection.<p>
3950     * 
3951     * @param securityManager the security manager
3952     * @param context the request context that contains the user authentication
3953     */
3954    private void init(CmsSecurityManager securityManager, CmsRequestContext context) {
3955
3956        m_securityManager = securityManager;
3957        m_context = context;
3958    }
3959
3960    /**
3961     * Locks a resource.<p>
3962     *
3963     * The <code>type</code> parameter controls what kind of lock is used.<br>
3964     * Possible values for this parameter are: <br>
3965     * <ul>
3966     * <li><code>{@link org.opencms.lock.CmsLockType#EXCLUSIVE}</code></li>
3967     * <li><code>{@link org.opencms.lock.CmsLockType#TEMPORARY}</code></li>
3968     * </ul><p>
3969     * 
3970     * @param resourcename the name of the resource to lock (full current site relative path)
3971     * @param type type of the lock
3972     * 
3973     * @throws CmsException if something goes wrong
3974     */
3975    private void lockResource(String resourcename, CmsLockType type) throws CmsException {
3976
3977        // throw the exception if resource name is an empty string
3978        if (CmsStringUtil.isEmptyOrWhitespaceOnly(resourcename)) {
3979            throw new CmsVfsResourceNotFoundException(Messages.get().container(
3980                Messages.ERR_LOCK_RESOURCE_1,
3981                resourcename));
3982        }
3983        CmsResource resource = readResource(resourcename, CmsResourceFilter.ALL);
3984        getResourceType(resource).lockResource(this, m_securityManager, resource, type);
3985    }
3986
3987}