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