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