Source Code Cross Referenced for CmsDriverManager.java in  » Content-Management-System » opencms » org » opencms » db » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Content Management System » opencms » org.opencms.db 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


00001:        /*
00002:         * File   : $Source: /usr/local/cvs/opencms/src/org/opencms/db/CmsDriverManager.java,v $
00003:         * Date   : $Date: 2008-02-29 10:39:59 $
00004:         * Version: $Revision: 1.611 $
00005:         *
00006:         * This library is part of OpenCms -
00007:         * the Open Source Content Management System
00008:         *
00009:         * Copyright (c) 2002 - 2008 Alkacon Software GmbH (http://www.alkacon.com)
00010:         *
00011:         * This library is free software; you can redistribute it and/or
00012:         * modify it under the terms of the GNU Lesser General Public
00013:         * License as published by the Free Software Foundation; either
00014:         * version 2.1 of the License, or (at your option) any later version.
00015:         *
00016:         * This library is distributed in the hope that it will be useful,
00017:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00019:         * Lesser General Public License for more details.
00020:         *
00021:         * For further information about Alkacon Software GmbH, please see the
00022:         * company website: http://www.alkacon.com
00023:         *
00024:         * For further information about OpenCms, please see the
00025:         * project website: http://www.opencms.org
00026:         * 
00027:         * You should have received a copy of the GNU Lesser General Public
00028:         * License along with this library; if not, write to the Free Software
00029:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00030:         */
00031:
00032:        package org.opencms.db;
00033:
00034:        import org.opencms.configuration.CmsConfigurationManager;
00035:        import org.opencms.configuration.CmsSystemConfiguration;
00036:        import org.opencms.file.CmsDataAccessException;
00037:        import org.opencms.file.CmsFile;
00038:        import org.opencms.file.CmsFolder;
00039:        import org.opencms.file.CmsGroup;
00040:        import org.opencms.file.CmsObject;
00041:        import org.opencms.file.CmsProject;
00042:        import org.opencms.file.CmsProperty;
00043:        import org.opencms.file.CmsPropertyDefinition;
00044:        import org.opencms.file.CmsRequestContext;
00045:        import org.opencms.file.CmsResource;
00046:        import org.opencms.file.CmsResourceFilter;
00047:        import org.opencms.file.CmsUser;
00048:        import org.opencms.file.CmsVfsException;
00049:        import org.opencms.file.CmsVfsResourceAlreadyExistsException;
00050:        import org.opencms.file.CmsVfsResourceNotFoundException;
00051:        import org.opencms.file.history.CmsHistoryFile;
00052:        import org.opencms.file.history.CmsHistoryFolder;
00053:        import org.opencms.file.history.CmsHistoryPrincipal;
00054:        import org.opencms.file.history.CmsHistoryProject;
00055:        import org.opencms.file.history.I_CmsHistoryResource;
00056:        import org.opencms.file.types.CmsResourceTypeFolder;
00057:        import org.opencms.file.types.CmsResourceTypeJsp;
00058:        import org.opencms.file.types.I_CmsResourceType;
00059:        import org.opencms.flex.CmsFlexRequestContextInfo;
00060:        import org.opencms.i18n.CmsLocaleManager;
00061:        import org.opencms.i18n.CmsMessageContainer;
00062:        import org.opencms.lock.CmsLock;
00063:        import org.opencms.lock.CmsLockException;
00064:        import org.opencms.lock.CmsLockFilter;
00065:        import org.opencms.lock.CmsLockManager;
00066:        import org.opencms.lock.CmsLockType;
00067:        import org.opencms.main.CmsEvent;
00068:        import org.opencms.main.CmsException;
00069:        import org.opencms.main.CmsIllegalArgumentException;
00070:        import org.opencms.main.CmsIllegalStateException;
00071:        import org.opencms.main.CmsInitException;
00072:        import org.opencms.main.CmsLog;
00073:        import org.opencms.main.CmsMultiException;
00074:        import org.opencms.main.I_CmsEventListener;
00075:        import org.opencms.main.OpenCms;
00076:        import org.opencms.module.CmsModule;
00077:        import org.opencms.publish.CmsPublishEngine;
00078:        import org.opencms.publish.CmsPublishJobInfoBean;
00079:        import org.opencms.publish.CmsPublishReport;
00080:        import org.opencms.relations.CmsLink;
00081:        import org.opencms.relations.CmsRelation;
00082:        import org.opencms.relations.CmsRelationFilter;
00083:        import org.opencms.relations.CmsRelationSystemValidator;
00084:        import org.opencms.relations.CmsRelationType;
00085:        import org.opencms.relations.I_CmsLinkParseable;
00086:        import org.opencms.report.CmsLogReport;
00087:        import org.opencms.report.I_CmsReport;
00088:        import org.opencms.security.CmsAccessControlEntry;
00089:        import org.opencms.security.CmsAccessControlList;
00090:        import org.opencms.security.CmsAuthentificationException;
00091:        import org.opencms.security.CmsOrganizationalUnit;
00092:        import org.opencms.security.CmsPasswordEncryptionException;
00093:        import org.opencms.security.CmsPermissionSet;
00094:        import org.opencms.security.CmsPermissionSetCustom;
00095:        import org.opencms.security.CmsRole;
00096:        import org.opencms.security.CmsSecurityException;
00097:        import org.opencms.security.I_CmsPermissionHandler;
00098:        import org.opencms.security.I_CmsPrincipal;
00099:        import org.opencms.util.CmsFileUtil;
00100:        import org.opencms.util.CmsStringUtil;
00101:        import org.opencms.util.CmsUUID;
00102:        import org.opencms.workplace.commons.CmsProgressThread;
00103:
00104:        import java.util.ArrayList;
00105:        import java.util.Arrays;
00106:        import java.util.Collection;
00107:        import java.util.Collections;
00108:        import java.util.Date;
00109:        import java.util.HashMap;
00110:        import java.util.HashSet;
00111:        import java.util.Iterator;
00112:        import java.util.List;
00113:        import java.util.ListIterator;
00114:        import java.util.Map;
00115:        import java.util.Set;
00116:        import java.util.TreeSet;
00117:        import java.util.regex.Pattern;
00118:        import java.util.regex.PatternSyntaxException;
00119:
00120:        import org.apache.commons.collections.ExtendedProperties;
00121:        import org.apache.commons.dbcp.PoolingDriver;
00122:        import org.apache.commons.logging.Log;
00123:        import org.apache.commons.pool.ObjectPool;
00124:
00125:        /**
00126:         * The OpenCms driver manager.<p>
00127:         * 
00128:         * @author Alexander Kandzior 
00129:         * @author Thomas Weckert 
00130:         * @author Carsten Weinholz 
00131:         * @author Michael Emmerich 
00132:         * @author Michael Moossen
00133:         * 
00134:         * @since 6.0.0
00135:         */
00136:        public final class CmsDriverManager implements  I_CmsEventListener {
00137:
00138:            /**
00139:             * Enumeration class for the mode parameter in the 
00140:             * {@link CmsDriverManager#readChangedResourcesInsideProject(CmsDbContext, CmsUUID, CmsReadChangedProjectResourceMode)} 
00141:             * method.<p>
00142:             */
00143:            private static class CmsReadChangedProjectResourceMode {
00144:
00145:                /**
00146:                 * Default constructor.<p>
00147:                 */
00148:                protected CmsReadChangedProjectResourceMode() {
00149:
00150:                    // noop
00151:                }
00152:            }
00153:
00154:            /** Cache key for all properties. */
00155:            public static final String CACHE_ALL_PROPERTIES = "_CAP_";
00156:
00157:            /** 
00158:             * Values indicating changes of a resource, 
00159:             * ordered according to the scope of the change. 
00160:             */
00161:            /** Value to indicate a change in access control entries of a resource. */
00162:            public static final int CHANGED_ACCESSCONTROL = 1;
00163:
00164:            /** Value to indicate a content change. */
00165:            public static final int CHANGED_CONTENT = 16;
00166:
00167:            /** Value to indicate a change in the lastmodified settings of a resource. */
00168:            public static final int CHANGED_LASTMODIFIED = 4;
00169:
00170:            /** Value to indicate a change in the resource data. */
00171:            public static final int CHANGED_RESOURCE = 8;
00172:
00173:            /** Value to indicate a change in the availability timeframe. */
00174:            public static final int CHANGED_TIMEFRAME = 2;
00175:
00176:            /** 
00177:             * "driver.backup" string in the configuration-file. 
00178:             * @deprecated use {@link #CONFIGURATION_HISTORY} instead 
00179:             */
00180:            public static final String CONFIGURATION_BACKUP = "driver.backup";
00181:
00182:            /** "cache" string in the configuration-file. */
00183:            public static final String CONFIGURATION_CACHE = "cache";
00184:
00185:            /** "db" string in the configuration-file. */
00186:            public static final String CONFIGURATION_DB = "db";
00187:
00188:            /** "driver.history" string in the configuration-file. */
00189:            public static final String CONFIGURATION_HISTORY = "driver.history";
00190:
00191:            /** "driver.project" string in the configuration-file. */
00192:            public static final String CONFIGURATION_PROJECT = "driver.project";
00193:
00194:            /** "driver.user" string in the configuration-file. */
00195:            public static final String CONFIGURATION_USER = "driver.user";
00196:
00197:            /** "driver.vfs" string in the configuration-file. */
00198:            public static final String CONFIGURATION_VFS = "driver.vfs";
00199:
00200:            /** The vfs path of the loast and found folder. */
00201:            public static final String LOST_AND_FOUND_FOLDER = "/system/lost-found";
00202:
00203:            /** The maximum length of a VFS resource path. */
00204:            public static final int MAX_VFS_RESOURCE_PATH_LENGTH = 512;
00205:
00206:            /** Key for indicating no changes. */
00207:            public static final int NOTHING_CHANGED = 0;
00208:
00209:            /** Indicates to ignore the resource path when matching resources. */
00210:            public static final String READ_IGNORE_PARENT = null;
00211:
00212:            /** Indicates to ignore the time value. */
00213:            public static final long READ_IGNORE_TIME = 0L;
00214:
00215:            /** Indicates to ignore the resource type when matching resources. */
00216:            public static final int READ_IGNORE_TYPE = -1;
00217:
00218:            /** Indicates to match resources NOT having the given state. */
00219:            public static final int READMODE_EXCLUDE_STATE = 8;
00220:
00221:            /** Indicates to match immediate children only. */
00222:            public static final int READMODE_EXCLUDE_TREE = 1;
00223:
00224:            /** Indicates to match resources NOT having the given type. */
00225:            public static final int READMODE_EXCLUDE_TYPE = 4;
00226:
00227:            /** Mode for reading project resources from the db. */
00228:            public static final int READMODE_IGNORESTATE = 0;
00229:
00230:            /** Indicates to match resources in given project only. */
00231:            public static final int READMODE_INCLUDE_PROJECT = 2;
00232:
00233:            /** Indicates to match all successors. */
00234:            public static final int READMODE_INCLUDE_TREE = 0;
00235:
00236:            /** Mode for reading project resources from the db. */
00237:            public static final int READMODE_MATCHSTATE = 1;
00238:
00239:            /** Indicates if only file resources should be read. */
00240:            public static final int READMODE_ONLY_FILES = 128;
00241:
00242:            /** Indicates if only folder resources should be read. */
00243:            public static final int READMODE_ONLY_FOLDERS = 64;
00244:
00245:            /** Mode for reading project resources from the db. */
00246:            public static final int READMODE_UNMATCHSTATE = 2;
00247:
00248:            /** Prefix char for temporary files in the VFS. */
00249:            public static final String TEMP_FILE_PREFIX = "~";
00250:
00251:            /** Key to indicate complete update. */
00252:            public static final int UPDATE_ALL = 3;
00253:
00254:            /** Key to indicate update of resource record. */
00255:            public static final int UPDATE_RESOURCE = 4;
00256:
00257:            /** Key to indicate update of last modified project reference. */
00258:            public static final int UPDATE_RESOURCE_PROJECT = 6;
00259:
00260:            /** Key to indicate update of resource state. */
00261:            public static final int UPDATE_RESOURCE_STATE = 1;
00262:
00263:            /** Key to indicate update of resource state including the content date. */
00264:            public static final int UPDATE_RESOURCE_STATE_CONTENT = 7;
00265:
00266:            /** Key to indicate update of structure record. */
00267:            public static final int UPDATE_STRUCTURE = 5;
00268:
00269:            /** Key to indicate update of structure state. */
00270:            public static final int UPDATE_STRUCTURE_STATE = 2;
00271:
00272:            /** The log object for this class. */
00273:            private static final Log LOG = CmsLog
00274:                    .getLog(CmsDriverManager.class);
00275:
00276:            /** Constant mode parameter to read all files and folders in the {@link #readChangedResourcesInsideProject(CmsDbContext, CmsUUID, CmsReadChangedProjectResourceMode)}} method. */
00277:            private static final CmsReadChangedProjectResourceMode RCPRM_FILES_AND_FOLDERS_MODE = new CmsReadChangedProjectResourceMode();
00278:
00279:            /** Constant mode parameter to read all files and folders in the {@link #readChangedResourcesInsideProject(CmsDbContext, CmsUUID, CmsReadChangedProjectResourceMode)}} method. */
00280:            private static final CmsReadChangedProjectResourceMode RCPRM_FILES_ONLY_MODE = new CmsReadChangedProjectResourceMode();
00281:
00282:            /** Constant mode parameter to read all files and folders in the {@link #readChangedResourcesInsideProject(CmsDbContext, CmsUUID, CmsReadChangedProjectResourceMode)}} method. */
00283:            private static final CmsReadChangedProjectResourceMode RCPRM_FOLDERS_ONLY_MODE = new CmsReadChangedProjectResourceMode();
00284:
00285:            /** The list of initialized JDBC pools. */
00286:            private List m_connectionPools;
00287:
00288:            /** The history driver. */
00289:            private I_CmsHistoryDriver m_historyDriver;
00290:
00291:            /** The HTML link validator. */
00292:            private CmsRelationSystemValidator m_htmlLinkValidator;
00293:
00294:            /** The class used for cache key generation. */
00295:            private I_CmsCacheKey m_keyGenerator;
00296:
00297:            /** The lock manager. */
00298:            private CmsLockManager m_lockManager;
00299:
00300:            /** The project driver. */
00301:            private I_CmsProjectDriver m_projectDriver;
00302:
00303:            /** The the configuration read from the <code>opencms.properties</code> file. */
00304:            private ExtendedProperties m_propertyConfiguration;
00305:
00306:            /* the publish engine. */
00307:            private CmsPublishEngine m_publishEngine;
00308:
00309:            /** The security manager (for access checks). */
00310:            private CmsSecurityManager m_securityManager;
00311:
00312:            /** The sql manager. */
00313:            private CmsSqlManager m_sqlManager;
00314:
00315:            /** The user driver. */
00316:            private I_CmsUserDriver m_userDriver;
00317:
00318:            /** The VFS driver. */
00319:            private I_CmsVfsDriver m_vfsDriver;
00320:
00321:            /**
00322:             * Private constructor, initializes some required member variables.<p> 
00323:             */
00324:            private CmsDriverManager() {
00325:
00326:                // intentionally left blank
00327:            }
00328:
00329:            /**
00330:             * Reads the required configurations from the opencms.properties file and creates
00331:             * the various drivers to access the cms resources.<p>
00332:             * 
00333:             * The initialization process of the driver manager and its drivers is split into
00334:             * the following phases:
00335:             * <ul>
00336:             * <li>the database pool configuration is read</li>
00337:             * <li>a plain and empty driver manager instance is created</li>
00338:             * <li>an instance of each driver is created</li>
00339:             * <li>the driver manager is passed to each driver during initialization</li>
00340:             * <li>finally, the driver instances are passed to the driver manager during initialization</li>
00341:             * </ul>
00342:             * 
00343:             * @param configurationManager the configuration manager
00344:             * @param securityManager the security manager
00345:             * @param runtimeInfoFactory the initialized OpenCms runtime info factory
00346:             * @param publishEngine the publish engine
00347:             * 
00348:             * @return CmsDriverManager the instantiated driver manager
00349:             * @throws CmsInitException if the driver manager couldn't be instantiated
00350:             */
00351:            public static CmsDriverManager newInstance(
00352:                    CmsConfigurationManager configurationManager,
00353:                    CmsSecurityManager securityManager,
00354:                    I_CmsDbContextFactory runtimeInfoFactory,
00355:                    CmsPublishEngine publishEngine) throws CmsInitException {
00356:
00357:                // read the opencms.properties from the configuration
00358:                ExtendedProperties config = (ExtendedProperties) configurationManager
00359:                        .getConfiguration();
00360:
00361:                List drivers = null;
00362:                String driverName = null;
00363:
00364:                I_CmsVfsDriver vfsDriver = null;
00365:                I_CmsUserDriver userDriver = null;
00366:                I_CmsProjectDriver projectDriver = null;
00367:                I_CmsHistoryDriver historyDriver = null;
00368:
00369:                CmsDriverManager driverManager = null;
00370:                try {
00371:                    // create a driver manager instance
00372:                    driverManager = new CmsDriverManager();
00373:                    if (CmsLog.INIT.isInfoEnabled()) {
00374:                        CmsLog.INIT.info(Messages.get().getBundle().key(
00375:                                Messages.INIT_DRIVER_MANAGER_START_PHASE1_0));
00376:                    }
00377:                    if ((runtimeInfoFactory == null)
00378:                            && CmsLog.INIT.isDebugEnabled()) {
00379:                        CmsLog.INIT.debug(Messages.get().getBundle().key(
00380:                                Messages.INIT_DRIVER_MANAGER_START_RT_0));
00381:                    }
00382:                } catch (Exception exc) {
00383:                    CmsMessageContainer message = Messages.get().container(
00384:                            Messages.LOG_ERR_DRIVER_MANAGER_START_0);
00385:                    if (LOG.isFatalEnabled()) {
00386:                        LOG.fatal(message.key(), exc);
00387:                    }
00388:                    throw new CmsInitException(message, exc);
00389:                }
00390:
00391:                // set the security manager
00392:                driverManager.m_securityManager = securityManager;
00393:
00394:                // set connection pools
00395:                driverManager.m_connectionPools = new ArrayList();
00396:
00397:                // set the lock manager
00398:                driverManager.m_lockManager = new CmsLockManager(driverManager);
00399:
00400:                // create and set the sql manager
00401:                driverManager.m_sqlManager = new CmsSqlManager(driverManager);
00402:
00403:                // set the publish engine
00404:                driverManager.m_publishEngine = publishEngine;
00405:
00406:                if (CmsLog.INIT.isInfoEnabled()) {
00407:                    CmsLog.INIT.info(Messages.get().getBundle().key(
00408:                            Messages.INIT_DRIVER_MANAGER_START_PHASE2_0));
00409:                }
00410:
00411:                // read the pool names to initialize
00412:                String[] driverPoolNames = config
00413:                        .getStringArray(CmsDriverManager.CONFIGURATION_DB
00414:                                + ".pools");
00415:                if (CmsLog.INIT.isInfoEnabled()) {
00416:                    String names = "";
00417:                    for (int p = 0; p < driverPoolNames.length; p++) {
00418:                        names += driverPoolNames[p] + " ";
00419:                    }
00420:                    CmsLog.INIT.info(Messages.get().getBundle().key(
00421:                            Messages.INIT_DRIVER_MANAGER_START_POOLS_1, names));
00422:                }
00423:
00424:                // initialize each pool
00425:                for (int p = 0; p < driverPoolNames.length; p++) {
00426:                    driverManager.newPoolInstance(config, driverPoolNames[p]);
00427:                }
00428:
00429:                // initialize the runtime info factory with the generated driver manager
00430:                if (runtimeInfoFactory != null) {
00431:                    runtimeInfoFactory.initialize(driverManager);
00432:                }
00433:
00434:                if (CmsLog.INIT.isInfoEnabled()) {
00435:                    CmsLog.INIT.info(Messages.get().getBundle().key(
00436:                            Messages.INIT_DRIVER_MANAGER_START_PHASE3_0));
00437:                }
00438:
00439:                // read the vfs driver class properties and initialize a new instance 
00440:                drivers = Arrays.asList(config
00441:                        .getStringArray(CmsDriverManager.CONFIGURATION_VFS));
00442:                String driverKey = (String) drivers.get(0) + ".vfs.driver";
00443:                driverName = config.getString(driverKey);
00444:                drivers = (drivers.size() > 1) ? drivers.subList(1, drivers
00445:                        .size()) : null;
00446:                if (driverName == null) {
00447:                    CmsLog.INIT.error(Messages.get().getBundle().key(
00448:                            Messages.INIT_DRIVER_FAILED_1, driverKey));
00449:                }
00450:                vfsDriver = (I_CmsVfsDriver) driverManager.newDriverInstance(
00451:                        configurationManager, driverName, drivers);
00452:
00453:                // read the user driver class properties and initialize a new instance 
00454:                drivers = Arrays.asList(config
00455:                        .getStringArray(CmsDriverManager.CONFIGURATION_USER));
00456:                driverKey = (String) drivers.get(0) + ".user.driver";
00457:                driverName = config.getString(driverKey);
00458:                drivers = (drivers.size() > 1) ? drivers.subList(1, drivers
00459:                        .size()) : null;
00460:                if (driverName == null) {
00461:                    CmsLog.INIT.error(Messages.get().getBundle().key(
00462:                            Messages.INIT_DRIVER_FAILED_1, driverKey));
00463:                }
00464:                userDriver = (I_CmsUserDriver) driverManager.newDriverInstance(
00465:                        configurationManager, driverName, drivers);
00466:
00467:                // read the project driver class properties and initialize a new instance 
00468:                drivers = Arrays
00469:                        .asList(config
00470:                                .getStringArray(CmsDriverManager.CONFIGURATION_PROJECT));
00471:                driverKey = (String) drivers.get(0) + ".project.driver";
00472:                driverName = config.getString(driverKey);
00473:                drivers = (drivers.size() > 1) ? drivers.subList(1, drivers
00474:                        .size()) : null;
00475:                if (driverName == null) {
00476:                    CmsLog.INIT.error(Messages.get().getBundle().key(
00477:                            Messages.INIT_DRIVER_FAILED_1, driverKey));
00478:                }
00479:                projectDriver = (I_CmsProjectDriver) driverManager
00480:                        .newDriverInstance(configurationManager, driverName,
00481:                                drivers);
00482:
00483:                // read the history driver class properties and initialize a new instance 
00484:                if (config.get(CmsDriverManager.CONFIGURATION_HISTORY) != null) {
00485:                    drivers = Arrays
00486:                            .asList(config
00487:                                    .getStringArray(CmsDriverManager.CONFIGURATION_HISTORY));
00488:                    driverKey = (String) drivers.get(0) + ".history.driver";
00489:                    driverName = config.getString(driverKey);
00490:                    drivers = (drivers.size() > 1) ? drivers.subList(1, drivers
00491:                            .size()) : null;
00492:                    if (driverName == null) {
00493:                        CmsLog.INIT.error(Messages.get().getBundle().key(
00494:                                Messages.INIT_DRIVER_FAILED_1, driverKey));
00495:                    }
00496:                    historyDriver = (I_CmsHistoryDriver) driverManager
00497:                            .newDriverInstance(configurationManager,
00498:                                    driverName, drivers);
00499:                } else {
00500:                    drivers = Arrays
00501:                            .asList(config
00502:                                    .getStringArray(CmsDriverManager.CONFIGURATION_BACKUP));
00503:                    driverKey = (String) drivers.get(0) + ".backup.driver";
00504:                    driverName = config.getString(driverKey);
00505:                    drivers = (drivers.size() > 1) ? drivers.subList(1, drivers
00506:                            .size()) : null;
00507:                    if (driverName == null) {
00508:                        CmsLog.INIT.error(Messages.get().getBundle().key(
00509:                                Messages.INIT_DRIVER_FAILED_1, driverKey));
00510:                    }
00511:                    historyDriver = (I_CmsHistoryDriver) driverManager
00512:                            .newDriverInstance(configurationManager,
00513:                                    driverName, drivers);
00514:                }
00515:
00516:                // store the access objects
00517:                driverManager.m_vfsDriver = vfsDriver;
00518:                driverManager.m_userDriver = userDriver;
00519:                driverManager.m_projectDriver = projectDriver;
00520:                driverManager.m_historyDriver = historyDriver;
00521:
00522:                // store the configuration
00523:                driverManager.m_propertyConfiguration = config;
00524:
00525:                // register the driver manager for required events
00526:                org.opencms.main.OpenCms
00527:                        .addCmsEventListener(
00528:                                driverManager,
00529:                                new int[] {
00530:                                        I_CmsEventListener.EVENT_UPDATE_EXPORTS,
00531:                                        I_CmsEventListener.EVENT_CLEAR_CACHES,
00532:                                        I_CmsEventListener.EVENT_CLEAR_PRINCIPAL_CACHES,
00533:                                        I_CmsEventListener.EVENT_PUBLISH_PROJECT });
00534:
00535:                // return the configured driver manager
00536:                return driverManager;
00537:            }
00538:
00539:            /**
00540:             * Adds a new relation to the given resource.<p>
00541:             * 
00542:             * @param dbc the database context
00543:             * @param resource the resource to add the relation to
00544:             * @param target the target of the relation
00545:             * @param type the type of the relation
00546:             * @param importCase if importing relations
00547:             * 
00548:             * @throws CmsException if something goes wrong
00549:             */
00550:            public void addRelationToResource(CmsDbContext dbc,
00551:                    CmsResource resource, CmsResource target,
00552:                    CmsRelationType type, boolean importCase)
00553:                    throws CmsException {
00554:
00555:                if (type.isDefinedInContent()) {
00556:                    throw new CmsIllegalArgumentException(Messages.get()
00557:                            .container(
00558:                                    Messages.ERR_ADD_RELATION_IN_CONTENT_3,
00559:                                    dbc.removeSiteRoot(resource.getRootPath()),
00560:                                    dbc.removeSiteRoot(target.getRootPath()),
00561:                                    type.getLocalizedName(dbc
00562:                                            .getRequestContext().getLocale())));
00563:                }
00564:                CmsRelation relation = new CmsRelation(resource, target, type);
00565:                m_vfsDriver.createRelation(dbc, dbc.currentProject().getUuid(),
00566:                        relation);
00567:                if (!importCase) {
00568:                    setDateLastModified(dbc, resource, System
00569:                            .currentTimeMillis());
00570:                }
00571:            }
00572:
00573:            /**
00574:             * Adds a resource to the given organizational unit.<p>
00575:             * 
00576:             * @param dbc the current db context
00577:             * @param orgUnit the organizational unit to add the resource to
00578:             * @param resource the resource that is to be added to the organizational unit
00579:             * 
00580:             * @throws CmsException if something goes wrong
00581:             * 
00582:             * @see org.opencms.security.CmsOrgUnitManager#addResourceToOrgUnit(CmsObject, String, String)
00583:             * @see org.opencms.security.CmsOrgUnitManager#addResourceToOrgUnit(CmsObject, String, String)
00584:             */
00585:            public void addResourceToOrgUnit(CmsDbContext dbc,
00586:                    CmsOrganizationalUnit orgUnit, CmsResource resource)
00587:                    throws CmsException {
00588:
00589:                OpenCms.getMemoryMonitor().flushRoles();
00590:                OpenCms.getMemoryMonitor().flushRoleLists();
00591:                m_userDriver.addResourceToOrganizationalUnit(dbc, orgUnit,
00592:                        resource);
00593:            }
00594:
00595:            /**
00596:             * Adds a user to a group.<p>
00597:             *
00598:             * @param dbc the current database context
00599:             * @param username the name of the user that is to be added to the group
00600:             * @param groupname the name of the group
00601:             * @param readRoles if reading roles or groups
00602:             *
00603:             * @throws CmsException if operation was not successful
00604:             * @throws CmsDbEntryNotFoundException if the given user or the given group was not found 
00605:             * 
00606:             * @see #removeUserFromGroup(CmsDbContext, String, String, boolean)
00607:             */
00608:            public void addUserToGroup(CmsDbContext dbc, String username,
00609:                    String groupname, boolean readRoles) throws CmsException,
00610:                    CmsDbEntryNotFoundException {
00611:
00612:                //check if group exists
00613:                CmsGroup group = readGroup(dbc, groupname);
00614:                if (group == null) {
00615:                    // the group does not exists
00616:                    throw new CmsDbEntryNotFoundException(Messages.get()
00617:                            .container(Messages.ERR_UNKNOWN_GROUP_1, groupname));
00618:                }
00619:                if (group.isVirtual() && !readRoles) {
00620:                    // if adding a user from a virtual role treat it as removing the user from the role
00621:                    addUserToGroup(dbc, username, CmsRole.valueOf(group)
00622:                            .getGroupName(), true);
00623:                    return;
00624:                }
00625:                if (group.isVirtual()) {
00626:                    // this is an hack to prevent unlimited recursive calls
00627:                    readRoles = false;
00628:                }
00629:                if ((readRoles && !group.isRole())
00630:                        || (!readRoles && group.isRole())) {
00631:                    // we want a role but we got a group, or the other way
00632:                    throw new CmsDbEntryNotFoundException(Messages.get()
00633:                            .container(Messages.ERR_UNKNOWN_GROUP_1, groupname));
00634:                }
00635:                if (userInGroup(dbc, username, groupname, readRoles)) {
00636:                    // the user is already member of the group
00637:                    return;
00638:                }
00639:                //check if the user exists
00640:                CmsUser user = readUser(dbc, username);
00641:                if (user == null) {
00642:                    // the user does not exists
00643:                    throw new CmsDbEntryNotFoundException(Messages.get()
00644:                            .container(Messages.ERR_UNKNOWN_USER_1, username));
00645:                }
00646:
00647:                // if adding an user to a role
00648:                if (readRoles) {
00649:                    CmsRole role = CmsRole.valueOf(group);
00650:                    // a role can only be set if the user has the given role
00651:                    m_securityManager.checkRole(dbc, role);
00652:                    // now we check if we already have the role 
00653:                    if (m_securityManager.hasRole(dbc, user, role)) {
00654:                        // do nothing
00655:                        return;
00656:                    }
00657:                    // and now we need to remove all possible child-roles
00658:                    List children = role.getChildren(true);
00659:                    Iterator itUserGroups = getGroupsOfUser(dbc, username,
00660:                            group.getOuFqn(), true, true, true,
00661:                            dbc.getRequestContext().getRemoteAddress())
00662:                            .iterator();
00663:                    while (itUserGroups.hasNext()) {
00664:                        CmsGroup roleGroup = (CmsGroup) itUserGroups.next();
00665:                        if (children.contains(CmsRole.valueOf(roleGroup))) {
00666:                            // remove only child roles
00667:                            removeUserFromGroup(dbc, username, roleGroup
00668:                                    .getName(), true);
00669:                        }
00670:                    }
00671:                    // update virtual groups
00672:                    Iterator it = getVirtualGroupsForRole(dbc, role).iterator();
00673:                    while (it.hasNext()) {
00674:                        CmsGroup virtualGroup = (CmsGroup) it.next();
00675:                        // here we say readroles = true, to prevent an unlimited recursive calls
00676:                        addUserToGroup(dbc, username, virtualGroup.getName(),
00677:                                true);
00678:                    }
00679:                    // if setting a role that is not the workplace user role ensure the user is also wp user
00680:                    CmsRole wpUser = CmsRole.WORKPLACE_USER.forOrgUnit(group
00681:                            .getOuFqn());
00682:                    if (!role.equals(wpUser)
00683:                            && !role.getChildren(true).contains(wpUser)
00684:                            && !m_securityManager.hasRole(dbc, user, wpUser)) {
00685:                        addUserToGroup(dbc, username, wpUser.getGroupName(),
00686:                                true);
00687:                    }
00688:                }
00689:
00690:                //add this user to the group
00691:                m_userDriver
00692:                        .createUserInGroup(dbc, user.getId(), group.getId());
00693:
00694:                // flush the cache
00695:                if (readRoles) {
00696:                    OpenCms.getMemoryMonitor().flushRoles();
00697:                    OpenCms.getMemoryMonitor().flushRoleLists();
00698:                }
00699:                OpenCms.getMemoryMonitor().flushUserGroups();
00700:            }
00701:
00702:            /**
00703:             * Changes the lock of a resource to the current user,
00704:             * that is "steals" the lock from another user.<p>
00705:             * 
00706:             * @param dbc the current database context
00707:             * @param resource the resource to change the lock for
00708:             * @param lockType the new lock type to set
00709:             * 
00710:             * @throws CmsException if something goes wrong
00711:             * @throws CmsSecurityException if something goes wrong
00712:             * 
00713:             * 
00714:             * @see CmsObject#changeLock(String)
00715:             * @see I_CmsResourceType#changeLock(CmsObject, CmsSecurityManager, CmsResource)
00716:             * 
00717:             * @see CmsSecurityManager#hasPermissions(CmsRequestContext, CmsResource, CmsPermissionSet, boolean, CmsResourceFilter)
00718:             */
00719:            public void changeLock(CmsDbContext dbc, CmsResource resource,
00720:                    CmsLockType lockType) throws CmsException,
00721:                    CmsSecurityException {
00722:
00723:                // get the current lock
00724:                CmsLock currentLock = getLock(dbc, resource);
00725:                // check if the resource is locked at all
00726:                if (currentLock.getEditionLock().isUnlocked()
00727:                        && currentLock.getSystemLock().isUnlocked()) {
00728:                    throw new CmsLockException(Messages.get().container(
00729:                            Messages.ERR_CHANGE_LOCK_UNLOCKED_RESOURCE_1,
00730:                            dbc.getRequestContext().getSitePath(resource)));
00731:                } else if ((lockType == CmsLockType.EXCLUSIVE)
00732:                        && currentLock.isExclusiveOwnedInProjectBy(dbc
00733:                                .currentUser(), dbc.currentProject())) {
00734:                    // the current lock requires no change
00735:                    return;
00736:                }
00737:
00738:                // duplicate logic from CmsSecurityManager#hasPermissions() because lock state can't be ignored
00739:                // if another user has locked the file, the current user can never get WRITE permissions with the default check
00740:                int denied = 0;
00741:
00742:                // check if the current user is vfs manager
00743:                boolean canIgnorePermissions = m_securityManager
00744:                        .hasRoleForResource(dbc, dbc.currentUser(),
00745:                                CmsRole.VFS_MANAGER, resource);
00746:                // if the resource type is jsp
00747:                // write is only allowed for developers
00748:                if (!canIgnorePermissions
00749:                        && (resource.getTypeId() == CmsResourceTypeJsp
00750:                                .getStaticTypeId())) {
00751:                    if (!m_securityManager.hasRoleForResource(dbc, dbc
00752:                            .currentUser(), CmsRole.DEVELOPER, resource)) {
00753:                        denied |= CmsPermissionSet.PERMISSION_WRITE;
00754:                    }
00755:                }
00756:                CmsPermissionSetCustom permissions;
00757:                if (canIgnorePermissions) {
00758:                    // if the current user is administrator, anything is allowed
00759:                    permissions = new CmsPermissionSetCustom(~0);
00760:                } else {
00761:                    // otherwise, get the permissions from the access control list
00762:                    permissions = getPermissions(dbc, resource, dbc
00763:                            .currentUser());
00764:                }
00765:                // revoke the denied permissions
00766:                permissions.denyPermissions(denied);
00767:                // now check if write permission is granted
00768:                if ((CmsPermissionSet.ACCESS_WRITE.getPermissions() & permissions
00769:                        .getPermissions()) != CmsPermissionSet.ACCESS_WRITE
00770:                        .getPermissions()) {
00771:                    // check failed, throw exception
00772:                    m_securityManager.checkPermissions(dbc.getRequestContext(),
00773:                            resource, CmsPermissionSet.ACCESS_WRITE,
00774:                            I_CmsPermissionHandler.PERM_DENIED);
00775:                }
00776:                // if we got here write permission is granted on the target
00777:
00778:                // remove the old lock
00779:                m_lockManager.removeResource(dbc, resource, true, lockType
00780:                        .isSystem());
00781:                // apply the new lock
00782:                lockResource(dbc, resource, lockType);
00783:            }
00784:
00785:            /**
00786:             * Returns a list with all sub resources of a given folder that have set the given property, 
00787:             * matching the current property's value with the given old value and replacing it by a given new value.<p>
00788:             *
00789:             * @param dbc the current database context
00790:             * @param resource the resource on which property definition values are changed
00791:             * @param propertyDefinition the name of the propertydefinition to change the value
00792:             * @param oldValue the old value of the propertydefinition
00793:             * @param newValue the new value of the propertydefinition
00794:             * @param recursive if true, change recursively all property values on sub-resources (only for folders)
00795:             * 
00796:             * @return a list with the <code>{@link CmsResource}</code>'s where the property value has been changed
00797:             *
00798:             * @throws CmsVfsException for now only when the search for the oldvalue failed. 
00799:             * @throws CmsException if operation was not successful
00800:             */
00801:            public List changeResourcesInFolderWithProperty(CmsDbContext dbc,
00802:                    CmsResource resource, String propertyDefinition,
00803:                    String oldValue, String newValue, boolean recursive)
00804:                    throws CmsVfsException, CmsException {
00805:
00806:                CmsResourceFilter filter = CmsResourceFilter.IGNORE_EXPIRATION;
00807:                // collect the resources to look up
00808:                List resources = new ArrayList();
00809:                if (recursive) {
00810:                    resources = readResourcesWithProperty(dbc, resource,
00811:                            propertyDefinition, null, filter);
00812:                } else {
00813:                    resources.add(resource);
00814:                }
00815:
00816:                Pattern oldPattern;
00817:                try {
00818:                    // compile regular expression pattern
00819:                    oldPattern = Pattern.compile(oldValue);
00820:                } catch (PatternSyntaxException e) {
00821:                    throw new CmsVfsException(
00822:                            Messages
00823:                                    .get()
00824:                                    .container(
00825:                                            Messages.ERR_CHANGE_RESOURCES_IN_FOLDER_WITH_PROP_4,
00826:                                            new Object[] { propertyDefinition,
00827:                                                    oldValue, newValue,
00828:                                                    resource.getRootPath() }),
00829:                            e);
00830:                }
00831:
00832:                List changedResources = new ArrayList(resources.size());
00833:                // create permission set and filter to check each resource
00834:                CmsPermissionSet perm = CmsPermissionSet.ACCESS_WRITE;
00835:                for (int i = 0; i < resources.size(); i++) {
00836:                    // loop through found resources and check property values
00837:                    CmsResource res = (CmsResource) resources.get(i);
00838:                    // check resource state and permissions
00839:                    try {
00840:                        m_securityManager.checkPermissions(dbc, res, perm,
00841:                                true, filter);
00842:                    } catch (Exception e) {
00843:                        // resource is deleted or not writable for current user
00844:                        continue;
00845:                    }
00846:                    CmsProperty property = readPropertyObject(dbc, res,
00847:                            propertyDefinition, false);
00848:                    String structureValue = property.getStructureValue();
00849:                    String resourceValue = property.getResourceValue();
00850:                    boolean changed = false;
00851:                    if ((structureValue != null)
00852:                            && oldPattern.matcher(structureValue).matches()) {
00853:                        // change structure value
00854:                        property.setStructureValue(newValue);
00855:                        changed = true;
00856:                    }
00857:                    if ((resourceValue != null)
00858:                            && oldPattern.matcher(resourceValue).matches()) {
00859:                        // change resource value
00860:                        property.setResourceValue(newValue);
00861:                        changed = true;
00862:                    }
00863:                    if (changed) {
00864:                        // write property object if something has changed
00865:                        writePropertyObject(dbc, res, property);
00866:                        changedResources.add(res);
00867:                    }
00868:                }
00869:                return changedResources;
00870:            }
00871:
00872:            /**
00873:             * Changes the resource flags of a resource.<p>
00874:             * 
00875:             * The resource flags are used to indicate various "special" conditions
00876:             * for a resource. Most notably, the "internal only" setting which signals 
00877:             * that a resource can not be directly requested with it's URL.<p>
00878:             * 
00879:             * @param dbc the current database context
00880:             * @param resource the resource to change the flags for
00881:             * @param flags the new resource flags for this resource
00882:             *
00883:             * @throws CmsException if something goes wrong
00884:             * 
00885:             * @see CmsObject#chflags(String, int)
00886:             * @see I_CmsResourceType#chflags(CmsObject, CmsSecurityManager, CmsResource, int)
00887:             */
00888:            public void chflags(CmsDbContext dbc, CmsResource resource,
00889:                    int flags) throws CmsException {
00890:
00891:                // must operate on a clone to ensure resource is not modified in case permissions are not granted
00892:                CmsResource clone = (CmsResource) resource.clone();
00893:                clone.setFlags(flags);
00894:                writeResource(dbc, clone);
00895:            }
00896:
00897:            /**
00898:             * Changes the resource type of a resource.<p>
00899:             * 
00900:             * OpenCms handles resources according to the resource type,
00901:             * not the file suffix. This is e.g. why a JSP in OpenCms can have the 
00902:             * suffix ".html" instead of ".jsp" only. Changing the resource type
00903:             * makes sense e.g. if you want to make a plain text file a JSP resource,
00904:             * or a binary file an image, etc.<p> 
00905:             * 
00906:             * @param dbc the current database context
00907:             * @param resource the resource to change the type for
00908:             * @param type the new resource type for this resource
00909:             *
00910:             * @throws CmsException if something goes wrong
00911:             * 
00912:             * @see CmsObject#chtype(String, int)
00913:             * @see I_CmsResourceType#chtype(CmsObject, CmsSecurityManager, CmsResource, int)
00914:             */
00915:            public void chtype(CmsDbContext dbc, CmsResource resource, int type)
00916:                    throws CmsException {
00917:
00918:                // must operate on a clone to ensure resource is not modified in case permissions are not granted
00919:                CmsResource clone = (CmsResource) resource.clone();
00920:                I_CmsResourceType newType = OpenCms.getResourceManager()
00921:                        .getResourceType(type);
00922:                clone.setType(newType.getTypeId());
00923:                writeResource(dbc, clone);
00924:            }
00925:
00926:            /**
00927:             * @see org.opencms.main.I_CmsEventListener#cmsEvent(org.opencms.main.CmsEvent)
00928:             */
00929:            public void cmsEvent(CmsEvent event) {
00930:
00931:                if (LOG.isDebugEnabled()) {
00932:                    LOG.debug(Messages.get().getBundle().key(
00933:                            Messages.LOG_CMS_EVENT_1,
00934:                            new Integer(event.getType())));
00935:                }
00936:
00937:                I_CmsReport report;
00938:                CmsDbContext dbc;
00939:
00940:                switch (event.getType()) {
00941:
00942:                case I_CmsEventListener.EVENT_UPDATE_EXPORTS:
00943:                    dbc = (CmsDbContext) event.getData().get(
00944:                            I_CmsEventListener.KEY_DBCONTEXT);
00945:                    updateExportPoints(dbc);
00946:                    break;
00947:
00948:                case I_CmsEventListener.EVENT_PUBLISH_PROJECT:
00949:                    CmsUUID publishHistoryId = new CmsUUID((String) event
00950:                            .getData().get(I_CmsEventListener.KEY_PUBLISHID));
00951:                    report = (I_CmsReport) event.getData().get(
00952:                            I_CmsEventListener.KEY_REPORT);
00953:                    dbc = (CmsDbContext) event.getData().get(
00954:                            I_CmsEventListener.KEY_DBCONTEXT);
00955:                    writeExportPoints(dbc, report, publishHistoryId);
00956:                    break;
00957:
00958:                case I_CmsEventListener.EVENT_CLEAR_CACHES:
00959:                    OpenCms.getMemoryMonitor().clearCache();
00960:                    break;
00961:                case I_CmsEventListener.EVENT_CLEAR_PRINCIPAL_CACHES:
00962:                    OpenCms.getMemoryMonitor().clearPrincipalsCache();
00963:                    break;
00964:                default:
00965:                    // noop
00966:                }
00967:            }
00968:
00969:            /**
00970:             * Copies the access control entries of a given resource to a destination resorce.<p>
00971:             *
00972:             * Already existing access control entries of the destination resource are removed.<p>
00973:             * @param dbc the current database context
00974:             * @param source the resource to copy the access control entries from
00975:             * @param destination the resource to which the access control entries are copied
00976:             * @param updateLastModifiedInfo if true, user and date "last modified" information on the target resource will be updated
00977:             * 
00978:             * @throws CmsException if something goes wrong
00979:             */
00980:            public void copyAccessControlEntries(CmsDbContext dbc,
00981:                    CmsResource source, CmsResource destination,
00982:                    boolean updateLastModifiedInfo) throws CmsException {
00983:
00984:                // get the entries to copy
00985:                ListIterator aceList = m_userDriver.readAccessControlEntries(
00986:                        dbc, dbc.currentProject(), source.getResourceId(),
00987:                        false).listIterator();
00988:
00989:                // remove the current entries from the destination
00990:                m_userDriver.removeAccessControlEntries(dbc, dbc
00991:                        .currentProject(), destination.getResourceId());
00992:
00993:                // now write the new entries
00994:                while (aceList.hasNext()) {
00995:                    CmsAccessControlEntry ace = (CmsAccessControlEntry) aceList
00996:                            .next();
00997:                    m_userDriver.createAccessControlEntry(dbc, dbc
00998:                            .currentProject(), destination.getResourceId(), ace
00999:                            .getPrincipal(), ace.getPermissions()
01000:                            .getAllowedPermissions(), ace.getPermissions()
01001:                            .getDeniedPermissions(), ace.getFlags());
01002:                }
01003:
01004:                // update the "last modified" information
01005:                if (updateLastModifiedInfo) {
01006:                    setDateLastModified(dbc, destination, destination
01007:                            .getDateLastModified());
01008:                }
01009:
01010:                // clear the cache
01011:                OpenCms.getMemoryMonitor().clearAccessControlListCache();
01012:
01013:                // fire a resource modification event
01014:                HashMap data = new HashMap(2);
01015:                data.put("resource", destination);
01016:                data.put("change", new Integer(CHANGED_ACCESSCONTROL));
01017:                OpenCms.fireCmsEvent(new CmsEvent(
01018:                        I_CmsEventListener.EVENT_RESOURCE_MODIFIED, data));
01019:            }
01020:
01021:            /**
01022:             * Copies a resource.<p>
01023:             * 
01024:             * You must ensure that the destination path is an absolute, valid and
01025:             * existing VFS path. Relative paths from the source are currently not supported.<p>
01026:             * 
01027:             * In case the target resource already exists, it is overwritten with the 
01028:             * source resource.<p>
01029:             * 
01030:             * The <code>siblingMode</code> parameter controls how to handle siblings 
01031:             * during the copy operation.
01032:             * Possible values for this parameter are: 
01033:             * <ul>
01034:             * <li><code>{@link org.opencms.file.CmsResource#COPY_AS_NEW}</code></li>
01035:             * <li><code>{@link org.opencms.file.CmsResource#COPY_AS_SIBLING}</code></li>
01036:             * <li><code>{@link org.opencms.file.CmsResource#COPY_PRESERVE_SIBLING}</code></li>
01037:             * </ul><p>
01038:             * 
01039:             * @param dbc the current database context
01040:             * @param source the resource to copy
01041:             * @param destination the name of the copy destination with complete path
01042:             * @param siblingMode indicates how to handle siblings during copy
01043:             * 
01044:             * @throws CmsException if something goes wrong
01045:             * @throws CmsIllegalArgumentException if the <code>source</code> argument is <code>null</code>
01046:             * 
01047:             * @see CmsObject#copyResource(String, String, CmsResource.CmsResourceCopyMode)
01048:             * @see I_CmsResourceType#copyResource(CmsObject, CmsSecurityManager, CmsResource, String, CmsResource.CmsResourceCopyMode)
01049:             */
01050:            public void copyResource(CmsDbContext dbc, CmsResource source,
01051:                    String destination,
01052:                    CmsResource.CmsResourceCopyMode siblingMode)
01053:                    throws CmsException, CmsIllegalArgumentException {
01054:
01055:                // check the sibling mode to see if this resource has to be copied as a sibling
01056:                boolean copyAsSibling = false;
01057:
01058:                // siblings of folders are not supported
01059:                if (!source.isFolder()) {
01060:                    // if the "copy as sibling" mode is used, set the flag to true
01061:                    if (siblingMode == CmsResource.COPY_AS_SIBLING) {
01062:                        copyAsSibling = true;
01063:                    }
01064:                    // if the mode is "preserve siblings", we have to check the sibling counter
01065:                    if (siblingMode == CmsResource.COPY_PRESERVE_SIBLING) {
01066:                        if (source.getSiblingCount() > 1) {
01067:                            copyAsSibling = true;
01068:                        }
01069:                    }
01070:                }
01071:
01072:                // read the source properties
01073:                List properties = readPropertyObjects(dbc, source, false);
01074:
01075:                if (copyAsSibling) {
01076:                    // create a sibling of the source file at the destination  
01077:                    CmsResource resource = createSibling(dbc, source,
01078:                            destination, properties);
01079:                    // copy relations
01080:                    Iterator itRelations = getRelationsForResource(
01081:                            dbc,
01082:                            source,
01083:                            CmsRelationFilter.TARGETS
01084:                                    .filterNotDefinedInContent()).iterator();
01085:                    while (itRelations.hasNext()) {
01086:                        CmsRelation relation = (CmsRelation) itRelations.next();
01087:                        CmsResource target = null;
01088:                        try {
01089:                            target = readResource(dbc, relation.getTargetId(),
01090:                                    CmsResourceFilter.ALL);
01091:                        } catch (CmsVfsResourceNotFoundException e) {
01092:                            try {
01093:                                target = readResource(dbc, relation
01094:                                        .getTargetPath(), CmsResourceFilter.ALL);
01095:                            } catch (CmsVfsResourceNotFoundException e1) {
01096:                                // ignore this broken relation
01097:                                if (LOG.isWarnEnabled()) {
01098:                                    LOG.warn(e1.getLocalizedMessage(), e1);
01099:                                }
01100:                                continue;
01101:                            }
01102:                        }
01103:                        addRelationToResource(dbc, resource, target, relation
01104:                                .getType(), true);
01105:                    }
01106:                    // after the sibling is created the copy operation is finished
01107:                    return;
01108:                }
01109:
01110:                // prepare the content if required
01111:                byte[] content = null;
01112:                if (source.isFile()) {
01113:                    if (source instanceof  CmsFile) {
01114:                        // resource already is a file
01115:                        content = ((CmsFile) source).getContents();
01116:                    }
01117:                    if ((content == null) || (content.length < 1)) {
01118:                        // no known content yet - read from database
01119:                        content = m_vfsDriver.readContent(dbc, dbc
01120:                                .currentProject().getUuid(), source
01121:                                .getResourceId());
01122:                    }
01123:                }
01124:
01125:                // determine destination folder        
01126:                String destinationFoldername = CmsResource
01127:                        .getParentFolder(destination);
01128:
01129:                // read the destination folder (will also check read permissions)
01130:                CmsFolder destinationFolder = m_securityManager.readFolder(dbc,
01131:                        destinationFoldername,
01132:                        CmsResourceFilter.IGNORE_EXPIRATION);
01133:
01134:                // no further permission check required here, will be done in createResource()
01135:
01136:                // set user and creation time stamps
01137:                long currentTime = System.currentTimeMillis();
01138:                long dateLastModified;
01139:                CmsUUID userLastModified;
01140:                if (source.isFolder()) {
01141:                    // folders always get a new date and user when they are copied
01142:                    dateLastModified = currentTime;
01143:                    userLastModified = dbc.currentUser().getId();
01144:                } else {
01145:                    // files keep the date and user last modified from the source
01146:                    dateLastModified = source.getDateLastModified();
01147:                    userLastModified = source.getUserLastModified();
01148:                }
01149:
01150:                // check the resource flags
01151:                int flags = source.getFlags();
01152:                if (source.isLabeled()) {
01153:                    // reset "labeled" link flag for new resource
01154:                    flags &= ~CmsResource.FLAG_LABELED;
01155:                }
01156:
01157:                // create the new resource        
01158:                CmsResource newResource = new CmsResource(new CmsUUID(),
01159:                        new CmsUUID(), destination, source.getTypeId(), source
01160:                                .isFolder(), flags, dbc.currentProject()
01161:                                .getUuid(), CmsResource.STATE_NEW, currentTime,
01162:                        dbc.currentUser().getId(), dateLastModified,
01163:                        userLastModified, source.getDateReleased(), source
01164:                                .getDateExpired(), 1, source.getLength(),
01165:                        source.getDateContent(), source.getVersion()); // version number does not matter since it will be computed later
01166:
01167:                // trigger "is touched" state on resource (will ensure modification date is kept unchanged)
01168:                newResource.setDateLastModified(dateLastModified);
01169:
01170:                // create the resource
01171:                newResource = createResource(dbc, destination, newResource,
01172:                        content, properties, false);
01173:                // copy relations
01174:                Iterator itRelations = getRelationsForResource(dbc, source,
01175:                        CmsRelationFilter.TARGETS.filterNotDefinedInContent())
01176:                        .iterator();
01177:                while (itRelations.hasNext()) {
01178:                    CmsRelation relation = (CmsRelation) itRelations.next();
01179:                    CmsResource target = null;
01180:                    try {
01181:                        target = readResource(dbc, relation.getTargetId(),
01182:                                CmsResourceFilter.ALL);
01183:                    } catch (CmsVfsResourceNotFoundException e) {
01184:                        try {
01185:                            target = readResource(dbc,
01186:                                    relation.getTargetPath(),
01187:                                    CmsResourceFilter.ALL);
01188:                        } catch (CmsVfsResourceNotFoundException e1) {
01189:                            // ignore this broken relation
01190:                            if (LOG.isWarnEnabled()) {
01191:                                LOG.warn(e1.getLocalizedMessage(), e1);
01192:                            }
01193:                            continue;
01194:                        }
01195:                    }
01196:                    addRelationToResource(dbc, newResource, target, relation
01197:                            .getType(), true);
01198:                }
01199:
01200:                // copy the access control entries to the created resource
01201:                copyAccessControlEntries(dbc, source, newResource, false);
01202:
01203:                // clear the cache
01204:                OpenCms.getMemoryMonitor().clearAccessControlListCache();
01205:
01206:                List modifiedResources = new ArrayList();
01207:                modifiedResources.add(source);
01208:                modifiedResources.add(newResource);
01209:                modifiedResources.add(destinationFolder);
01210:                OpenCms.fireCmsEvent(new CmsEvent(
01211:                        I_CmsEventListener.EVENT_RESOURCE_COPIED, Collections
01212:                                .singletonMap("resources", modifiedResources)));
01213:            }
01214:
01215:            /**
01216:             * Copies a resource to the current project of the user.<p>
01217:             * 
01218:             * @param dbc the current database context
01219:             * @param resource the resource to apply this operation to
01220:             * 
01221:             * @throws CmsException if something goes wrong
01222:             * 
01223:             * @see CmsObject#copyResourceToProject(String)
01224:             * @see I_CmsResourceType#copyResourceToProject(CmsObject, CmsSecurityManager, CmsResource)
01225:             */
01226:            public void copyResourceToProject(CmsDbContext dbc,
01227:                    CmsResource resource) throws CmsException {
01228:
01229:                // copy the resource to the project only if the resource is not already in the project
01230:                if (!isInsideCurrentProject(dbc, resource.getRootPath())) {
01231:                    // check if there are already any subfolders of this resource
01232:                    if (resource.isFolder()) {
01233:                        List projectResources = m_projectDriver
01234:                                .readProjectResources(dbc, dbc.currentProject());
01235:                        for (int i = 0; i < projectResources.size(); i++) {
01236:                            String resname = (String) projectResources.get(i);
01237:                            if (resname.startsWith(resource.getRootPath())) {
01238:                                // delete the existing project resource first
01239:                                m_projectDriver.deleteProjectResource(dbc, dbc
01240:                                        .currentProject().getUuid(), resname);
01241:                            }
01242:                        }
01243:                    }
01244:                    try {
01245:                        m_projectDriver.createProjectResource(dbc, dbc
01246:                                .currentProject().getUuid(), resource
01247:                                .getRootPath());
01248:                    } catch (CmsException exc) {
01249:                        // if the subfolder exists already - all is ok
01250:                    } finally {
01251:                        OpenCms.getMemoryMonitor().flushProjectResources();
01252:
01253:                        OpenCms.fireCmsEvent(new CmsEvent(
01254:                                I_CmsEventListener.EVENT_PROJECT_MODIFIED,
01255:                                Collections.singletonMap("project", dbc
01256:                                        .currentProject())));
01257:                    }
01258:                }
01259:            }
01260:
01261:            /**
01262:             * Counts the locked resources in this project.<p>
01263:             *
01264:             * @param project the project to count the locked resources in
01265:             * 
01266:             * @return the amount of locked resources in this project
01267:             */
01268:            public int countLockedResources(CmsProject project) {
01269:
01270:                // count locks
01271:                return m_lockManager.countExclusiveLocksInProject(project);
01272:            }
01273:
01274:            /**
01275:             * Add a new group to the Cms.<p>
01276:             *
01277:             * Only the admin can do this.
01278:             * Only users, which are in the group "administrators" are granted.<p>
01279:             * 
01280:             * @param dbc the current database context
01281:             * @param id the id of the new group
01282:             * @param name the name of the new group
01283:             * @param description the description for the new group
01284:             * @param flags the flags for the new group
01285:             * @param parent the name of the parent group (or <code>null</code>)
01286:             * 
01287:             * @return new created group
01288:             * 
01289:             * @throws CmsException if the creation of the group failed
01290:             * @throws CmsIllegalArgumentException if the length of the given name was below 1
01291:             */
01292:            public CmsGroup createGroup(CmsDbContext dbc, CmsUUID id,
01293:                    String name, String description, int flags, String parent)
01294:                    throws CmsIllegalArgumentException, CmsException {
01295:
01296:                // check the group name
01297:                OpenCms.getValidationHandler().checkGroupName(
01298:                        CmsOrganizationalUnit.getSimpleName(name));
01299:                // trim the name
01300:                name = name.trim();
01301:                // check the ou
01302:                readOrganizationalUnit(dbc, CmsOrganizationalUnit
01303:                        .getParentFqn(name));
01304:
01305:                // get the id of the parent group if necessary
01306:                if (CmsStringUtil.isNotEmpty(parent)) {
01307:                    CmsGroup parentGroup = readGroup(dbc, parent);
01308:                    if (!parentGroup.isRole()
01309:                            && !CmsOrganizationalUnit.getParentFqn(parent)
01310:                                    .equals(
01311:                                            CmsOrganizationalUnit
01312:                                                    .getParentFqn(name))) {
01313:                        throw new CmsDataAccessException(
01314:                                Messages
01315:                                        .get()
01316:                                        .container(
01317:                                                Messages.ERR_PARENT_GROUP_MUST_BE_IN_SAME_OU_3,
01318:                                                CmsOrganizationalUnit
01319:                                                        .getSimpleName(name),
01320:                                                CmsOrganizationalUnit
01321:                                                        .getParentFqn(name),
01322:                                                parent));
01323:                    }
01324:                }
01325:
01326:                // create the group
01327:                CmsGroup group = m_userDriver.createGroup(dbc, id, name,
01328:                        description, flags, parent);
01329:
01330:                // if group is virtualizing a role, initialize it
01331:                if (group.isVirtual()) {
01332:                    // get all users that have the given role
01333:                    String groupname = CmsRole.valueOf(group).getGroupName();
01334:                    Iterator it = getUsersOfGroup(dbc, groupname, true, false,
01335:                            true).iterator();
01336:                    while (it.hasNext()) {
01337:                        CmsUser user = (CmsUser) it.next();
01338:                        // put them in the new group
01339:                        addUserToGroup(dbc, user.getName(), group.getName(),
01340:                                true);
01341:                    }
01342:                }
01343:
01344:                // put it into the cache
01345:                OpenCms.getMemoryMonitor().cacheGroup(group);
01346:                // return it
01347:                return group;
01348:            }
01349:
01350:            /**
01351:             * Creates a new organizational unit.<p>
01352:             * 
01353:             * @param dbc the current db context
01354:             * @param ouFqn the fully qualified name of the new organizational unit
01355:             * @param description the description of the new organizational unit
01356:             * @param flags the flags for the new organizational unit
01357:             * @param resource the first associated resource
01358:             *
01359:             * @return a <code>{@link CmsOrganizationalUnit}</code> object representing 
01360:             *          the newly created organizational unit
01361:             *
01362:             * @throws CmsException if operation was not successful
01363:             * 
01364:             * @see org.opencms.security.CmsOrgUnitManager#createOrganizationalUnit(CmsObject, String, String, int, String)
01365:             */
01366:            public CmsOrganizationalUnit createOrganizationalUnit(
01367:                    CmsDbContext dbc, String ouFqn, String description,
01368:                    int flags, CmsResource resource) throws CmsException {
01369:
01370:                // normal case
01371:                CmsOrganizationalUnit parent = readOrganizationalUnit(dbc,
01372:                        CmsOrganizationalUnit.getParentFqn(ouFqn));
01373:                String name = CmsOrganizationalUnit.getSimpleName(ouFqn);
01374:                if (name.endsWith(CmsOrganizationalUnit.SEPARATOR)) {
01375:                    name = name.substring(0, name.length() - 1);
01376:                }
01377:
01378:                // check the name
01379:                CmsResource.checkResourceName(name);
01380:
01381:                // trim the name
01382:                name = name.trim();
01383:
01384:                // check the description
01385:                if (CmsStringUtil.isEmptyOrWhitespaceOnly(description)) {
01386:                    throw new CmsIllegalArgumentException(Messages.get()
01387:                            .container(Messages.ERR_BAD_OU_DESCRIPTION_EMPTY_0));
01388:                }
01389:
01390:                // create the organizational unit
01391:                CmsOrganizationalUnit orgUnit = m_userDriver
01392:                        .createOrganizationalUnit(dbc, name, description,
01393:                                flags, parent, resource != null ? resource
01394:                                        .getRootPath() : null);
01395:                // put the new created org unit into the cache
01396:                OpenCms.getMemoryMonitor().cacheOrgUnit(orgUnit);
01397:
01398:                // flush relevant caches
01399:                OpenCms.getMemoryMonitor().clearPrincipalsCache();
01400:                OpenCms.getMemoryMonitor().flushProperties();
01401:                OpenCms.getMemoryMonitor().flushPropertyLists();
01402:
01403:                // create a publish list for the 'virtual' publish event
01404:                CmsResource ouRes = readResource(dbc, orgUnit.getId(),
01405:                        CmsResourceFilter.DEFAULT);
01406:                CmsPublishList pl = new CmsPublishList(ouRes, false);
01407:                pl.add(ouRes, false);
01408:
01409:                // fire the 'virtual' publish event
01410:                Map eventData = new HashMap();
01411:                eventData.put(I_CmsEventListener.KEY_PUBLISHID, pl
01412:                        .getPublishHistoryId().toString());
01413:                eventData.put(I_CmsEventListener.KEY_PROJECTID, dbc
01414:                        .currentProject().getUuid());
01415:                eventData.put(I_CmsEventListener.KEY_DBCONTEXT, dbc);
01416:                CmsEvent afterPublishEvent = new CmsEvent(
01417:                        I_CmsEventListener.EVENT_PUBLISH_PROJECT, eventData);
01418:                OpenCms.fireCmsEvent(afterPublishEvent);
01419:
01420:                // return it
01421:                return orgUnit;
01422:            }
01423:
01424:            /**
01425:             * Creates a project.<p>
01426:             *
01427:             * @param dbc the current database context
01428:             * @param name the name of the project to create
01429:             * @param description the description of the project
01430:             * @param groupname the project user group to be set
01431:             * @param managergroupname the project manager group to be set
01432:             * @param projecttype the type of the project
01433:             * 
01434:             * @return the created project
01435:             * 
01436:             * @throws CmsIllegalArgumentException if the chosen <code>name</code> is already used 
01437:             *         by the online project, or if the name is not valid
01438:             * @throws CmsException if something goes wrong
01439:             */
01440:            public CmsProject createProject(CmsDbContext dbc, String name,
01441:                    String description, String groupname,
01442:                    String managergroupname,
01443:                    CmsProject.CmsProjectType projecttype)
01444:                    throws CmsIllegalArgumentException, CmsException {
01445:
01446:                if (CmsProject.ONLINE_PROJECT_NAME.equals(name)) {
01447:                    throw new CmsIllegalArgumentException(
01448:                            Messages
01449:                                    .get()
01450:                                    .container(
01451:                                            Messages.ERR_CREATE_PROJECT_ONLINE_PROJECT_NAME_1,
01452:                                            CmsProject.ONLINE_PROJECT_NAME));
01453:                }
01454:                // check the name
01455:                CmsProject.checkProjectName(CmsOrganizationalUnit
01456:                        .getSimpleName(name));
01457:                // check the ou
01458:                readOrganizationalUnit(dbc, CmsOrganizationalUnit
01459:                        .getParentFqn(name));
01460:                // read the needed groups from the cms
01461:                CmsGroup group = readGroup(dbc, groupname);
01462:                CmsGroup managergroup = readGroup(dbc, managergroupname);
01463:
01464:                return m_projectDriver.createProject(dbc, new CmsUUID(), dbc
01465:                        .currentUser(), group, managergroup, name, description,
01466:                        CmsProject.PROJECT_FLAG_NONE, projecttype);
01467:            }
01468:
01469:            /**
01470:             * Creates a property definition.<p>
01471:             *
01472:             * Property definitions are valid for all resource types.<p>
01473:             * 
01474:             * @param dbc the current database context
01475:             * @param name the name of the property definition to create
01476:             * 
01477:             * @return the created property definition
01478:             * 
01479:             * @throws CmsException if something goes wrong
01480:             */
01481:            public CmsPropertyDefinition createPropertyDefinition(
01482:                    CmsDbContext dbc, String name) throws CmsException {
01483:
01484:                CmsPropertyDefinition propertyDefinition = null;
01485:
01486:                name = name.trim();
01487:                // validate the property name
01488:                CmsPropertyDefinition.checkPropertyName(name);
01489:                // TODO: make the type a parameter
01490:                try {
01491:                    try {
01492:                        propertyDefinition = m_vfsDriver
01493:                                .readPropertyDefinition(dbc, name, dbc
01494:                                        .currentProject().getUuid());
01495:                    } catch (CmsException e) {
01496:                        propertyDefinition = m_vfsDriver
01497:                                .createPropertyDefinition(dbc, dbc
01498:                                        .currentProject().getUuid(), name,
01499:                                        CmsPropertyDefinition.TYPE_NORMAL);
01500:                    }
01501:
01502:                    try {
01503:                        m_vfsDriver.readPropertyDefinition(dbc, name,
01504:                                CmsProject.ONLINE_PROJECT_ID);
01505:                    } catch (CmsException e) {
01506:                        m_vfsDriver.createPropertyDefinition(dbc,
01507:                                CmsProject.ONLINE_PROJECT_ID, name,
01508:                                CmsPropertyDefinition.TYPE_NORMAL);
01509:                    }
01510:
01511:                    try {
01512:                        m_historyDriver.readPropertyDefinition(dbc, name);
01513:                    } catch (CmsException e) {
01514:                        m_historyDriver.createPropertyDefinition(dbc, name,
01515:                                CmsPropertyDefinition.TYPE_NORMAL);
01516:                    }
01517:                } finally {
01518:
01519:                    // fire an event that a property of a resource has been deleted
01520:                    OpenCms
01521:                            .fireCmsEvent(new CmsEvent(
01522:                                    I_CmsEventListener.EVENT_PROPERTY_DEFINITION_CREATED,
01523:                                    Collections.singletonMap(
01524:                                            "propertyDefinition",
01525:                                            propertyDefinition)));
01526:
01527:                }
01528:
01529:                return propertyDefinition;
01530:            }
01531:
01532:            /**
01533:             * Creates a new publish job.<p>
01534:             * 
01535:             * @param dbc the current database context
01536:             * @param publishJob the publish job to create
01537:             * 
01538:             * @throws CmsException if something goes wrong
01539:             */
01540:            public void createPublishJob(CmsDbContext dbc,
01541:                    CmsPublishJobInfoBean publishJob) throws CmsException {
01542:
01543:                m_projectDriver.createPublishJob(dbc, publishJob);
01544:            }
01545:
01546:            /**
01547:             * Creates a new resource with the provided content and properties.<p>
01548:             * 
01549:             * The <code>content</code> parameter may be <code>null</code> if the resource id 
01550:             * already exists. If so, the created resource will be a sibling of the existing 
01551:             * resource, the existing content will remain unchanged.<p>
01552:             * 
01553:             * This is used during file import for import of siblings as the 
01554:             * <code>manifest.xml</code> only contains one binary copy per file.<p>
01555:             *  
01556:             * If the resource id exists but the <code>content</code> is not <code>null</code>,
01557:             * the created resource will be made a sibling of the existing resource,
01558:             * and both will share the new content.<p>
01559:             * 
01560:             * @param dbc the current database context
01561:             * @param resourcePath the name of the resource to create (full path)
01562:             * @param resource the new resource to create
01563:             * @param content the content for the new resource
01564:             * @param properties the properties for the new resource
01565:             * @param importCase if <code>true</code>, signals that this operation is done while 
01566:             *                      importing resource, causing different lock behavior and 
01567:             *                      potential "lost and found" usage
01568:             * 
01569:             * @return the created resource
01570:             * 
01571:             * @throws CmsException if something goes wrong
01572:             */
01573:            public synchronized CmsResource createResource(CmsDbContext dbc,
01574:                    String resourcePath, CmsResource resource, byte[] content,
01575:                    List properties, boolean importCase) throws CmsException {
01576:
01577:                CmsResource newResource = null;
01578:                if (resource.isFolder()) {
01579:                    resourcePath = CmsFileUtil
01580:                            .addTrailingSeparator(resourcePath);
01581:                }
01582:
01583:                try {
01584:                    // need to provide the parent folder id for resource creation
01585:                    String parentFolderName = CmsResource
01586:                            .getParentFolder(resourcePath);
01587:                    CmsResource parentFolder = readFolder(dbc,
01588:                            parentFolderName,
01589:                            CmsResourceFilter.IGNORE_EXPIRATION);
01590:
01591:                    CmsLock parentLock = getLock(dbc, parentFolder);
01592:                    // it is not allowed to create a resource in a folder locked by other user
01593:                    if (!parentLock.isUnlocked()
01594:                            && !parentLock.isOwnedBy(dbc.currentUser())) {
01595:                        // one exception is if the admin user tries to create a temporary resource
01596:                        if (!CmsResource.getName(resourcePath).startsWith(
01597:                                TEMP_FILE_PREFIX)
01598:                                || !m_securityManager.hasRole(dbc, dbc
01599:                                        .currentUser(), CmsRole.ROOT_ADMIN)) {
01600:                            throw new CmsLockException(
01601:                                    Messages
01602:                                            .get()
01603:                                            .container(
01604:                                                    Messages.ERR_CREATE_RESOURCE_PARENT_LOCK_1,
01605:                                                    dbc
01606:                                                            .removeSiteRoot(resourcePath)));
01607:                        }
01608:                    }
01609:
01610:                    // check import configuration of "lost and found" folder
01611:                    boolean useLostAndFound = importCase
01612:                            && !OpenCms.getImportExportManager()
01613:                                    .overwriteCollidingResources();
01614:
01615:                    // check if the resource already exists by name
01616:                    CmsResource currentResourceByName = null;
01617:                    try {
01618:                        currentResourceByName = readResource(dbc, resourcePath,
01619:                                CmsResourceFilter.ALL);
01620:                    } catch (CmsVfsResourceNotFoundException e) {
01621:                        // if the resource does exist, we have to check the id later to decide what to do
01622:                    }
01623:
01624:                    // check if the resource already exists by id
01625:                    try {
01626:                        CmsResource currentResourceById = readResource(dbc,
01627:                                resource.getStructureId(),
01628:                                CmsResourceFilter.ALL);
01629:                        // it is not allowed to import resources when there is already a resource with the same id but different path 
01630:                        if (!currentResourceById.getRootPath().equals(
01631:                                resourcePath)) {
01632:                            throw new CmsVfsResourceAlreadyExistsException(
01633:                                    Messages
01634:                                            .get()
01635:                                            .container(
01636:                                                    Messages.ERR_RESOURCE_WITH_ID_ALREADY_EXISTS_3,
01637:                                                    dbc
01638:                                                            .removeSiteRoot(resourcePath),
01639:                                                    dbc
01640:                                                            .removeSiteRoot(currentResourceById
01641:                                                                    .getRootPath()),
01642:                                                    currentResourceById
01643:                                                            .getStructureId()));
01644:                        }
01645:                    } catch (CmsVfsResourceNotFoundException e) {
01646:                        // if the resource does exist, we have to check the id later to decide what to do
01647:                    }
01648:
01649:                    // check the permissions
01650:                    if (currentResourceByName == null) {
01651:                        // resource does not exist - check parent folder
01652:                        m_securityManager.checkPermissions(dbc, parentFolder,
01653:                                CmsPermissionSet.ACCESS_WRITE, false,
01654:                                CmsResourceFilter.IGNORE_EXPIRATION);
01655:                    } else {
01656:                        // resource already exists - check existing resource              
01657:                        m_securityManager.checkPermissions(dbc,
01658:                                currentResourceByName,
01659:                                CmsPermissionSet.ACCESS_WRITE, !importCase,
01660:                                CmsResourceFilter.ALL);
01661:                    }
01662:
01663:                    // now look for the resource by name
01664:                    if (currentResourceByName != null) {
01665:                        boolean overwrite = true;
01666:                        if (currentResourceByName.getState().isDeleted()) {
01667:                            if (!currentResourceByName.isFolder()) {
01668:                                // if a non-folder resource was deleted it's treated like a new resource
01669:                                overwrite = false;
01670:                            }
01671:                        } else {
01672:                            if (!importCase) {
01673:                                // direct "overwrite" of a resource is possible only during import, 
01674:                                // or if the resource has been deleted
01675:                                throw new CmsVfsResourceAlreadyExistsException(
01676:                                        org.opencms.db.generic.Messages
01677:                                                .get()
01678:                                                .container(
01679:                                                        org.opencms.db.generic.Messages.ERR_RESOURCE_WITH_NAME_ALREADY_EXISTS_1,
01680:                                                        dbc
01681:                                                                .removeSiteRoot(resource
01682:                                                                        .getRootPath())));
01683:                            }
01684:                            // the resource already exists
01685:                            if (!resource.isFolder()
01686:                                    && useLostAndFound
01687:                                    && (!currentResourceByName.getResourceId()
01688:                                            .equals(resource.getResourceId()))) {
01689:                                // semantic change: the current resource is moved to L&F and the imported resource will overwrite the old one                
01690:                                // will leave the resource with state deleted, 
01691:                                // but it does not matter, since the state will be set later again
01692:                                moveToLostAndFound(dbc, currentResourceByName,
01693:                                        false);
01694:                            }
01695:                        }
01696:                        if (!overwrite) {
01697:                            // lock the resource, will throw an exception if not lockable
01698:                            lockResource(dbc, currentResourceByName,
01699:                                    CmsLockType.EXCLUSIVE);
01700:
01701:                            // trigger createResource instead of writeResource
01702:                            currentResourceByName = null;
01703:                        }
01704:                    }
01705:                    // if null, create new resource, if not null write resource
01706:                    CmsResource overwrittenResource = currentResourceByName;
01707:
01708:                    // extract the name (without path)
01709:                    String targetName = CmsResource.getName(resourcePath);
01710:
01711:                    int contentLength;
01712:
01713:                    // modify target name and content length in case of folder creation
01714:                    if (resource.isFolder()) {
01715:                        // folders never have any content
01716:                        contentLength = -1;
01717:                        // must cut of trailing '/' for folder creation (or name check fails)
01718:                        if (CmsResource.isFolder(targetName)) {
01719:                            targetName = targetName.substring(0, targetName
01720:                                    .length() - 1);
01721:                        }
01722:                    } else {
01723:                        // otherwise ensure content and content length are set correctly
01724:                        if (content != null) {
01725:                            // if a content is provided, in each case the length is the length of this content
01726:                            contentLength = content.length;
01727:                        } else if (overwrittenResource != null) {
01728:                            // we have no content, but an already existing resource - length remains unchanged
01729:                            contentLength = overwrittenResource.getLength();
01730:                        } else {
01731:                            // we have no content - length is used as set in the resource
01732:                            contentLength = resource.getLength();
01733:                        }
01734:                    }
01735:
01736:                    // check if the target name is valid (forbidden chars etc.), 
01737:                    // if not throw an exception
01738:                    // must do this here since targetName is modified in folder case (see above)
01739:                    CmsResource.checkResourceName(targetName);
01740:
01741:                    // set structure and resource ids as given
01742:                    CmsUUID structureId = resource.getStructureId();
01743:                    CmsUUID resourceId = resource.getResourceId();
01744:
01745:                    // decide which structure id to use
01746:                    if (overwrittenResource != null) {
01747:                        // resource exists, re-use existing ids
01748:                        structureId = overwrittenResource.getStructureId();
01749:                    }
01750:                    if (structureId.isNullUUID()) {
01751:                        // need a new structure id
01752:                        structureId = new CmsUUID();
01753:                    }
01754:
01755:                    // decide which resource id to use
01756:                    if (overwrittenResource != null) {
01757:                        // if we are overwriting we have to assure the resource id is the same
01758:                        resourceId = overwrittenResource.getResourceId();
01759:                    }
01760:                    if (resourceId.isNullUUID()) {
01761:                        // need a new resource id
01762:                        resourceId = new CmsUUID();
01763:                    }
01764:
01765:                    try {
01766:                        // check online resource
01767:                        CmsResource onlineResource = m_vfsDriver.readResource(
01768:                                dbc, CmsProject.ONLINE_PROJECT_ID,
01769:                                resourcePath, true);
01770:                        // only allow to overwrite with different id if importing (createResource will set the right id)
01771:                        try {
01772:                            CmsResource offlineResource = m_vfsDriver
01773:                                    .readResource(dbc, dbc.currentProject()
01774:                                            .getUuid(), onlineResource
01775:                                            .getStructureId(), true);
01776:                            if (!offlineResource.getRootPath().equals(
01777:                                    onlineResource.getRootPath())) {
01778:                                throw new CmsVfsOnlineResourceAlreadyExistsException(
01779:                                        Messages
01780:                                                .get()
01781:                                                .container(
01782:                                                        Messages.ERR_ONLINE_RESOURCE_EXISTS_2,
01783:                                                        dbc
01784:                                                                .removeSiteRoot(resourcePath),
01785:                                                        dbc
01786:                                                                .removeSiteRoot(offlineResource
01787:                                                                        .getRootPath())));
01788:                            }
01789:                        } catch (CmsVfsResourceNotFoundException e) {
01790:                            // there is no problem for now
01791:                            // but should never happen
01792:                            if (LOG.isErrorEnabled()) {
01793:                                LOG.error(e.getLocalizedMessage(), e);
01794:                            }
01795:                        }
01796:                    } catch (CmsVfsResourceNotFoundException e) {
01797:                        // ok, there is no online entry to worry about
01798:                    }
01799:
01800:                    // now create a resource object with all informations
01801:                    newResource = new CmsResource(structureId, resourceId,
01802:                            resourcePath, resource.getTypeId(), resource
01803:                                    .isFolder(), resource.getFlags(), dbc
01804:                                    .currentProject().getUuid(), resource
01805:                                    .getState(), resource.getDateCreated(),
01806:                            resource.getUserCreated(), resource
01807:                                    .getDateLastModified(), resource
01808:                                    .getUserLastModified(), resource
01809:                                    .getDateReleased(), resource
01810:                                    .getDateExpired(), 1, contentLength,
01811:                            resource.getDateContent(), resource.getVersion()); // version number does not matter since it will be computed later
01812:
01813:                    // ensure date is updated only if required
01814:                    if (resource.isTouched()) {
01815:                        // this will trigger the internal "is touched" state on the new resource
01816:                        newResource.setDateLastModified(resource
01817:                                .getDateLastModified());
01818:                    }
01819:
01820:                    if (resource.isFile()) {
01821:                        // check if a sibling to the imported resource lies in a marked site
01822:                        if (labelResource(dbc, resource, resourcePath, 2)) {
01823:                            int flags = resource.getFlags();
01824:                            flags |= CmsResource.FLAG_LABELED;
01825:                            resource.setFlags(flags);
01826:                        }
01827:                        // ensure siblings don't overwrite existing resource records
01828:                        if (content == null) {
01829:                            newResource.setState(CmsResource.STATE_KEEP);
01830:                        }
01831:                    }
01832:
01833:                    // delete all relations for the resource, before writing the content
01834:                    m_vfsDriver.deleteRelations(dbc, dbc.currentProject()
01835:                            .getUuid(), newResource, CmsRelationFilter.TARGETS);
01836:                    if (overwrittenResource == null) {
01837:                        CmsLock lock = getLock(dbc, newResource);
01838:                        if (lock.getEditionLock().isExclusive()) {
01839:                            unlockResource(dbc, newResource, true, false);
01840:                        }
01841:                        // resource does not exist.
01842:                        newResource = m_vfsDriver.createResource(dbc, dbc
01843:                                .currentProject().getUuid(), newResource,
01844:                                content);
01845:                    } else {
01846:                        // resource already exists. 
01847:                        // probably the resource is a merged page file that gets overwritten during import, or it gets 
01848:                        // overwritten by a copy operation. if so, the structure & resource state are not modified to changed.
01849:                        int updateStates = (overwrittenResource.getState()
01850:                                .isNew() ? CmsDriverManager.NOTHING_CHANGED
01851:                                : CmsDriverManager.UPDATE_ALL);
01852:                        m_vfsDriver.writeResource(dbc, dbc.currentProject()
01853:                                .getUuid(), newResource, updateStates);
01854:
01855:                        if ((content != null) && resource.isFile()) {
01856:                            // also update file content if required                    
01857:                            m_vfsDriver.writeContent(dbc, newResource
01858:                                    .getResourceId(), content);
01859:                        }
01860:                    }
01861:
01862:                    // write the properties (internal operation, no events or duplicate permission checks)
01863:                    writePropertyObjects(dbc, newResource, properties, false);
01864:
01865:                    // lock the created resource
01866:                    try {
01867:                        // if it is locked by another user (copied or moved resource) this lock should be preserved and 
01868:                        // the exception is OK: locks on created resources are a slave feature to original locks 
01869:                        lockResource(dbc, newResource, CmsLockType.EXCLUSIVE);
01870:                    } catch (CmsLockException cle) {
01871:                        if (LOG.isDebugEnabled()) {
01872:                            LOG.debug(Messages.get().getBundle().key(
01873:                                    Messages.ERR_CREATE_RESOURCE_LOCK_1,
01874:                                    new Object[] { dbc
01875:                                            .removeSiteRoot(newResource
01876:                                                    .getRootPath()) }));
01877:                        }
01878:                    }
01879:                } finally {
01880:                    // clear the internal caches
01881:                    OpenCms.getMemoryMonitor().clearAccessControlListCache();
01882:                    OpenCms.getMemoryMonitor().flushProperties();
01883:                    OpenCms.getMemoryMonitor().flushPropertyLists();
01884:
01885:                    if (newResource != null) {
01886:                        // fire an event that a new resource has been created
01887:                        OpenCms.fireCmsEvent(new CmsEvent(
01888:                                I_CmsEventListener.EVENT_RESOURCE_CREATED,
01889:                                Collections.singletonMap("resource",
01890:                                        newResource)));
01891:                    }
01892:                }
01893:                return newResource;
01894:            }
01895:
01896:            /**
01897:             * Creates a new resource of the given resource type
01898:             * with the provided content and properties.<p>
01899:             * 
01900:             * If the provided content is null and the resource is not a folder,
01901:             * the content will be set to an empty byte array.<p>  
01902:             * 
01903:             * @param dbc the current database context
01904:             * @param resourcename the name of the resource to create (full path)
01905:             * @param type the type of the resource to create
01906:             * @param content the content for the new resource
01907:             * @param properties the properties for the new resource
01908:             * 
01909:             * @return the created resource
01910:             * 
01911:             * @throws CmsException if something goes wrong
01912:             * @throws CmsIllegalArgumentException if the <code>resourcename</code> argument is null or of length 0
01913:             * 
01914:             * @see CmsObject#createResource(String, int, byte[], List)
01915:             * @see CmsObject#createResource(String, int)
01916:             * @see I_CmsResourceType#createResource(CmsObject, CmsSecurityManager, String, byte[], List)
01917:             */
01918:            public CmsResource createResource(CmsDbContext dbc,
01919:                    String resourcename, int type, byte[] content,
01920:                    List properties) throws CmsException,
01921:                    CmsIllegalArgumentException {
01922:
01923:                String targetName = resourcename;
01924:
01925:                if (content == null) {
01926:                    // name based resource creation MUST have a content
01927:                    content = new byte[0];
01928:                }
01929:                int size;
01930:
01931:                if (CmsFolder.isFolderType(type)) {
01932:                    // must cut of trailing '/' for folder creation
01933:                    if (CmsResource.isFolder(targetName)) {
01934:                        targetName = targetName.substring(0, targetName
01935:                                .length() - 1);
01936:                    }
01937:                    size = -1;
01938:                } else {
01939:                    size = content.length;
01940:                }
01941:
01942:                // create a new resource
01943:                CmsResource newResource = new CmsResource(
01944:                        CmsUUID.getNullUUID(), // uuids will be "corrected" later
01945:                        CmsUUID.getNullUUID(), targetName, type, CmsFolder
01946:                                .isFolderType(type), 0, dbc.currentProject()
01947:                                .getUuid(), CmsResource.STATE_NEW, 0, dbc
01948:                                .currentUser().getId(), 0, dbc.currentUser()
01949:                                .getId(), CmsResource.DATE_RELEASED_DEFAULT,
01950:                        CmsResource.DATE_EXPIRED_DEFAULT, 1, size, 0, // version number does not matter since it will be computed later
01951:                        0); // content time will be corrected later
01952:
01953:                return createResource(dbc, targetName, newResource, content,
01954:                        properties, false);
01955:            }
01956:
01957:            /**
01958:             * Creates a new sibling of the source resource.<p>
01959:             * 
01960:             * @param dbc the current database context
01961:             * @param source the resource to create a sibling for
01962:             * @param destination the name of the sibling to create with complete path
01963:             * @param properties the individual properties for the new sibling
01964:             * 
01965:             * @return the new created sibling
01966:             * 
01967:             * @throws CmsException if something goes wrong
01968:             * 
01969:             * @see CmsObject#createSibling(String, String, List)
01970:             * @see I_CmsResourceType#createSibling(CmsObject, CmsSecurityManager, CmsResource, String, List)
01971:             */
01972:            public CmsResource createSibling(CmsDbContext dbc,
01973:                    CmsResource source, String destination, List properties)
01974:                    throws CmsException {
01975:
01976:                if (source.isFolder()) {
01977:                    throw new CmsVfsException(Messages.get().container(
01978:                            Messages.ERR_VFS_FOLDERS_DONT_SUPPORT_SIBLINGS_0));
01979:                }
01980:
01981:                // determine destination folder and resource name        
01982:                String destinationFoldername = CmsResource
01983:                        .getParentFolder(destination);
01984:
01985:                // read the destination folder (will also check read permissions)
01986:                CmsFolder destinationFolder = readFolder(dbc,
01987:                        destinationFoldername,
01988:                        CmsResourceFilter.IGNORE_EXPIRATION);
01989:
01990:                // no further permission check required here, will be done in createResource()
01991:
01992:                // check the resource flags
01993:                int flags = source.getFlags();
01994:                if (labelResource(dbc, source, destination, 1)) {
01995:                    // set "labeled" link flag for new resource
01996:                    flags |= CmsResource.FLAG_LABELED;
01997:                }
01998:
01999:                // create the new resource        
02000:                CmsResource newResource = new CmsResource(new CmsUUID(), source
02001:                        .getResourceId(), destination, source.getTypeId(),
02002:                        source.isFolder(), flags,
02003:                        dbc.currentProject().getUuid(),
02004:                        CmsResource.STATE_KEEP,
02005:                        source.getDateCreated(), // ensures current resource record remains untouched 
02006:                        source.getUserCreated(), source.getDateLastModified(),
02007:                        source.getUserLastModified(), source.getDateReleased(),
02008:                        source.getDateExpired(), source.getSiblingCount() + 1,
02009:                        source.getLength(), source.getDateContent(), source
02010:                                .getVersion()); // version number does not matter since it will be computed later
02011:
02012:                // trigger "is touched" state on resource (will ensure modification date is kept unchanged)
02013:                newResource.setDateLastModified(newResource
02014:                        .getDateLastModified());
02015:
02016:                // create the resource (null content signals creation of sibling)
02017:                newResource = createResource(dbc, destination, newResource,
02018:                        null, properties, false);
02019:
02020:                // clear the caches
02021:                OpenCms.getMemoryMonitor().clearAccessControlListCache();
02022:
02023:                List modifiedResources = new ArrayList();
02024:                modifiedResources.add(source);
02025:                modifiedResources.add(newResource);
02026:                modifiedResources.add(destinationFolder);
02027:                OpenCms
02028:                        .fireCmsEvent(new CmsEvent(
02029:                                I_CmsEventListener.EVENT_RESOURCES_AND_PROPERTIES_MODIFIED,
02030:                                Collections.singletonMap("resources",
02031:                                        modifiedResources)));
02032:
02033:                return newResource;
02034:            }
02035:
02036:            /**
02037:             * Creates the project for the temporary workplace files.<p>
02038:             *
02039:             * @param dbc the current database context
02040:             * 
02041:             * @return the created project for the temporary workplace files
02042:             * 
02043:             * @throws CmsException if something goes wrong
02044:             */
02045:            public CmsProject createTempfileProject(CmsDbContext dbc)
02046:                    throws CmsException {
02047:
02048:                // read the needed groups from the cms
02049:                CmsGroup projectUserGroup = readGroup(dbc, dbc.currentProject()
02050:                        .getGroupId());
02051:                CmsGroup projectManagerGroup = readGroup(dbc, dbc
02052:                        .currentProject().getManagerGroupId());
02053:
02054:                CmsProject tempProject = m_projectDriver
02055:                        .createProject(
02056:                                dbc,
02057:                                new CmsUUID(),
02058:                                dbc.currentUser(),
02059:                                projectUserGroup,
02060:                                projectManagerGroup,
02061:                                I_CmsProjectDriver.TEMP_FILE_PROJECT_NAME,
02062:                                Messages
02063:                                        .get()
02064:                                        .getBundle(
02065:                                                dbc.getRequestContext()
02066:                                                        .getLocale())
02067:                                        .key(
02068:                                                Messages.GUI_WORKPLACE_TEMPFILE_PROJECT_DESC_0),
02069:                                CmsProject.PROJECT_FLAG_HIDDEN,
02070:                                CmsProject.PROJECT_TYPE_NORMAL);
02071:                m_projectDriver.createProjectResource(dbc, tempProject
02072:                        .getUuid(), "/");
02073:
02074:                OpenCms.fireCmsEvent(new CmsEvent(
02075:                        I_CmsEventListener.EVENT_PROJECT_MODIFIED, Collections
02076:                                .singletonMap("project", tempProject)));
02077:
02078:                return tempProject;
02079:            }
02080:
02081:            /**
02082:             * Creates a new user.<p>
02083:             *
02084:             * @param dbc the current database context
02085:             * @param name the name for the new user
02086:             * @param password the password for the new user
02087:             * @param description the description for the new user
02088:             * @param additionalInfos the additional infos for the user
02089:             *
02090:             * @return the created user
02091:             * 
02092:             * @see CmsObject#createUser(String, String, String, Map)
02093:             * 
02094:             * @throws CmsException if something goes wrong
02095:             * @throws CmsIllegalArgumentException if the name for the user is not valid
02096:             */
02097:            public CmsUser createUser(CmsDbContext dbc, String name,
02098:                    String password, String description, Map additionalInfos)
02099:                    throws CmsException, CmsIllegalArgumentException {
02100:
02101:                // no space before or after the name
02102:                name = name.trim();
02103:                // check the user name
02104:                String userName = CmsOrganizationalUnit.getSimpleName(name);
02105:                OpenCms.getValidationHandler().checkUserName(userName);
02106:                if (CmsStringUtil.isEmptyOrWhitespaceOnly(userName)) {
02107:                    throw new CmsIllegalArgumentException(Messages.get()
02108:                            .container(Messages.ERR_BAD_USER_1, userName));
02109:                }
02110:                // check the ou
02111:                CmsOrganizationalUnit ou = readOrganizationalUnit(dbc,
02112:                        CmsOrganizationalUnit.getParentFqn(name));
02113:                // check the password
02114:                validatePassword(password);
02115:
02116:                Map info = new HashMap();
02117:                if (additionalInfos != null) {
02118:                    info.putAll(additionalInfos);
02119:                }
02120:                if (description != null) {
02121:                    info.put(CmsUserSettings.ADDITIONAL_INFO_DESCRIPTION,
02122:                            description);
02123:                }
02124:                int flags = 0;
02125:                if (ou.hasFlagWebuser()) {
02126:                    flags += I_CmsPrincipal.FLAG_USER_WEBUSER;
02127:                }
02128:                return m_userDriver.createUser(dbc, new CmsUUID(), name,
02129:                        OpenCms.getPasswordHandler().digest(password), " ",
02130:                        " ", " ", 0, I_CmsPrincipal.FLAG_ENABLED + flags, 0,
02131:                        info);
02132:            }
02133:
02134:            /**
02135:             * Deletes all property values of a file or folder.<p>
02136:             * 
02137:             * If there are no other siblings than the specified resource,
02138:             * both the structure and resource property values get deleted.
02139:             * If the specified resource has siblings, only the structure
02140:             * property values get deleted.<p>
02141:             * 
02142:             * @param dbc the current database context
02143:             * @param resourcename the name of the resource for which all properties should be deleted
02144:             * 
02145:             * @throws CmsException if operation was not successful
02146:             */
02147:            public void deleteAllProperties(CmsDbContext dbc,
02148:                    String resourcename) throws CmsException {
02149:
02150:                CmsResource resource = null;
02151:                List resources = new ArrayList();
02152:
02153:                try {
02154:                    // read the resource
02155:                    resource = readResource(dbc, resourcename,
02156:                            CmsResourceFilter.IGNORE_EXPIRATION);
02157:
02158:                    // check the security
02159:                    m_securityManager.checkPermissions(dbc, resource,
02160:                            CmsPermissionSet.ACCESS_WRITE, false,
02161:                            CmsResourceFilter.ALL);
02162:
02163:                    // delete the property values
02164:                    if (resource.getSiblingCount() > 1) {
02165:                        // the resource has siblings- delete only the (structure) properties of this sibling
02166:                        m_vfsDriver
02167:                                .deletePropertyObjects(
02168:                                        dbc,
02169:                                        dbc.currentProject().getUuid(),
02170:                                        resource,
02171:                                        CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_VALUES);
02172:                        resources.addAll(readSiblings(dbc, resource,
02173:                                CmsResourceFilter.ALL));
02174:
02175:                    } else {
02176:                        // the resource has no other siblings- delete all (structure+resource) properties
02177:                        m_vfsDriver
02178:                                .deletePropertyObjects(
02179:                                        dbc,
02180:                                        dbc.currentProject().getUuid(),
02181:                                        resource,
02182:                                        CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES);
02183:                        resources.add(resource);
02184:                    }
02185:                } finally {
02186:                    // clear the driver manager cache
02187:                    OpenCms.getMemoryMonitor().flushProperties();
02188:                    OpenCms.getMemoryMonitor().flushPropertyLists();
02189:
02190:                    // fire an event that all properties of a resource have been deleted
02191:                    OpenCms
02192:                            .fireCmsEvent(new CmsEvent(
02193:                                    I_CmsEventListener.EVENT_RESOURCES_AND_PROPERTIES_MODIFIED,
02194:                                    Collections.singletonMap("resources",
02195:                                            resources)));
02196:                }
02197:            }
02198:
02199:            /**
02200:             * Deletes all entries in the published resource table.<p>
02201:             * 
02202:             * @param dbc the current database context
02203:             * @param linkType the type of resource deleted (0= non-paramter, 1=parameter)
02204:             * 
02205:             * @throws CmsException if something goes wrong
02206:             */
02207:            public void deleteAllStaticExportPublishedResources(
02208:                    CmsDbContext dbc, int linkType) throws CmsException {
02209:
02210:                m_projectDriver.deleteAllStaticExportPublishedResources(dbc,
02211:                        linkType);
02212:            }
02213:
02214:            /**
02215:             * Deletes a group, where all permissions, users and children of the group
02216:             * are transfered to a replacement group.<p>
02217:             * 
02218:             * @param dbc the current request context
02219:             * @param group the id of the group to be deleted
02220:             * @param replacementId the id of the group to be transfered, can be <code>null</code>
02221:             *
02222:             * @throws CmsException if operation was not successful
02223:             * @throws CmsDataAccessException if group to be deleted contains user
02224:             */
02225:            public void deleteGroup(CmsDbContext dbc, CmsGroup group,
02226:                    CmsUUID replacementId) throws CmsDataAccessException,
02227:                    CmsException {
02228:
02229:                CmsGroup replacementGroup = null;
02230:                if (replacementId != null) {
02231:                    replacementGroup = readGroup(dbc, replacementId);
02232:                }
02233:                // get all child groups of the group
02234:                List children = getChildren(dbc, group, false);
02235:                // get all users in this group
02236:                List users = getUsersOfGroup(dbc, group.getName(), true, false,
02237:                        group.isRole());
02238:                // get online project
02239:                CmsProject onlineProject = readProject(dbc,
02240:                        CmsProject.ONLINE_PROJECT_ID);
02241:                if (replacementGroup == null) {
02242:                    // remove users
02243:                    Iterator itUsers = users.iterator();
02244:                    while (itUsers.hasNext()) {
02245:                        CmsUser user = (CmsUser) itUsers.next();
02246:                        if (userInGroup(dbc, user.getName(), group.getName(),
02247:                                group.isRole())) {
02248:                            removeUserFromGroup(dbc, user.getName(), group
02249:                                    .getName(), group.isRole());
02250:                        }
02251:                    }
02252:                    // transfer children to grandfather if possible
02253:                    CmsUUID parentId = group.getParentId();
02254:                    if (parentId == null) {
02255:                        parentId = CmsUUID.getNullUUID();
02256:                    }
02257:                    Iterator itChildren = children.iterator();
02258:                    while (itChildren.hasNext()) {
02259:                        CmsGroup child = (CmsGroup) itChildren.next();
02260:                        child.setParentId(parentId);
02261:                        writeGroup(dbc, child);
02262:                    }
02263:                } else {
02264:                    // move children
02265:                    Iterator itChildren = children.iterator();
02266:                    while (itChildren.hasNext()) {
02267:                        CmsGroup child = (CmsGroup) itChildren.next();
02268:                        child.setParentId(replacementId);
02269:                        writeGroup(dbc, child);
02270:                    }
02271:                    // move users
02272:                    Iterator itUsers = users.iterator();
02273:                    while (itUsers.hasNext()) {
02274:                        CmsUser user = (CmsUser) itUsers.next();
02275:                        addUserToGroup(dbc, user.getName(), replacementGroup
02276:                                .getName(), group.isRole());
02277:                        removeUserFromGroup(dbc, user.getName(), group
02278:                                .getName(), group.isRole());
02279:                    }
02280:                    // transfer for offline
02281:                    transferPrincipalResources(dbc, dbc.currentProject(), group
02282:                            .getId(), replacementId, true);
02283:                    // transfer for online
02284:                    transferPrincipalResources(dbc, onlineProject, group
02285:                            .getId(), replacementId, true);
02286:                }
02287:                // remove the group
02288:                m_userDriver.removeAccessControlEntriesForPrincipal(dbc, dbc
02289:                        .currentProject(), onlineProject, group.getId());
02290:                m_userDriver.deleteGroup(dbc, group.getName());
02291:                // backup the group
02292:                m_historyDriver.writePrincipal(dbc, group);
02293:
02294:                // clear the relevant caches
02295:                OpenCms.getMemoryMonitor().uncacheGroup(group);
02296:                OpenCms.getMemoryMonitor().flushUserGroups();
02297:                OpenCms.getMemoryMonitor().flushACLs();
02298:            }
02299:
02300:            /**
02301:             * Deletes the versions from the history tables, keeping the given number of versions per resource.<p>
02302:             * 
02303:             * if the <code>cleanUp</code> option is set, additionally versions of deleted resources will be removed.<p>
02304:             * 
02305:             * @param dbc the current database context
02306:             * @param folder the folder (with subresources) to delete historical versions for 
02307:             * @param versionsToKeep number of versions to keep, is ignored if negative 
02308:             * @param versionsDeleted number of versions to keep for deleted resources, is ignored if negative
02309:             * @param timeDeleted deleted resources older than this will also be deleted, is ignored if negative
02310:             * @param report the report for output logging
02311:             * 
02312:             * @throws CmsException if operation was not successful
02313:             */
02314:            public void deleteHistoricalVersions(CmsDbContext dbc,
02315:                    CmsFolder folder, int versionsToKeep, int versionsDeleted,
02316:                    long timeDeleted, I_CmsReport report) throws CmsException {
02317:
02318:                report.println(Messages.get().container(
02319:                        Messages.RPT_START_DELETE_VERSIONS_0),
02320:                        I_CmsReport.FORMAT_HEADLINE);
02321:                if (versionsToKeep >= 0) {
02322:                    report.println(Messages.get().container(
02323:                            Messages.RPT_START_DELETE_ACT_VERSIONS_1,
02324:                            new Integer(versionsToKeep)),
02325:                            I_CmsReport.FORMAT_HEADLINE);
02326:
02327:                    List resources = m_historyDriver.getAllNotDeletedEntries(
02328:                            dbc, folder.getStructureId());
02329:                    if (resources.isEmpty()) {
02330:                        report.println(Messages.get().container(
02331:                                Messages.RPT_DELETE_NOTHING_0),
02332:                                I_CmsReport.FORMAT_OK);
02333:                    }
02334:                    int n = resources.size();
02335:                    int m = 1;
02336:                    Iterator itResources = resources.iterator();
02337:                    while (itResources.hasNext()) {
02338:                        I_CmsHistoryResource histResource = (I_CmsHistoryResource) itResources
02339:                                .next();
02340:
02341:                        report
02342:                                .print(
02343:                                        org.opencms.report.Messages
02344:                                                .get()
02345:                                                .container(
02346:                                                        org.opencms.report.Messages.RPT_SUCCESSION_2,
02347:                                                        String.valueOf(m),
02348:                                                        String.valueOf(n)),
02349:                                        I_CmsReport.FORMAT_NOTE);
02350:                        report
02351:                                .print(org.opencms.report.Messages
02352:                                        .get()
02353:                                        .container(
02354:                                                org.opencms.report.Messages.RPT_ARGUMENT_1,
02355:                                                dbc.removeSiteRoot(histResource
02356:                                                        .getRootPath())));
02357:                        report
02358:                                .print(org.opencms.report.Messages
02359:                                        .get()
02360:                                        .container(
02361:                                                org.opencms.report.Messages.RPT_DOTS_0));
02362:
02363:                        try {
02364:                            int deleted = m_historyDriver.deleteEntries(dbc,
02365:                                    histResource, versionsToKeep, -1);
02366:
02367:                            report.print(Messages.get().container(
02368:                                    Messages.RPT_VERSION_DELETING_1,
02369:                                    new Integer(deleted)),
02370:                                    I_CmsReport.FORMAT_NOTE);
02371:                            report
02372:                                    .print(org.opencms.report.Messages
02373:                                            .get()
02374:                                            .container(
02375:                                                    org.opencms.report.Messages.RPT_DOTS_0));
02376:                            report
02377:                                    .println(
02378:                                            org.opencms.report.Messages
02379:                                                    .get()
02380:                                                    .container(
02381:                                                            org.opencms.report.Messages.RPT_OK_0),
02382:                                            I_CmsReport.FORMAT_OK);
02383:                        } catch (CmsDataAccessException e) {
02384:                            report
02385:                                    .println(
02386:                                            org.opencms.report.Messages
02387:                                                    .get()
02388:                                                    .container(
02389:                                                            org.opencms.report.Messages.RPT_ERROR_0),
02390:                                            I_CmsReport.FORMAT_ERROR);
02391:
02392:                            if (LOG.isDebugEnabled()) {
02393:                                LOG.debug(e.getLocalizedMessage(), e);
02394:                            }
02395:                        }
02396:
02397:                        m++;
02398:                    }
02399:
02400:                    report.println(Messages.get().container(
02401:                            Messages.RPT_END_DELETE_ACT_VERSIONS_0),
02402:                            I_CmsReport.FORMAT_HEADLINE);
02403:                }
02404:                if ((versionsDeleted >= 0) || (timeDeleted >= 0)) {
02405:                    if (timeDeleted >= 0) {
02406:                        report.println(Messages.get().container(
02407:                                Messages.RPT_START_DELETE_DEL_VERSIONS_2,
02408:                                new Integer(versionsDeleted),
02409:                                new Date(timeDeleted)),
02410:                                I_CmsReport.FORMAT_HEADLINE);
02411:                    } else {
02412:                        report.println(Messages.get().container(
02413:                                Messages.RPT_START_DELETE_DEL_VERSIONS_1,
02414:                                new Integer(versionsDeleted)),
02415:                                I_CmsReport.FORMAT_HEADLINE);
02416:                    }
02417:                    List resources = m_historyDriver.getAllDeletedEntries(dbc,
02418:                            folder.getStructureId());
02419:                    if (resources.isEmpty()) {
02420:                        report.println(Messages.get().container(
02421:                                Messages.RPT_DELETE_NOTHING_0),
02422:                                I_CmsReport.FORMAT_OK);
02423:                    }
02424:                    int n = resources.size();
02425:                    int m = 1;
02426:                    Iterator itResources = resources.iterator();
02427:                    while (itResources.hasNext()) {
02428:                        I_CmsHistoryResource histResource = (I_CmsHistoryResource) itResources
02429:                                .next();
02430:
02431:                        report
02432:                                .print(
02433:                                        org.opencms.report.Messages
02434:                                                .get()
02435:                                                .container(
02436:                                                        org.opencms.report.Messages.RPT_SUCCESSION_2,
02437:                                                        String.valueOf(m),
02438:                                                        String.valueOf(n)),
02439:                                        I_CmsReport.FORMAT_NOTE);
02440:                        report
02441:                                .print(org.opencms.report.Messages
02442:                                        .get()
02443:                                        .container(
02444:                                                org.opencms.report.Messages.RPT_ARGUMENT_1,
02445:                                                dbc.removeSiteRoot(histResource
02446:                                                        .getRootPath())));
02447:                        report
02448:                                .print(org.opencms.report.Messages
02449:                                        .get()
02450:                                        .container(
02451:                                                org.opencms.report.Messages.RPT_DOTS_0));
02452:
02453:                        try {
02454:                            int deleted = m_historyDriver.deleteEntries(dbc,
02455:                                    histResource, versionsDeleted, timeDeleted);
02456:
02457:                            report.print(Messages.get().container(
02458:                                    Messages.RPT_VERSION_DELETING_1,
02459:                                    new Integer(deleted)),
02460:                                    I_CmsReport.FORMAT_NOTE);
02461:                            report
02462:                                    .print(org.opencms.report.Messages
02463:                                            .get()
02464:                                            .container(
02465:                                                    org.opencms.report.Messages.RPT_DOTS_0));
02466:                            report
02467:                                    .println(
02468:                                            org.opencms.report.Messages
02469:                                                    .get()
02470:                                                    .container(
02471:                                                            org.opencms.report.Messages.RPT_OK_0),
02472:                                            I_CmsReport.FORMAT_OK);
02473:                        } catch (CmsDataAccessException e) {
02474:                            report
02475:                                    .println(
02476:                                            org.opencms.report.Messages
02477:                                                    .get()
02478:                                                    .container(
02479:                                                            org.opencms.report.Messages.RPT_ERROR_0),
02480:                                            I_CmsReport.FORMAT_ERROR);
02481:
02482:                            if (LOG.isDebugEnabled()) {
02483:                                LOG.debug(e.getLocalizedMessage(), e);
02484:                            }
02485:                        }
02486:
02487:                        m++;
02488:                    }
02489:                    report.println(Messages.get().container(
02490:                            Messages.RPT_END_DELETE_DEL_VERSIONS_0),
02491:                            I_CmsReport.FORMAT_HEADLINE);
02492:                }
02493:                report.println(Messages.get().container(
02494:                        Messages.RPT_END_DELETE_VERSIONS_0),
02495:                        I_CmsReport.FORMAT_HEADLINE);
02496:            }
02497:
02498:            /**
02499:             * Deletes an organizational unit.<p>
02500:             *
02501:             * Only organizational units that contain no suborganizational unit can be deleted.<p>
02502:             * 
02503:             * The organizational unit can not be delete if it is used in the request context, 
02504:             * or if the current user belongs to it.<p>
02505:             * 
02506:             * All users and groups in the given organizational unit will be deleted.<p>
02507:             * 
02508:             * @param dbc the current db context
02509:             * @param organizationalUnit the organizational unit to delete
02510:             * 
02511:             * @throws CmsException if operation was not successful
02512:             * 
02513:             * @see org.opencms.security.CmsOrgUnitManager#deleteOrganizationalUnit(CmsObject, String)
02514:             */
02515:            public void deleteOrganizationalUnit(CmsDbContext dbc,
02516:                    CmsOrganizationalUnit organizationalUnit)
02517:                    throws CmsException {
02518:
02519:                // check organizational unit in context
02520:                if (dbc.getRequestContext().getOuFqn().equals(
02521:                        organizationalUnit.getName())) {
02522:                    throw new CmsDbConsistencyException(Messages.get()
02523:                            .container(
02524:                                    Messages.ERR_ORGUNIT_DELETE_IN_CONTEXT_1,
02525:                                    organizationalUnit.getName()));
02526:                }
02527:                // check organizational unit for user
02528:                if (dbc.currentUser().getOuFqn().equals(
02529:                        organizationalUnit.getName())) {
02530:                    throw new CmsDbConsistencyException(Messages.get()
02531:                            .container(
02532:                                    Messages.ERR_ORGUNIT_DELETE_CURRENT_USER_1,
02533:                                    organizationalUnit.getName()));
02534:                }
02535:                // check sub organizational units
02536:                if (!getOrganizationalUnits(dbc, organizationalUnit, true)
02537:                        .isEmpty()) {
02538:                    throw new CmsDbConsistencyException(Messages.get()
02539:                            .container(
02540:                                    Messages.ERR_ORGUNIT_DELETE_SUB_ORGUNITS_1,
02541:                                    organizationalUnit.getName()));
02542:                }
02543:                // check groups
02544:                List groups = getGroups(dbc, organizationalUnit, true, false);
02545:                Iterator itGroups = groups.iterator();
02546:                while (itGroups.hasNext()) {
02547:                    CmsGroup group = (CmsGroup) itGroups.next();
02548:                    if (!OpenCms.getDefaultUsers().isDefaultGroup(
02549:                            group.getName())) {
02550:                        throw new CmsDbConsistencyException(Messages.get()
02551:                                .container(
02552:                                        Messages.ERR_ORGUNIT_DELETE_GROUPS_1,
02553:                                        organizationalUnit.getName()));
02554:                    }
02555:                }
02556:                // check users
02557:                if (!getUsers(dbc, organizationalUnit, true).isEmpty()) {
02558:                    throw new CmsDbConsistencyException(Messages.get()
02559:                            .container(Messages.ERR_ORGUNIT_DELETE_USERS_1,
02560:                                    organizationalUnit.getName()));
02561:                }
02562:
02563:                // delete default groups if needed
02564:                itGroups = groups.iterator();
02565:                while (itGroups.hasNext()) {
02566:                    CmsGroup group = (CmsGroup) itGroups.next();
02567:                    deleteGroup(dbc, group, null);
02568:                }
02569:
02570:                // delete projects
02571:                Iterator itProjects = m_projectDriver.readProjects(dbc,
02572:                        organizationalUnit.getName()).iterator();
02573:                while (itProjects.hasNext()) {
02574:                    CmsProject project = (CmsProject) itProjects.next();
02575:                    deleteProject(dbc, project);
02576:                }
02577:
02578:                // delete roles
02579:                Iterator itRoles = getGroups(dbc, organizationalUnit, true,
02580:                        true).iterator();
02581:                while (itRoles.hasNext()) {
02582:                    CmsGroup role = (CmsGroup) itRoles.next();
02583:                    deleteGroup(dbc, role, null);
02584:                }
02585:
02586:                // create a publish list for the 'virtual' publish event
02587:                CmsResource resource = readResource(dbc, organizationalUnit
02588:                        .getId(), CmsResourceFilter.DEFAULT);
02589:                CmsPublishList pl = new CmsPublishList(resource, false);
02590:                pl.add(resource, false);
02591:
02592:                // remove the organizational unit itself
02593:                m_userDriver.deleteOrganizationalUnit(dbc, organizationalUnit);
02594:
02595:                // write the publish history entry
02596:                m_projectDriver.writePublishHistory(dbc, pl
02597:                        .getPublishHistoryId(), new CmsPublishedResource(
02598:                        resource));
02599:
02600:                // flush relevant caches
02601:                OpenCms.getMemoryMonitor().clearPrincipalsCache();
02602:                OpenCms.getMemoryMonitor().flushProperties();
02603:                OpenCms.getMemoryMonitor().flushPropertyLists();
02604:
02605:                // fire the 'virtual' publish event
02606:                Map eventData = new HashMap();
02607:                eventData.put(I_CmsEventListener.KEY_PUBLISHID, pl
02608:                        .getPublishHistoryId().toString());
02609:                eventData.put(I_CmsEventListener.KEY_PROJECTID, dbc
02610:                        .currentProject().getUuid());
02611:                eventData.put(I_CmsEventListener.KEY_DBCONTEXT, dbc);
02612:                CmsEvent afterPublishEvent = new CmsEvent(
02613:                        I_CmsEventListener.EVENT_PUBLISH_PROJECT, eventData);
02614:                OpenCms.fireCmsEvent(afterPublishEvent);
02615:
02616:                m_lockManager
02617:                        .removeDeletedResource(dbc, resource.getRootPath());
02618:            }
02619:
02620:            /**
02621:             * Deletes a project.<p>
02622:             *
02623:             * Only the admin or the owner of the project can do this.
02624:             * 
02625:             * @param dbc the current database context
02626:             * @param deleteProject the project to be deleted
02627:             *
02628:             * @throws CmsException if something goes wrong
02629:             */
02630:            public void deleteProject(CmsDbContext dbc, CmsProject deleteProject)
02631:                    throws CmsException {
02632:
02633:                CmsUUID projectId = deleteProject.getUuid();
02634:                // changed/new/deleted files in the specified project
02635:                List modifiedFiles = readChangedResourcesInsideProject(dbc,
02636:                        projectId, RCPRM_FILES_ONLY_MODE);
02637:                // changed/new/deleted folders in the specified project
02638:                List modifiedFolders = readChangedResourcesInsideProject(dbc,
02639:                        projectId, RCPRM_FOLDERS_ONLY_MODE);
02640:
02641:                // all resources inside the project have to be be reset to their online state.
02642:                // 1. step: delete all new files
02643:                for (int i = 0; i < modifiedFiles.size(); i++) {
02644:                    CmsResource currentFile = (CmsResource) modifiedFiles
02645:                            .get(i);
02646:                    if (currentFile.getState().isNew()) {
02647:                        CmsLock lock = getLock(dbc, currentFile);
02648:                        if (lock.isNullLock()) {
02649:                            // lock the resource
02650:                            lockResource(dbc, currentFile,
02651:                                    CmsLockType.EXCLUSIVE);
02652:                        } else if (!lock.isOwnedBy(dbc.currentUser())
02653:                                || !lock.isInProject(dbc.currentProject())) {
02654:                            changeLock(dbc, currentFile, CmsLockType.EXCLUSIVE);
02655:                        }
02656:                        // delete the properties
02657:                        m_vfsDriver
02658:                                .deletePropertyObjects(
02659:                                        dbc,
02660:                                        projectId,
02661:                                        currentFile,
02662:                                        CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES);
02663:                        // delete the file
02664:                        m_vfsDriver.removeFile(dbc, dbc.currentProject()
02665:                                .getUuid(), currentFile);
02666:                        // remove the access control entries
02667:                        m_userDriver.removeAccessControlEntries(dbc, dbc
02668:                                .currentProject(), currentFile.getResourceId());
02669:                        // fire the corresponding event
02670:                        OpenCms
02671:                                .fireCmsEvent(new CmsEvent(
02672:                                        I_CmsEventListener.EVENT_RESOURCE_AND_PROPERTIES_MODIFIED,
02673:                                        Collections.singletonMap("resource",
02674:                                                currentFile)));
02675:                    }
02676:                }
02677:
02678:                // 2. step: delete all new folders
02679:                for (int i = 0; i < modifiedFolders.size(); i++) {
02680:                    CmsResource currentFolder = (CmsResource) modifiedFolders
02681:                            .get(i);
02682:                    if (currentFolder.getState().isNew()) {
02683:                        // delete the properties
02684:                        m_vfsDriver
02685:                                .deletePropertyObjects(
02686:                                        dbc,
02687:                                        projectId,
02688:                                        currentFolder,
02689:                                        CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES);
02690:                        // delete the folder
02691:                        m_vfsDriver.removeFolder(dbc, dbc.currentProject(),
02692:                                currentFolder);
02693:                        // remove the access control entries
02694:                        m_userDriver.removeAccessControlEntries(dbc, dbc
02695:                                .currentProject(), currentFolder
02696:                                .getResourceId());
02697:                        // fire the corresponding event
02698:                        OpenCms
02699:                                .fireCmsEvent(new CmsEvent(
02700:                                        I_CmsEventListener.EVENT_RESOURCE_AND_PROPERTIES_MODIFIED,
02701:                                        Collections.singletonMap("resource",
02702:                                                currentFolder)));
02703:                    }
02704:                }
02705:
02706:                // 3. step: undo changes on all changed or deleted folders
02707:                for (int i = 0; i < modifiedFolders.size(); i++) {
02708:                    CmsResource currentFolder = (CmsResource) modifiedFolders
02709:                            .get(i);
02710:                    if ((currentFolder.getState().isChanged())
02711:                            || (currentFolder.getState().isDeleted())) {
02712:                        CmsLock lock = getLock(dbc, currentFolder);
02713:                        if (lock.isNullLock()) {
02714:                            // lock the resource
02715:                            lockResource(dbc, currentFolder,
02716:                                    CmsLockType.EXCLUSIVE);
02717:                        } else if (!lock.isOwnedBy(dbc.currentUser())
02718:                                || !lock.isInProject(dbc.currentProject())) {
02719:                            changeLock(dbc, currentFolder,
02720:                                    CmsLockType.EXCLUSIVE);
02721:                        }
02722:                        // undo all changes in the folder
02723:                        undoChanges(dbc, currentFolder,
02724:                                CmsResource.UNDO_CONTENT);
02725:                        // fire the corresponding event
02726:                        OpenCms
02727:                                .fireCmsEvent(new CmsEvent(
02728:                                        I_CmsEventListener.EVENT_RESOURCE_AND_PROPERTIES_MODIFIED,
02729:                                        Collections.singletonMap("resource",
02730:                                                currentFolder)));
02731:                    }
02732:                }
02733:
02734:                // 4. step: undo changes on all changed or deleted files 
02735:                for (int i = 0; i < modifiedFiles.size(); i++) {
02736:                    CmsResource currentFile = (CmsResource) modifiedFiles
02737:                            .get(i);
02738:                    if (currentFile.getState().isChanged()
02739:                            || currentFile.getState().isDeleted()) {
02740:                        CmsLock lock = getLock(dbc, currentFile);
02741:                        if (lock.isNullLock()) {
02742:                            // lock the resource
02743:                            lockResource(dbc, currentFile,
02744:                                    CmsLockType.EXCLUSIVE);
02745:                        } else if (!lock.isOwnedInProjectBy(dbc.currentUser(),
02746:                                dbc.currentProject())) {
02747:                            if (lock.isLockableBy(dbc.currentUser())) {
02748:                                changeLock(dbc, currentFile,
02749:                                        CmsLockType.EXCLUSIVE);
02750:                            }
02751:                        }
02752:                        // undo all changes in the file
02753:                        undoChanges(dbc, currentFile, CmsResource.UNDO_CONTENT);
02754:                        // fire the corresponding event
02755:                        OpenCms
02756:                                .fireCmsEvent(new CmsEvent(
02757:                                        I_CmsEventListener.EVENT_RESOURCE_AND_PROPERTIES_MODIFIED,
02758:                                        Collections.singletonMap("resource",
02759:                                                currentFile)));
02760:                    }
02761:                }
02762:
02763:                // unlock all resources in the project
02764:                m_lockManager.removeResourcesInProject(deleteProject.getUuid(),
02765:                        true);
02766:                OpenCms.getMemoryMonitor().clearAccessControlListCache();
02767:                OpenCms.getMemoryMonitor().clearResourceCache();
02768:
02769:                // set project to online project if current project is the one which will be deleted 
02770:                if (projectId.equals(dbc.currentProject().getUuid())) {
02771:                    dbc.getRequestContext().setCurrentProject(
02772:                            readProject(dbc, CmsProject.ONLINE_PROJECT_ID));
02773:                }
02774:
02775:                // delete the project itself
02776:                m_projectDriver.deleteProject(dbc, deleteProject);
02777:                OpenCms.getMemoryMonitor().uncacheProject(deleteProject);
02778:
02779:                // fire the corresponding event
02780:                OpenCms.fireCmsEvent(new CmsEvent(
02781:                        I_CmsEventListener.EVENT_PROJECT_MODIFIED, Collections
02782:                                .singletonMap("project", deleteProject)));
02783:
02784:            }
02785:
02786:            /**
02787:             * Deletes a property definition.<p>
02788:             *
02789:             * @param dbc the current database context
02790:             * @param name the name of the property definition to delete
02791:             * 
02792:             * @throws CmsException if something goes wrong
02793:             */
02794:            public void deletePropertyDefinition(CmsDbContext dbc, String name)
02795:                    throws CmsException {
02796:
02797:                CmsPropertyDefinition propertyDefinition = null;
02798:
02799:                try {
02800:                    // first read and then delete the metadefinition.            
02801:                    propertyDefinition = readPropertyDefinition(dbc, name);
02802:                    m_vfsDriver.deletePropertyDefinition(dbc,
02803:                            propertyDefinition);
02804:                    m_historyDriver.deletePropertyDefinition(dbc,
02805:                            propertyDefinition);
02806:                } finally {
02807:
02808:                    // fire an event that a property of a resource has been deleted
02809:                    OpenCms
02810:                            .fireCmsEvent(new CmsEvent(
02811:                                    I_CmsEventListener.EVENT_PROPERTY_DEFINITION_MODIFIED,
02812:                                    Collections.singletonMap(
02813:                                            "propertyDefinition",
02814:                                            propertyDefinition)));
02815:                }
02816:            }
02817:
02818:            /**
02819:             * Deletes a publish job identified by its history id.<p>
02820:             * 
02821:             * @param dbc the current database context
02822:             * @param publishHistoryId the history id identifying the publish job
02823:             * 
02824:             * @throws CmsException if something goes wrong
02825:             */
02826:            public void deletePublishJob(CmsDbContext dbc,
02827:                    CmsUUID publishHistoryId) throws CmsException {
02828:
02829:                m_projectDriver.deletePublishJob(dbc, publishHistoryId);
02830:            }
02831:
02832:            /**
02833:             * Deletes the publish list assigned to a publish job.<p>
02834:             * 
02835:             * @param dbc the current database context 
02836:             * @param publishHistoryId the history id identifying the publish job
02837:             * @throws CmsException if something goes wrong
02838:             */
02839:            public void deletePublishList(CmsDbContext dbc,
02840:                    CmsUUID publishHistoryId) throws CmsException {
02841:
02842:                m_projectDriver.deletePublishList(dbc, publishHistoryId);
02843:            }
02844:
02845:            /**
02846:             * Deletes all relations for the given resource matching the given filter.<p>
02847:             * 
02848:             * @param dbc the current db context
02849:             * @param resource the resource to delete the relations for
02850:             * @param filter the filter to use for deletion
02851:             * 
02852:             * @throws CmsException if something goes wrong
02853:             * 
02854:             * @see CmsSecurityManager#deleteRelationsForResource(CmsRequestContext, CmsResource, CmsRelationFilter)
02855:             */
02856:            public void deleteRelationsForResource(CmsDbContext dbc,
02857:                    CmsResource resource, CmsRelationFilter filter)
02858:                    throws CmsException {
02859:
02860:                if (filter.includesDefinedInContent()) {
02861:                    throw new CmsIllegalArgumentException(Messages.get()
02862:                            .container(
02863:                                    Messages.ERR_DELETE_RELATION_IN_CONTENT_2,
02864:                                    dbc.removeSiteRoot(resource.getRootPath()),
02865:                                    filter.getTypes()));
02866:                }
02867:                m_vfsDriver.deleteRelations(dbc,
02868:                        dbc.currentProject().getUuid(), resource, filter);
02869:                setDateLastModified(dbc, resource, System.currentTimeMillis());
02870:            }
02871:
02872:            /**
02873:             * Deletes a resource.<p>
02874:             * 
02875:             * The <code>siblingMode</code> parameter controls how to handle siblings 
02876:             * during the delete operation.
02877:             * Possible values for this parameter are: 
02878:             * <ul>
02879:             * <li><code>{@link CmsResource#DELETE_REMOVE_SIBLINGS}</code></li>
02880:             * <li><code>{@link CmsResource#DELETE_PRESERVE_SIBLINGS}</code></li>
02881:             * </ul><p>
02882:             * 
02883:             * @param dbc the current database context
02884:             * @param resource the name of the resource to delete (full path)
02885:             * @param siblingMode indicates how to handle siblings of the deleted resource
02886:             * 
02887:             * @throws CmsException if something goes wrong
02888:             * 
02889:             * @see CmsObject#deleteResource(String, CmsResource.CmsResourceDeleteMode)
02890:             * @see I_CmsResourceType#deleteResource(CmsObject, CmsSecurityManager, CmsResource, CmsResource.CmsResourceDeleteMode)
02891:             */
02892:            public void deleteResource(CmsDbContext dbc, CmsResource resource,
02893:                    CmsResource.CmsResourceDeleteMode siblingMode)
02894:                    throws CmsException {
02895:
02896:                // upgrade a potential inherited, non-shared lock into a common lock
02897:                CmsLock currentLock = getLock(dbc, resource);
02898:                if (currentLock.getEditionLock().isDirectlyInherited()) {
02899:                    // upgrade the lock status if required
02900:                    lockResource(dbc, resource, CmsLockType.EXCLUSIVE);
02901:                }
02902:
02903:                // check if siblings of the resource exist and must be deleted as well
02904:                if (resource.isFolder()) {
02905:                    // folder can have no siblings
02906:                    siblingMode = CmsResource.DELETE_PRESERVE_SIBLINGS;
02907:                }
02908:
02909:                // if selected, add all siblings of this resource to the list of resources to be deleted    
02910:                boolean allSiblingsRemoved;
02911:                List resources;
02912:                if (siblingMode == CmsResource.DELETE_REMOVE_SIBLINGS) {
02913:                    resources = new ArrayList(readSiblings(dbc, resource,
02914:                            CmsResourceFilter.ALL));
02915:                    allSiblingsRemoved = true;
02916:
02917:                    // ensure that the resource requested to be deleted is the last resource that gets actually deleted
02918:                    // to keep the shared locks of the siblings while those get deleted.
02919:                    resources.remove(resource);
02920:                    resources.add(resource);
02921:                } else {
02922:                    // only delete the resource, no siblings
02923:                    resources = Collections.singletonList(resource);
02924:                    allSiblingsRemoved = false;
02925:                }
02926:
02927:                int size = resources.size();
02928:                // if we have only one resource no further check is required
02929:                if (size > 1) {
02930:                    CmsMultiException me = new CmsMultiException();
02931:                    // ensure that each sibling is unlocked or locked by the current user
02932:                    for (int i = 0; i < size; i++) {
02933:                        CmsResource currentResource = (CmsResource) resources
02934:                                .get(i);
02935:                        currentLock = getLock(dbc, currentResource);
02936:                        if (!currentLock.getEditionLock().isUnlocked()
02937:                                && !currentLock.isOwnedBy(dbc.currentUser())) {
02938:                            // the resource is locked by a user different from the current user
02939:                            CmsRequestContext context = dbc.getRequestContext();
02940:                            me
02941:                                    .addException(new CmsLockException(
02942:                                            org.opencms.lock.Messages
02943:                                                    .get()
02944:                                                    .container(
02945:                                                            org.opencms.lock.Messages.ERR_SIBLING_LOCKED_2,
02946:                                                            context
02947:                                                                    .getSitePath(currentResource),
02948:                                                            context
02949:                                                                    .getSitePath(resource))));
02950:                        }
02951:                    }
02952:                    if (!me.getExceptions().isEmpty()) {
02953:                        throw me;
02954:                    }
02955:                }
02956:
02957:                boolean removeAce = true;
02958:
02959:                if (resource.isFolder()) {
02960:                    // check if the folder has any resources in it
02961:                    Iterator childResources = m_vfsDriver.readChildResources(
02962:                            dbc, dbc.currentProject(), resource, true, true)
02963:                            .iterator();
02964:
02965:                    CmsUUID projectId = CmsProject.ONLINE_PROJECT_ID;
02966:                    if (dbc.currentProject().isOnlineProject()) {
02967:                        projectId = CmsUUID.getOpenCmsUUID(); // HACK: to get an offline project id
02968:                    }
02969:
02970:                    // collect the names of the resources inside the folder, excluding the moved resources
02971:                    StringBuffer errorResNames = new StringBuffer(128);
02972:                    while (childResources.hasNext()) {
02973:                        CmsResource errorRes = (CmsResource) childResources
02974:                                .next();
02975:                        if (errorRes.getState().isDeleted()) {
02976:                            continue;
02977:                        }
02978:                        // if deleting offline, or not moved, or just renamed inside the deleted folder
02979:                        // so, it may remain some orphan online entries for moved resources
02980:                        // which will be fixed during the publishing of the moved resources
02981:                        boolean error = !dbc.currentProject().isOnlineProject();
02982:                        if (!error) {
02983:                            try {
02984:                                String originalPath = m_vfsDriver.readResource(
02985:                                        dbc, projectId, errorRes.getRootPath(),
02986:                                        true).getRootPath();
02987:                                error = originalPath.equals(errorRes
02988:                                        .getRootPath())
02989:                                        || originalPath.startsWith(resource
02990:                                                .getRootPath());
02991:                            } catch (CmsVfsResourceNotFoundException e) {
02992:                                // ignore
02993:                            }
02994:                        }
02995:                        if (error) {
02996:                            if (errorResNames.length() != 0) {
02997:                                errorResNames.append(", ");
02998:                            }
02999:                            errorResNames.append("["
03000:                                    + dbc
03001:                                            .removeSiteRoot(errorRes
03002:                                                    .getRootPath()) + "]");
03003:                        }
03004:                    }
03005:
03006:                    // the current implementation only deletes empty folders
03007:                    if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(errorResNames
03008:                            .toString())) {
03009:                        throw new CmsVfsException(
03010:                                org.opencms.db.generic.Messages
03011:                                        .get()
03012:                                        .container(
03013:                                                org.opencms.db.generic.Messages.ERR_DELETE_NONEMTY_FOLDER_2,
03014:                                                dbc.removeSiteRoot(resource
03015:                                                        .getRootPath()),
03016:                                                errorResNames.toString()));
03017:                    }
03018:                }
03019:
03020:                // delete all collected resources
03021:                for (int i = 0; i < size; i++) {
03022:                    CmsResource currentResource = (CmsResource) resources
03023:                            .get(i);
03024:
03025:                    // try to delete/remove the resource only if the user has write access to the resource
03026:                    // check permissions only for the sibling, the resource it self was already checked or 
03027:                    // is to be removed without write permissions, ie. while deleting a folder
03028:                    if (!currentResource.equals(resource)
03029:                            && (I_CmsPermissionHandler.PERM_ALLOWED != m_securityManager
03030:                                    .hasPermissions(dbc, currentResource,
03031:                                            CmsPermissionSet.ACCESS_WRITE,
03032:                                            true, CmsResourceFilter.ALL))) {
03033:
03034:                        // no write access to sibling - must keep ACE (see below)
03035:                        allSiblingsRemoved = false;
03036:                    } else {
03037:                        // write access to sibling granted                 
03038:                        boolean existsOnline = m_vfsDriver
03039:                                .validateStructureIdExists(dbc,
03040:                                        CmsProject.ONLINE_PROJECT_ID,
03041:                                        currentResource.getStructureId());
03042:
03043:                        if (!existsOnline) {
03044:                            // the resource does not exist online => remove the resource
03045:                            // this means the resource is "new" (blue) in the offline project                
03046:
03047:                            // delete all properties of this resource
03048:                            deleteAllProperties(dbc, currentResource
03049:                                    .getRootPath());
03050:
03051:                            if (currentResource.isFolder()) {
03052:                                m_vfsDriver.removeFolder(dbc, dbc
03053:                                        .currentProject(), currentResource);
03054:                            } else {
03055:                                // check labels
03056:                                if (currentResource.isLabeled()
03057:                                        && !labelResource(dbc, currentResource,
03058:                                                null, 2)) {
03059:                                    // update the resource flags to "un label" the other siblings
03060:                                    int flags = currentResource.getFlags();
03061:                                    flags &= ~CmsResource.FLAG_LABELED;
03062:                                    currentResource.setFlags(flags);
03063:                                }
03064:                                m_vfsDriver.removeFile(dbc, dbc
03065:                                        .currentProject().getUuid(),
03066:                                        currentResource);
03067:                            }
03068:
03069:                            // ensure an exclusive lock is removed in the lock manager for a deleted new resource,
03070:                            // otherwise it would "stick" in the lock manager, preventing other users from creating 
03071:                            // a file with the same name (issue with temp files in editor)
03072:                            m_lockManager.removeDeletedResource(dbc,
03073:                                    currentResource.getRootPath());
03074:                            // delete relations
03075:                            m_vfsDriver.deleteRelations(dbc, dbc
03076:                                    .currentProject().getUuid(),
03077:                                    currentResource, CmsRelationFilter.TARGETS);
03078:                        } else {
03079:                            // the resource exists online => mark the resource as deleted
03080:                            // structure record is removed during next publish
03081:                            // if one (or more) siblings are not removed, the ACE can not be removed
03082:                            removeAce = false;
03083:
03084:                            // set resource state to deleted
03085:                            currentResource.setState(CmsResource.STATE_DELETED);
03086:                            m_vfsDriver.writeResourceState(dbc, dbc
03087:                                    .currentProject(), currentResource,
03088:                                    UPDATE_STRUCTURE, false);
03089:
03090:                            // update the project ID
03091:                            m_vfsDriver.writeLastModifiedProjectId(dbc, dbc
03092:                                    .currentProject(), dbc.currentProject()
03093:                                    .getUuid(), currentResource);
03094:                        }
03095:                    }
03096:                }
03097:
03098:                if ((resource.getSiblingCount() <= 1) || allSiblingsRemoved) {
03099:                    if (removeAce) {
03100:                        // remove the access control entries
03101:                        m_userDriver.removeAccessControlEntries(dbc, dbc
03102:                                .currentProject(), resource.getResourceId());
03103:                    }
03104:                }
03105:
03106:                // flush all caches
03107:                OpenCms.getMemoryMonitor().clearAccessControlListCache();
03108:                OpenCms.getMemoryMonitor().flushProperties();
03109:                OpenCms.getMemoryMonitor().flushPropertyLists();
03110:                OpenCms.getMemoryMonitor().flushProjectResources();
03111:
03112:                OpenCms.fireCmsEvent(new CmsEvent(
03113:                        I_CmsEventListener.EVENT_RESOURCE_DELETED, Collections
03114:                                .singletonMap("resources", resources)));
03115:            }
03116:
03117:            /**
03118:             * Deletes an entry in the published resource table.<p>
03119:             * 
03120:             * @param dbc the current database context
03121:             * @param resourceName The name of the resource to be deleted in the static export
03122:             * @param linkType the type of resource deleted (0= non-parameter, 1=parameter)
03123:             * @param linkParameter the parameters of the resource
03124:             * 
03125:             * @throws CmsException if something goes wrong
03126:             */
03127:            public void deleteStaticExportPublishedResource(CmsDbContext dbc,
03128:                    String resourceName, int linkType, String linkParameter)
03129:                    throws CmsException {
03130:
03131:                m_projectDriver.deleteStaticExportPublishedResource(dbc,
03132:                        resourceName, linkType, linkParameter);
03133:            }
03134:
03135:            /**
03136:             * Deletes a user, where all permissions and resources attributes of the user
03137:             * were transfered to a replacement user, if given.<p>
03138:             *
03139:             * Only users, which are in the group "administrators" are granted.<p>
03140:             * 
03141:             * @param dbc the current database context
03142:             * @param project the current project
03143:             * @param username the name of the user to be deleted
03144:             * @param replacementUsername the name of the user to be transfered, can be <code>null</code>
03145:             * 
03146:             * @throws CmsException if operation was not successful
03147:             */
03148:            public void deleteUser(CmsDbContext dbc, CmsProject project,
03149:                    String username, String replacementUsername)
03150:                    throws CmsException {
03151:
03152:                // Test if the users exists
03153:                CmsUser user = readUser(dbc, username);
03154:                CmsUser replacementUser = null;
03155:                if (replacementUsername != null) {
03156:                    replacementUser = readUser(dbc, replacementUsername);
03157:                }
03158:
03159:                CmsProject onlineProject = readProject(dbc,
03160:                        CmsProject.ONLINE_PROJECT_ID);
03161:                boolean withACEs = true;
03162:                if (replacementUser == null) {
03163:                    withACEs = false;
03164:                    replacementUser = readUser(dbc, OpenCms.getDefaultUsers()
03165:                            .getUserDeletedResource());
03166:                }
03167:
03168:                boolean isVfsManager = m_securityManager.hasRole(dbc,
03169:                        replacementUser, CmsRole.VFS_MANAGER);
03170:
03171:                for (int i = 0; i < 2; i++) {
03172:                    boolean readRoles = false; // iterate groups and roles
03173:                    Iterator itGroups = getGroupsOfUser(dbc, username, "",
03174:                            true, readRoles, true,
03175:                            dbc.getRequestContext().getRemoteAddress())
03176:                            .iterator();
03177:                    while (itGroups.hasNext()) {
03178:                        CmsGroup group = (CmsGroup) itGroups.next();
03179:                        if (!isVfsManager) {
03180:                            // add replacement user to user groups
03181:                            if (!userInGroup(dbc, replacementUser.getName(),
03182:                                    group.getName(), false)) {
03183:                                addUserToGroup(dbc, replacementUser.getName(),
03184:                                        group.getName(), false);
03185:                            }
03186:                        }
03187:                        // remove user from groups
03188:                        if (userInGroup(dbc, username, group.getName(),
03189:                                readRoles)) {
03190:                            removeUserFromGroup(dbc, username, group.getName(),
03191:                                    readRoles);
03192:                        }
03193:                    }
03194:                    readRoles = !readRoles;
03195:                }
03196:                // remove all locks set for the deleted user
03197:                m_lockManager.removeLocks(user.getId());
03198:                // offline
03199:                transferPrincipalResources(dbc, project, user.getId(),
03200:                        replacementUser.getId(), withACEs);
03201:                // online
03202:                transferPrincipalResources(dbc, onlineProject, user.getId(),
03203:                        replacementUser.getId(), withACEs);
03204:                m_userDriver.removeAccessControlEntriesForPrincipal(dbc,
03205:                        project, onlineProject, user.getId());
03206:                m_historyDriver.writePrincipal(dbc, user);
03207:                m_userDriver.deleteUser(dbc, username);
03208:                // delete user from cache
03209:                OpenCms.getMemoryMonitor().clearUserCache(user);
03210:            }
03211:
03212:            /**
03213:             * Destroys this driver manager and releases all allocated resources.<p>
03214:             */
03215:            public void destroy() {
03216:
03217:                try {
03218:                    if (m_projectDriver != null) {
03219:                        try {
03220:                            m_projectDriver.destroy();
03221:                        } catch (Throwable t) {
03222:                            LOG.error(Messages.get().getBundle().key(
03223:                                    Messages.ERR_CLOSE_PROJECT_DRIVER_0), t);
03224:                        }
03225:                        m_projectDriver = null;
03226:                    }
03227:                    if (m_userDriver != null) {
03228:                        try {
03229:                            m_userDriver.destroy();
03230:                        } catch (Throwable t) {
03231:                            LOG.error(Messages.get().getBundle().key(
03232:                                    Messages.ERR_CLOSE_USER_DRIVER_0), t);
03233:                        }
03234:                        m_userDriver = null;
03235:                    }
03236:                    if (m_vfsDriver != null) {
03237:                        try {
03238:                            m_vfsDriver.destroy();
03239:                        } catch (Throwable t) {
03240:                            LOG.error(Messages.get().getBundle().key(
03241:                                    Messages.ERR_CLOSE_VFS_DRIVER_0), t);
03242:                        }
03243:                        m_vfsDriver = null;
03244:                    }
03245:                    if (m_historyDriver != null) {
03246:                        try {
03247:                            m_historyDriver.destroy();
03248:                        } catch (Throwable t) {
03249:                            LOG.error(Messages.get().getBundle().key(
03250:                                    Messages.ERR_CLOSE_HISTORY_DRIVER_0), t);
03251:                        }
03252:                        m_historyDriver = null;
03253:                    }
03254:
03255:                    if (m_connectionPools != null) {
03256:                        for (int i = 0; i < m_connectionPools.size(); i++) {
03257:                            PoolingDriver driver = (PoolingDriver) m_connectionPools
03258:                                    .get(i);
03259:                            String[] pools = driver.getPoolNames();
03260:                            for (int j = 0; j < pools.length; j++) {
03261:                                try {
03262:                                    driver.closePool(pools[j]);
03263:                                    if (CmsLog.INIT.isDebugEnabled()) {
03264:                                        CmsLog.INIT
03265:                                                .debug(Messages
03266:                                                        .get()
03267:                                                        .getBundle()
03268:                                                        .key(
03269:                                                                Messages.INIT_CLOSE_CONN_POOL_1,
03270:                                                                pools[j]));
03271:                                    }
03272:                                } catch (Throwable t) {
03273:                                    LOG
03274:                                            .error(
03275:                                                    Messages
03276:                                                            .get()
03277:                                                            .getBundle()
03278:                                                            .key(
03279:                                                                    Messages.LOG_CLOSE_CONN_POOL_ERROR_1,
03280:                                                                    pools[j]),
03281:                                                    t);
03282:                                }
03283:                            }
03284:                        }
03285:                        m_connectionPools = null;
03286:                    }
03287:
03288:                    OpenCms.getMemoryMonitor().clearCache();
03289:
03290:                    m_lockManager = null;
03291:                    m_htmlLinkValidator = null;
03292:                } catch (Throwable t) {
03293:                    // ignore
03294:                }
03295:                if (CmsLog.INIT.isInfoEnabled()) {
03296:                    CmsLog.INIT.info(Messages.get().getBundle().key(
03297:                            Messages.INIT_DRIVER_MANAGER_DESTROY_1,
03298:                            getClass().getName()));
03299:                }
03300:            }
03301:
03302:            /**
03303:             * Tests if a resource with the given resourceId does already exist in the Database.<p>
03304:             * 
03305:             * @param dbc the current database context
03306:             * @param resourceId the resource id to test for
03307:             * @return true if a resource with the given id was found, false otherweise
03308:             * @throws CmsException if something goes wrong
03309:             */
03310:            public boolean existsResourceId(CmsDbContext dbc, CmsUUID resourceId)
03311:                    throws CmsException {
03312:
03313:                return m_vfsDriver.validateResourceIdExists(dbc, dbc
03314:                        .currentProject().getUuid(), resourceId);
03315:            }
03316:
03317:            /**
03318:             * Fills the given publish list with the the VFS resources that actually get published.<p>
03319:             * 
03320:             * Please refer to the source code of this method for the rules on how to decide whether a
03321:             * new/changed/deleted <code>{@link CmsResource}</code> object can be published or not.<p>
03322:             * 
03323:             * @param dbc the current database context
03324:             * @param publishList must be initialized with basic publish information (Project or direct publish operation),
03325:             *                    the given publish list will be filled with all new/changed/deleted files from the current 
03326:             *                    (offline) project that will be actually published 
03327:             * 
03328:             * @throws CmsException if something goes wrong
03329:             * 
03330:             * @see org.opencms.db.CmsPublishList
03331:             */
03332:            public void fillPublishList(CmsDbContext dbc,
03333:                    CmsPublishList publishList) throws CmsException {
03334:
03335:                if (!publishList.isDirectPublish()) {
03336:                    // when publishing a project
03337:                    // all modified resources with the last change done in the current project are candidates if unlocked
03338:                    List folderList = m_vfsDriver.readResourceTree(dbc, dbc
03339:                            .currentProject().getUuid(),
03340:                            CmsDriverManager.READ_IGNORE_PARENT,
03341:                            CmsDriverManager.READ_IGNORE_TYPE,
03342:                            CmsResource.STATE_UNCHANGED,
03343:                            CmsDriverManager.READ_IGNORE_TIME,
03344:                            CmsDriverManager.READ_IGNORE_TIME,
03345:                            CmsDriverManager.READ_IGNORE_TIME,
03346:                            CmsDriverManager.READ_IGNORE_TIME,
03347:                            CmsDriverManager.READ_IGNORE_TIME,
03348:                            CmsDriverManager.READ_IGNORE_TIME,
03349:                            CmsDriverManager.READMODE_INCLUDE_TREE
03350:                                    | CmsDriverManager.READMODE_INCLUDE_PROJECT
03351:                                    | CmsDriverManager.READMODE_EXCLUDE_STATE
03352:                                    | CmsDriverManager.READMODE_ONLY_FOLDERS);
03353:
03354:                    publishList.addAll(filterResources(dbc, null, folderList),
03355:                            true);
03356:
03357:                    List fileList = m_vfsDriver.readResourceTree(dbc, dbc
03358:                            .currentProject().getUuid(),
03359:                            CmsDriverManager.READ_IGNORE_PARENT,
03360:                            CmsDriverManager.READ_IGNORE_TYPE,
03361:                            CmsResource.STATE_UNCHANGED,
03362:                            CmsDriverManager.READ_IGNORE_TIME,
03363:                            CmsDriverManager.READ_IGNORE_TIME,
03364:                            CmsDriverManager.READ_IGNORE_TIME,
03365:                            CmsDriverManager.READ_IGNORE_TIME,
03366:                            CmsDriverManager.READ_IGNORE_TIME,
03367:                            CmsDriverManager.READ_IGNORE_TIME,
03368:                            CmsDriverManager.READMODE_INCLUDE_TREE
03369:                                    | CmsDriverManager.READMODE_INCLUDE_PROJECT
03370:                                    | CmsDriverManager.READMODE_EXCLUDE_STATE
03371:                                    | CmsDriverManager.READMODE_ONLY_FILES);
03372:
03373:                    publishList.addAll(filterResources(dbc, publishList,
03374:                            fileList), true);
03375:                } else {
03376:                    // this is a direct publish
03377:                    Iterator it = publishList.getDirectPublishResources()
03378:                            .iterator();
03379:                    while (it.hasNext()) {
03380:                        // iterate all resources in the direct publish list
03381:                        CmsResource directPublishResource = (CmsResource) it
03382:                                .next();
03383:                        if (directPublishResource.isFolder()) {
03384:                            // when publishing a folder directly, 
03385:                            // the folder and all modified resources within the tree below this folder 
03386:                            // and with the last change done in the current project are candidates if lockable
03387:                            CmsLock lock = getLock(dbc, directPublishResource);
03388:                            if (!directPublishResource.getState().isUnchanged()
03389:                                    && lock.isLockableBy(dbc.currentUser())) {
03390:
03391:                                try {
03392:                                    m_securityManager
03393:                                            .checkPermissions(
03394:                                                    dbc,
03395:                                                    directPublishResource,
03396:                                                    CmsPermissionSet.ACCESS_DIRECT_PUBLISH,
03397:                                                    false,
03398:                                                    CmsResourceFilter.ALL);
03399:                                    publishList
03400:                                            .add(directPublishResource, true);
03401:                                } catch (CmsException e) {
03402:                                    // skip if not enough permissions
03403:                                }
03404:                            }
03405:
03406:                            if (publishList.isPublishSubResources()) {
03407:                                // add all sub resources of the folder
03408:                                List folderList = m_vfsDriver
03409:                                        .readResourceTree(
03410:                                                dbc,
03411:                                                dbc.currentProject().getUuid(),
03412:                                                directPublishResource
03413:                                                        .getRootPath(),
03414:                                                CmsDriverManager.READ_IGNORE_TYPE,
03415:                                                CmsResource.STATE_UNCHANGED,
03416:                                                CmsDriverManager.READ_IGNORE_TIME,
03417:                                                CmsDriverManager.READ_IGNORE_TIME,
03418:                                                CmsDriverManager.READ_IGNORE_TIME,
03419:                                                CmsDriverManager.READ_IGNORE_TIME,
03420:                                                CmsDriverManager.READ_IGNORE_TIME,
03421:                                                CmsDriverManager.READ_IGNORE_TIME,
03422:                                                CmsDriverManager.READMODE_INCLUDE_TREE
03423:                                                        | CmsDriverManager.READMODE_INCLUDE_PROJECT
03424:                                                        | CmsDriverManager.READMODE_EXCLUDE_STATE
03425:                                                        | CmsDriverManager.READMODE_ONLY_FOLDERS);
03426:
03427:                                publishList.addAll(filterResources(dbc,
03428:                                        publishList, folderList), true);
03429:
03430:                                List fileList = m_vfsDriver
03431:                                        .readResourceTree(
03432:                                                dbc,
03433:                                                dbc.currentProject().getUuid(),
03434:                                                directPublishResource
03435:                                                        .getRootPath(),
03436:                                                CmsDriverManager.READ_IGNORE_TYPE,
03437:                                                CmsResource.STATE_UNCHANGED,
03438:                                                CmsDriverManager.READ_IGNORE_TIME,
03439:                                                CmsDriverManager.READ_IGNORE_TIME,
03440:                                                CmsDriverManager.READ_IGNORE_TIME,
03441:                                                CmsDriverManager.READ_IGNORE_TIME,
03442:                                                CmsDriverManager.READ_IGNORE_TIME,
03443:                                                CmsDriverManager.READ_IGNORE_TIME,
03444:                                                CmsDriverManager.READMODE_INCLUDE_TREE
03445:                                                        | CmsDriverManager.READMODE_INCLUDE_PROJECT
03446:                                                        | CmsDriverManager.READMODE_EXCLUDE_STATE
03447:                                                        | CmsDriverManager.READMODE_ONLY_FILES);
03448:
03449:                                publishList.addAll(filterResources(dbc,
03450:                                        publishList, fileList), true);
03451:                            }
03452:                        } else if (directPublishResource.isFile()
03453:                                && !directPublishResource.getState()
03454:                                        .isUnchanged()) {
03455:
03456:                            // when publishing a file directly this file is the only candidate
03457:                            // if it is modified and lockable
03458:                            CmsLock lock = getLock(dbc, directPublishResource);
03459:                            if (lock.isLockableBy(dbc.currentUser())) {
03460:                                // check permissions
03461:                                try {
03462:                                    m_securityManager
03463:                                            .checkPermissions(
03464:                                                    dbc,
03465:                                                    directPublishResource,
03466:                                                    CmsPermissionSet.ACCESS_DIRECT_PUBLISH,
03467:                                                    false,
03468:                                                    CmsResourceFilter.ALL);
03469:                                    publishList
03470:                                            .add(directPublishResource, true);
03471:                                } catch (CmsException e) {
03472:                                    // skip if not enough permissions
03473:                                }
03474:                            }
03475:                        }
03476:                    }
03477:                }
03478:
03479:                // Step 2: if desired, extend the list of files to publish with related siblings
03480:                if (publishList.isPublishSiblings()) {
03481:                    List publishFiles = publishList.getFileList();
03482:                    int size = publishFiles.size();
03483:
03484:                    // Improved: first calculate closure of all siblings, then filter and add them
03485:                    Set siblingsClosure = new HashSet(publishFiles);
03486:                    for (int i = 0; i < size; i++) {
03487:                        CmsResource currentFile = (CmsResource) publishFiles
03488:                                .get(i);
03489:                        if (currentFile.getSiblingCount() > 1) {
03490:                            siblingsClosure
03491:                                    .addAll(readSiblings(dbc, currentFile,
03492:                                            CmsResourceFilter.ALL_MODIFIED));
03493:                        }
03494:                    }
03495:                    publishList.addAll(filterSiblings(dbc, publishList,
03496:                            siblingsClosure), true);
03497:                }
03498:                publishList.initialize();
03499:            }
03500:
03501:            /**
03502:             * Returns the list of access control entries of a resource given its name.<p>
03503:             * 
03504:             * @param dbc the current database context
03505:             * @param resource the resource to read the access control entries for
03506:             * @param getInherited true if the result should include all access control entries inherited by parent folders
03507:             * 
03508:             * @return a list of <code>{@link CmsAccessControlEntry}</code> objects defining all permissions for the given resource
03509:             * 
03510:             * @throws CmsException if something goes wrong
03511:             */
03512:            public List getAccessControlEntries(CmsDbContext dbc,
03513:                    CmsResource resource, boolean getInherited)
03514:                    throws CmsException {
03515:
03516:                // get the ACE of the resource itself
03517:                List ace = m_userDriver.readAccessControlEntries(dbc, dbc
03518:                        .currentProject(), resource.getResourceId(), false);
03519:
03520:                // sort and check if we got the 'overwrite all' ace to stop looking up
03521:                boolean overwriteAll = sortAceList(ace);
03522:
03523:                // get the ACE of each parent folder
03524:                // Note: for the immediate parent, get non-inherited access control entries too,
03525:                // if the resource is not a folder
03526:                String parentPath = CmsResource.getParentFolder(resource
03527:                        .getRootPath());
03528:                int d = (resource.isFolder()) ? 1 : 0;
03529:
03530:                while (!overwriteAll && getInherited && (parentPath != null)) {
03531:                    resource = m_vfsDriver.readFolder(dbc, dbc.currentProject()
03532:                            .getUuid(), parentPath);
03533:                    List entries = m_userDriver.readAccessControlEntries(dbc,
03534:                            dbc.currentProject(), resource.getResourceId(),
03535:                            d > 0);
03536:
03537:                    // sort and check if we got the 'overwrite all' ace to stop looking up
03538:                    overwriteAll = sortAceList(entries);
03539:
03540:                    for (Iterator i = entries.iterator(); i.hasNext();) {
03541:                        CmsAccessControlEntry e = (CmsAccessControlEntry) i
03542:                                .next();
03543:                        e
03544:                                .setFlags(CmsAccessControlEntry.ACCESS_FLAGS_INHERITED);
03545:                    }
03546:
03547:                    ace.addAll(entries);
03548:                    parentPath = CmsResource.getParentFolder(resource
03549:                            .getRootPath());
03550:                    d++;
03551:                }
03552:
03553:                return ace;
03554:            }
03555:
03556:            /**
03557:             * Returns the full access control list of a given resource.<p>
03558:             * 
03559:             * @param dbc the current database context
03560:             * @param resource the resource
03561:             * 
03562:             * @return the access control list of the resource
03563:             * 
03564:             * @throws CmsException if something goes wrong
03565:             */
03566:            public CmsAccessControlList getAccessControlList(CmsDbContext dbc,
03567:                    CmsResource resource) throws CmsException {
03568:
03569:                return getAccessControlList(dbc, resource, false);
03570:            }
03571:
03572:            /**
03573:             * Returns the access control list of a given resource.<p>
03574:             *
03575:             * If <code>inheritedOnly</code> is set, only inherited access control entries 
03576:             * are returned.<p>
03577:             * 
03578:             * Note: For file resources, *all* permissions set at the immediate parent folder are inherited,
03579:             * not only these marked to inherit. 
03580:             * 
03581:             * @param dbc the current database context
03582:             * @param resource the resource
03583:             * @param inheritedOnly skip non-inherited entries if set
03584:             * 
03585:             * @return the access control list of the resource
03586:             * 
03587:             * @throws CmsException if something goes wrong
03588:             */
03589:            public CmsAccessControlList getAccessControlList(CmsDbContext dbc,
03590:                    CmsResource resource, boolean inheritedOnly)
03591:                    throws CmsException {
03592:
03593:                return getAccessControlList(dbc, resource, inheritedOnly,
03594:                        resource.isFolder(), 0);
03595:            }
03596:
03597:            /** 
03598:             * Returns the number of active connections managed by a pool.<p> 
03599:             * 
03600:             * @param dbPoolUrl the url of a pool 
03601:             * @return the number of active connections 
03602:             * @throws CmsDbException if something goes wrong 
03603:             */
03604:            public int getActiveConnections(String dbPoolUrl)
03605:                    throws CmsDbException {
03606:
03607:                try {
03608:                    for (Iterator i = m_connectionPools.iterator(); i.hasNext();) {
03609:                        PoolingDriver d = (PoolingDriver) i.next();
03610:                        ObjectPool p = d.getConnectionPool(dbPoolUrl);
03611:                        return p.getNumActive();
03612:                    }
03613:                } catch (Exception exc) {
03614:                    CmsMessageContainer message = Messages.get().container(
03615:                            Messages.ERR_ACCESSING_POOL_1, dbPoolUrl);
03616:                    throw new CmsDbException(message, exc);
03617:                }
03618:
03619:                CmsMessageContainer message = Messages.get().container(
03620:                        Messages.ERR_UNKNOWN_POOL_URL_1, dbPoolUrl);
03621:                throw new CmsDbException(message);
03622:            }
03623:
03624:            /**
03625:             * Returns all projects which are owned by the current user or which are 
03626:             * accessible by the current user.<p>
03627:             *
03628:             * @param dbc the current database context
03629:             * 
03630:             * @return a list of objects of type <code>{@link CmsProject}</code>
03631:             * 
03632:             * @throws CmsException if something goes wrong
03633:             */
03634:            public List getAllAccessibleProjects(CmsDbContext dbc)
03635:                    throws CmsException {
03636:
03637:                Set projects = new HashSet();
03638:
03639:                // get the ous where the user has the project manager role
03640:                List ous = getOrgUnitsForRole(dbc, CmsRole.PROJECT_MANAGER
03641:                        .forOrgUnit(""), true);
03642:
03643:                // get the groups of the user if needed
03644:                Set userGroupIds = new HashSet();
03645:                Iterator itGroups = getGroupsOfUser(dbc,
03646:                        dbc.currentUser().getName(), false).iterator();
03647:                while (itGroups.hasNext()) {
03648:                    CmsGroup group = (CmsGroup) itGroups.next();
03649:                    userGroupIds.add(group.getId());
03650:                }
03651:
03652:                // get all projects
03653:                projects.addAll(m_projectDriver.readProjects(dbc, ""));
03654:
03655:                // filter hidden and not accessible projects
03656:                Iterator itProjects = projects.iterator();
03657:                while (itProjects.hasNext()) {
03658:                    CmsProject project = (CmsProject) itProjects.next();
03659:                    // if hidden
03660:                    if (project.isHidden()) {
03661:                        itProjects.remove();
03662:                        continue;
03663:                    }
03664:
03665:                    boolean accessible = false;
03666:                    // online project
03667:                    accessible = accessible || project.isOnlineProject();
03668:                    // if owner
03669:                    accessible = accessible
03670:                            || project.getOwnerId().equals(
03671:                                    dbc.currentUser().getId());
03672:
03673:                    // project managers
03674:                    Iterator itOus = ous.iterator();
03675:                    while (!accessible && itOus.hasNext()) {
03676:                        CmsOrganizationalUnit ou = (CmsOrganizationalUnit) itOus
03677:                                .next();
03678:                        // for project managers check visibility
03679:                        accessible = accessible
03680:                                || project.getOuFqn().startsWith(ou.getName());
03681:                    }
03682:
03683:                    if (!accessible) {
03684:                        // if direct user or manager of project 
03685:                        CmsUUID groupId = null;
03686:                        if (userGroupIds.contains(project.getGroupId())) {
03687:                            groupId = project.getGroupId();
03688:                        } else if (userGroupIds.contains(project
03689:                                .getManagerGroupId())) {
03690:                            groupId = project.getManagerGroupId();
03691:                        }
03692:                        if (groupId != null) {
03693:                            String oufqn = readGroup(dbc, groupId).getOuFqn();
03694:                            accessible = accessible
03695:                                    || (oufqn.startsWith(dbc
03696:                                            .getRequestContext().getOuFqn()));
03697:                        }
03698:                    }
03699:                    if (!accessible) {
03700:                        // remove not accessible project
03701:                        itProjects.remove();
03702:                    }
03703:                }
03704:
03705:                ArrayList accessibleProjects = new ArrayList(projects);
03706:                // sort the list of projects based on the project name
03707:                Collections.sort(accessibleProjects);
03708:                // ensure the online project is in first place
03709:                CmsProject onlineProject = readProject(dbc,
03710:                        CmsProject.ONLINE_PROJECT_ID);
03711:                if (accessibleProjects.contains(onlineProject)) {
03712:                    accessibleProjects.remove(onlineProject);
03713:                    accessibleProjects.add(0, onlineProject);
03714:                }
03715:
03716:                return accessibleProjects;
03717:            }
03718:
03719:            /**
03720:             * Returns a list with all projects from history.<p>
03721:             *
03722:             * @param dbc the current database context
03723:             * 
03724:             * @return list of <code>{@link CmsHistoryProject}</code> objects 
03725:             *           with all projects from history.
03726:             * 
03727:             * @throws CmsException if operation was not successful
03728:             */
03729:            public List getAllHistoricalProjects(CmsDbContext dbc)
03730:                    throws CmsException {
03731:
03732:                return m_historyDriver.readProjects(dbc);
03733:            }
03734:
03735:            /**
03736:             * Returns all projects which are owned by the current user or which are manageable
03737:             * for the group of the user.<p>
03738:             *
03739:             * @param dbc the current database context
03740:             * 
03741:             * @return a list of objects of type <code>{@link CmsProject}</code>
03742:             * 
03743:             * @throws CmsException if operation was not successful
03744:             */
03745:            public List getAllManageableProjects(CmsDbContext dbc)
03746:                    throws CmsException {
03747:
03748:                // the result set
03749:                Set projects = new HashSet();
03750:
03751:                if (m_securityManager.hasRole(dbc, dbc.currentUser(),
03752:                        CmsRole.PROJECT_MANAGER)) {
03753:                    // user is allowed to access all existing projects for the ous he has the project_manager role
03754:                    Iterator itOus = getOrgUnitsForRole(dbc,
03755:                            CmsRole.PROJECT_MANAGER, true).iterator();
03756:                    while (itOus.hasNext()) {
03757:                        CmsOrganizationalUnit ou = (CmsOrganizationalUnit) itOus
03758:                                .next();
03759:                        projects.addAll(m_projectDriver.readProjects(dbc, ou
03760:                                .getName()));
03761:                    }
03762:                }
03763:                // add all projects which are owned by the user
03764:                projects.addAll(m_projectDriver.readProjectsForUser(dbc, dbc
03765:                        .currentUser()));
03766:
03767:                // get all groups of the user
03768:                List groups = getGroupsOfUser(dbc, dbc.currentUser().getName(),
03769:                        false);
03770:
03771:                // add all projects, that the user can access with his groups
03772:                for (int i = 0, n = groups.size(); i < n; i++) {
03773:                    projects.addAll(m_projectDriver
03774:                            .readProjectsForManagerGroup(dbc, (CmsGroup) groups
03775:                                    .get(i)));
03776:                }
03777:
03778:                // remove the online-project, it is not manageable!
03779:                projects.remove(readProject(dbc, CmsProject.ONLINE_PROJECT_ID));
03780:
03781:                // filter hidden projects
03782:                Iterator itProjects = projects.iterator();
03783:                while (itProjects.hasNext()) {
03784:                    CmsProject project = (CmsProject) itProjects.next();
03785:                    if (project.isHidden()
03786:                            || !project.getOuFqn().startsWith(
03787:                                    dbc.currentUser().getOuFqn())) {
03788:                        // remove hidden projects
03789:                        itProjects.remove();
03790:                        continue;
03791:                    }
03792:                }
03793:
03794:                // return the list of projects
03795:                ArrayList manageableProjects = new ArrayList(projects);
03796:                Collections.sort(manageableProjects);
03797:                return manageableProjects;
03798:            }
03799:
03800:            /**
03801:             * Returns all child groups of a group.<p>
03802:             *
03803:             * @param dbc the current database context
03804:             * @param group the group to get the child for
03805:             * @param includeSubChildren if set also returns all sub-child groups of the given group
03806:             * 
03807:             * @return a list of all child <code>{@link CmsGroup}</code> objects
03808:             * 
03809:             * @throws CmsException if operation was not successful
03810:             */
03811:            public List getChildren(CmsDbContext dbc, CmsGroup group,
03812:                    boolean includeSubChildren) throws CmsException {
03813:
03814:                if (!includeSubChildren) {
03815:                    return m_userDriver.readChildGroups(dbc, group.getName());
03816:                }
03817:                Set allChildren = new TreeSet();
03818:                // iterate all child groups
03819:                Iterator it = m_userDriver
03820:                        .readChildGroups(dbc, group.getName()).iterator();
03821:                while (it.hasNext()) {
03822:                    CmsGroup child = (CmsGroup) it.next();
03823:                    // add the group itself
03824:                    allChildren.add(child);
03825:                    // now get all sub-children for each group
03826:                    allChildren.addAll(getChildren(dbc, child, true));
03827:                }
03828:                return new ArrayList(allChildren);
03829:            }
03830:
03831:            /**
03832:             * Returns all groups of the given organizational unit.<p>
03833:             *
03834:             * @param dbc the current db context
03835:             * @param orgUnit the organizational unit to get the groups for
03836:             * @param includeSubOus if all groups of sub-organizational units should be retrieved too
03837:             * @param readRoles if to read roles or groups
03838:             * 
03839:             * @return all <code>{@link CmsGroup}</code> objects in the organizational unit
03840:             *
03841:             * @throws CmsException if operation was not successful
03842:             * 
03843:             * @see org.opencms.security.CmsOrgUnitManager#getResourcesForOrganizationalUnit(CmsObject, String)
03844:             * @see org.opencms.security.CmsOrgUnitManager#getGroups(CmsObject, String, boolean)
03845:             */
03846:            public List getGroups(CmsDbContext dbc,
03847:                    CmsOrganizationalUnit orgUnit, boolean includeSubOus,
03848:                    boolean readRoles) throws CmsException {
03849:
03850:                return m_userDriver.getGroups(dbc, orgUnit, includeSubOus,
03851:                        readRoles);
03852:            }
03853:
03854:            /**
03855:             * Returns the groups of an user filtered by the specified IP address.<p>
03856:             * 
03857:             * @param dbc the current database context
03858:             * @param username the name of the user
03859:             * @param readRoles if to read roles or groups
03860:             * 
03861:             * @return the groups of the given user, as a list of {@link CmsGroup} objects
03862:             * 
03863:             * @throws CmsException if something goes wrong
03864:             */
03865:            public List getGroupsOfUser(CmsDbContext dbc, String username,
03866:                    boolean readRoles) throws CmsException {
03867:
03868:                return getGroupsOfUser(dbc, username, "", true, readRoles,
03869:                        false, dbc.getRequestContext().getRemoteAddress());
03870:            }
03871:
03872:            /**
03873:             * Returns the groups of an user filtered by the specified IP address.<p>
03874:             * 
03875:             * @param dbc the current database context
03876:             * @param username the name of the user
03877:             * @param ouFqn the fully qualified name of the organizational unit to restrict the result set for
03878:             * @param includeChildOus include groups of child organizational units
03879:             * @param readRoles if to read roles or groups
03880:             * @param directGroupsOnly if set only the direct assigned groups will be returned, if not also indirect groups
03881:             * @param remoteAddress the IP address to filter the groups in the result list 
03882:             *
03883:             * @return a list of <code>{@link CmsGroup}</code> objects
03884:             * 
03885:             * @throws CmsException if operation was not successful
03886:             */
03887:            public List getGroupsOfUser(CmsDbContext dbc, String username,
03888:                    String ouFqn, boolean includeChildOus, boolean readRoles,
03889:                    boolean directGroupsOnly, String remoteAddress)
03890:                    throws CmsException {
03891:
03892:                CmsUser user = readUser(dbc, username);
03893:                String prefix = ouFqn + "_" + includeChildOus + "_"
03894:                        + directGroupsOnly + "_" + readRoles + "_"
03895:                        + remoteAddress;
03896:                String cacheKey = m_keyGenerator.getCacheKeyForUserGroups(
03897:                        prefix, dbc, user);
03898:                List groups = OpenCms.getMemoryMonitor().getCachedUserGroups(
03899:                        cacheKey);
03900:                if (groups == null) {
03901:                    // get all groups of the user
03902:                    List directGroups = m_userDriver.readGroupsOfUser(dbc, user
03903:                            .getId(), readRoles ? "" : ouFqn, readRoles ? true
03904:                            : includeChildOus, remoteAddress, readRoles);
03905:                    Set allGroups = new HashSet();
03906:                    if (!readRoles) {
03907:                        allGroups.addAll(directGroups);
03908:                    }
03909:                    if (!directGroupsOnly) {
03910:                        if (!readRoles) {
03911:                            // now get all parents of the groups
03912:                            for (int i = 0; i < directGroups.size(); i++) {
03913:                                CmsGroup parent = getParent(dbc,
03914:                                        ((CmsGroup) directGroups.get(i))
03915:                                                .getName());
03916:                                while ((parent != null)
03917:                                        && (!allGroups.contains(parent))) {
03918:                                    if (parent.getOuFqn().startsWith(ouFqn)) {
03919:                                        allGroups.add(parent);
03920:                                    }
03921:                                    // read next parent group
03922:                                    parent = getParent(dbc, parent.getName());
03923:                                }
03924:                            }
03925:                        }
03926:                    }
03927:                    if (readRoles) {
03928:                        // for each for role 
03929:                        for (int i = 0; i < directGroups.size(); i++) {
03930:                            CmsGroup group = (CmsGroup) directGroups.get(i);
03931:                            CmsRole role = CmsRole.valueOf(group);
03932:                            if (!includeChildOus
03933:                                    && role.getOuFqn().equals(ouFqn)) {
03934:                                allGroups.add(group);
03935:                            }
03936:                            if (includeChildOus
03937:                                    && role.getOuFqn().startsWith(ouFqn)) {
03938:                                allGroups.add(group);
03939:                            }
03940:                            if (directGroupsOnly) {
03941:                                continue;
03942:                            }
03943:                            // get the child roles
03944:                            Iterator itChildRoles = role.getChildren(true)
03945:                                    .iterator();
03946:                            while (itChildRoles.hasNext()) {
03947:                                CmsRole childRole = (CmsRole) itChildRoles
03948:                                        .next();
03949:                                if (childRole.isSystemRole()) {
03950:                                    // include system roles only
03951:                                    allGroups.add(readGroup(dbc, childRole
03952:                                            .getGroupName()));
03953:                                }
03954:                            }
03955:                            if (includeChildOus) {
03956:                                // if needed include the roles of child ous 
03957:                                Iterator itSubOus = getOrganizationalUnits(
03958:                                        dbc,
03959:                                        readOrganizationalUnit(dbc, group
03960:                                                .getOuFqn()), true).iterator();
03961:                                while (itSubOus.hasNext()) {
03962:                                    CmsOrganizationalUnit subOu = (CmsOrganizationalUnit) itSubOus
03963:                                            .next();
03964:                                    // add role in child ou
03965:                                    try {
03966:                                        allGroups.add(readGroup(dbc, role
03967:                                                .forOrgUnit(subOu.getName())
03968:                                                .getGroupName()));
03969:                                    } catch (CmsDbEntryNotFoundException e) {
03970:                                        // ignore, this may happen while deleting an orgunit
03971:                                        if (LOG.isDebugEnabled()) {
03972:                                            LOG.debug(e.getLocalizedMessage(),
03973:                                                    e);
03974:                                        }
03975:                                    }
03976:                                    // add child roles in child ous
03977:                                    itChildRoles = role.getChildren(true)
03978:                                            .iterator();
03979:                                    while (itChildRoles.hasNext()) {
03980:                                        CmsRole childRole = (CmsRole) itChildRoles
03981:                                                .next();
03982:                                        try {
03983:                                            allGroups.add(readGroup(dbc,
03984:                                                    childRole.forOrgUnit(
03985:                                                            subOu.getName())
03986:                                                            .getGroupName()));
03987:                                        } catch (CmsDbEntryNotFoundException e) {
03988:                                            // ignore, this may happen while deleting an orgunit
03989:                                            if (LOG.isDebugEnabled()) {
03990:                                                LOG.debug(e
03991:                                                        .getLocalizedMessage(),
03992:                                                        e);
03993:                                            }
03994:                                        }
03995:                                    }
03996:                                }
03997:                            }
03998:                        }
03999:                    }
04000:                    // make group list unmodifiable for caching
04001:                    groups = Collections.unmodifiableList(new ArrayList(
04002:                            allGroups));
04003:                    OpenCms.getMemoryMonitor()
04004:                            .cacheUserGroups(cacheKey, groups);
04005:                }
04006:
04007:                return groups;
04008:            }
04009:
04010:            /**
04011:             * Returns the history driver.<p>
04012:             * 
04013:             * @return the history driver
04014:             */
04015:            public I_CmsHistoryDriver getHistoryDriver() {
04016:
04017:                return m_historyDriver;
04018:            }
04019:
04020:            /** 
04021:             * Returns the number of idle connections managed by a pool.<p> 
04022:             * 
04023:             * @param dbPoolUrl the url of a pool 
04024:             * @return the number of idle connections 
04025:             * @throws CmsDbException if something goes wrong 
04026:             */
04027:            public int getIdleConnections(String dbPoolUrl)
04028:                    throws CmsDbException {
04029:
04030:                try {
04031:                    for (Iterator i = m_connectionPools.iterator(); i.hasNext();) {
04032:                        PoolingDriver d = (PoolingDriver) i.next();
04033:                        ObjectPool p = d.getConnectionPool(dbPoolUrl);
04034:                        return p.getNumIdle();
04035:                    }
04036:                } catch (Exception exc) {
04037:                    CmsMessageContainer message = Messages.get().container(
04038:                            Messages.ERR_ACCESSING_POOL_1, dbPoolUrl);
04039:                    throw new CmsDbException(message, exc);
04040:                }
04041:
04042:                CmsMessageContainer message = Messages.get().container(
04043:                        Messages.ERR_UNKNOWN_POOL_URL_1, dbPoolUrl);
04044:                throw new CmsDbException(message);
04045:            }
04046:
04047:            /**
04048:             * Returns the lock state of a resource.<p>
04049:             * 
04050:             * @param dbc the current database context
04051:             * @param resource the resource to return the lock state for
04052:             * 
04053:             * @return the lock state of the resource
04054:             * 
04055:             * @throws CmsException if something goes wrong
04056:             */
04057:            public CmsLock getLock(CmsDbContext dbc, CmsResource resource)
04058:                    throws CmsException {
04059:
04060:                return m_lockManager.getLock(dbc, resource);
04061:            }
04062:
04063:            /**
04064:             * Returns all locked resources in a given folder.<p>
04065:             *
04066:             * @param dbc the current database context
04067:             * @param resource the folder to search in
04068:             * @param filter the lock filter
04069:             * 
04070:             * @return a list of locked resource paths (relative to current site)
04071:             * 
04072:             * @throws CmsException if the current project is locked
04073:             */
04074:            public List getLockedResources(CmsDbContext dbc,
04075:                    CmsResource resource, CmsLockFilter filter)
04076:                    throws CmsException {
04077:
04078:                List lockedResources = new ArrayList();
04079:                // get locked resources
04080:                Iterator it = m_lockManager.getLocks(dbc,
04081:                        resource.getRootPath(), filter).iterator();
04082:                while (it.hasNext()) {
04083:                    CmsLock lock = (CmsLock) it.next();
04084:                    lockedResources.add(dbc.removeSiteRoot(lock
04085:                            .getResourceName()));
04086:                }
04087:                Collections.sort(lockedResources);
04088:                return lockedResources;
04089:            }
04090:
04091:            /**
04092:             * Returns the next publish tag for the published historical resources.<p>
04093:             *
04094:             * @param dbc the current database context
04095:             * 
04096:             * @return the next available publish tag
04097:             */
04098:            public int getNextPublishTag(CmsDbContext dbc) {
04099:
04100:                return m_historyDriver.readNextPublishTag(dbc);
04101:            }
04102:
04103:            /**
04104:             * Returns all child organizational units of the given parent organizational unit including 
04105:             * hierarchical deeper organization units if needed.<p>
04106:             *
04107:             * @param dbc the current db context
04108:             * @param parent the parent organizational unit, or <code>null</code> for the root
04109:             * @param includeChildren if hierarchical deeper organization units should also be returned
04110:             * 
04111:             * @return a list of <code>{@link CmsOrganizationalUnit}</code> objects
04112:             * 
04113:             * @throws CmsException if operation was not successful
04114:             * 
04115:             * @see org.opencms.security.CmsOrgUnitManager#getOrganizationalUnits(CmsObject, String, boolean)
04116:             */
04117:            public List getOrganizationalUnits(CmsDbContext dbc,
04118:                    CmsOrganizationalUnit parent, boolean includeChildren)
04119:                    throws CmsException {
04120:
04121:                if (parent == null) {
04122:                    throw new CmsIllegalArgumentException(Messages.get()
04123:                            .container(Messages.ERR_PARENT_ORGUNIT_NULL_0));
04124:                }
04125:                return m_userDriver.getOrganizationalUnits(dbc, parent,
04126:                        includeChildren);
04127:            }
04128:
04129:            /**
04130:             * Returns all the organizational units for which the current user has the given role.<p>
04131:             * 
04132:             * @param dbc the current database context
04133:             * @param role the role to check
04134:             * @param includeSubOus if sub organizational units should be included in the search 
04135:             *  
04136:             * @return a list of {@link org.opencms.security.CmsOrganizationalUnit} objects
04137:             * 
04138:             * @throws CmsException if something goes wrong
04139:             */
04140:            public List getOrgUnitsForRole(CmsDbContext dbc, CmsRole role,
04141:                    boolean includeSubOus) throws CmsException {
04142:
04143:                String ouFqn = role.getOuFqn();
04144:                if (ouFqn == null) {
04145:                    ouFqn = "";
04146:                    role = role.forOrgUnit("");
04147:                }
04148:                CmsOrganizationalUnit ou = readOrganizationalUnit(dbc, ouFqn);
04149:                List orgUnits = new ArrayList();
04150:                if (m_securityManager.hasRole(dbc, dbc.currentUser(), role)) {
04151:                    orgUnits.add(ou);
04152:                }
04153:                if (includeSubOus) {
04154:                    Iterator it = getOrganizationalUnits(dbc, ou, true)
04155:                            .iterator();
04156:                    while (it.hasNext()) {
04157:                        CmsOrganizationalUnit orgUnit = (CmsOrganizationalUnit) it
04158:                                .next();
04159:                        if (m_securityManager.hasRole(dbc, dbc.currentUser(),
04160:                                role.forOrgUnit(orgUnit.getName()))) {
04161:                            orgUnits.add(orgUnit);
04162:                        }
04163:                    }
04164:                }
04165:                return orgUnits;
04166:            }
04167:
04168:            /**
04169:             * Returns the parent group of a group.<p>
04170:             *
04171:             * @param dbc the current database context
04172:             * @param groupname the name of the group
04173:             * 
04174:             * @return group the parent group or <code>null</code>
04175:             * 
04176:             * @throws CmsException if operation was not successful
04177:             */
04178:            public CmsGroup getParent(CmsDbContext dbc, String groupname)
04179:                    throws CmsException {
04180:
04181:                CmsGroup group = readGroup(dbc, groupname);
04182:                if (group.getParentId().isNullUUID()) {
04183:                    return null;
04184:                }
04185:
04186:                // try to read from cache
04187:                CmsGroup parent = OpenCms.getMemoryMonitor().getCachedGroup(
04188:                        group.getParentId().toString());
04189:                if (parent == null) {
04190:                    parent = m_userDriver.readGroup(dbc, group.getParentId());
04191:                    OpenCms.getMemoryMonitor().cacheGroup(parent);
04192:                }
04193:                return parent;
04194:            }
04195:
04196:            /**
04197:             * Returns the set of permissions of the current user for a given resource.<p>
04198:             * 
04199:             * @param dbc the current database context
04200:             * @param resource the resource
04201:             * @param user the user
04202:             * 
04203:             * @return bit set with allowed permissions
04204:             * 
04205:             * @throws CmsException if something goes wrong
04206:             */
04207:            public CmsPermissionSetCustom getPermissions(CmsDbContext dbc,
04208:                    CmsResource resource, CmsUser user) throws CmsException {
04209:
04210:                CmsAccessControlList acList = getAccessControlList(dbc,
04211:                        resource, false);
04212:                return acList.getPermissions(user, getGroupsOfUser(dbc, user
04213:                        .getName(), false), getRolesForUser(dbc, user));
04214:            }
04215:
04216:            /**
04217:             * Returns the project driver.<p>
04218:             *
04219:             * @return the project driver
04220:             */
04221:            public I_CmsProjectDriver getProjectDriver() {
04222:
04223:                return m_projectDriver;
04224:            }
04225:
04226:            /**
04227:             * Returns the uuid id for the given id.<p>
04228:             * 
04229:             * TODO: remove this method as soon as possible
04230:             * 
04231:             * @param dbc the current database context
04232:             * @param id the old project id
04233:             * 
04234:             * @return the new uuid for the given id
04235:             * 
04236:             * @throws CmsException if something goes wrong 
04237:             */
04238:            public CmsUUID getProjectId(CmsDbContext dbc, int id)
04239:                    throws CmsException {
04240:
04241:                Iterator itProjects = getAllAccessibleProjects(dbc).iterator();
04242:                while (itProjects.hasNext()) {
04243:                    CmsProject project = (CmsProject) itProjects.next();
04244:                    if (project.getUuid().hashCode() == id) {
04245:                        return project.getUuid();
04246:                    }
04247:                }
04248:                return null;
04249:            }
04250:
04251:            /**
04252:             * Returns the configuration read from the <code>opencms.properties</code> file.<p>
04253:             *
04254:             * @return the configuration read from the <code>opencms.properties</code> file
04255:             */
04256:            public ExtendedProperties getPropertyConfiguration() {
04257:
04258:                return m_propertyConfiguration;
04259:            }
04260:
04261:            /**
04262:             * Returns a new publish list that contains the unpublished resources related 
04263:             * to all resources in the given publish list, the related resources exclude 
04264:             * all resources in the given publish list and also locked (by other users) resources.<p>
04265:             * 
04266:             * @param dbc the current database context
04267:             * @param publishList the publish list to exclude from result
04268:             * @param filter the relation filter to use to get the related resources
04269:             * 
04270:             * @return a new publish list that contains the related resources
04271:             * 
04272:             * @throws CmsException if something goes wrong
04273:             * 
04274:             * @see org.opencms.publish.CmsPublishManager#getRelatedResourcesToPublish(CmsObject, CmsPublishList)
04275:             */
04276:            public CmsPublishList getRelatedResourcesToPublish(
04277:                    CmsDbContext dbc, CmsPublishList publishList,
04278:                    CmsRelationFilter filter) throws CmsException {
04279:
04280:                Map relations = new HashMap();
04281:
04282:                // check if progress should be set in the thread
04283:                CmsProgressThread thread = null;
04284:                if (Thread.currentThread() instanceof  CmsProgressThread) {
04285:                    thread = (CmsProgressThread) Thread.currentThread();
04286:                }
04287:
04288:                // get all resources to publish
04289:                List publishResources = publishList.getAllResources();
04290:                Iterator itCheckList = publishResources.iterator();
04291:                // iterate over them
04292:                int count = 0;
04293:                while (itCheckList.hasNext()) {
04294:
04295:                    // set progress in thread
04296:                    count++;
04297:                    if (thread != null) {
04298:
04299:                        if (thread.isInterrupted()) {
04300:                            throw new CmsIllegalStateException(
04301:                                    org.opencms.workplace.commons.Messages
04302:                                            .get()
04303:                                            .container(
04304:                                                    org.opencms.workplace.commons.Messages.ERR_PROGRESS_INTERRUPTED_0));
04305:                        }
04306:                        thread
04307:                                .setProgress(count * 20
04308:                                        / publishResources.size());
04309:                        thread
04310:                                .setDescription(org.opencms.workplace.commons.Messages
04311:                                        .get()
04312:                                        .getBundle()
04313:                                        .key(
04314:                                                org.opencms.workplace.commons.Messages.GUI_PROGRESS_PUBLISH_STEP1_2,
04315:                                                new Integer(count),
04316:                                                new Integer(publishResources
04317:                                                        .size())));
04318:                    }
04319:
04320:                    CmsResource checkResource = (CmsResource) itCheckList
04321:                            .next();
04322:                    // get and iterate over all related resources
04323:                    Iterator itRelations = getRelationsForResource(dbc,
04324:                            checkResource, filter).iterator();
04325:                    while (itRelations.hasNext()) {
04326:                        CmsRelation relation = (CmsRelation) itRelations.next();
04327:                        try {
04328:                            // get the target of the relation, see CmsRelation#getTarget(CmsObject, CmsResourceFilter)
04329:                            CmsResource target;
04330:                            try {
04331:                                // first look up by id
04332:                                target = readResource(dbc, relation
04333:                                        .getTargetId(), CmsResourceFilter.ALL);
04334:                            } catch (CmsVfsResourceNotFoundException e) {
04335:                                // then look up by name, but from the root site
04336:                                String storedSiteRoot = dbc.getRequestContext()
04337:                                        .getSiteRoot();
04338:                                try {
04339:                                    dbc.getRequestContext().setSiteRoot("");
04340:                                    target = readResource(dbc, relation
04341:                                            .getTargetPath(),
04342:                                            CmsResourceFilter.ALL);
04343:                                } finally {
04344:                                    dbc.getRequestContext().setSiteRoot(
04345:                                            storedSiteRoot);
04346:                                }
04347:                            }
04348:                            // just add resources that may come in question
04349:                            if (!publishResources.contains(target) // is not in the original list
04350:                                    && !relations.containsKey(target
04351:                                            .getRootPath()) // has not been already added by another relation
04352:                                    && !target.getState().isUnchanged()) { // has been changed
04353:
04354:                                relations.put(target.getRootPath(), target);
04355:                                // now check the folder structure
04356:                                CmsResource parent = m_vfsDriver
04357:                                        .readParentFolder(dbc, dbc
04358:                                                .currentProject().getUuid(),
04359:                                                target.getStructureId());
04360:                                while ((parent != null)
04361:                                        && parent.getState().isNew()) {
04362:                                    // just add resources that may come in question
04363:                                    if (!publishResources.contains(parent) // is not in the original list
04364:                                            && !relations.containsKey(parent
04365:                                                    .getRootPath())) { // has not been already added by another relation
04366:
04367:                                        relations.put(parent.getRootPath(),
04368:                                                parent);
04369:                                    }
04370:                                    parent = m_vfsDriver.readParentFolder(dbc,
04371:                                            dbc.currentProject().getUuid(),
04372:                                            parent.getStructureId());
04373:                                }
04374:                            }
04375:                        } catch (CmsVfsResourceNotFoundException e) {
04376:                            // ignore broken links
04377:                            if (LOG.isDebugEnabled()) {
04378:                                LOG.debug(e.getLocalizedMessage(), e);
04379:                            }
04380:                        }
04381:                    }
04382:                }
04383:
04384:                CmsPublishList ret = new CmsPublishList(publishList
04385:                        .getDirectPublishResources(), false, false);
04386:                ret.addAll(relations.values(), false);
04387:                ret.initialize();
04388:                return ret;
04389:            }
04390:
04391:            /**
04392:             * Returns all relations for the given resource matching the given filter.<p> 
04393:             * 
04394:             * @param dbc the current db context
04395:             * @param resource the resource to retrieve the relations for
04396:             * @param filter the filter to match the relation 
04397:             * 
04398:             * @return all {@link CmsRelation} objects for the given resource matching the given filter
04399:             * 
04400:             * @throws CmsException if something goes wrong
04401:             * 
04402:             * @see CmsSecurityManager#getRelationsForResource(CmsRequestContext, CmsResource, CmsRelationFilter)
04403:             */
04404:            public List getRelationsForResource(CmsDbContext dbc,
04405:                    CmsResource resource, CmsRelationFilter filter)
04406:                    throws CmsException {
04407:
04408:                return m_vfsDriver.readRelations(dbc, dbc.getProjectId()
04409:                        .isNullUUID() ? dbc.currentProject().getUuid() : dbc
04410:                        .getProjectId(), resource, filter);
04411:            }
04412:
04413:            /**
04414:             * Returns all resources of the given organizational unit.<p>
04415:             *
04416:             * @param dbc the current db context
04417:             * @param orgUnit the organizational unit to get all resources for
04418:             * 
04419:             * @return all <code>{@link CmsResource}</code> objects in the organizational unit
04420:             *
04421:             * @throws CmsException if operation was not successful
04422:             * 
04423:             * @see org.opencms.security.CmsOrgUnitManager#getResourcesForOrganizationalUnit(CmsObject, String)
04424:             * @see org.opencms.security.CmsOrgUnitManager#getUsers(CmsObject, String, boolean)
04425:             * @see org.opencms.security.CmsOrgUnitManager#getGroups(CmsObject, String, boolean)
04426:             */
04427:            public List getResourcesForOrganizationalUnit(CmsDbContext dbc,
04428:                    CmsOrganizationalUnit orgUnit) throws CmsException {
04429:
04430:                return m_userDriver.getResourcesForOrganizationalUnit(dbc,
04431:                        orgUnit);
04432:            }
04433:
04434:            /**
04435:             * Returns all resources associated to a given principal via an ACE with the given permissions.<p> 
04436:             * 
04437:             * If the <code>includeAttr</code> flag is set it returns also all resources associated to 
04438:             * a given principal through some of following attributes.<p> 
04439:             * 
04440:             * <ul>
04441:             *    <li>User Created</li>
04442:             *    <li>User Last Modified</li>
04443:             * </ul><p>
04444:             * 
04445:             * @param dbc the current database context
04446:             * @param project the to read the entries from
04447:             * @param principalId the id of the principal
04448:             * @param permissions a set of permissions to match, can be <code>null</code> for all ACEs
04449:             * @param includeAttr a flag to include resources associated by attributes
04450:             * 
04451:             * @return a list of <code>{@link CmsResource}</code> objects
04452:             * 
04453:             * @throws CmsException if something goes wrong
04454:             */
04455:            public List getResourcesForPrincipal(CmsDbContext dbc,
04456:                    CmsProject project, CmsUUID principalId,
04457:                    CmsPermissionSet permissions, boolean includeAttr)
04458:                    throws CmsException {
04459:
04460:                List resources = m_vfsDriver.readResourcesForPrincipalACE(dbc,
04461:                        project, principalId);
04462:                if (permissions != null) {
04463:                    Iterator itRes = resources.iterator();
04464:                    while (itRes.hasNext()) {
04465:                        CmsAccessControlEntry ace = readAccessControlEntry(dbc,
04466:                                (CmsResource) itRes.next(), principalId);
04467:                        if ((ace.getPermissions().getPermissions() & permissions
04468:                                .getPermissions()) != permissions
04469:                                .getPermissions()) {
04470:                            // remove if permissions does not match
04471:                            itRes.remove();
04472:                        }
04473:                    }
04474:                }
04475:                if (includeAttr) {
04476:                    resources.addAll(m_vfsDriver.readResourcesForPrincipalAttr(
04477:                            dbc, project, principalId));
04478:                }
04479:                // remove duplicated
04480:                Set resNames = new HashSet();
04481:                Iterator itRes = resources.iterator();
04482:                while (itRes.hasNext()) {
04483:                    String resName = ((CmsResource) itRes.next()).getRootPath();
04484:                    if (resNames.contains(resName)) {
04485:                        itRes.remove();
04486:                    } else {
04487:                        resNames.add(resName);
04488:                    }
04489:                }
04490:                return resources;
04491:            }
04492:
04493:            /**
04494:             * Returns all roles the given user has for the given resource.<p>
04495:             * 
04496:             * @param dbc the current database context
04497:             * @param user the user to check
04498:             * @param resource the resource to check the roles for 
04499:             * 
04500:             * @return a list of {@link CmsRole} objects
04501:             * 
04502:             * @throws CmsException if something goes wrong 
04503:             */
04504:            public List getRolesForResource(CmsDbContext dbc, CmsUser user,
04505:                    CmsResource resource) throws CmsException {
04506:
04507:                // guest user has no role
04508:                if (user.isGuestUser()) {
04509:                    return Collections.EMPTY_LIST;
04510:                }
04511:
04512:                // try to read from cache
04513:                String key = user.getId().toString() + resource.getRootPath();
04514:                List result = OpenCms.getMemoryMonitor().getCachedRoleList(key);
04515:                if (result != null) {
04516:                    return result;
04517:                }
04518:                result = new ArrayList();
04519:
04520:                // read all roles of the current user
04521:                List roles = new ArrayList(getGroupsOfUser(dbc, user.getName(),
04522:                        "", true, true, false, dbc.getRequestContext()
04523:                                .getRemoteAddress()));
04524:
04525:                // check the roles applying to the given resource
04526:                Iterator it = roles.iterator();
04527:                while (it.hasNext()) {
04528:                    CmsGroup group = (CmsGroup) it.next();
04529:                    CmsRole givenRole = CmsRole.valueOf(group);
04530:                    if (result.contains(givenRole.forOrgUnit(null))) {
04531:                        // skip already added roles
04532:                        continue;
04533:                    }
04534:                    // now check the resource if needed
04535:                    if (givenRole.getOuFqn() != null) {
04536:                        CmsOrganizationalUnit orgUnit = readOrganizationalUnit(
04537:                                dbc, givenRole.getOuFqn());
04538:                        Iterator itResources = getResourcesForOrganizationalUnit(
04539:                                dbc, orgUnit).iterator();
04540:                        while (itResources.hasNext()) {
04541:                            CmsResource givenResource = (CmsResource) itResources
04542:                                    .next();
04543:                            if (resource.getRootPath().startsWith(
04544:                                    givenResource.getRootPath())) {
04545:                                result.add(givenRole.forOrgUnit(null));
04546:                                break;
04547:                            }
04548:                        }
04549:                    } else {
04550:                        result.add(givenRole);
04551:                    }
04552:                }
04553:                result = Collections.unmodifiableList(result);
04554:                OpenCms.getMemoryMonitor().cacheRoleList(key, result);
04555:                return result;
04556:            }
04557:
04558:            /**
04559:             * Returns all roles the given user has independent of the resource.<p>
04560:             * 
04561:             * @param dbc the current database context
04562:             * @param user the user to check
04563:             * 
04564:             * @return a list of {@link CmsRole} objects
04565:             * 
04566:             * @throws CmsException if something goes wrong 
04567:             */
04568:            public List getRolesForUser(CmsDbContext dbc, CmsUser user)
04569:                    throws CmsException {
04570:
04571:                // guest user has no role
04572:                if (user.isGuestUser()) {
04573:                    return Collections.EMPTY_LIST;
04574:                }
04575:
04576:                // try to read from cache
04577:                String key = user.getId().toString();
04578:                List result = OpenCms.getMemoryMonitor().getCachedRoleList(key);
04579:                if (result != null) {
04580:                    return result;
04581:                }
04582:                result = new ArrayList();
04583:
04584:                // read all roles of the current user
04585:                List roles = new ArrayList(getGroupsOfUser(dbc, user.getName(),
04586:                        "", true, true, false, dbc.getRequestContext()
04587:                                .getRemoteAddress()));
04588:
04589:                // check the roles applying to the given resource
04590:                Iterator it = roles.iterator();
04591:                while (it.hasNext()) {
04592:                    CmsGroup group = (CmsGroup) it.next();
04593:                    CmsRole givenRole = CmsRole.valueOf(group);
04594:                    givenRole = givenRole.forOrgUnit(null);
04595:                    if (!result.contains(givenRole)) {
04596:                        result.add(givenRole);
04597:                    }
04598:                }
04599:                result = Collections.unmodifiableList(result);
04600:                OpenCms.getMemoryMonitor().cacheRoleList(key, result);
04601:                return result;
04602:            }
04603:
04604:            /**
04605:             * Returns the security manager this driver manager belongs to.<p>
04606:             * 
04607:             * @return the security manager this driver manager belongs to
04608:             */
04609:            public CmsSecurityManager getSecurityManager() {
04610:
04611:                return m_securityManager;
04612:            }
04613:
04614:            /**
04615:             * Returns an instance of the common sql manager.<p>
04616:             * 
04617:             * @return an instance of the common sql manager
04618:             */
04619:            public CmsSqlManager getSqlManager() {
04620:
04621:                return m_sqlManager;
04622:            }
04623:
04624:            /**
04625:             * Returns the user driver.<p>
04626:             * 
04627:             * @return the user driver
04628:             */
04629:            public I_CmsUserDriver getUserDriver() {
04630:
04631:                return m_userDriver;
04632:            }
04633:
04634:            /**
04635:             * Returns all direct users of the given organizational unit.<p>
04636:             *
04637:             * @param dbc the current db context
04638:             * @param orgUnit the organizational unit to get all users for
04639:             * @param recursive if all groups of sub-organizational units should be retrieved too
04640:             * 
04641:             * @return all <code>{@link CmsUser}</code> objects in the organizational unit
04642:             *
04643:             * @throws CmsException if operation was not successful
04644:             * 
04645:             * @see org.opencms.security.CmsOrgUnitManager#getResourcesForOrganizationalUnit(CmsObject, String)
04646:             * @see org.opencms.security.CmsOrgUnitManager#getUsers(CmsObject, String, boolean)
04647:             */
04648:            public List getUsers(CmsDbContext dbc,
04649:                    CmsOrganizationalUnit orgUnit, boolean recursive)
04650:                    throws CmsException {
04651:
04652:                return m_userDriver.getUsers(dbc, orgUnit, recursive);
04653:            }
04654:
04655:            /**
04656:             * Returns a list of users in a group.<p>
04657:             *
04658:             * @param dbc the current database context
04659:             * @param groupname the name of the group to list users from
04660:             * @param includeOtherOuUsers include users of other organizational units
04661:             * @param directUsersOnly if set only the direct assigned users will be returned, 
04662:             *                        if not also indirect users, ie. members of parent roles, 
04663:             *                        this parameter only works with roles
04664:             * @param readRoles if to read roles or groups
04665:             * 
04666:             * @return all <code>{@link CmsUser}</code> objects in the group
04667:             * 
04668:             * @throws CmsException if operation was not successful
04669:             */
04670:            public List getUsersOfGroup(CmsDbContext dbc, String groupname,
04671:                    boolean includeOtherOuUsers, boolean directUsersOnly,
04672:                    boolean readRoles) throws CmsException {
04673:
04674:                return internalUsersOfGroup(dbc, CmsOrganizationalUnit
04675:                        .getParentFqn(groupname), groupname,
04676:                        includeOtherOuUsers, directUsersOnly, readRoles);
04677:            }
04678:
04679:            /**
04680:             * Returns the VFS driver.<p>
04681:             * 
04682:             * @return the VFS driver
04683:             */
04684:            public I_CmsVfsDriver getVfsDriver() {
04685:
04686:                return m_vfsDriver;
04687:            }
04688:
04689:            /**
04690:             * Writes a vector of access control entries as new access control entries of a given resource.<p>
04691:             * 
04692:             * Already existing access control entries of this resource are removed before.
04693:             * Access is granted, if:<p>
04694:             * <ul>
04695:             * <li>the current user has control permission on the resource</li>
04696:             * </ul>
04697:             * 
04698:             * @param dbc the current database context
04699:             * @param resource the resource
04700:             * @param acEntries a list of <code>{@link CmsAccessControlEntry}</code> objects
04701:             * 
04702:             * @throws CmsException if something goes wrong
04703:             */
04704:            public void importAccessControlEntries(CmsDbContext dbc,
04705:                    CmsResource resource, List acEntries) throws CmsException {
04706:
04707:                m_userDriver.removeAccessControlEntries(dbc, dbc
04708:                        .currentProject(), resource.getResourceId());
04709:
04710:                Iterator i = acEntries.iterator();
04711:                while (i.hasNext()) {
04712:                    m_userDriver
04713:                            .writeAccessControlEntry(dbc, dbc.currentProject(),
04714:                                    (CmsAccessControlEntry) i.next());
04715:                }
04716:                OpenCms.getMemoryMonitor().clearAccessControlListCache();
04717:            }
04718:
04719:            /**
04720:             * Creates a new user by import.<p>
04721:             * 
04722:             * @param dbc the current database context
04723:             * @param id the id of the user
04724:             * @param name the new name for the user
04725:             * @param password the new password for the user
04726:             * @param firstname the firstname of the user
04727:             * @param lastname the lastname of the user
04728:             * @param email the email of the user
04729:             * @param flags the flags for a user (for example <code>{@link I_CmsPrincipal#FLAG_ENABLED}</code>)
04730:             * @param dateCreated the creation date
04731:             * @param additionalInfos the additional user infos
04732:             * 
04733:             * @return the imported user
04734:             *
04735:             * @throws CmsException if something goes wrong
04736:             */
04737:            public CmsUser importUser(CmsDbContext dbc, String id, String name,
04738:                    String password, String firstname, String lastname,
04739:                    String email, int flags, long dateCreated,
04740:                    Map additionalInfos) throws CmsException {
04741:
04742:                // no space before or after the name
04743:                name = name.trim();
04744:                // check the user name
04745:                String userName = CmsOrganizationalUnit.getSimpleName(name);
04746:                OpenCms.getValidationHandler().checkUserName(userName);
04747:                if (CmsStringUtil.isEmptyOrWhitespaceOnly(userName)) {
04748:                    throw new CmsIllegalArgumentException(Messages.get()
04749:                            .container(Messages.ERR_BAD_USER_1, userName));
04750:                }
04751:                // check the ou
04752:                CmsOrganizationalUnit ou = readOrganizationalUnit(dbc,
04753:                        CmsOrganizationalUnit.getParentFqn(name));
04754:                // check the password
04755:                validatePassword(password);
04756:
04757:                // check webuser ou
04758:                if (ou.hasFlagWebuser()
04759:                        && ((flags & I_CmsPrincipal.FLAG_USER_WEBUSER) == 0)) {
04760:                    flags += I_CmsPrincipal.FLAG_USER_WEBUSER;
04761:                }
04762:                CmsUser newUser = m_userDriver.createUser(dbc, new CmsUUID(id),
04763:                        name, password, firstname, lastname, email, 0, flags,
04764:                        dateCreated, additionalInfos);
04765:                return newUser;
04766:            }
04767:
04768:            /**
04769:             * Initializes the driver and sets up all required modules and connections.<p>
04770:             * 
04771:             * @param configurationManager the configuration manager
04772:             * 
04773:             * @throws CmsException if something goes wrong
04774:             * @throws Exception if something goes wrong
04775:             */
04776:            public void init(CmsConfigurationManager configurationManager)
04777:                    throws CmsException, Exception {
04778:
04779:                // initialize the access-module.
04780:                if (CmsLog.INIT.isInfoEnabled()) {
04781:                    CmsLog.INIT.info(Messages.get().getBundle().key(
04782:                            Messages.INIT_DRIVER_MANAGER_START_PHASE4_0));
04783:                }
04784:
04785:                CmsSystemConfiguration systemConfiguation = (CmsSystemConfiguration) configurationManager
04786:                        .getConfiguration(CmsSystemConfiguration.class);
04787:                CmsCacheSettings settings = systemConfiguation
04788:                        .getCacheSettings();
04789:
04790:                // initialize the key generator
04791:                m_keyGenerator = (I_CmsCacheKey) Class.forName(
04792:                        settings.getCacheKeyGenerator()).newInstance();
04793:
04794:                // initialize the HTML link validator
04795:                m_htmlLinkValidator = new CmsRelationSystemValidator(this );
04796:
04797:                // fills the defaults if needed
04798:                getUserDriver().fillDefaults(new CmsDbContext());
04799:                getProjectDriver().fillDefaults(new CmsDbContext());
04800:                // set the driver manager in the publish engine
04801:                m_publishEngine.setDriverManager(this );
04802:                // create the root organizational unit if needed
04803:                CmsDbContext dbc = new CmsDbContext(new CmsRequestContext(
04804:                        readUser(new CmsDbContext(), OpenCms.getDefaultUsers()
04805:                                .getUserAdmin()), readProject(
04806:                                new CmsDbContext(),
04807:                                CmsProject.ONLINE_PROJECT_ID), null, "", null,
04808:                        null, null, 0, null, null, ""));
04809:                getUserDriver().createRootOrganizationalUnit(dbc);
04810:            }
04811:
04812:            /**
04813:             * Checks if the specified resource is inside the current project.<p>
04814:             * 
04815:             * The project "view" is determined by a set of path prefixes. 
04816:             * If the resource starts with any one of this prefixes, it is considered to 
04817:             * be "inside" the project.<p>
04818:             * 
04819:             * @param dbc the current database context
04820:             * @param resourcename the specified resource name (full path)
04821:             * 
04822:             * @return <code>true</code>, if the specified resource is inside the current project
04823:             */
04824:            public boolean isInsideCurrentProject(CmsDbContext dbc,
04825:                    String resourcename) {
04826:
04827:                List projectResources = null;
04828:                try {
04829:                    projectResources = readProjectResources(dbc, dbc
04830:                            .currentProject());
04831:                } catch (CmsException e) {
04832:                    if (LOG.isErrorEnabled()) {
04833:                        LOG
04834:                                .error(
04835:                                        Messages
04836:                                                .get()
04837:                                                .getBundle()
04838:                                                .key(
04839:                                                        Messages.LOG_CHECK_RESOURCE_INSIDE_CURRENT_PROJECT_2,
04840:                                                        resourcename,
04841:                                                        dbc.currentProject()
04842:                                                                .getName()), e);
04843:                    }
04844:                    return false;
04845:                }
04846:                return CmsProject.isInsideProject(projectResources,
04847:                        resourcename);
04848:            }
04849:
04850:            /**
04851:             * Checks if a project is the tempfile project.<p>
04852:             * @param project the project to test
04853:             * @return true if the project is the tempfile project
04854:             */
04855:            public boolean isTempfileProject(CmsProject project) {
04856:
04857:                return project.getName().equals("tempFileProject");
04858:            }
04859:
04860:            /**
04861:             * Checks if one of the resources (except the resource itself) 
04862:             * is a sibling in a "labeled" site folder.<p>
04863:             * 
04864:             * This method is used when creating a new sibling 
04865:             * (use the newResource parameter & action = 1) 
04866:             * or deleting/importing a resource (call with action = 2).<p> 
04867:             *   
04868:             * @param dbc the current database context
04869:             * @param resource the resource
04870:             * @param newResource absolute path for a resource sibling which will be created
04871:             * @param action the action which has to be performed (1 = create VFS link, 2 all other actions)
04872:             * @return true if the flag should be set for the resource, otherwise false
04873:             * @throws CmsDataAccessException if something goes wrong
04874:             */
04875:            public boolean labelResource(CmsDbContext dbc,
04876:                    CmsResource resource, String newResource, int action)
04877:                    throws CmsDataAccessException {
04878:
04879:                // get the list of labeled site folders from the runtime property
04880:                List labeledSites = OpenCms.getWorkplaceManager()
04881:                        .getLabelSiteFolders();
04882:
04883:                if (labeledSites.size() == 0) {
04884:                    // no labeled sites defined, just return false 
04885:                    return false;
04886:                }
04887:
04888:                if (action == 1) {
04889:                    // CASE 1: a new resource is created, check the sites
04890:                    if (!resource.isLabeled()) {
04891:                        // source isn't labeled yet, so check!
04892:                        boolean linkInside = false;
04893:                        boolean sourceInside = false;
04894:                        for (int i = 0; i < labeledSites.size(); i++) {
04895:                            String curSite = (String) labeledSites.get(i);
04896:                            if (newResource.startsWith(curSite)) {
04897:                                // the link lies in a labeled site
04898:                                linkInside = true;
04899:                            }
04900:                            if (resource.getRootPath().startsWith(curSite)) {
04901:                                // the source lies in a labeled site
04902:                                sourceInside = true;
04903:                            }
04904:                            if (linkInside && sourceInside) {
04905:                                break;
04906:                            }
04907:                        }
04908:                        // return true when either source or link is in labeled site, otherwise false
04909:                        return (linkInside != sourceInside);
04910:                    }
04911:                    // resource is already labeled
04912:                    return false;
04913:
04914:                } else {
04915:                    // CASE 2: the resource will be deleted or created (import)
04916:                    // check if at least one of the other siblings resides inside a "labeled site"
04917:                    // and if at least one of the other siblings resides outside a "labeled site"
04918:                    boolean isInside = false;
04919:                    boolean isOutside = false;
04920:                    // check if one of the other vfs links lies in a labeled site folder
04921:                    List siblings = m_vfsDriver.readSiblings(dbc, dbc
04922:                            .currentProject().getUuid(), resource, false);
04923:                    updateContextDates(dbc, siblings);
04924:                    Iterator i = siblings.iterator();
04925:                    while (i.hasNext() && (!isInside || !isOutside)) {
04926:                        CmsResource currentResource = (CmsResource) i.next();
04927:                        if (currentResource.equals(resource)) {
04928:                            // dont't check the resource itself!
04929:                            continue;
04930:                        }
04931:                        String curPath = currentResource.getRootPath();
04932:                        boolean curInside = false;
04933:                        for (int k = 0; k < labeledSites.size(); k++) {
04934:                            if (curPath
04935:                                    .startsWith((String) labeledSites.get(k))) {
04936:                                // the link is in the labeled site
04937:                                isInside = true;
04938:                                curInside = true;
04939:                                break;
04940:                            }
04941:                        }
04942:                        if (!curInside) {
04943:                            // the current link was not found in labeled site, so it is outside
04944:                            isOutside = true;
04945:                        }
04946:                    }
04947:                    // now check the new resource name if present
04948:                    if (newResource != null) {
04949:                        boolean curInside = false;
04950:                        for (int k = 0; k < labeledSites.size(); k++) {
04951:                            if (newResource.startsWith((String) labeledSites
04952:                                    .get(k))) {
04953:                                // the new resource is in the labeled site
04954:                                isInside = true;
04955:                                curInside = true;
04956:                                break;
04957:                            }
04958:                        }
04959:                        if (!curInside) {
04960:                            // the new resource was not found in labeled site, so it is outside
04961:                            isOutside = true;
04962:                        }
04963:                    }
04964:                    return (isInside && isOutside);
04965:                }
04966:            }
04967:
04968:            /**
04969:             * Returns the user, who had locked the resource.<p>
04970:             *
04971:             * A user can lock a resource, so he is the only one who can write this
04972:             * resource. This methods checks, if a resource was locked.
04973:             *
04974:             * @param dbc the current database context
04975:             * @param resource the resource
04976:             *
04977:             * @return the user, who had locked the resource
04978:             *
04979:             * @throws CmsException will be thrown, if the user has not the rights for this resource
04980:             */
04981:            public CmsUser lockedBy(CmsDbContext dbc, CmsResource resource)
04982:                    throws CmsException {
04983:
04984:                return readUser(dbc, m_lockManager.getLock(dbc, resource)
04985:                        .getEditionLock().getUserId());
04986:            }
04987:
04988:            /**
04989:             * Locks a resource.<p>
04990:             *
04991:             * The <code>type</code> parameter controls what kind of lock is used.<br>
04992:             * Possible values for this parameter are: <br>
04993:             * <ul>
04994:             * <li><code>{@link org.opencms.lock.CmsLockType#EXCLUSIVE}</code></li>
04995:             * <li><code>{@link org.opencms.lock.CmsLockType#TEMPORARY}</code></li>
04996:             * <li><code>{@link org.opencms.lock.CmsLockType#PUBLISH}</code></li>
04997:             * </ul><p>
04998:             * 
04999:             * @param dbc the current database context
05000:             * @param resource the resource to lock
05001:             * @param type type of the lock
05002:             * 
05003:             * @throws CmsException if something goes wrong
05004:             * 
05005:             * @see CmsObject#lockResource(String)
05006:             * @see CmsObject#lockResourceTemporary(String)
05007:             * @see org.opencms.file.types.I_CmsResourceType#lockResource(CmsObject, CmsSecurityManager, CmsResource, CmsLockType)
05008:             */
05009:            public void lockResource(CmsDbContext dbc, CmsResource resource,
05010:                    CmsLockType type) throws CmsException {
05011:
05012:                // update the resource cache
05013:                OpenCms.getMemoryMonitor().clearResourceCache();
05014:
05015:                CmsProject project = dbc.currentProject();
05016:
05017:                // add the resource to the lock dispatcher
05018:                m_lockManager.addResource(dbc, resource, dbc.currentUser(),
05019:                        project, type);
05020:
05021:                if (!resource.getState().isUnchanged()
05022:                        && !resource.getState().isKeep()) {
05023:                    // update the project flag of a modified resource as "last modified inside the current project"
05024:                    m_vfsDriver.writeLastModifiedProjectId(dbc, project,
05025:                            project.getUuid(), resource);
05026:                }
05027:
05028:                // we must also clear the permission cache
05029:                OpenCms.getMemoryMonitor().flushPermissions();
05030:
05031:                // fire resource modification event
05032:                HashMap data = new HashMap(2);
05033:                data.put("resource", resource);
05034:                data.put("change", new Integer(NOTHING_CHANGED));
05035:                OpenCms.fireCmsEvent(new CmsEvent(
05036:                        I_CmsEventListener.EVENT_RESOURCE_MODIFIED, data));
05037:            }
05038:
05039:            /**
05040:             * Attempts to authenticate a user into OpenCms with the given password.<p>
05041:             * 
05042:             * @param dbc the current database context
05043:             * @param userName the name of the user to be logged in
05044:             * @param password the password of the user
05045:             * @param remoteAddress the ip address of the request
05046:             * 
05047:             * @return the logged in user
05048:             *
05049:             * @throws CmsAuthentificationException if the login was not successful
05050:             * @throws CmsDataAccessException in case of errors accessing the database
05051:             * @throws CmsPasswordEncryptionException in case of errors encrypting the users password
05052:             */
05053:            public CmsUser loginUser(CmsDbContext dbc, String userName,
05054:                    String password, String remoteAddress)
05055:                    throws CmsAuthentificationException,
05056:                    CmsDataAccessException, CmsPasswordEncryptionException {
05057:
05058:                if (CmsStringUtil.isEmptyOrWhitespaceOnly(password)) {
05059:                    throw new CmsDbEntryNotFoundException(Messages.get()
05060:                            .container(Messages.ERR_UNKNOWN_USER_1, userName));
05061:                }
05062:                CmsUser newUser;
05063:                try {
05064:                    // read the user from the driver to avoid the cache
05065:                    newUser = m_userDriver.readUser(dbc, userName, password,
05066:                            remoteAddress);
05067:                } catch (CmsDbEntryNotFoundException e) {
05068:                    // this indicates that the username / password combination does not exist
05069:                    // any other exception indicates database issues, these are not catched here
05070:
05071:                    // check if a user with this name exists at all 
05072:                    boolean userExists = true;
05073:                    try {
05074:                        readUser(dbc, userName);
05075:                    } catch (CmsDataAccessException e2) {
05076:                        // apparently this user does not exist in the database
05077:                        userExists = false;
05078:                    }
05079:
05080:                    if (userExists) {
05081:                        if (dbc.currentUser().isGuestUser()) {
05082:                            // add an invalid login attempt for this user to the storage
05083:                            OpenCms.getLoginManager().addInvalidLogin(userName,
05084:                                    remoteAddress);
05085:                        }
05086:                        throw new CmsAuthentificationException(
05087:                                org.opencms.security.Messages
05088:                                        .get()
05089:                                        .container(
05090:                                                org.opencms.security.Messages.ERR_LOGIN_FAILED_2,
05091:                                                userName, remoteAddress), e);
05092:                    } else {
05093:                        String userOu = CmsOrganizationalUnit
05094:                                .getParentFqn(userName);
05095:                        if (userOu != null) {
05096:                            String parentOu = CmsOrganizationalUnit
05097:                                    .getParentFqn(userOu);
05098:                            if (parentOu != null) {
05099:                                // try a higher level ou
05100:                                String uName = CmsOrganizationalUnit
05101:                                        .getSimpleName(userName);
05102:                                return loginUser(dbc, parentOu + uName,
05103:                                        password, remoteAddress);
05104:                            }
05105:                        }
05106:                        throw new CmsAuthentificationException(
05107:                                org.opencms.security.Messages
05108:                                        .get()
05109:                                        .container(
05110:                                                org.opencms.security.Messages.ERR_LOGIN_FAILED_NO_USER_2,
05111:                                                userName, remoteAddress), e);
05112:                    }
05113:                }
05114:                // check if the "enabled" flag is set for the user
05115:                if (!newUser.isEnabled()) {
05116:                    // user is disabled, throw a securiy exception
05117:                    throw new CmsAuthentificationException(
05118:                            org.opencms.security.Messages
05119:                                    .get()
05120:                                    .container(
05121:                                            org.opencms.security.Messages.ERR_LOGIN_FAILED_DISABLED_2,
05122:                                            userName, remoteAddress));
05123:                }
05124:
05125:                if (dbc.currentUser().isGuestUser()) {
05126:                    // check if this account is temporarily disabled because of too many invalid login attempts
05127:                    // this will throw an exception if the test fails
05128:                    OpenCms.getLoginManager().checkInvalidLogins(userName,
05129:                            remoteAddress);
05130:                    // test successful, remove all previous invalid login attempts for this user from the storage
05131:                    OpenCms.getLoginManager().removeInvalidLogins(userName,
05132:                            remoteAddress);
05133:                }
05134:
05135:                if (!m_securityManager.hasRole(dbc, newUser,
05136:                        CmsRole.ADMINISTRATOR.forOrgUnit(dbc
05137:                                .getRequestContext().getOuFqn()))) {
05138:                    // new user is not Administrator, check if login is currently allowed
05139:                    OpenCms.getLoginManager().checkLoginAllowed();
05140:                }
05141:
05142:                // set the last login time to the current time
05143:                newUser.setLastlogin(System.currentTimeMillis());
05144:
05145:                // write the changed user object back to the user driver
05146:                m_userDriver.writeUser(dbc, newUser);
05147:
05148:                // update cache
05149:                OpenCms.getMemoryMonitor().cacheUser(newUser);
05150:
05151:                // invalidate all user dependent caches
05152:                OpenCms.getMemoryMonitor().flushACLs();
05153:                OpenCms.getMemoryMonitor().flushGroups();
05154:                OpenCms.getMemoryMonitor().flushOrgUnits();
05155:                OpenCms.getMemoryMonitor().flushUserGroups();
05156:                OpenCms.getMemoryMonitor().flushPermissions();
05157:                OpenCms.getMemoryMonitor().flushResourceLists();
05158:
05159:                // return the user object read from the driver
05160:                return newUser;
05161:            }
05162:
05163:            /**
05164:             * Lookup and read the user or group with the given UUID.<p>
05165:             * 
05166:             * @param dbc the current database context
05167:             * @param principalId the UUID of the principal to lookup
05168:             * 
05169:             * @return the principal (group or user) if found, otherwise <code>null</code>
05170:             */
05171:            public I_CmsPrincipal lookupPrincipal(CmsDbContext dbc,
05172:                    CmsUUID principalId) {
05173:
05174:                try {
05175:                    CmsGroup group = m_userDriver.readGroup(dbc, principalId);
05176:                    if (group != null) {
05177:                        return group;
05178:                    }
05179:                } catch (Exception e) {
05180:                    // ignore this exception 
05181:                }
05182:
05183:                try {
05184:                    CmsUser user = readUser(dbc, principalId);
05185:                    if (user != null) {
05186:                        return user;
05187:                    }
05188:                } catch (Exception e) {
05189:                    // ignore this exception
05190:                }
05191:
05192:                return null;
05193:            }
05194:
05195:            /**
05196:             * Lookup and read the user or group with the given name.<p>
05197:             * 
05198:             * @param dbc the current database context
05199:             * @param principalName the name of the principal to lookup
05200:             * 
05201:             * @return the principal (group or user) if found, otherwise <code>null</code>
05202:             */
05203:            public I_CmsPrincipal lookupPrincipal(CmsDbContext dbc,
05204:                    String principalName) {
05205:
05206:                try {
05207:                    CmsGroup group = m_userDriver.readGroup(dbc, principalName);
05208:                    if (group != null) {
05209:                        return group;
05210:                    }
05211:                } catch (Exception e) {
05212:                    // ignore this exception
05213:                }
05214:
05215:                try {
05216:                    CmsUser user = readUser(dbc, principalName);
05217:                    if (user != null) {
05218:                        return user;
05219:                    }
05220:                } catch (Exception e) {
05221:                    // ignore this exception
05222:                }
05223:
05224:                return null;
05225:            }
05226:
05227:            /**
05228:             * Moves a resource.<p>
05229:             * 
05230:             * You must ensure that the parent of the destination path is an absolute, valid and
05231:             * existing VFS path. Relative paths from the source are not supported.<p>
05232:             * 
05233:             * The moved resource will always be locked to the current user
05234:             * after the move operation.<p>
05235:             * 
05236:             * In case the target resource already exists, it will be overwritten with the 
05237:             * source resource if possible.<p>
05238:             * 
05239:             * @param dbc the current database context
05240:             * @param source the resource to move
05241:             * @param destination the name of the move destination with complete path
05242:             * @param internal if set nothing more than the path is modified
05243:             * 
05244:             * @throws CmsException if something goes wrong
05245:             * 
05246:             * @see CmsSecurityManager#moveResource(CmsRequestContext, CmsResource, String)
05247:             */
05248:            public void moveResource(CmsDbContext dbc, CmsResource source,
05249:                    String destination, boolean internal) throws CmsException {
05250:
05251:                CmsFolder destinationFolder = readFolder(dbc, CmsResource
05252:                        .getParentFolder(destination),
05253:                        CmsResourceFilter.IGNORE_EXPIRATION);
05254:                m_securityManager.checkPermissions(dbc, destinationFolder,
05255:                        CmsPermissionSet.ACCESS_WRITE, false,
05256:                        CmsResourceFilter.IGNORE_EXPIRATION);
05257:
05258:                if (source.isFolder()) {
05259:                    OpenCms.getMemoryMonitor().flushRoles();
05260:                    OpenCms.getMemoryMonitor().flushRoleLists();
05261:                }
05262:                m_vfsDriver.moveResource(dbc, dbc.getRequestContext()
05263:                        .currentProject().getUuid(), source, destination);
05264:
05265:                if (!internal) {
05266:                    CmsResourceState newState = CmsResource.STATE_CHANGED;
05267:                    if (source.getState().isNew()) {
05268:                        newState = CmsResource.STATE_NEW;
05269:                    } else if (source.getState().isDeleted()) {
05270:                        newState = CmsResource.STATE_DELETED;
05271:                    }
05272:                    source.setState(newState);
05273:                    // safe since this operation always uses the ids instead of the resource path
05274:                    m_vfsDriver.writeResourceState(dbc, dbc.currentProject(),
05275:                            source, CmsDriverManager.UPDATE_STRUCTURE_STATE,
05276:                            false);
05277:                }
05278:
05279:                CmsResource destRes = readResource(dbc, destination,
05280:                        CmsResourceFilter.ALL);
05281:                // move lock 
05282:                m_lockManager.moveResource(source.getRootPath(), destRes
05283:                        .getRootPath());
05284:
05285:                // flush all relevant caches
05286:                OpenCms.getMemoryMonitor().clearAccessControlListCache();
05287:                OpenCms.getMemoryMonitor().flushProperties();
05288:                OpenCms.getMemoryMonitor().flushPropertyLists();
05289:                OpenCms.getMemoryMonitor().flushProjectResources();
05290:
05291:                List resources = new ArrayList(4);
05292:                // source
05293:                resources.add(source);
05294:                try {
05295:                    resources.add(readFolder(dbc, CmsResource
05296:                            .getParentFolder(source.getRootPath()),
05297:                            CmsResourceFilter.ALL));
05298:                } catch (Exception e) {
05299:                    if (LOG.isDebugEnabled()) {
05300:                        LOG.debug(e);
05301:                    }
05302:                }
05303:                // destination
05304:                resources.add(destRes);
05305:                resources.add(destinationFolder);
05306:
05307:                // fire the events
05308:                OpenCms.fireCmsEvent(new CmsEvent(
05309:                        I_CmsEventListener.EVENT_RESOURCE_MOVED, Collections
05310:                                .singletonMap("resources", resources)));
05311:            }
05312:
05313:            /**
05314:             * Moves a resource to the "lost and found" folder.<p>
05315:             * 
05316:             * The method can also be used to check get the name of a resource
05317:             * in the "lost and found" folder only without actually moving the
05318:             * the resource. To do this, the <code>returnNameOnly</code> flag
05319:             * must be set to <code>true</code>.<p>
05320:             * 
05321:             * @param dbc the current database context
05322:             * @param resource the resource to apply this operation to
05323:             * @param returnNameOnly if <code>true</code>, only the name of the resource in the "lost and found" 
05324:             *        folder is returned, the move operation is not really performed
05325:             * 
05326:             * @return the name of the resource inside the "lost and found" folder
05327:             * 
05328:             * @throws CmsException if something goes wrong
05329:             * @throws CmsIllegalArgumentException if the <code>resourcename</code> argument is null or of length 0
05330:             * 
05331:             * @see CmsObject#moveToLostAndFound(String)
05332:             * @see CmsObject#getLostAndFoundName(String)
05333:             */
05334:            public String moveToLostAndFound(CmsDbContext dbc,
05335:                    CmsResource resource, boolean returnNameOnly)
05336:                    throws CmsException, CmsIllegalArgumentException {
05337:
05338:                String resourcename = dbc
05339:                        .removeSiteRoot(resource.getRootPath());
05340:
05341:                String siteRoot = dbc.getRequestContext().getSiteRoot();
05342:                dbc.getRequestContext().setSiteRoot("");
05343:                String destination = CmsDriverManager.LOST_AND_FOUND_FOLDER
05344:                        + resourcename;
05345:                // create the required folders if necessary
05346:                try {
05347:                    // collect all folders...
05348:                    String folderPath = CmsResource
05349:                            .getParentFolder(destination);
05350:                    folderPath = folderPath.substring(1,
05351:                            folderPath.length() - 1); // cut out leading and trailing '/'
05352:                    Iterator folders = CmsStringUtil.splitAsList(folderPath,
05353:                            '/').iterator();
05354:                    // ...now create them....
05355:                    folderPath = "/";
05356:                    while (folders.hasNext()) {
05357:                        folderPath += folders.next().toString() + "/";
05358:                        try {
05359:                            readFolder(dbc, folderPath,
05360:                                    CmsResourceFilter.IGNORE_EXPIRATION);
05361:                        } catch (Exception e1) {
05362:                            if (returnNameOnly) {
05363:                                // we can use the original name without risk, and we do not need to recreate the parent folders 
05364:                                break;
05365:                            }
05366:                            // the folder is not existing, so create it
05367:                            createResource(dbc, folderPath,
05368:                                    CmsResourceTypeFolder.RESOURCE_TYPE_ID,
05369:                                    null, Collections.EMPTY_LIST);
05370:                        }
05371:                    }
05372:                    // check if this resource name does already exist
05373:                    // if so add a postfix to the name
05374:                    String des = destination;
05375:                    int postfix = 1;
05376:                    boolean found = true;
05377:                    while (found) {
05378:                        try {
05379:                            // try to read the file.....
05380:                            found = true;
05381:                            readResource(dbc, des, CmsResourceFilter.ALL);
05382:                            // ....it's there, so add a postfix and try again
05383:                            String path = destination.substring(0, destination
05384:                                    .lastIndexOf('/') + 1);
05385:                            String filename = destination
05386:                                    .substring(
05387:                                            destination.lastIndexOf('/') + 1,
05388:                                            destination.length());
05389:
05390:                            des = path;
05391:
05392:                            if (filename.lastIndexOf('.') > 0) {
05393:                                des += filename.substring(0, filename
05394:                                        .lastIndexOf('.'));
05395:                            } else {
05396:                                des += filename;
05397:                            }
05398:                            des += "_" + postfix;
05399:                            if (filename.lastIndexOf('.') > 0) {
05400:                                des += filename.substring(filename
05401:                                        .lastIndexOf('.'), filename.length());
05402:                            }
05403:                            postfix++;
05404:                        } catch (CmsException e3) {
05405:                            // the file does not exist, so we can use this filename                               
05406:                            found = false;
05407:                        }
05408:                    }
05409:                    destination = des;
05410:
05411:                    if (!returnNameOnly) {
05412:                        // do not use the move semantic here! to prevent links pointing to the lost & found folder
05413:                        copyResource(dbc, resource, destination,
05414:                                CmsResource.COPY_AS_SIBLING);
05415:                        deleteResource(dbc, resource,
05416:                                CmsResource.DELETE_PRESERVE_SIBLINGS);
05417:                    }
05418:                } catch (CmsException e2) {
05419:                    throw e2;
05420:                } finally {
05421:                    // set the site root to the old value again
05422:                    dbc.getRequestContext().setSiteRoot(siteRoot);
05423:                }
05424:                return destination;
05425:            }
05426:
05427:            /**
05428:             * Gets a new driver instance.<p>
05429:             * 
05430:             * @param configurationManager the configuration manager
05431:             * @param driverName the driver name
05432:             * @param successiveDrivers the list of successive drivers
05433:             * 
05434:             * @return the driver object
05435:             * @throws CmsInitException if the selected driver could not be initialized
05436:             */
05437:            public Object newDriverInstance(
05438:                    CmsConfigurationManager configurationManager,
05439:                    String driverName, List successiveDrivers)
05440:                    throws CmsInitException {
05441:
05442:                Class driverClass = null;
05443:                I_CmsDriver driver = null;
05444:                CmsDbContext dbc = new CmsDbContext();
05445:
05446:                try {
05447:                    // try to get the class
05448:                    driverClass = Class.forName(driverName);
05449:                    if (CmsLog.INIT.isInfoEnabled()) {
05450:                        CmsLog.INIT.info(Messages.get().getBundle().key(
05451:                                Messages.INIT_DRIVER_START_1, driverName));
05452:                    }
05453:
05454:                    // try to create a instance
05455:                    driver = (I_CmsDriver) driverClass.newInstance();
05456:                    if (CmsLog.INIT.isInfoEnabled()) {
05457:                        CmsLog.INIT.info(Messages.get().getBundle()
05458:                                .key(Messages.INIT_DRIVER_INITIALIZING_1,
05459:                                        driverName));
05460:                    }
05461:
05462:                    // invoke the init-method of this access class
05463:                    driver.init(dbc, configurationManager, successiveDrivers,
05464:                            this );
05465:                    if (CmsLog.INIT.isInfoEnabled()) {
05466:                        CmsLog.INIT.info(Messages.get().getBundle().key(
05467:                                Messages.INIT_DRIVER_INIT_FINISHED_0));
05468:                    }
05469:
05470:                } catch (Throwable t) {
05471:                    CmsMessageContainer message = Messages.get().container(
05472:                            Messages.ERR_ERROR_INITIALIZING_DRIVER_1,
05473:                            driverName);
05474:                    if (LOG.isErrorEnabled()) {
05475:                        LOG.error(message.key(), t);
05476:                    }
05477:                    throw new CmsInitException(message, t);
05478:                }
05479:
05480:                return driver;
05481:            }
05482:
05483:            /**
05484:             * Method to create a new instance of a driver.<p>
05485:             * 
05486:             * @param configuration the configurations from the propertyfile
05487:             * @param driverName the class name of the driver
05488:             * @param driverPoolUrl the pool url for the driver
05489:             * @return an initialized instance of the driver
05490:             * @throws CmsException if something goes wrong
05491:             */
05492:            public Object newDriverInstance(ExtendedProperties configuration,
05493:                    String driverName, String driverPoolUrl)
05494:                    throws CmsException {
05495:
05496:                Class[] initParamClasses = { ExtendedProperties.class,
05497:                        String.class, CmsDriverManager.class };
05498:                Object[] initParams = { configuration, driverPoolUrl, this  };
05499:
05500:                Class driverClass = null;
05501:                Object driver = null;
05502:
05503:                try {
05504:                    // try to get the class
05505:                    driverClass = Class.forName(driverName);
05506:                    if (CmsLog.INIT.isInfoEnabled()) {
05507:                        CmsLog.INIT.info(Messages.get().getBundle().key(
05508:                                Messages.INIT_DRIVER_START_1, driverName));
05509:                    }
05510:
05511:                    // try to create a instance
05512:                    driver = driverClass.newInstance();
05513:                    if (CmsLog.INIT.isInfoEnabled()) {
05514:                        CmsLog.INIT.info(Messages.get().getBundle()
05515:                                .key(Messages.INIT_DRIVER_INITIALIZING_1,
05516:                                        driverName));
05517:                    }
05518:
05519:                    // invoke the init-method of this access class
05520:                    driver.getClass().getMethod("init", initParamClasses)
05521:                            .invoke(driver, initParams);
05522:                    if (CmsLog.INIT.isInfoEnabled()) {
05523:                        CmsLog.INIT.info(Messages.get().getBundle().key(
05524:                                Messages.INIT_DRIVER_INIT_FINISHED_1,
05525:                                driverPoolUrl));
05526:                    }
05527:
05528:                } catch (Exception exc) {
05529:
05530:                    CmsMessageContainer message = Messages.get().container(
05531:                            Messages.ERR_INIT_DRIVER_MANAGER_1);
05532:                    if (LOG.isFatalEnabled()) {
05533:                        LOG.fatal(message.key(), exc);
05534:                    }
05535:                    throw new CmsDbException(message, exc);
05536:
05537:                }
05538:
05539:                return driver;
05540:            }
05541:
05542:            /**
05543:             * Method to create a new instance of a pool.<p>
05544:             * 
05545:             * @param configuration the configurations from the propertyfile
05546:             * @param poolName the configuration name of the pool
05547:             * 
05548:             * @throws CmsInitException if the pools could not be initialized
05549:             */
05550:            public void newPoolInstance(Map configuration, String poolName)
05551:                    throws CmsInitException {
05552:
05553:                PoolingDriver driver;
05554:
05555:                try {
05556:                    driver = CmsDbPool.createDriverManagerConnectionPool(
05557:                            configuration, poolName);
05558:                } catch (Exception e) {
05559:
05560:                    CmsMessageContainer message = Messages.get().container(
05561:                            Messages.ERR_INIT_CONN_POOL_1, poolName);
05562:                    if (LOG.isErrorEnabled()) {
05563:                        LOG.error(message.key(), e);
05564:                    }
05565:                    throw new CmsInitException(message, e);
05566:                }
05567:
05568:                m_connectionPools.add(driver);
05569:            }
05570:
05571:            /**
05572:             * Publishes the given publish job.<p>
05573:             * 
05574:             * @param cms the cms context
05575:             * @param dbc the db context
05576:             * @param publishList the list of resources to publish
05577:             * @param report the report to write to
05578:             * 
05579:             * @throws CmsException if something goes wrong
05580:             */
05581:            public void publishJob(CmsObject cms, CmsDbContext dbc,
05582:                    CmsPublishList publishList, I_CmsReport report)
05583:                    throws CmsException {
05584:
05585:                try {
05586:                    // check state and lock
05587:                    List allResources = new ArrayList(publishList
05588:                            .getFolderList());
05589:                    allResources.addAll(publishList.getDeletedFolderList());
05590:                    allResources.addAll(publishList.getFileList());
05591:                    Iterator itResources = allResources.iterator();
05592:                    while (itResources.hasNext()) {
05593:                        CmsResource resource = (CmsResource) itResources.next();
05594:                        try {
05595:                            resource = readResource(dbc, resource
05596:                                    .getStructureId(), CmsResourceFilter.ALL);
05597:                        } catch (CmsVfsResourceNotFoundException e) {
05598:                            continue;
05599:                        }
05600:                        if (resource.getState().isUnchanged()) {
05601:                            // remove files that were published by a concurrent job
05602:                            if (LOG.isDebugEnabled()) {
05603:                                LOG
05604:                                        .debug(Messages
05605:                                                .get()
05606:                                                .getBundle()
05607:                                                .key(
05608:                                                        Messages.RPT_PUBLISH_REMOVED_RESOURCE_1,
05609:                                                        dbc
05610:                                                                .removeSiteRoot(resource
05611:                                                                        .getRootPath())));
05612:                            }
05613:                            publishList.remove(resource);
05614:                            unlockResource(dbc, resource, true, true);
05615:                            continue;
05616:                        }
05617:                        CmsLock lock = m_lockManager.getLock(dbc, resource,
05618:                                false);
05619:                        if (!lock.getSystemLock().isPublish()) {
05620:                            // remove files that are not locked for publishing
05621:                            if (LOG.isDebugEnabled()) {
05622:                                LOG
05623:                                        .debug(Messages
05624:                                                .get()
05625:                                                .getBundle()
05626:                                                .key(
05627:                                                        Messages.RPT_PUBLISH_REMOVED_RESOURCE_1,
05628:                                                        dbc
05629:                                                                .removeSiteRoot(resource
05630:                                                                        .getRootPath())));
05631:                            }
05632:                            publishList.remove(resource);
05633:                            continue;
05634:                        }
05635:                    }
05636:
05637:                    CmsProject onlineProject = readProject(dbc,
05638:                            CmsProject.ONLINE_PROJECT_ID);
05639:
05640:                    // clear the cache
05641:                    OpenCms.getMemoryMonitor().clearCache();
05642:
05643:                    int publishTag = getNextPublishTag(dbc);
05644:                    getProjectDriver().publishProject(dbc, report,
05645:                            onlineProject, publishList, publishTag);
05646:
05647:                    // iterate the initialized module action instances
05648:                    Iterator i = OpenCms.getModuleManager().getModuleNames()
05649:                            .iterator();
05650:                    while (i.hasNext()) {
05651:                        CmsModule module = OpenCms.getModuleManager()
05652:                                .getModule(i.next().toString());
05653:                        if ((module != null)
05654:                                && (module.getActionInstance() != null)) {
05655:                            module.getActionInstance().publishProject(cms,
05656:                                    publishList, publishTag, report);
05657:                        }
05658:                    }
05659:
05660:                    boolean temporaryProject = (cms.getRequestContext()
05661:                            .currentProject().getType() == CmsProject.PROJECT_TYPE_TEMPORARY);
05662:                    // the project was stored in the history tables for history
05663:                    // it will be deleted if the project_flag is PROJECT_TYPE_TEMPORARY
05664:                    if ((temporaryProject) && (!publishList.isDirectPublish())) {
05665:                        try {
05666:                            getProjectDriver().deleteProject(dbc,
05667:                                    dbc.currentProject());
05668:                        } catch (CmsException e) {
05669:                            LOG.error(Messages.get().getBundle().key(
05670:                                    Messages.LOG_DELETE_TEMP_PROJECT_FAILED_1,
05671:                                    cms.getRequestContext().currentProject()
05672:                                            .getName()));
05673:                        }
05674:                        // if project was temporary set context to online project
05675:                        cms.getRequestContext()
05676:                                .setCurrentProject(onlineProject);
05677:                    }
05678:                } finally {
05679:                    // clear the cache again
05680:                    OpenCms.getMemoryMonitor().clearCache();
05681:                }
05682:            }
05683:
05684:            /**
05685:             * Publishes the resources of a specified publish list.<p>
05686:             *
05687:             * @param cms the current request context
05688:             * @param dbc the current database context
05689:             * @param publishList a publish list
05690:             * @param report an instance of <code>{@link I_CmsReport}</code> to print messages
05691:             * 
05692:             * @throws CmsException if something goes wrong
05693:             * 
05694:             * @see #fillPublishList(CmsDbContext, CmsPublishList)
05695:             */
05696:            public synchronized void publishProject(CmsObject cms,
05697:                    CmsDbContext dbc, CmsPublishList publishList,
05698:                    I_CmsReport report) throws CmsException {
05699:
05700:                // check the parent folders
05701:                checkParentFolders(dbc, publishList);
05702:
05703:                try {
05704:                    // fire an event that a project is to be published
05705:                    Map eventData = new HashMap();
05706:                    eventData.put(I_CmsEventListener.KEY_REPORT, report);
05707:                    eventData.put(I_CmsEventListener.KEY_PUBLISHLIST,
05708:                            publishList);
05709:                    eventData.put(I_CmsEventListener.KEY_PROJECTID, dbc
05710:                            .currentProject().getUuid());
05711:                    eventData.put(I_CmsEventListener.KEY_DBCONTEXT, dbc);
05712:                    CmsEvent beforePublishEvent = new CmsEvent(
05713:                            I_CmsEventListener.EVENT_BEFORE_PUBLISH_PROJECT,
05714:                            eventData);
05715:                    OpenCms.fireCmsEvent(beforePublishEvent);
05716:                } catch (Throwable t) {
05717:                    report.addError(t);
05718:                    report.println(t);
05719:                }
05720:
05721:                // lock all resources with the special publish lock
05722:                Iterator itResources = new ArrayList(publishList
05723:                        .getAllResources()).iterator();
05724:                while (itResources.hasNext()) {
05725:                    CmsResource resource = (CmsResource) itResources.next();
05726:                    CmsLock lock = m_lockManager.getLock(dbc, resource, false);
05727:                    if (lock.getSystemLock().isUnlocked()
05728:                            && lock.isLockableBy(dbc.currentUser())) {
05729:                        if (getLock(dbc, resource).getEditionLock()
05730:                                .isNullLock()) {
05731:                            lockResource(dbc, resource, CmsLockType.PUBLISH);
05732:                        } else {
05733:                            changeLock(dbc, resource, CmsLockType.PUBLISH);
05734:                        }
05735:                    } else if (lock.getSystemLock().isPublish()) {
05736:                        if (LOG.isWarnEnabled()) {
05737:                            LOG
05738:                                    .warn(Messages
05739:                                            .get()
05740:                                            .getBundle()
05741:                                            .key(
05742:                                                    Messages.RPT_PUBLISH_REMOVED_RESOURCE_1,
05743:                                                    dbc.removeSiteRoot(resource
05744:                                                            .getRootPath())));
05745:                        }
05746:                        // remove files that are already waiting to be published
05747:                        publishList.remove(resource);
05748:                        continue;
05749:                    } else {
05750:                        // this is needed to fix TestPublishIsssues#testPublishScenarioE
05751:                        changeLock(dbc, resource, CmsLockType.PUBLISH);
05752:                    }
05753:                    // now re-check the lock state
05754:                    lock = m_lockManager.getLock(dbc, resource, false);
05755:                    if (!lock.getSystemLock().isPublish()) {
05756:                        if (report != null) {
05757:                            report
05758:                                    .println(
05759:                                            Messages
05760:                                                    .get()
05761:                                                    .container(
05762:                                                            Messages.RPT_PUBLISH_REMOVED_RESOURCE_1,
05763:                                                            dbc
05764:                                                                    .removeSiteRoot(resource
05765:                                                                            .getRootPath())),
05766:                                            I_CmsReport.FORMAT_WARNING);
05767:                        }
05768:                        if (LOG.isWarnEnabled()) {
05769:                            LOG
05770:                                    .warn(Messages
05771:                                            .get()
05772:                                            .getBundle()
05773:                                            .key(
05774:                                                    Messages.RPT_PUBLISH_REMOVED_RESOURCE_1,
05775:                                                    dbc.removeSiteRoot(resource
05776:                                                            .getRootPath())));
05777:                        }
05778:                        // remove files that could not be locked
05779:                        publishList.remove(resource);
05780:                    }
05781:                }
05782:
05783:                // enqueue the publish job
05784:                CmsException enqueueException = null;
05785:                try {
05786:                    m_publishEngine.enqueuePublishJob(cms, publishList, report);
05787:                } catch (CmsException exc) {
05788:                    enqueueException = exc;
05789:                }
05790:
05791:                // if an exception was raised, remove the publish locks
05792:                // and throw the exception again
05793:                if (enqueueException != null) {
05794:                    itResources = publishList.getAllResources().iterator();
05795:                    while (itResources.hasNext()) {
05796:                        CmsResource resource = (CmsResource) itResources.next();
05797:                        CmsLock lock = m_lockManager.getLock(dbc, resource,
05798:                                false);
05799:                        if (lock.getSystemLock().isPublish()
05800:                                && lock.getSystemLock().isOwnedInProjectBy(
05801:                                        cms.getRequestContext().currentUser(),
05802:                                        cms.getRequestContext()
05803:                                                .currentProject())) {
05804:                            unlockResource(dbc, resource, true, true);
05805:                        }
05806:                    }
05807:
05808:                    throw enqueueException;
05809:                }
05810:            }
05811:
05812:            /**
05813:             * Reads an access control entry from the cms.<p>
05814:             * 
05815:             * The access control entries of a resource are readable by everyone.
05816:             * 
05817:             * @param dbc the current database context
05818:             * @param resource the resource
05819:             * @param principal the id of a group or a user any other entity
05820:             * @return an access control entry that defines the permissions of the entity for the given resource
05821:             * @throws CmsException if something goes wrong
05822:             */
05823:            public CmsAccessControlEntry readAccessControlEntry(
05824:                    CmsDbContext dbc, CmsResource resource, CmsUUID principal)
05825:                    throws CmsException {
05826:
05827:                return m_userDriver.readAccessControlEntry(dbc, dbc
05828:                        .currentProject(), resource.getResourceId(), principal);
05829:            }
05830:
05831:            /**
05832:             * Reads all versions of the given resource.<br>
05833:             * 
05834:             * This method returns a list with the history of the given resource, i.e.
05835:             * the historical resource entries, independent of the project they were attached to.<br>
05836:             *
05837:             * The reading excludes the file content.<p>
05838:             *
05839:             * @param dbc the current database context
05840:             * @param resource the resource to read the history for
05841:             * 
05842:             * @return a list of file headers, as <code>{@link I_CmsHistoryResource}</code> objects
05843:             * 
05844:             * @throws CmsException if something goes wrong
05845:             */
05846:            public List readAllAvailableVersions(CmsDbContext dbc,
05847:                    CmsResource resource) throws CmsException {
05848:
05849:                // read the historical resources
05850:                List versions = m_historyDriver.readAllAvailableVersions(dbc,
05851:                        resource.getStructureId());
05852:                if ((versions.size() > OpenCms.getSystemInfo()
05853:                        .getHistoryVersions())
05854:                        && (OpenCms.getSystemInfo().getHistoryVersions() > -1)) {
05855:                    return versions.subList(0, OpenCms.getSystemInfo()
05856:                            .getHistoryVersions());
05857:                }
05858:                return versions;
05859:            }
05860:
05861:            /**
05862:             * Reads all property definitions for the given mapping type.<p>
05863:             *
05864:             * @param dbc the current database context
05865:             * 
05866:             * @return a list with the <code>{@link CmsPropertyDefinition}</code> objects (may be empty)
05867:             * 
05868:             * @throws CmsException if something goes wrong
05869:             */
05870:            public List readAllPropertyDefinitions(CmsDbContext dbc)
05871:                    throws CmsException {
05872:
05873:                List returnValue = m_vfsDriver.readPropertyDefinitions(dbc, dbc
05874:                        .currentProject().getUuid());
05875:                Collections.sort(returnValue);
05876:                return returnValue;
05877:            }
05878:
05879:            /**
05880:             * Returns the child resources of a resource, that is the resources
05881:             * contained in a folder.<p>
05882:             * 
05883:             * With the parameters <code>getFolders</code> and <code>getFiles</code>
05884:             * you can control what type of resources you want in the result list:
05885:             * files, folders, or both.<p>
05886:             * 
05887:             * This method is mainly used by the workplace explorer.<p> 
05888:             * 
05889:             * @param dbc the current database context
05890:             * @param resource the resource to return the child resources for
05891:             * @param filter the resource filter to use
05892:             * @param getFolders if true the child folders are included in the result
05893:             * @param getFiles if true the child files are included in the result
05894:             * @param checkPermissions if the resources should be filtered with the current user permissions
05895:             * 
05896:             * @return a list of all child resources
05897:             * 
05898:             * @throws CmsException if something goes wrong
05899:             */
05900:            public List readChildResources(CmsDbContext dbc,
05901:                    CmsResource resource, CmsResourceFilter filter,
05902:                    boolean getFolders, boolean getFiles,
05903:                    boolean checkPermissions) throws CmsException {
05904:
05905:                // try to get the sub resources from the cache
05906:                String cacheKey = getCacheKey(new String[] {
05907:                        dbc.currentUser().getName(),
05908:                        getFolders ? (getFiles ? CmsCacheKey.CACHE_KEY_SUBALL
05909:                                : CmsCacheKey.CACHE_KEY_SUBFOLDERS)
05910:                                : CmsCacheKey.CACHE_KEY_SUBFILES,
05911:                        checkPermissions ? "+" : "-", filter.getCacheId(),
05912:                        resource.getRootPath() }, dbc.currentProject());
05913:
05914:                List resourceList = OpenCms.getMemoryMonitor()
05915:                        .getCachedResourceList(cacheKey);
05916:                if (resourceList == null) {
05917:                    // read the result form the database
05918:                    resourceList = m_vfsDriver.readChildResources(dbc, dbc
05919:                            .currentProject(), resource, getFolders, getFiles);
05920:
05921:                    if (checkPermissions) {
05922:                        // apply the permission filter
05923:                        resourceList = filterPermissions(dbc, resourceList,
05924:                                filter);
05925:                    }
05926:                    // cache the sub resources
05927:                    OpenCms.getMemoryMonitor().cacheResourceList(cacheKey,
05928:                            resourceList);
05929:                }
05930:
05931:                // we must always apply the result filter and update the context dates
05932:                return updateContextDates(dbc, resourceList, filter);
05933:            }
05934:
05935:            /**
05936:             * Returns the default file for the given folder.<p>
05937:             * 
05938:             * If the given resource is a file, then this file is returned.<p>
05939:             * 
05940:             * Otherwise, in case of a folder:<br> 
05941:             * <ol>
05942:             *   <li>the {@link CmsPropertyDefinition#PROPERTY_DEFAULT_FILE} is checked, and
05943:             *   <li>if still no file could be found, the configured default files in the 
05944:             *       <code>opencms-vfs.xml</code> configuration are iterated until a match is 
05945:             *       found, and
05946:             *   <li>if still no file could be found, <code>null</code> is retuned
05947:             * </ol>
05948:             * 
05949:             * @param dbc the database context
05950:             * @param resource the folder to get the default file for
05951:             * 
05952:             * @return the default file for the given folder
05953:             * 
05954:             * @see CmsObject#readDefaultFile(String)
05955:             * @see CmsDriverManager#readDefaultFile(CmsDbContext, CmsResource)
05956:             */
05957:            public CmsResource readDefaultFile(CmsDbContext dbc,
05958:                    CmsResource resource) {
05959:
05960:                // resource exists, lets check if we have a file or a folder
05961:                if (resource.isFolder()) {
05962:                    // the resource is a folder, check if PROPERTY_DEFAULT_FILE is set on folder
05963:                    try {
05964:                        String defaultFileName = readPropertyObject(dbc,
05965:                                resource,
05966:                                CmsPropertyDefinition.PROPERTY_DEFAULT_FILE,
05967:                                false).getValue();
05968:                        if (defaultFileName != null) {
05969:                            // property was set, so look up this file first
05970:                            String folderName = CmsResource
05971:                                    .getFolderPath(resource.getRootPath());
05972:                            resource = readResource(dbc, folderName
05973:                                    + defaultFileName,
05974:                                    CmsResourceFilter.DEFAULT);
05975:                        }
05976:                    } catch (CmsException e) {
05977:                        // ignore all other exceptions and continue the lookup process
05978:                        if (LOG.isDebugEnabled()) {
05979:                            LOG.debug(e.getLocalizedMessage(), e);
05980:                        }
05981:                    }
05982:                    if (resource.isFolder()) {
05983:                        String folderName = CmsResource.getFolderPath(resource
05984:                                .getRootPath());
05985:                        // resource is (still) a folder, check default files specified in configuration
05986:                        Iterator it = OpenCms.getDefaultFiles().iterator();
05987:                        while (it.hasNext()) {
05988:                            String tmpResourceName = folderName
05989:                                    + it.next().toString();
05990:                            try {
05991:                                resource = readResource(dbc, tmpResourceName,
05992:                                        CmsResourceFilter.DEFAULT);
05993:                                // no exception? So we have found the default file
05994:                                // stop looking for default files   
05995:                                break;
05996:                            } catch (CmsException e) {
05997:                                // ignore all other exceptions and continue the lookup process
05998:                                if (LOG.isDebugEnabled()) {
05999:                                    LOG.debug(e.getLocalizedMessage(), e);
06000:                                }
06001:                            }
06002:                        }
06003:                    }
06004:                }
06005:                if (resource.isFolder()) {
06006:                    // we only want files as a result for further processing
06007:                    resource = null;
06008:                }
06009:                return resource;
06010:            }
06011:
06012:            /**
06013:             * Reads all deleted (historical) resources below the given path, 
06014:             * including the full tree below the path, if required.<p>
06015:             * 
06016:             * @param dbc the current db context
06017:             * @param resource the parent resource to read the resources from
06018:             * @param readTree <code>true</code> to read all subresources
06019:             * @param isVfsManager <code>true</code> if the current user has the vfs manager role
06020:             * 
06021:             * @return a list of <code>{@link I_CmsHistoryResource}</code> objects
06022:             * 
06023:             * @throws CmsException if something goes wrong
06024:             * 
06025:             * @see CmsObject#readResource(CmsUUID, int)
06026:             * @see CmsObject#readResources(String, CmsResourceFilter, boolean)
06027:             * @see CmsObject#readDeletedResources(String, boolean)
06028:             */
06029:            public List readDeletedResources(CmsDbContext dbc,
06030:                    CmsResource resource, boolean readTree, boolean isVfsManager)
06031:                    throws CmsException {
06032:
06033:                Set result = new HashSet();
06034:                List deletedResources = m_historyDriver.readDeletedResources(
06035:                        dbc, resource.getStructureId(), isVfsManager ? null
06036:                                : dbc.currentUser().getId());
06037:                result.addAll(deletedResources);
06038:                List newResult = new ArrayList(result.size());
06039:                Iterator it = result.iterator();
06040:                while (it.hasNext()) {
06041:                    I_CmsHistoryResource histRes = (I_CmsHistoryResource) it
06042:                            .next();
06043:                    // adjust the paths
06044:                    try {
06045:                        if (!getVfsDriver().validateStructureIdExists(dbc,
06046:                                dbc.currentProject().getUuid(),
06047:                                histRes.getStructureId())) {
06048:                            // adjust the path in case of deleted files
06049:                            String resourcePath = histRes.getRootPath();
06050:                            String resName = CmsResource.getName(resourcePath);
06051:                            String path = CmsResource
06052:                                    .getParentFolder(resourcePath);
06053:
06054:                            CmsUUID parentId = histRes.getParentId();
06055:                            try {
06056:                                // first look for the path through the parent id
06057:                                path = readResource(dbc, parentId,
06058:                                        CmsResourceFilter.IGNORE_EXPIRATION)
06059:                                        .getRootPath();
06060:                            } catch (CmsDataAccessException e) {
06061:                                // if the resource with the parent id is not found, try to get a new parent id with the path
06062:                                try {
06063:                                    parentId = readResource(dbc, path,
06064:                                            CmsResourceFilter.IGNORE_EXPIRATION)
06065:                                            .getStructureId();
06066:                                } catch (CmsDataAccessException e1) {
06067:                                    // ignore, the parent folder has been completely deleted
06068:                                }
06069:                            }
06070:                            resourcePath = path + resName;
06071:
06072:                            boolean isFolder = resourcePath.endsWith("/");
06073:                            if (isFolder) {
06074:                                newResult.add(new CmsHistoryFolder(histRes
06075:                                        .getPublishTag(), histRes
06076:                                        .getStructureId(), histRes
06077:                                        .getResourceId(), resourcePath, histRes
06078:                                        .getTypeId(), histRes.getFlags(),
06079:                                        histRes.getProjectLastModified(),
06080:                                        histRes.getState(), histRes
06081:                                                .getDateCreated(), histRes
06082:                                                .getUserCreated(), histRes
06083:                                                .getDateLastModified(), histRes
06084:                                                .getUserLastModified(), histRes
06085:                                                .getDateReleased(), histRes
06086:                                                .getDateExpired(), histRes
06087:                                                .getVersion(), parentId,
06088:                                        histRes.getResourceVersion(), histRes
06089:                                                .getStructureVersion()));
06090:                            } else {
06091:                                newResult.add(new CmsHistoryFile(histRes
06092:                                        .getPublishTag(), histRes
06093:                                        .getStructureId(), histRes
06094:                                        .getResourceId(), resourcePath, histRes
06095:                                        .getTypeId(), histRes.getFlags(),
06096:                                        histRes.getProjectLastModified(),
06097:                                        histRes.getState(), histRes
06098:                                                .getDateCreated(), histRes
06099:                                                .getUserCreated(), histRes
06100:                                                .getDateLastModified(), histRes
06101:                                                .getUserLastModified(), histRes
06102:                                                .getDateReleased(), histRes
06103:                                                .getDateExpired(), histRes
06104:                                                .getLength(), histRes
06105:                                                .getDateContent(), histRes
06106:                                                .getVersion(), parentId, null,
06107:                                        histRes.getResourceVersion(), histRes
06108:                                                .getStructureVersion()));
06109:                            }
06110:                        } else {
06111:                            newResult.add(histRes);
06112:                        }
06113:                    } catch (CmsDataAccessException e) {
06114:                        // should never happen
06115:                        if (LOG.isErrorEnabled()) {
06116:                            LOG.error(e.getLocalizedMessage(), e);
06117:                        }
06118:                    }
06119:                }
06120:                if (readTree) {
06121:                    Iterator itDeleted = deletedResources.iterator();
06122:                    while (itDeleted.hasNext()) {
06123:                        I_CmsHistoryResource delResource = (I_CmsHistoryResource) itDeleted
06124:                                .next();
06125:                        if (delResource.isFolder()) {
06126:                            newResult.addAll(readDeletedResources(dbc,
06127:                                    (CmsFolder) delResource, readTree,
06128:                                    isVfsManager));
06129:                        }
06130:                    }
06131:                    try {
06132:                        readResource(dbc, resource.getStructureId(),
06133:                                CmsResourceFilter.ALL);
06134:                        // resource exists, so recurse
06135:                        Iterator itResources = readResources(dbc, resource,
06136:                                CmsResourceFilter.ALL.addRequireFolder(),
06137:                                readTree).iterator();
06138:                        while (itResources.hasNext()) {
06139:                            CmsResource subResource = (CmsResource) itResources
06140:                                    .next();
06141:                            if (subResource.isFolder()) {
06142:                                newResult.addAll(readDeletedResources(dbc,
06143:                                        subResource, readTree, isVfsManager));
06144:                            }
06145:                        }
06146:                    } catch (Exception e) {
06147:                        // resource does not exists
06148:                        if (LOG.isDebugEnabled()) {
06149:                            LOG.debug(e.getLocalizedMessage(), e);
06150:                        }
06151:                    }
06152:                }
06153:                Collections.sort(newResult, CmsResource.COMPARE_ROOT_PATH);
06154:                return newResult;
06155:            }
06156:
06157:            /**
06158:             * Reads a file resource (including it's binary content) from the VFS,
06159:             * using the specified resource filter.<p>
06160:             * 
06161:             * In case you do not need the file content, 
06162:             * use <code>{@link #readResource(CmsDbContext, String, CmsResourceFilter)}</code> instead.<p>
06163:             * 
06164:             * The specified filter controls what kind of resources should be "found" 
06165:             * during the read operation. This will depend on the application. For example, 
06166:             * using <code>{@link CmsResourceFilter#DEFAULT}</code> will only return currently
06167:             * "valid" resources, while using <code>{@link CmsResourceFilter#IGNORE_EXPIRATION}</code>
06168:             * will ignore the date release / date expired information of the resource.<p>
06169:             * 
06170:             * @param dbc the current database context
06171:             * @param resource the base file resource (without content)
06172:             * @return the file read from the VFS
06173:             * @throws CmsException if operation was not successful
06174:             */
06175:            public CmsFile readFile(CmsDbContext dbc, CmsResource resource)
06176:                    throws CmsException {
06177:
06178:                if (resource.isFolder()) {
06179:                    throw new CmsVfsResourceNotFoundException(Messages.get()
06180:                            .container(Messages.ERR_ACCESS_FOLDER_AS_FILE_1,
06181:                                    dbc.removeSiteRoot(resource.getRootPath())));
06182:                }
06183:
06184:                CmsUUID projectId = dbc.currentProject().getUuid();
06185:                CmsFile file = null;
06186:                if (resource instanceof  I_CmsHistoryResource) {
06187:                    file = new CmsHistoryFile((I_CmsHistoryResource) resource);
06188:                    file.setContents(m_historyDriver.readContent(dbc, resource
06189:                            .getResourceId(), ((I_CmsHistoryResource) resource)
06190:                            .getPublishTag()));
06191:                } else {
06192:                    file = new CmsFile(resource);
06193:                    file.setContents(m_vfsDriver.readContent(dbc, projectId,
06194:                            resource.getResourceId()));
06195:                }
06196:                return file;
06197:            }
06198:
06199:            /**
06200:             * Reads a folder from the VFS,
06201:             * using the specified resource filter.<p>
06202:             * 
06203:             * @param dbc the current database context
06204:             * @param resourcename the name of the folder to read (full path)
06205:             * @param filter the resource filter to use while reading
06206:             *
06207:             * @return the folder that was read
06208:             *
06209:             * @throws CmsDataAccessException if something goes wrong
06210:             *
06211:             * @see #readResource(CmsDbContext, String, CmsResourceFilter)
06212:             * @see CmsObject#readFolder(String)
06213:             * @see CmsObject#readFolder(String, CmsResourceFilter)
06214:             */
06215:            public CmsFolder readFolder(CmsDbContext dbc, String resourcename,
06216:                    CmsResourceFilter filter) throws CmsDataAccessException {
06217:
06218:                CmsResource resource = readResource(dbc, resourcename, filter);
06219:
06220:                return convertResourceToFolder(resource);
06221:            }
06222:
06223:            /**
06224:             * Reads the group of a project.<p>
06225:             *
06226:             * @param dbc the current database context
06227:             * @param project the project to read from
06228:             * 
06229:             * @return the group of a resource
06230:             */
06231:            public CmsGroup readGroup(CmsDbContext dbc, CmsProject project) {
06232:
06233:                try {
06234:                    return readGroup(dbc, project.getGroupId());
06235:                } catch (CmsException exc) {
06236:                    return new CmsGroup(CmsUUID.getNullUUID(), CmsUUID
06237:                            .getNullUUID(), project.getGroupId() + "",
06238:                            "deleted group", 0);
06239:                }
06240:            }
06241:
06242:            /**
06243:             * Reads a group based on its id.<p>
06244:             *
06245:             * @param dbc the current database context
06246:             * @param groupId the id of the group that is to be read
06247:             * 
06248:             * @return the requested group
06249:             * 
06250:             * @throws CmsException if operation was not successful
06251:             */
06252:            public CmsGroup readGroup(CmsDbContext dbc, CmsUUID groupId)
06253:                    throws CmsException {
06254:
06255:                CmsGroup group = null;
06256:                // try to read group from cache
06257:                group = OpenCms.getMemoryMonitor().getCachedGroup(
06258:                        groupId.toString());
06259:                if (group == null) {
06260:                    group = m_userDriver.readGroup(dbc, groupId);
06261:                    OpenCms.getMemoryMonitor().cacheGroup(group);
06262:                }
06263:                return group;
06264:            }
06265:
06266:            /**
06267:             * Reads a group based on its name.<p>
06268:             * 
06269:             * @param dbc the current database context
06270:             * @param groupname the name of the group that is to be read
06271:             *
06272:             * @return the requested group
06273:             * 
06274:             * @throws CmsDataAccessException if operation was not successful
06275:             */
06276:            public CmsGroup readGroup(CmsDbContext dbc, String groupname)
06277:                    throws CmsDataAccessException {
06278:
06279:                CmsGroup group = null;
06280:                // try to read group from cache
06281:                group = OpenCms.getMemoryMonitor().getCachedGroup(groupname);
06282:                if (group == null) {
06283:                    group = m_userDriver.readGroup(dbc, groupname);
06284:                    OpenCms.getMemoryMonitor().cacheGroup(group);
06285:                }
06286:                return group;
06287:            }
06288:
06289:            /**
06290:             * Reads a principal (an user or group) from the historical archive based on its ID.<p>
06291:             * 
06292:             * @param dbc the current database context
06293:             * @param principalId the id of the principal to read
06294:             * 
06295:             * @return the historical principal entry with the given id
06296:             * 
06297:             * @throws CmsException if something goes wrong, ie. {@link CmsDbEntryNotFoundException}
06298:             * 
06299:             * @see CmsObject#readUser(CmsUUID)
06300:             * @see CmsObject#readGroup(CmsUUID)
06301:             * @see CmsObject#readHistoryPrincipal(CmsUUID)
06302:             */
06303:            public CmsHistoryPrincipal readHistoricalPrincipal(
06304:                    CmsDbContext dbc, CmsUUID principalId) throws CmsException {
06305:
06306:                return m_historyDriver.readPrincipal(dbc, principalId);
06307:            }
06308:
06309:            /**
06310:             * Returns a historical project entry.<p>
06311:             *
06312:             * @param dbc the current database context
06313:             * @param publishTag the publish tag of the project
06314:             * 
06315:             * @return the requested historical project entry
06316:             * 
06317:             * @throws CmsException if something goes wrong
06318:             */
06319:            public CmsHistoryProject readHistoryProject(CmsDbContext dbc,
06320:                    int publishTag) throws CmsException {
06321:
06322:                return m_historyDriver.readProject(dbc, publishTag);
06323:            }
06324:
06325:            /**
06326:             * Reads the list of all <code>{@link CmsProperty}</code> objects that belongs to the given historical resource.<p>
06327:             * 
06328:             * @param dbc the current database context
06329:             * @param historyResource the historical resource to read the properties for
06330:             * 
06331:             * @return the list of <code>{@link CmsProperty}</code> objects
06332:             * 
06333:             * @throws CmsException if something goes wrong
06334:             */
06335:            public List readHistoryPropertyObjects(CmsDbContext dbc,
06336:                    I_CmsHistoryResource historyResource) throws CmsException {
06337:
06338:                return m_historyDriver.readProperties(dbc, historyResource);
06339:            }
06340:
06341:            /**
06342:             * Reads the locks that were saved to the database in the previous run of OpenCms.<p>
06343:             * 
06344:             * @param dbc the current database context
06345:             * 
06346:             * @throws CmsException if something goes wrong
06347:             */
06348:            public void readLocks(CmsDbContext dbc) throws CmsException {
06349:
06350:                m_lockManager.readLocks(dbc);
06351:            }
06352:
06353:            /**
06354:             * Reads the manager group of a project.<p>
06355:             *
06356:             * @param dbc the current database context
06357:             * @param project the project to read from
06358:             * 
06359:             * @return the group of a resource
06360:             */
06361:            public CmsGroup readManagerGroup(CmsDbContext dbc,
06362:                    CmsProject project) {
06363:
06364:                try {
06365:                    return readGroup(dbc, project.getManagerGroupId());
06366:                } catch (CmsException exc) {
06367:                    // the group does not exist any more - return a dummy-group
06368:                    return new CmsGroup(CmsUUID.getNullUUID(), CmsUUID
06369:                            .getNullUUID(), project.getManagerGroupId() + "",
06370:                            "deleted group", 0);
06371:                }
06372:            }
06373:
06374:            /**
06375:             * Reads an organizational Unit based on its fully qualified name.<p>
06376:             *
06377:             * @param dbc the current db context
06378:             * @param ouFqn the fully qualified name of the organizational Unit to be read
06379:             * 
06380:             * @return the organizational Unit that with the provided fully qualified name
06381:             * 
06382:             * @throws CmsException if something goes wrong
06383:             */
06384:            public CmsOrganizationalUnit readOrganizationalUnit(
06385:                    CmsDbContext dbc, String ouFqn) throws CmsException {
06386:
06387:                CmsOrganizationalUnit organizationalUnit = null;
06388:                // try to read organizational unit from cache
06389:                organizationalUnit = OpenCms.getMemoryMonitor()
06390:                        .getCachedOrgUnit(ouFqn);
06391:                if (organizationalUnit == null) {
06392:                    organizationalUnit = m_userDriver.readOrganizationalUnit(
06393:                            dbc, ouFqn);
06394:                    OpenCms.getMemoryMonitor().cacheOrgUnit(organizationalUnit);
06395:                }
06396:                return organizationalUnit;
06397:            }
06398:
06399:            /**
06400:             * Reads the owner of a project.<p>
06401:             *
06402:             * @param dbc the current database context
06403:             * @param project the project to get the owner from
06404:             * 
06405:             * @return the owner of a resource
06406:             * @throws CmsException if something goes wrong
06407:             */
06408:            public CmsUser readOwner(CmsDbContext dbc, CmsProject project)
06409:                    throws CmsException {
06410:
06411:                return readUser(dbc, project.getOwnerId());
06412:            }
06413:
06414:            /**
06415:             * Builds a list of resources for a given path.<p>
06416:             * 
06417:             * @param dbc the current database context
06418:             * @param projectId the project to lookup the resource
06419:             * @param path the requested path
06420:             * @param filter a filter object (only "includeDeleted" information is used!)
06421:             * 
06422:             * @return list of <code>{@link CmsResource}</code>s
06423:             * 
06424:             * @throws CmsException if something goes wrong
06425:             */
06426:            public List readPath(CmsDbContext dbc, CmsUUID projectId,
06427:                    String path, CmsResourceFilter filter) throws CmsException {
06428:
06429:                // # of folders in the path
06430:                int folderCount = 0;
06431:                // true if the path doesn't end with a folder
06432:                boolean lastResourceIsFile = false;
06433:                // holds the CmsResource instances in the path
06434:                List pathList = null;
06435:                // the current path token
06436:                String currentResourceName = null;
06437:                // the current resource
06438:                CmsResource currentResource = null;
06439:                // this is a comment. i love comments!
06440:                int i = 0, count = 0;
06441:                // key to cache the resources
06442:                String cacheKey = null;
06443:
06444:                // splits the path into folder and filename tokens
06445:                List tokens = CmsStringUtil.splitAsList(path, '/');
06446:
06447:                // the root folder is no token in the path but a resource which has to be added to the path
06448:                count = tokens.size() + 1;
06449:                pathList = new ArrayList(count);
06450:
06451:                folderCount = count;
06452:                if (!path.endsWith("/")) {
06453:                    folderCount--;
06454:                    lastResourceIsFile = true;
06455:                }
06456:
06457:                // read the root folder, coz it's ID is required to read any sub-resources
06458:                currentResourceName = "/";
06459:                StringBuffer currentPath = new StringBuffer(64);
06460:                currentPath.append('/');
06461:
06462:                String cp = currentPath.toString();
06463:                cacheKey = getCacheKey(null, false, projectId, cp);
06464:                currentResource = OpenCms.getMemoryMonitor().getCachedResource(
06465:                        cacheKey);
06466:                if (currentResource == null) {
06467:                    currentResource = m_vfsDriver
06468:                            .readFolder(dbc, projectId, cp);
06469:                    OpenCms.getMemoryMonitor().cacheResource(cacheKey,
06470:                            currentResource);
06471:                }
06472:
06473:                pathList.add(0, currentResource);
06474:
06475:                if (count == 1) {
06476:                    // the root folder was requested- no further operations required
06477:                    return pathList;
06478:                }
06479:
06480:                Iterator it = tokens.iterator();
06481:                currentResourceName = (String) it.next();
06482:
06483:                // read the folder resources in the path /a/b/c/
06484:                for (i = 1; i < folderCount; i++) {
06485:                    currentPath.append(currentResourceName);
06486:                    currentPath.append('/');
06487:                    // read the folder
06488:                    cp = currentPath.toString();
06489:                    cacheKey = getCacheKey(null, false, projectId, cp);
06490:                    currentResource = OpenCms.getMemoryMonitor()
06491:                            .getCachedResource(cacheKey);
06492:                    if (currentResource == null) {
06493:                        currentResource = m_vfsDriver.readFolder(dbc,
06494:                                projectId, cp);
06495:                        OpenCms.getMemoryMonitor().cacheResource(cacheKey,
06496:                                currentResource);
06497:                    }
06498:
06499:                    pathList.add(i, currentResource);
06500:
06501:                    if (i < folderCount - 1) {
06502:                        currentResourceName = (String) it.next();
06503:                    }
06504:                }
06505:
06506:                // read the (optional) last file resource in the path /x.html
06507:                if (lastResourceIsFile) {
06508:                    if (it.hasNext()) {
06509:                        // this will only be false if a resource in the 
06510:                        // top level root folder (e.g. "/index.html") was requested
06511:                        currentResourceName = (String) it.next();
06512:                    }
06513:                    currentPath.append(currentResourceName);
06514:
06515:                    // read the file
06516:                    cp = currentPath.toString();
06517:                    cacheKey = getCacheKey(null, false, projectId, cp);
06518:                    currentResource = OpenCms.getMemoryMonitor()
06519:                            .getCachedResource(cacheKey);
06520:                    if (currentResource == null) {
06521:                        currentResource = m_vfsDriver.readResource(dbc,
06522:                                projectId, cp, filter.includeDeleted());
06523:                        OpenCms.getMemoryMonitor().cacheResource(cacheKey,
06524:                                currentResource);
06525:                    }
06526:
06527:                    pathList.add(i, currentResource);
06528:                }
06529:
06530:                return pathList;
06531:            }
06532:
06533:            /**
06534:             * Reads a project given the projects id.<p>
06535:             *
06536:             * @param dbc the current database context
06537:             * @param id the id of the project
06538:             * 
06539:             * @return the project read
06540:             * 
06541:             * @throws CmsDataAccessException if something goes wrong
06542:             */
06543:            public CmsProject readProject(CmsDbContext dbc, CmsUUID id)
06544:                    throws CmsDataAccessException {
06545:
06546:                CmsProject project = null;
06547:                project = OpenCms.getMemoryMonitor().getCachedProject(
06548:                        id.toString());
06549:                if (project == null) {
06550:                    project = m_projectDriver.readProject(dbc, id);
06551:                    OpenCms.getMemoryMonitor().cacheProject(project);
06552:                }
06553:                return project;
06554:            }
06555:
06556:            /**
06557:             * Reads a project.<p>
06558:             *
06559:             * Important: Since a project name can be used multiple times, this is NOT the most efficient 
06560:             * way to read the project. This is only a convenience for front end developing.
06561:             * Reading a project by name will return the first project with that name. 
06562:             * All core classes must use the id version {@link #readProject(CmsDbContext, CmsUUID)} to ensure the right project is read.<p>
06563:             * 
06564:             * @param dbc the current database context
06565:             * @param name the name of the project
06566:             * 
06567:             * @return the project read
06568:             * 
06569:             * @throws CmsException if something goes wrong
06570:             */
06571:            public CmsProject readProject(CmsDbContext dbc, String name)
06572:                    throws CmsException {
06573:
06574:                CmsProject project = null;
06575:                project = OpenCms.getMemoryMonitor().getCachedProject(name);
06576:                if (project == null) {
06577:                    project = m_projectDriver.readProject(dbc, name);
06578:                    OpenCms.getMemoryMonitor().cacheProject(project);
06579:                }
06580:                return project;
06581:            }
06582:
06583:            /**
06584:             * Returns the list of all resource names that define the "view" of the given project.<p>
06585:             *
06586:             * @param dbc the current database context
06587:             * @param project the project to get the project resources for
06588:             * 
06589:             * @return the list of all resources, as <code>{@link String}</code> objects 
06590:             *              that define the "view" of the given project.
06591:             * 
06592:             * @throws CmsException if something goes wrong
06593:             */
06594:            public List readProjectResources(CmsDbContext dbc,
06595:                    CmsProject project) throws CmsException {
06596:
06597:                return m_projectDriver.readProjectResources(dbc, project);
06598:            }
06599:
06600:            /**
06601:             * Reads all resources of a project that match a given state from the VFS.<p>
06602:             * 
06603:             * Possible values for the <code>state</code> parameter are:<br>
06604:             * <ul>
06605:             * <li><code>{@link CmsResource#STATE_CHANGED}</code>: Read all "changed" resources in the project</li>
06606:             * <li><code>{@link CmsResource#STATE_NEW}</code>: Read all "new" resources in the project</li>
06607:             * <li><code>{@link CmsResource#STATE_DELETED}</code>: Read all "deleted" resources in the project</li>
06608:             * <li><code>{@link CmsResource#STATE_KEEP}</code>: Read all resources either "changed", "new" or "deleted" in the project</li>
06609:             * </ul><p>
06610:             * 
06611:             * @param dbc the current database context
06612:             * @param projectId the id of the project to read the file resources for
06613:             * @param state the resource state to match 
06614:             *
06615:             * @return a list of <code>{@link CmsResource}</code> objects matching the filter criteria
06616:             * 
06617:             * @throws CmsException if something goes wrong
06618:             * 
06619:             * @see CmsObject#readProjectView(CmsUUID, CmsResourceState)
06620:             */
06621:            public List readProjectView(CmsDbContext dbc, CmsUUID projectId,
06622:                    CmsResourceState state) throws CmsException {
06623:
06624:                List resources;
06625:                if (state.isNew() || state.isChanged() || state.isDeleted()) {
06626:                    // get all resources form the database that match the selected state
06627:                    resources = m_vfsDriver.readResources(dbc, projectId,
06628:                            state, CmsDriverManager.READMODE_MATCHSTATE);
06629:                } else {
06630:                    // get all resources form the database that are somehow changed (i.e. not unchanged)
06631:                    resources = m_vfsDriver.readResources(dbc, projectId,
06632:                            CmsResource.STATE_UNCHANGED,
06633:                            CmsDriverManager.READMODE_UNMATCHSTATE);
06634:                }
06635:
06636:                // filter the permissions
06637:                List result = filterPermissions(dbc, resources,
06638:                        CmsResourceFilter.ALL);
06639:                // sort the result
06640:                Collections.sort(result);
06641:                // set the full resource names
06642:                return updateContextDates(dbc, result);
06643:            }
06644:
06645:            /**
06646:             * Reads a property definition.<p>
06647:             *
06648:             * If no property definition with the given name is found, 
06649:             * <code>null</code> is returned.<p>
06650:             * 
06651:             * @param dbc the current database context
06652:             * @param name the name of the property definition to read
06653:             *
06654:             * @return the property definition that was read, 
06655:             *          or <code>null</code> if there is no property definition with the given name.
06656:             * 
06657:             * @throws CmsException if something goes wrong
06658:             */
06659:            public CmsPropertyDefinition readPropertyDefinition(
06660:                    CmsDbContext dbc, String name) throws CmsException {
06661:
06662:                return m_vfsDriver.readPropertyDefinition(dbc, name, dbc
06663:                        .currentProject().getUuid());
06664:            }
06665:
06666:            /**
06667:             * Reads a property object from a resource specified by a property name.<p>
06668:             * 
06669:             * Returns <code>{@link CmsProperty#getNullProperty()}</code> if the property is not found.<p>
06670:             * 
06671:             * @param dbc the current database context
06672:             * @param resource the resource where the property is read from
06673:             * @param key the property key name
06674:             * @param search if <code>true</code>, the property is searched on all parent folders of the resource. 
06675:             *      if it's not found attached directly to the resource.
06676:             * 
06677:             * @return the required property, or <code>{@link CmsProperty#getNullProperty()}</code> if the property was not found
06678:             * 
06679:             * @throws CmsException if something goes wrong
06680:             */
06681:            public CmsProperty readPropertyObject(CmsDbContext dbc,
06682:                    CmsResource resource, String key, boolean search)
06683:                    throws CmsException {
06684:
06685:                // check if we have the result already cached
06686:                String cacheKey = getCacheKey(key, search, dbc.currentProject()
06687:                        .getUuid(), resource.getRootPath());
06688:                CmsProperty value = OpenCms.getMemoryMonitor()
06689:                        .getCachedProperty(cacheKey);
06690:
06691:                if (value == null) {
06692:                    // check if the map of all properties for this resource is already cached
06693:                    String cacheKey2 = getCacheKey(CACHE_ALL_PROPERTIES,
06694:                            search, dbc.currentProject().getUuid(), resource
06695:                                    .getRootPath());
06696:
06697:                    List allProperties = OpenCms.getMemoryMonitor()
06698:                            .getCachedPropertyList(cacheKey2);
06699:
06700:                    if (allProperties != null) {
06701:                        // list of properties already read, look up value there 
06702:                        for (int i = 0; i < allProperties.size(); i++) {
06703:                            CmsProperty property = (CmsProperty) allProperties
06704:                                    .get(i);
06705:                            if (property.getName().equals(key)) {
06706:                                value = property;
06707:                                break;
06708:                            }
06709:                        }
06710:                    } else if (search) {
06711:                        // result not cached, look it up recursively with search enabled
06712:                        String cacheKey3 = getCacheKey(key, search, dbc
06713:                                .currentProject().getUuid(), resource
06714:                                .getRootPath());
06715:                        value = OpenCms.getMemoryMonitor().getCachedProperty(
06716:                                cacheKey3);
06717:
06718:                        if ((value == null) || value.isNullProperty()) {
06719:                            boolean cont;
06720:                            do {
06721:                                try {
06722:                                    value = readPropertyObject(dbc, resource,
06723:                                            key, false);
06724:                                    cont = value.isNullProperty()
06725:                                            && (resource.getRootPath().length() > 1);
06726:                                } catch (CmsSecurityException se) {
06727:                                    // a security exception (probably no read permission) we return the current result                      
06728:                                    cont = false;
06729:                                }
06730:                                if (cont) {
06731:                                    // no permission check on parent folder is required since we must have "read" 
06732:                                    // permissions to read the child resource anyway
06733:                                    resource = readResource(dbc, CmsResource
06734:                                            .getParentFolder(resource
06735:                                                    .getRootPath()),
06736:                                            CmsResourceFilter.ALL);
06737:                                }
06738:                            } while (cont);
06739:                        }
06740:                    } else {
06741:                        // result not cached, look it up in the DB without search
06742:                        value = m_vfsDriver.readPropertyObject(dbc, key, dbc
06743:                                .currentProject(), resource);
06744:                    }
06745:                    if (value == null) {
06746:                        value = CmsProperty.getNullProperty();
06747:                    }
06748:
06749:                    // freeze the value
06750:                    value.setFrozen(true);
06751:                    // store the result in the cache
06752:                    OpenCms.getMemoryMonitor().cacheProperty(cacheKey, value);
06753:                }
06754:
06755:                // ensure the result value is not frozen
06756:                return value.cloneAsProperty();
06757:            }
06758:
06759:            /**
06760:             * Reads all property objects mapped to a specified resource from the database.<p>
06761:             * 
06762:             * All properties in the result List will be in frozen (read only) state, so you can't change the values.<p>
06763:             * 
06764:             * Returns an empty list if no properties are found at all.<p>
06765:             * 
06766:             * @param dbc the current database context
06767:             * @param resource the resource where the properties are read from
06768:             * @param search true, if the properties should be searched on all parent folders  if not found on the resource
06769:             * 
06770:             * @return a list of CmsProperty objects containing the structure and/or resource value
06771:             * 
06772:             * @throws CmsException if something goes wrong
06773:             * 
06774:             * @see CmsObject#readPropertyObjects(String, boolean)
06775:             */
06776:            public List readPropertyObjects(CmsDbContext dbc,
06777:                    CmsResource resource, boolean search) throws CmsException {
06778:
06779:                // check if we have the result already cached
06780:                String cacheKey = getCacheKey(CACHE_ALL_PROPERTIES, search, dbc
06781:                        .currentProject().getUuid(), resource.getRootPath());
06782:
06783:                List properties = OpenCms.getMemoryMonitor()
06784:                        .getCachedPropertyList(cacheKey);
06785:
06786:                if (properties == null) {
06787:                    // result not cached, let's look it up in the DB
06788:                    if (search) {
06789:                        boolean cont;
06790:                        properties = new ArrayList();
06791:                        List parentProperties = null;
06792:
06793:                        do {
06794:                            try {
06795:                                parentProperties = readPropertyObjects(dbc,
06796:                                        resource, false);
06797:
06798:                                // make sure properties from lower folders "overwrite" properties from upper folders
06799:                                parentProperties.removeAll(properties);
06800:                                parentProperties.addAll(properties);
06801:
06802:                                properties.clear();
06803:                                properties.addAll(parentProperties);
06804:
06805:                                cont = resource.getRootPath().length() > 1;
06806:                            } catch (CmsSecurityException se) {
06807:                                // a security exception (probably no read permission) we return the current result                      
06808:                                cont = false;
06809:                            }
06810:                            if (cont) {
06811:                                // no permission check on parent folder is required since we must have "read" 
06812:                                // permissions to read the child resource anyway
06813:                                resource = readResource(dbc,
06814:                                        CmsResource.getParentFolder(resource
06815:                                                .getRootPath()),
06816:                                        CmsResourceFilter.ALL);
06817:                            }
06818:                        } while (cont);
06819:                    } else {
06820:                        properties = m_vfsDriver.readPropertyObjects(dbc, dbc
06821:                                .currentProject(), resource);
06822:                    }
06823:
06824:                    // set all properties in the result lisst as frozen
06825:                    CmsProperty.setFrozen(properties);
06826:                    // store the result in the driver manager's cache
06827:                    OpenCms.getMemoryMonitor().cachePropertyList(cacheKey,
06828:                            properties);
06829:                }
06830:
06831:                return new ArrayList(properties);
06832:            }
06833:
06834:            /**
06835:             * Reads the resources that were published in a publish task for a given publish history ID.<p>
06836:             * 
06837:             * @param dbc the current database context
06838:             * @param publishHistoryId unique int ID to identify each publish task in the publish history
06839:             * 
06840:             * @return a list of <code>{@link org.opencms.db.CmsPublishedResource}</code> objects
06841:             * 
06842:             * @throws CmsException if something goes wrong
06843:             */
06844:            public List readPublishedResources(CmsDbContext dbc,
06845:                    CmsUUID publishHistoryId) throws CmsException {
06846:
06847:                return m_projectDriver.readPublishedResources(dbc,
06848:                        publishHistoryId);
06849:            }
06850:
06851:            /**
06852:             * Reads a single publish job identified by its publish history id.<p>
06853:             * 
06854:             * @param dbc the current database context
06855:             * @param publishHistoryId unique id to identify the publish job in the publish history
06856:             * @return an object of type <code>{@link CmsPublishJobInfoBean}</code> 
06857:             * 
06858:             * @throws CmsException if something goes wrong
06859:             */
06860:            public CmsPublishJobInfoBean readPublishJob(CmsDbContext dbc,
06861:                    CmsUUID publishHistoryId) throws CmsException {
06862:
06863:                return m_projectDriver.readPublishJob(dbc, publishHistoryId);
06864:            }
06865:
06866:            /**
06867:             * Reads all available publish jobs.<p>
06868:             * 
06869:             * @param dbc the current database context
06870:             * @param startTime the start of the time range for finish time
06871:             * @param endTime the end of the time range for finish time
06872:             * @return a list of objects of type <code>{@link CmsPublishJobInfoBean}</code>
06873:             * 
06874:             * @throws CmsException if something goes wrong
06875:             */
06876:            public List readPublishJobs(CmsDbContext dbc, long startTime,
06877:                    long endTime) throws CmsException {
06878:
06879:                return m_projectDriver.readPublishJobs(dbc, startTime, endTime);
06880:            }
06881:
06882:            /**
06883:             * Reads the publish list assigned to a publish job.<p>
06884:             * 
06885:             * @param dbc the current database context
06886:             * @param publishHistoryId the history id identifying the publish job
06887:             * @return the assigned publish list
06888:             * @throws CmsException if something goes wrong
06889:             */
06890:            public CmsPublishList readPublishList(CmsDbContext dbc,
06891:                    CmsUUID publishHistoryId) throws CmsException {
06892:
06893:                return m_projectDriver.readPublishList(dbc, publishHistoryId);
06894:            }
06895:
06896:            /**
06897:             * Reads the publish report assigned to a publish job.<p>
06898:             * 
06899:             * @param dbc the current database context
06900:             * @param publishHistoryId the history id identifying the publish job  
06901:             * @return the content of the assigned publish report
06902:             * @throws CmsException if something goes wrong
06903:             */
06904:            public byte[] readPublishReportContents(CmsDbContext dbc,
06905:                    CmsUUID publishHistoryId) throws CmsException {
06906:
06907:                return m_projectDriver.readPublishReportContents(dbc,
06908:                        publishHistoryId);
06909:            }
06910:
06911:            /**
06912:             * Reads an historical resource entry for the given resource and with the given version number.<p>
06913:             *
06914:             * @param dbc the current db context
06915:             * @param resource the resource to be read
06916:             * @param version the version number to retrieve
06917:             *
06918:             * @return the resource that was read
06919:             *
06920:             * @throws CmsException if the resource could not be read for any reason
06921:             * 
06922:             * @see CmsObject#restoreResourceVersion(CmsUUID, int)
06923:             * @see CmsObject#readResource(CmsUUID, int)
06924:             */
06925:            public I_CmsHistoryResource readResource(CmsDbContext dbc,
06926:                    CmsResource resource, int version) throws CmsException {
06927:
06928:                Iterator itVersions = m_historyDriver.readAllAvailableVersions(
06929:                        dbc, resource.getStructureId()).iterator();
06930:                while (itVersions.hasNext()) {
06931:                    I_CmsHistoryResource histRes = (I_CmsHistoryResource) itVersions
06932:                            .next();
06933:                    if (histRes.getVersion() == version) {
06934:                        return histRes;
06935:                    }
06936:                }
06937:                throw new CmsVfsResourceNotFoundException(
06938:                        org.opencms.db.generic.Messages
06939:                                .get()
06940:                                .container(
06941:                                        org.opencms.db.generic.Messages.ERR_HISTORY_FILE_NOT_FOUND_1,
06942:                                        resource.getStructureId()));
06943:            }
06944:
06945:            /**
06946:             * Reads a resource from the VFS, using the specified resource filter.<p>
06947:             * 
06948:             * @param dbc the current database context
06949:             * @param structureID the structure id of the resource to read
06950:             * @param filter the resource filter to use while reading
06951:             *
06952:             * @return the resource that was read
06953:             *
06954:             * @throws CmsDataAccessException if something goes wrong
06955:             * 
06956:             * @see CmsObject#readResource(CmsUUID, CmsResourceFilter)
06957:             * @see CmsObject#readResource(CmsUUID)
06958:             */
06959:            public CmsResource readResource(CmsDbContext dbc,
06960:                    CmsUUID structureID, CmsResourceFilter filter)
06961:                    throws CmsDataAccessException {
06962:
06963:                // please note: the filter will be applied in the security manager later
06964:                CmsResource resource = m_vfsDriver.readResource(dbc, dbc
06965:                        .getProjectId().isNullUUID() ? dbc.currentProject()
06966:                        .getUuid() : dbc.getProjectId(), structureID, filter
06967:                        .includeDeleted());
06968:
06969:                // context dates need to be updated
06970:                updateContextDates(dbc, resource);
06971:
06972:                // return the resource
06973:                return resource;
06974:            }
06975:
06976:            /**
06977:             * Reads a resource from the VFS, using the specified resource filter.<p>
06978:             * 
06979:             * @param dbc the current database context
06980:             * @param resourcePath the name of the resource to read (full path)
06981:             * @param filter the resource filter to use while reading
06982:             *
06983:             * @return the resource that was read
06984:             *
06985:             * @throws CmsDataAccessException if something goes wrong
06986:             * 
06987:             * @see CmsObject#readResource(String, CmsResourceFilter)
06988:             * @see CmsObject#readResource(String)
06989:             * @see CmsObject#readFile(CmsResource)
06990:             */
06991:            public CmsResource readResource(CmsDbContext dbc,
06992:                    String resourcePath, CmsResourceFilter filter)
06993:                    throws CmsDataAccessException {
06994:
06995:                // please note: the filter will be applied in the security manager later
06996:                CmsResource resource = m_vfsDriver.readResource(dbc, dbc
06997:                        .getProjectId().isNullUUID() ? dbc.currentProject()
06998:                        .getUuid() : dbc.getProjectId(), resourcePath, filter
06999:                        .includeDeleted());
07000:
07001:                // context dates need to be updated 
07002:                updateContextDates(dbc, resource);
07003:
07004:                // return the resource
07005:                return resource;
07006:            }
07007:
07008:            /**
07009:             * Reads a resource in the current project with the given publish tag from the historical archive.<p>
07010:             * 
07011:             * @param dbc the current db context
07012:             * @param resource the resource to restore from the archive
07013:             * @param publishTag the publish tag of the resource
07014:             * 
07015:             * @return the file in the current project with the given publish tag from the historical archive, or
07016:             *         {@link CmsVfsResourceNotFoundException} if not found 
07017:             *
07018:             * @throws CmsException if something goes wrong
07019:             * 
07020:             * @see CmsObject#readResource(CmsUUID, int)
07021:             * @see CmsObject#readResourceByPublishTag(CmsUUID, int)
07022:             * 
07023:             * @deprecated use {@link #readResource(CmsDbContext, CmsResource, int)} instead
07024:             *             but notice that the <code>publishTag != version</code>
07025:             */
07026:            public I_CmsHistoryResource readResourceForPublishTag(
07027:                    CmsDbContext dbc, CmsResource resource, int publishTag)
07028:                    throws CmsException {
07029:
07030:                return m_historyDriver.readFile(dbc, resource.getStructureId(),
07031:                        publishTag);
07032:            }
07033:
07034:            /**
07035:             * Reads all resources below the given path matching the filter criteria,
07036:             * including the full tree below the path only in case the <code>readTree</code> 
07037:             * parameter is <code>true</code>.<p>
07038:             * 
07039:             * @param dbc the current database context
07040:             * @param parent the parent path to read the resources from
07041:             * @param filter the filter
07042:             * @param readTree <code>true</code> to read all subresources
07043:             * 
07044:             * @return a list of <code>{@link CmsResource}</code> objects matching the filter criteria
07045:             *  
07046:             * @throws CmsDataAccessException if the bare reading of the resources fails
07047:             * @throws CmsException if security and permission checks for the resources read fail 
07048:             */
07049:            public List readResources(CmsDbContext dbc, CmsResource parent,
07050:                    CmsResourceFilter filter, boolean readTree)
07051:                    throws CmsException, CmsDataAccessException {
07052:
07053:                // try to get the sub resources from the cache
07054:                String cacheKey = getCacheKey(new String[] {
07055:                        dbc.currentUser().getName(), filter.getCacheId(),
07056:                        readTree ? "+" : "-", parent.getRootPath() }, dbc
07057:                        .currentProject());
07058:
07059:                List resourceList = OpenCms.getMemoryMonitor()
07060:                        .getCachedResourceList(cacheKey);
07061:                if (resourceList == null) {
07062:                    // read the result from the database
07063:                    resourceList = m_vfsDriver
07064:                            .readResourceTree(
07065:                                    dbc,
07066:                                    dbc.currentProject().getUuid(),
07067:                                    (readTree ? parent.getRootPath() : parent
07068:                                            .getStructureId().toString()),
07069:                                    filter.getType(),
07070:                                    filter.getState(),
07071:                                    filter.getModifiedAfter(),
07072:                                    filter.getModifiedBefore(),
07073:                                    filter.getReleaseAfter(),
07074:                                    filter.getReleaseBefore(),
07075:                                    filter.getExpireAfter(),
07076:                                    filter.getExpireBefore(),
07077:                                    (readTree ? CmsDriverManager.READMODE_INCLUDE_TREE
07078:                                            : CmsDriverManager.READMODE_EXCLUDE_TREE)
07079:                                            | (filter.excludeType() ? CmsDriverManager.READMODE_EXCLUDE_TYPE
07080:                                                    : 0)
07081:                                            | (filter.excludeState() ? CmsDriverManager.READMODE_EXCLUDE_STATE
07082:                                                    : 0)
07083:                                            | ((filter.getOnlyFolders() != null) ? (filter
07084:                                                    .getOnlyFolders()
07085:                                                    .booleanValue() ? CmsDriverManager.READMODE_ONLY_FOLDERS
07086:                                                    : CmsDriverManager.READMODE_ONLY_FILES)
07087:                                                    : 0));
07088:
07089:                    // HACK: do not take care of permissions if reading organizational units
07090:                    if (!parent.getRootPath().startsWith("/system/orgunits/")) {
07091:                        // apply permission filter
07092:                        resourceList = filterPermissions(dbc, resourceList,
07093:                                filter);
07094:                    }
07095:                    // store the result in the resourceList cache
07096:                    OpenCms.getMemoryMonitor().cacheResourceList(cacheKey,
07097:                            resourceList);
07098:                }
07099:                // we must always apply the result filter and update the context dates
07100:                return updateContextDates(dbc, resourceList, filter);
07101:            }
07102:
07103:            /**
07104:             * Reads all resources that have a value (containing the given value string) set 
07105:             * for the specified property (definition) in the given path.<p>
07106:             * 
07107:             * Both individual and shared properties of a resource are checked.<p>
07108:             *
07109:             * If the <code>value</code> parameter is <code>null</code>, all resources having the
07110:             * given property set are returned.<p>
07111:             * 
07112:             * @param dbc the current database context
07113:             * @param folder the folder to get the resources with the property from
07114:             * @param propertyDefinition the name of the property (definition) to check for
07115:             * @param value the string to search in the value of the property
07116:             * @param filter the resource filter to apply to the result set
07117:             * 
07118:             * @return a list of all <code>{@link CmsResource}</code> objects 
07119:             *          that have a value set for the specified property.
07120:             * 
07121:             * @throws CmsException if something goes wrong
07122:             */
07123:            public List readResourcesWithProperty(CmsDbContext dbc,
07124:                    CmsResource folder, String propertyDefinition,
07125:                    String value, CmsResourceFilter filter) throws CmsException {
07126:
07127:                String cacheKey;
07128:                if (value == null) {
07129:                    cacheKey = getCacheKey(new String[] {
07130:                            dbc.currentUser().getName(), folder.getRootPath(),
07131:                            propertyDefinition, filter.getCacheId() }, dbc
07132:                            .currentProject());
07133:                } else {
07134:                    cacheKey = getCacheKey(new String[] {
07135:                            dbc.currentUser().getName(), folder.getRootPath(),
07136:                            propertyDefinition, value, filter.getCacheId() },
07137:                            dbc.currentProject());
07138:                }
07139:                List resourceList = OpenCms.getMemoryMonitor()
07140:                        .getCachedResourceList(cacheKey);
07141:                if (resourceList == null) {
07142:                    // first read the property definition
07143:                    CmsPropertyDefinition propDef = readPropertyDefinition(dbc,
07144:                            propertyDefinition);
07145:                    // now read the list of resources that have a value set for the property definition
07146:                    resourceList = m_vfsDriver.readResourcesWithProperty(dbc,
07147:                            dbc.currentProject().getUuid(), propDef.getId(),
07148:                            folder.getRootPath(), value);
07149:                    // apply permission filter
07150:                    resourceList = filterPermissions(dbc, resourceList, filter);
07151:                    // store the result in the resourceList cache
07152:                    OpenCms.getMemoryMonitor().cacheResourceList(cacheKey,
07153:                            resourceList);
07154:                }
07155:                // we must always apply the result filter and update the context dates
07156:                return updateContextDates(dbc, resourceList, filter);
07157:            }
07158:
07159:            /**
07160:             * Returns the set of users that are responsible for a specific resource.<p>
07161:             * 
07162:             * @param dbc the current database context
07163:             * @param resource the resource to get the responsible users from
07164:             * 
07165:             * @return the set of users that are responsible for a specific resource
07166:             * 
07167:             * @throws CmsException if something goes wrong
07168:             */
07169:            public Set readResponsiblePrincipals(CmsDbContext dbc,
07170:                    CmsResource resource) throws CmsException {
07171:
07172:                Set result = new HashSet();
07173:                Iterator aces = getAccessControlEntries(dbc, resource, true)
07174:                        .iterator();
07175:                while (aces.hasNext()) {
07176:                    CmsAccessControlEntry ace = (CmsAccessControlEntry) aces
07177:                            .next();
07178:                    if (ace.isResponsible()) {
07179:                        I_CmsPrincipal p = lookupPrincipal(dbc, ace
07180:                                .getPrincipal());
07181:                        if (p != null) {
07182:                            result.add(p);
07183:                        }
07184:                    }
07185:                }
07186:                return result;
07187:            }
07188:
07189:            /**
07190:             * Returns the set of users that are responsible for a specific resource.<p>
07191:             * 
07192:             * @param dbc the current database context
07193:             * @param resource the resource to get the responsible users from
07194:             * 
07195:             * @return the set of users that are responsible for a specific resource
07196:             * 
07197:             * @throws CmsException if something goes wrong
07198:             */
07199:            public Set readResponsibleUsers(CmsDbContext dbc,
07200:                    CmsResource resource) throws CmsException {
07201:
07202:                Set result = new HashSet();
07203:                Iterator principals = readResponsiblePrincipals(dbc, resource)
07204:                        .iterator();
07205:                while (principals.hasNext()) {
07206:                    I_CmsPrincipal principal = (I_CmsPrincipal) principals
07207:                            .next();
07208:                    if (principal instanceof  CmsGroup) {
07209:                        try {
07210:                            result.addAll(getUsersOfGroup(dbc, principal
07211:                                    .getName(), true, false, false));
07212:                        } catch (CmsException e) {
07213:                            if (LOG.isInfoEnabled()) {
07214:                                LOG.info(e);
07215:                            }
07216:                        }
07217:                    } else {
07218:                        result.add(principal);
07219:                    }
07220:                }
07221:                return result;
07222:            }
07223:
07224:            /**
07225:             * Returns a List of all siblings of the specified resource,
07226:             * the specified resource being always part of the result set.<p>
07227:             * 
07228:             * The result is a list of <code>{@link CmsResource}</code> objects.<p>
07229:             * 
07230:             * @param dbc the current database context
07231:             * @param resource the resource to read the siblings for
07232:             * @param filter a filter object
07233:             * 
07234:             * @return a list of <code>{@link CmsResource}</code> Objects that 
07235:             *          are siblings to the specified resource, 
07236:             *          including the specified resource itself
07237:             * 
07238:             * @throws CmsException if something goes wrong
07239:             */
07240:            public List readSiblings(CmsDbContext dbc, CmsResource resource,
07241:                    CmsResourceFilter filter) throws CmsException {
07242:
07243:                List siblings = m_vfsDriver.readSiblings(dbc, dbc
07244:                        .currentProject().getUuid(), resource, filter
07245:                        .includeDeleted());
07246:
07247:                // important: there is no permission check done on the returned list of siblings
07248:                // this is because of possible issues with the "publish all siblings" option,
07249:                // moreover the user has read permission for the content through
07250:                // the selected sibling anyway
07251:                return updateContextDates(dbc, siblings, filter);
07252:            }
07253:
07254:            /**
07255:             * Returns the parameters of a resource in the table of all published template resources.<p>
07256:             *
07257:             * @param dbc the current database context
07258:             * @param rfsName the rfs name of the resource
07259:             * 
07260:             * @return the parameter string of the requested resource
07261:             * 
07262:             * @throws CmsException if something goes wrong
07263:             */
07264:            public String readStaticExportPublishedResourceParameters(
07265:                    CmsDbContext dbc, String rfsName) throws CmsException {
07266:
07267:                return m_projectDriver
07268:                        .readStaticExportPublishedResourceParameters(dbc,
07269:                                rfsName);
07270:            }
07271:
07272:            /**
07273:             * Returns a list of all template resources which must be processed during a static export.<p>
07274:             * 
07275:             * @param dbc the current database context
07276:             * @param parameterResources flag for reading resources with parameters (1) or without (0)
07277:             * @param timestamp for reading the data from the db
07278:             * 
07279:             * @return a list of template resources as <code>{@link String}</code> objects
07280:             * 
07281:             * @throws CmsException if something goes wrong
07282:             */
07283:            public List readStaticExportResources(CmsDbContext dbc,
07284:                    int parameterResources, long timestamp) throws CmsException {
07285:
07286:                return m_projectDriver.readStaticExportResources(dbc,
07287:                        parameterResources, timestamp);
07288:            }
07289:
07290:            /**
07291:             * Returns a user object based on the id of a user.<p>
07292:             *
07293:             * @param dbc the current database context
07294:             * @param id the id of the user to read
07295:             *
07296:             * @return the user read
07297:             * 
07298:             * @throws CmsException if something goes wrong
07299:             */
07300:            public CmsUser readUser(CmsDbContext dbc, CmsUUID id)
07301:                    throws CmsException {
07302:
07303:                CmsUser user = OpenCms.getMemoryMonitor().getCachedUser(
07304:                        id.toString());
07305:                if (user == null) {
07306:                    user = m_userDriver.readUser(dbc, id);
07307:                    OpenCms.getMemoryMonitor().cacheUser(user);
07308:                }
07309:                return user;
07310:            }
07311:
07312:            /**
07313:             * Returns a user object.<p>
07314:             *
07315:             * @param dbc the current database context
07316:             * @param username the name of the user that is to be read
07317:             *
07318:             * @return user read
07319:             * 
07320:             * @throws CmsDataAccessException if operation was not successful
07321:             */
07322:            public CmsUser readUser(CmsDbContext dbc, String username)
07323:                    throws CmsDataAccessException {
07324:
07325:                CmsUser user = OpenCms.getMemoryMonitor().getCachedUser(
07326:                        username);
07327:                if (user == null) {
07328:                    user = m_userDriver.readUser(dbc, username);
07329:                    OpenCms.getMemoryMonitor().cacheUser(user);
07330:                }
07331:                return user;
07332:            }
07333:
07334:            /**
07335:             * Returns a user object if the password for the user is correct.<p>
07336:             *
07337:             * If the user/pwd pair is not valid a <code>{@link CmsException}</code> is thrown.<p>
07338:             *
07339:             * @param dbc the current database context
07340:             * @param username the username of the user that is to be read
07341:             * @param password the password of the user that is to be read
07342:             * 
07343:             * @return user read
07344:             * 
07345:             * @throws CmsException if operation was not successful
07346:             */
07347:            public CmsUser readUser(CmsDbContext dbc, String username,
07348:                    String password) throws CmsException {
07349:
07350:                // don't read user from cache here because password may have changed
07351:                CmsUser user = m_userDriver.readUser(dbc, username, password,
07352:                        null);
07353:                OpenCms.getMemoryMonitor().cacheUser(user);
07354:                return user;
07355:            }
07356:
07357:            /**
07358:             * Removes an access control entry for a given resource and principal.<p>
07359:             * 
07360:             * @param dbc the current database context
07361:             * @param resource the resource
07362:             * @param principal the id of the principal to remove the the access control entry for
07363:             * 
07364:             * @throws CmsException if something goes wrong
07365:             */
07366:            public void removeAccessControlEntry(CmsDbContext dbc,
07367:                    CmsResource resource, CmsUUID principal)
07368:                    throws CmsException {
07369:
07370:                // remove the ace
07371:                m_userDriver.removeAccessControlEntry(dbc,
07372:                        dbc.currentProject(), resource.getResourceId(),
07373:                        principal);
07374:
07375:                // update the "last modified" information
07376:                setDateLastModified(dbc, resource, resource
07377:                        .getDateLastModified());
07378:
07379:                // clear the cache
07380:                OpenCms.getMemoryMonitor().clearAccessControlListCache();
07381:
07382:                // fire a resource modification event
07383:                HashMap data = new HashMap(2);
07384:                data.put("resource", resource);
07385:                data.put("change", new Integer(CHANGED_ACCESSCONTROL));
07386:                OpenCms.fireCmsEvent(new CmsEvent(
07387:                        I_CmsEventListener.EVENT_RESOURCE_MODIFIED, data));
07388:            }
07389:
07390:            /**
07391:             * Removes a resource from the given organizational unit.<p>
07392:             * 
07393:             * @param dbc the current db context
07394:             * @param orgUnit the organizational unit to remove the resource from
07395:             * @param resource the resource that is to be removed from the organizational unit
07396:             * 
07397:             * @throws CmsException if something goes wrong
07398:             * 
07399:             * @see org.opencms.security.CmsOrgUnitManager#addResourceToOrgUnit(CmsObject, String, String)
07400:             * @see org.opencms.security.CmsOrgUnitManager#addResourceToOrgUnit(CmsObject, String, String)
07401:             */
07402:            public void removeResourceFromOrgUnit(CmsDbContext dbc,
07403:                    CmsOrganizationalUnit orgUnit, CmsResource resource)
07404:                    throws CmsException {
07405:
07406:                OpenCms.getMemoryMonitor().flushRoles();
07407:                OpenCms.getMemoryMonitor().flushRoleLists();
07408:                m_userDriver.removeResourceFromOrganizationalUnit(dbc, orgUnit,
07409:                        resource);
07410:            }
07411:
07412:            /**
07413:             * Removes a resource from the current project of the user.<p>
07414:             * 
07415:             * @param dbc the current database context
07416:             * @param resource the resource to apply this operation to
07417:             * 
07418:             * @throws CmsException if something goes wrong
07419:             * 
07420:             * @see CmsObject#copyResourceToProject(String)
07421:             * @see I_CmsResourceType#copyResourceToProject(CmsObject, CmsSecurityManager, CmsResource)
07422:             */
07423:            public void removeResourceFromProject(CmsDbContext dbc,
07424:                    CmsResource resource) throws CmsException {
07425:
07426:                // remove the resource to the project only if the resource is already in the project
07427:                if (isInsideCurrentProject(dbc, resource.getRootPath())) {
07428:                    // check if there are already any subfolders of this resource
07429:                    if (resource.isFolder()) {
07430:                        List projectResources = m_projectDriver
07431:                                .readProjectResources(dbc, dbc.currentProject());
07432:                        for (int i = 0; i < projectResources.size(); i++) {
07433:                            String resname = (String) projectResources.get(i);
07434:                            if (resname.startsWith(resource.getRootPath())) {
07435:                                // delete the existing project resource first
07436:                                m_projectDriver.deleteProjectResource(dbc, dbc
07437:                                        .currentProject().getUuid(), resname);
07438:                            }
07439:                        }
07440:                    }
07441:                    try {
07442:                        m_projectDriver.deleteProjectResource(dbc, dbc
07443:                                .currentProject().getUuid(), resource
07444:                                .getRootPath());
07445:                    } catch (CmsException exc) {
07446:                        // if the subfolder exists already - all is ok
07447:                    } finally {
07448:                        OpenCms.getMemoryMonitor().flushProjectResources();
07449:
07450:                        OpenCms.fireCmsEvent(new CmsEvent(
07451:                                I_CmsEventListener.EVENT_PROJECT_MODIFIED,
07452:                                Collections.singletonMap("project", dbc
07453:                                        .currentProject())));
07454:                    }
07455:                }
07456:            }
07457:
07458:            /**
07459:             * Removes a user from a group.<p>
07460:             *
07461:             * @param dbc the current database context
07462:             * @param username the name of the user that is to be removed from the group
07463:             * @param groupname the name of the group
07464:             * @param readRoles if to read roles or groups
07465:             *
07466:             * @throws CmsException if operation was not successful
07467:             * @throws CmsIllegalArgumentException if the given user was not member in the given group
07468:             * @throws CmsDbEntryNotFoundException if the given group was not found 
07469:             * @throws CmsSecurityException if the given user was <b>read as 'null' from the database</b>
07470:             * 
07471:             * @see #addUserToGroup(CmsDbContext, String, String, boolean)
07472:             */
07473:            public void removeUserFromGroup(CmsDbContext dbc, String username,
07474:                    String groupname, boolean readRoles) throws CmsException,
07475:                    CmsIllegalArgumentException, CmsDbEntryNotFoundException,
07476:                    CmsSecurityException {
07477:
07478:                CmsGroup group = readGroup(dbc, groupname);
07479:                //check if group exists
07480:                if (group == null) {
07481:                    // the group does not exists
07482:                    throw new CmsDbEntryNotFoundException(Messages.get()
07483:                            .container(Messages.ERR_UNKNOWN_GROUP_1, groupname));
07484:                }
07485:                if (group.isVirtual() && !readRoles) {
07486:                    // if removing a user from a virtual role treat it as removing the user from the role
07487:                    removeUserFromGroup(dbc, username, CmsRole.valueOf(group)
07488:                            .getGroupName(), true);
07489:                    return;
07490:                }
07491:                if (group.isVirtual()) {
07492:                    // this is an hack so to prevent a unlimited recursive calls
07493:                    readRoles = false;
07494:                }
07495:                if ((readRoles && !group.isRole())
07496:                        || (!readRoles && group.isRole())) {
07497:                    // we want a role but we got a group, or the other way
07498:                    throw new CmsDbEntryNotFoundException(Messages.get()
07499:                            .container(Messages.ERR_UNKNOWN_GROUP_1, groupname));
07500:                }
07501:
07502:                // test if this user is existing in the group
07503:                if (!userInGroup(dbc, username, groupname, readRoles)) {
07504:                    // user is not in the group, throw exception
07505:                    throw new CmsIllegalArgumentException(Messages.get()
07506:                            .container(Messages.ERR_USER_NOT_IN_GROUP_2,
07507:                                    username, groupname));
07508:                }
07509:
07510:                CmsUser user = readUser(dbc, username);
07511:                //check if the user exists
07512:                if (user == null) {
07513:                    // the user does not exists
07514:                    throw new CmsIllegalArgumentException(Messages.get()
07515:                            .container(Messages.ERR_USER_NOT_IN_GROUP_2,
07516:                                    username, groupname));
07517:                }
07518:
07519:                if (readRoles) {
07520:                    CmsRole role = CmsRole.valueOf(group);
07521:                    // the workplace user role can only be removed if no other user has no other role
07522:                    if (role.equals(CmsRole.WORKPLACE_USER.forOrgUnit(role
07523:                            .getOuFqn()))) {
07524:                        if (getGroupsOfUser(dbc, username, role.getOuFqn(),
07525:                                false, true, true,
07526:                                dbc.getRequestContext().getRemoteAddress())
07527:                                .size() > 1) {
07528:                            return;
07529:                        }
07530:                    }
07531:                    // update virtual groups
07532:                    Iterator it = getVirtualGroupsForRole(dbc, role).iterator();
07533:                    while (it.hasNext()) {
07534:                        CmsGroup virtualGroup = (CmsGroup) it.next();
07535:                        if (userInGroup(dbc, username, virtualGroup.getName(),
07536:                                false)) {
07537:                            // here we say readroles = true, to prevent an unlimited recursive calls
07538:                            removeUserFromGroup(dbc, username, virtualGroup
07539:                                    .getName(), true);
07540:                        }
07541:                    }
07542:                }
07543:                m_userDriver
07544:                        .deleteUserInGroup(dbc, user.getId(), group.getId());
07545:
07546:                // flush relevant caches
07547:                if (readRoles) {
07548:                    OpenCms.getMemoryMonitor().flushRoles();
07549:                    OpenCms.getMemoryMonitor().flushRoleLists();
07550:                }
07551:                OpenCms.getMemoryMonitor().flushUserGroups();
07552:            }
07553:
07554:            /**
07555:             * Replaces the content, type and properties of a resource.<p>
07556:             * 
07557:             * @param dbc the current database context
07558:             * @param resource the name of the resource to apply this operation to
07559:             * @param type the new type of the resource
07560:             * @param content the new content of the resource
07561:             * @param properties the new properties of the resource
07562:             * 
07563:             * @throws CmsException if something goes wrong
07564:             * 
07565:             * @see CmsObject#replaceResource(String, int, byte[], List)
07566:             * @see I_CmsResourceType#replaceResource(CmsObject, CmsSecurityManager, CmsResource, int, byte[], List)
07567:             */
07568:            public void replaceResource(CmsDbContext dbc, CmsResource resource,
07569:                    int type, byte[] content, List properties)
07570:                    throws CmsException {
07571:
07572:                // replace the existing with the new file content
07573:                m_vfsDriver.replaceResource(dbc, resource, content, type);
07574:
07575:                if ((properties != null)
07576:                        && (properties != Collections.EMPTY_LIST)) {
07577:                    // write the properties
07578:                    m_vfsDriver.writePropertyObjects(dbc, dbc.currentProject(),
07579:                            resource, properties);
07580:                    OpenCms.getMemoryMonitor().flushProperties();
07581:                    OpenCms.getMemoryMonitor().flushPropertyLists();
07582:                }
07583:
07584:                // update the resource state
07585:                if (resource.getState().isUnchanged()) {
07586:                    resource.setState(CmsResource.STATE_CHANGED);
07587:                }
07588:                resource.setUserLastModified(dbc.currentUser().getId());
07589:
07590:                setDateLastModified(dbc, resource, System.currentTimeMillis());
07591:
07592:                m_vfsDriver.writeResourceState(dbc, dbc.currentProject(),
07593:                        resource, UPDATE_RESOURCE, false);
07594:
07595:                deleteRelationsWithSiblings(dbc, resource);
07596:
07597:                // clear the cache
07598:                OpenCms.getMemoryMonitor().clearResourceCache();
07599:
07600:                HashMap data = new HashMap(2);
07601:                data.put("resource", resource);
07602:                data.put("change", new Integer(CHANGED_RESOURCE
07603:                        | CHANGED_CONTENT));
07604:                OpenCms.fireCmsEvent(new CmsEvent(
07605:                        I_CmsEventListener.EVENT_RESOURCE_MODIFIED, data));
07606:            }
07607:
07608:            /**
07609:             * Resets the password for a specified user.<p>
07610:             *
07611:             * @param dbc the current database context
07612:             * @param username the name of the user
07613:             * @param oldPassword the old password
07614:             * @param newPassword the new password
07615:             * 
07616:             * @throws CmsException if the user data could not be read from the database
07617:             * @throws CmsSecurityException if the specified username and old password could not be verified
07618:             */
07619:            public void resetPassword(CmsDbContext dbc, String username,
07620:                    String oldPassword, String newPassword)
07621:                    throws CmsException, CmsSecurityException {
07622:
07623:                if ((oldPassword != null) && (newPassword != null)) {
07624:
07625:                    CmsUser user = null;
07626:
07627:                    validatePassword(newPassword);
07628:
07629:                    // read the user as a system user to verify that the specified old password is correct
07630:                    try {
07631:                        user = m_userDriver.readUser(dbc, username,
07632:                                oldPassword, null);
07633:                    } catch (CmsDbEntryNotFoundException e) {
07634:                        throw new CmsDataAccessException(Messages.get()
07635:                                .container(Messages.ERR_RESET_PASSWORD_1,
07636:                                        username), e);
07637:                    }
07638:
07639:                    if ((user == null) || user.isManaged()) {
07640:                        throw new CmsDataAccessException(Messages.get()
07641:                                .container(Messages.ERR_RESET_PASSWORD_1,
07642:                                        username));
07643:                    }
07644:
07645:                    m_userDriver.writePassword(dbc, username, oldPassword,
07646:                            newPassword);
07647:
07648:                } else if (CmsStringUtil.isEmpty(oldPassword)) {
07649:                    throw new CmsDataAccessException(Messages.get().container(
07650:                            Messages.ERR_PWD_OLD_MISSING_0));
07651:                } else if (CmsStringUtil.isEmpty(newPassword)) {
07652:                    throw new CmsDataAccessException(Messages.get().container(
07653:                            Messages.ERR_PWD_NEW_MISSING_0));
07654:                }
07655:            }
07656:
07657:            /**
07658:             * Restores a deleted resource identified by its structure id from the historical archive.<p>
07659:             * 
07660:             * @param dbc the current database context
07661:             * @param structureId the structure id of the resource to restore
07662:             * 
07663:             * @throws CmsException if something goes wrong
07664:             * 
07665:             * @see CmsObject#restoreDeletedResource(CmsUUID)
07666:             */
07667:            public void restoreDeletedResource(CmsDbContext dbc,
07668:                    CmsUUID structureId) throws CmsException {
07669:
07670:                // get the last version, which should be the deleted one
07671:                int version = m_historyDriver.readLastVersion(dbc, structureId);
07672:                // get that version
07673:                I_CmsHistoryResource histRes = m_historyDriver.readResource(
07674:                        dbc, structureId, version);
07675:
07676:                // check the parent path
07677:                CmsResource parent;
07678:                try {
07679:                    // try to read the parent resource by id
07680:                    parent = m_vfsDriver.readResource(dbc, dbc.currentProject()
07681:                            .getUuid(), histRes.getParentId(), true);
07682:                } catch (CmsVfsResourceNotFoundException e) {
07683:                    // if not found try to read the parent resource by name
07684:                    try {
07685:                        // try to read the parent resource by id
07686:                        parent = m_vfsDriver.readResource(dbc, dbc
07687:                                .currentProject().getUuid(), CmsResource
07688:                                .getParentFolder(histRes.getRootPath()), true);
07689:                    } catch (CmsVfsResourceNotFoundException e1) {
07690:                        // if not found try to restore the parent resource
07691:                        restoreDeletedResource(dbc, histRes.getParentId());
07692:                        parent = readResource(dbc, histRes.getParentId(),
07693:                                CmsResourceFilter.IGNORE_EXPIRATION);
07694:                    }
07695:                }
07696:                // check write permissions
07697:                m_securityManager.checkPermissions(dbc, parent,
07698:                        CmsPermissionSet.ACCESS_WRITE, false,
07699:                        CmsResourceFilter.IGNORE_EXPIRATION);
07700:
07701:                // check the name
07702:                String path = CmsResource
07703:                        .getParentFolder(histRes.getRootPath()); // path
07704:                String resName = CmsResource.getName(histRes.getRootPath()); // name
07705:                String ext = "";
07706:                if (resName.charAt(resName.length() - 1) == '/') {
07707:                    resName = resName.substring(0, resName.length() - 1);
07708:                } else {
07709:                    ext = CmsFileUtil.getExtension(resName); // extension
07710:                }
07711:                String nameWOExt = resName.substring(0, resName.length()
07712:                        - ext.length()); // name without extension
07713:                for (int i = 1; true; i++) {
07714:                    try {
07715:                        readResource(dbc, path + resName, CmsResourceFilter.ALL);
07716:                        resName = nameWOExt + "_" + i + ext;
07717:                        // try the next resource name with following schema: path/name_{i}.ext
07718:                    } catch (CmsVfsResourceNotFoundException e) {
07719:                        // ok, we found a not used resource name
07720:                        break;
07721:                    }
07722:                }
07723:
07724:                // check structure id
07725:                CmsUUID id = structureId;
07726:                if (m_vfsDriver.validateStructureIdExists(dbc, dbc
07727:                        .currentProject().getUuid(), structureId)) {
07728:                    // should never happen, but if already exists create a new one
07729:                    id = new CmsUUID();
07730:                }
07731:
07732:                byte[] contents = null;
07733:                boolean isFolder = true;
07734:
07735:                // do we need the contents?
07736:                if (histRes instanceof  CmsFile) {
07737:                    contents = ((CmsFile) histRes).getContents();
07738:                    if ((contents == null) || (contents.length == 0)) {
07739:                        contents = m_historyDriver.readContent(dbc, histRes
07740:                                .getResourceId(), histRes.getPublishTag());
07741:                    }
07742:                    isFolder = false;
07743:                }
07744:
07745:                // now read the historical properties
07746:                List properties = m_historyDriver.readProperties(dbc, histRes);
07747:
07748:                // create the object to create
07749:                CmsResource newResource = new CmsResource(id, histRes
07750:                        .getResourceId(), path + resName, histRes.getTypeId(),
07751:                        isFolder, histRes.getFlags(), dbc.currentProject()
07752:                                .getUuid(), CmsResource.STATE_NEW, histRes
07753:                                .getDateCreated(), histRes.getUserCreated(),
07754:                        histRes.getDateLastModified(), dbc.currentUser()
07755:                                .getId(), histRes.getDateReleased(), histRes
07756:                                .getDateExpired(), histRes.getSiblingCount(),
07757:                        histRes.getLength(), histRes.getDateContent(), histRes
07758:                                .getVersion());
07759:
07760:                // prevent the date last modified is set to the current time
07761:                newResource.setDateLastModified(newResource
07762:                        .getDateLastModified());
07763:                // restore the resource!
07764:                CmsResource resource = createResource(dbc, path + resName,
07765:                        newResource, contents, properties, true);
07766:                // set resource state to changed
07767:                newResource.setState(CmsResource.STATE_CHANGED);
07768:                m_vfsDriver.writeResourceState(dbc, dbc.currentProject(),
07769:                        newResource, UPDATE_RESOURCE_STATE, false);
07770:                newResource.setState(CmsResource.STATE_NEW);
07771:                // fire the event
07772:                HashMap data = new HashMap(2);
07773:                data.put("resource", resource);
07774:                data.put("change", new Integer(CHANGED_RESOURCE
07775:                        | CHANGED_CONTENT));
07776:                OpenCms.fireCmsEvent(new CmsEvent(
07777:                        I_CmsEventListener.EVENT_RESOURCE_MODIFIED, data));
07778:            }
07779:
07780:            /**
07781:             * Restores a resource in the current project with a version from the historical archive.<p>
07782:             * 
07783:             * @param dbc the current database context
07784:             * @param resource the resource to restore from the archive
07785:             * @param version the version number to restore from the archive
07786:             * 
07787:             * @throws CmsException if something goes wrong
07788:             * 
07789:             * @see CmsObject#restoreResourceVersion(CmsUUID, int)
07790:             * @see I_CmsResourceType#restoreResource(CmsObject, CmsSecurityManager, CmsResource, int)
07791:             */
07792:            public void restoreResource(CmsDbContext dbc, CmsResource resource,
07793:                    int version) throws CmsException {
07794:
07795:                I_CmsHistoryResource historyResource = readResource(dbc,
07796:                        resource, version);
07797:                CmsResourceState state = CmsResource.STATE_CHANGED;
07798:                if (resource.getState().isNew()) {
07799:                    state = CmsResource.STATE_NEW;
07800:                }
07801:                int newVersion = resource.getVersion();
07802:                if (resource.getState().isUnchanged()) {
07803:                    newVersion++;
07804:                }
07805:                CmsResource newResource = null;
07806:                // is the resource a file?
07807:                if (historyResource instanceof  CmsFile) {
07808:                    // get the historical up flags 
07809:                    int flags = historyResource.getFlags();
07810:                    if (resource.isLabeled()) {
07811:                        // set the flag for labeled links on the restored file
07812:                        flags |= CmsResource.FLAG_LABELED;
07813:                    }
07814:                    CmsFile newFile = new CmsFile(resource.getStructureId(),
07815:                            resource.getResourceId(), resource.getRootPath(),
07816:                            historyResource.getTypeId(), flags, dbc
07817:                                    .currentProject().getUuid(), state,
07818:                            resource.getDateCreated(), historyResource
07819:                                    .getUserCreated(), resource
07820:                                    .getDateLastModified(), dbc.currentUser()
07821:                                    .getId(),
07822:                            historyResource.getDateReleased(), historyResource
07823:                                    .getDateExpired(), resource
07824:                                    .getSiblingCount(), historyResource
07825:                                    .getLength(), historyResource
07826:                                    .getDateContent(), newVersion, readFile(
07827:                                    dbc, (CmsHistoryFile) historyResource)
07828:                                    .getContents());
07829:
07830:                    newResource = writeFile(dbc, newFile);
07831:                } else {
07832:                    // it is a folder!
07833:                    newResource = new CmsFolder(resource.getStructureId(),
07834:                            resource.getResourceId(), resource.getRootPath(),
07835:                            historyResource.getTypeId(), historyResource
07836:                                    .getFlags(),
07837:                            dbc.currentProject().getUuid(), state, resource
07838:                                    .getDateCreated(), historyResource
07839:                                    .getUserCreated(), resource
07840:                                    .getDateLastModified(), dbc.currentUser()
07841:                                    .getId(),
07842:                            historyResource.getDateReleased(), historyResource
07843:                                    .getDateExpired(), newVersion);
07844:
07845:                    writeResource(dbc, newResource);
07846:                }
07847:                if (newResource != null) {
07848:                    // now read the historical properties
07849:                    List historyProperties = m_historyDriver.readProperties(
07850:                            dbc, historyResource);
07851:                    // remove all properties
07852:                    deleteAllProperties(dbc, newResource.getRootPath());
07853:                    // write them to the restored resource
07854:                    writePropertyObjects(dbc, newResource, historyProperties,
07855:                            false);
07856:
07857:                    OpenCms.getMemoryMonitor().clearResourceCache();
07858:                }
07859:
07860:                HashMap data = new HashMap(2);
07861:                data.put("resource", resource);
07862:                data.put("change", new Integer(CHANGED_RESOURCE
07863:                        | CHANGED_CONTENT));
07864:                OpenCms.fireCmsEvent(new CmsEvent(
07865:                        I_CmsEventListener.EVENT_RESOURCE_MODIFIED, data));
07866:            }
07867:
07868:            /**
07869:             * Changes the "expire" date of a resource.<p>
07870:             * 
07871:             * @param dbc the current database context
07872:             * @param resource the resource to touch
07873:             * @param dateExpired the new expire date of the resource
07874:             * 
07875:             * @throws CmsDataAccessException if something goes wrong
07876:             * 
07877:             * @see CmsObject#setDateExpired(String, long, boolean)
07878:             * @see I_CmsResourceType#setDateExpired(CmsObject, CmsSecurityManager, CmsResource, long, boolean)
07879:             */
07880:            public void setDateExpired(CmsDbContext dbc, CmsResource resource,
07881:                    long dateExpired) throws CmsDataAccessException {
07882:
07883:                resource.setDateExpired(dateExpired);
07884:                if (resource.getState().isUnchanged()) {
07885:                    resource.setState(CmsResource.STATE_CHANGED);
07886:                }
07887:                m_vfsDriver.writeResourceState(dbc, dbc.currentProject(),
07888:                        resource, UPDATE_STRUCTURE, false);
07889:
07890:                // modify the last modified project reference
07891:                m_vfsDriver.writeResourceState(dbc, dbc.currentProject(),
07892:                        resource, UPDATE_RESOURCE_PROJECT, false);
07893:
07894:                // clear the cache
07895:                OpenCms.getMemoryMonitor().clearResourceCache();
07896:
07897:                // fire the event
07898:                HashMap data = new HashMap(2);
07899:                data.put("resource", resource);
07900:                data.put("change", new Integer(CHANGED_TIMEFRAME));
07901:                OpenCms.fireCmsEvent(new CmsEvent(
07902:                        I_CmsEventListener.EVENT_RESOURCE_MODIFIED, data));
07903:            }
07904:
07905:            /**
07906:             * Changes the "last modified" timestamp of a resource.<p>
07907:             * 
07908:             * @param dbc the current database context
07909:             * @param resource the resource to touch
07910:             * @param dateLastModified the new last modified date of the resource
07911:             * 
07912:             * @throws CmsDataAccessException if something goes wrong
07913:             * 
07914:             * @see CmsObject#setDateLastModified(String, long, boolean)
07915:             * @see I_CmsResourceType#setDateLastModified(CmsObject, CmsSecurityManager, CmsResource, long, boolean)
07916:             */
07917:            public void setDateLastModified(CmsDbContext dbc,
07918:                    CmsResource resource, long dateLastModified)
07919:                    throws CmsDataAccessException {
07920:
07921:                // modify the last modification date
07922:                resource.setDateLastModified(dateLastModified);
07923:                if (resource.getState().isUnchanged()) {
07924:                    resource.setState(CmsResource.STATE_CHANGED);
07925:                } else if (resource.getState().isNew()
07926:                        && (resource.getSiblingCount() > 1)) {
07927:                    // in case of new resources with siblings make sure the state is correct
07928:                    resource.setState(CmsResource.STATE_CHANGED);
07929:                }
07930:                resource.setUserLastModified(dbc.currentUser().getId());
07931:                m_vfsDriver.writeResourceState(dbc, dbc.currentProject(),
07932:                        resource, UPDATE_RESOURCE, false);
07933:
07934:                // clear the cache
07935:                OpenCms.getMemoryMonitor().clearResourceCache();
07936:
07937:                // fire the event
07938:                HashMap data = new HashMap(2);
07939:                data.put("resource", resource);
07940:                data.put("change", new Integer(CHANGED_LASTMODIFIED));
07941:                OpenCms.fireCmsEvent(new CmsEvent(
07942:                        I_CmsEventListener.EVENT_RESOURCE_MODIFIED, data));
07943:            }
07944:
07945:            /**
07946:             * Changes the "release" date of a resource.<p>
07947:             * 
07948:             * @param dbc the current database context
07949:             * @param resource the resource to touch
07950:             * @param dateReleased the new release date of the resource
07951:             * 
07952:             * @throws CmsDataAccessException if something goes wrong
07953:             * 
07954:             * @see CmsObject#setDateReleased(String, long, boolean)
07955:             * @see I_CmsResourceType#setDateReleased(CmsObject, CmsSecurityManager, CmsResource, long, boolean)
07956:             */
07957:            public void setDateReleased(CmsDbContext dbc, CmsResource resource,
07958:                    long dateReleased) throws CmsDataAccessException {
07959:
07960:                // modify the last modification date
07961:                resource.setDateReleased(dateReleased);
07962:                if (resource.getState().isUnchanged()) {
07963:                    resource.setState(CmsResource.STATE_CHANGED);
07964:                }
07965:                m_vfsDriver.writeResourceState(dbc, dbc.currentProject(),
07966:                        resource, UPDATE_STRUCTURE, false);
07967:
07968:                // modify the last modified project reference
07969:                m_vfsDriver.writeResourceState(dbc, dbc.currentProject(),
07970:                        resource, UPDATE_RESOURCE_PROJECT, false);
07971:
07972:                // clear the cache
07973:                OpenCms.getMemoryMonitor().clearResourceCache();
07974:
07975:                // fire the event
07976:                HashMap data = new HashMap(2);
07977:                data.put("resource", resource);
07978:                data.put("change", new Integer(CHANGED_TIMEFRAME));
07979:                OpenCms.fireCmsEvent(new CmsEvent(
07980:                        I_CmsEventListener.EVENT_RESOURCE_MODIFIED, data));
07981:            }
07982:
07983:            /**
07984:             * Sets a new parent group for an already existing group.<p>
07985:             *
07986:             * @param dbc the current database context
07987:             * @param groupName the name of the group that should be written
07988:             * @param parentGroupName the name of the parent group to set, 
07989:             *                      or <code>null</code> if the parent
07990:             *                      group should be deleted.
07991:             *
07992:             * @throws CmsException if operation was not successful
07993:             * @throws CmsDataAccessException if the group with <code>groupName</code> could not be read from VFS
07994:             */
07995:            public void setParentGroup(CmsDbContext dbc, String groupName,
07996:                    String parentGroupName) throws CmsException,
07997:                    CmsDataAccessException {
07998:
07999:                CmsGroup group = readGroup(dbc, groupName);
08000:                CmsUUID parentGroupId = CmsUUID.getNullUUID();
08001:
08002:                // if the group exists, use its id, else set to unknown.
08003:                if (parentGroupName != null) {
08004:                    parentGroupId = readGroup(dbc, parentGroupName).getId();
08005:                }
08006:
08007:                group.setParentId(parentGroupId);
08008:
08009:                // write the changes to the cms
08010:                writeGroup(dbc, group);
08011:            }
08012:
08013:            /**
08014:             * Sets the password for a user.<p>
08015:             *
08016:             * @param dbc the current database context
08017:             * @param username the name of the user
08018:             * @param newPassword the new password
08019:             * 
08020:             * @throws CmsException if operation was not successful
08021:             * @throws CmsIllegalArgumentException if the user with the <code>username</code> was not found
08022:             */
08023:            public void setPassword(CmsDbContext dbc, String username,
08024:                    String newPassword) throws CmsException,
08025:                    CmsIllegalArgumentException {
08026:
08027:                validatePassword(newPassword);
08028:
08029:                // read the user as a system user to verify that the specified old password is correct
08030:                m_userDriver.readUser(dbc, username);
08031:                // only continue if not found and read user from web might succeed
08032:                m_userDriver.writePassword(dbc, username, null, newPassword);
08033:            }
08034:
08035:            /**
08036:             * Moves an user to the given organizational unit.<p>
08037:             * 
08038:             * @param dbc the current db context
08039:             * @param orgUnit the organizational unit to add the resource to
08040:             * @param user the user that is to be moved to the organizational unit
08041:             * 
08042:             * @throws CmsException if something goes wrong
08043:             * 
08044:             * @see org.opencms.security.CmsOrgUnitManager#setUsersOrganizationalUnit(CmsObject, String, String)
08045:             */
08046:            public void setUsersOrganizationalUnit(CmsDbContext dbc,
08047:                    CmsOrganizationalUnit orgUnit, CmsUser user)
08048:                    throws CmsException {
08049:
08050:                if (!getGroupsOfUser(dbc, user.getName(), false).isEmpty()) {
08051:                    throw new CmsDbConsistencyException(Messages.get()
08052:                            .container(Messages.ERR_ORGUNIT_MOVE_USER_2,
08053:                                    orgUnit.getName(), user.getName()));
08054:                }
08055:
08056:                // move the principal
08057:                m_userDriver.setUsersOrganizationalUnit(dbc, orgUnit, user);
08058:                // remove the principal from cache
08059:                OpenCms.getMemoryMonitor().clearUserCache(user);
08060:            }
08061:
08062:            /**
08063:             * Undelete the resource.<p>
08064:             * 
08065:             * @param dbc the current database context
08066:             * @param resource the name of the resource to apply this operation to
08067:             * 
08068:             * @throws CmsException if something goes wrong
08069:             * 
08070:             * @see CmsObject#undeleteResource(String, boolean)
08071:             * @see I_CmsResourceType#undelete(CmsObject, CmsSecurityManager, CmsResource, boolean)
08072:             */
08073:            public void undelete(CmsDbContext dbc, CmsResource resource)
08074:                    throws CmsException {
08075:
08076:                if (!resource.getState().isDeleted()) {
08077:                    throw new CmsVfsException(Messages.get().container(
08078:                            Messages.ERR_UNDELETE_FOR_RESOURCE_DELETED_1,
08079:                            dbc.removeSiteRoot(resource.getRootPath())));
08080:                }
08081:
08082:                // set the state to changed
08083:                resource.setState(CmsResourceState.STATE_CHANGED);
08084:                // perform the changes
08085:                updateState(dbc, resource, false);
08086:
08087:                // clear the cache
08088:                OpenCms.getMemoryMonitor().clearResourceCache();
08089:
08090:                // fire change event
08091:                HashMap data = new HashMap(2);
08092:                data.put("resource", resource);
08093:                data.put("change", new Integer(CHANGED_RESOURCE));
08094:                OpenCms.fireCmsEvent(new CmsEvent(
08095:                        I_CmsEventListener.EVENT_RESOURCE_MODIFIED, data));
08096:            }
08097:
08098:            /**
08099:             * Undos all changes in the resource by restoring the version from the 
08100:             * online project to the current offline project.<p>
08101:             * 
08102:             * @param dbc the current database context
08103:             * @param resource the name of the resource to apply this operation to
08104:             * @param mode the undo mode, one of the <code>{@link org.opencms.file.CmsResource.CmsResourceUndoMode}#UNDO_XXX</code> constants 
08105:             *      please note that the recursive flag is ignored at this level
08106:             * 
08107:             * @throws CmsException if something goes wrong
08108:             * 
08109:             * @see CmsObject#undoChanges(String, CmsResource.CmsResourceUndoMode)
08110:             * @see I_CmsResourceType#undoChanges(CmsObject, CmsSecurityManager, CmsResource, CmsResource.CmsResourceUndoMode)
08111:             */
08112:            public void undoChanges(CmsDbContext dbc, CmsResource resource,
08113:                    CmsResource.CmsResourceUndoMode mode) throws CmsException {
08114:
08115:                if (resource.getState().isNew()) {
08116:                    // undo changes is impossible on a new resource
08117:                    throw new CmsVfsException(Messages.get().container(
08118:                            Messages.ERR_UNDO_CHANGES_FOR_RESOURCE_NEW_0));
08119:                }
08120:
08121:                // we need this for later use
08122:                CmsProject onlineProject = readProject(dbc,
08123:                        CmsProject.ONLINE_PROJECT_ID);
08124:                // read the resource from the online project
08125:                CmsResource onlineResource = m_vfsDriver.readResource(dbc,
08126:                        CmsProject.ONLINE_PROJECT_ID,
08127:                        resource.getStructureId(), true);
08128:
08129:                CmsResource onlineResourceByPath = null;
08130:                try {
08131:                    // this is needed to figure out if a moved resource overwrote a deleted one
08132:                    onlineResourceByPath = m_vfsDriver.readResource(dbc,
08133:                            CmsProject.ONLINE_PROJECT_ID, resource
08134:                                    .getRootPath(), true);
08135:
08136:                    // force undo move operation if needed
08137:                    if (!mode.isUndoMove()
08138:                            && !onlineResourceByPath.getRootPath().equals(
08139:                                    onlineResource.getRootPath())) {
08140:                        mode = mode.includeMove();
08141:                    }
08142:                } catch (Exception e) {
08143:                    // ok
08144:                }
08145:
08146:                boolean moved = !onlineResource.getRootPath().equals(
08147:                        resource.getRootPath());
08148:                // undo move operation if required
08149:                if (moved && mode.isUndoMove()) {
08150:                    moveResource(dbc, resource, onlineResource.getRootPath(),
08151:                            true);
08152:                    if ((onlineResourceByPath != null)
08153:                            && !onlineResourceByPath.getRootPath().equals(
08154:                                    onlineResource.getRootPath())) {
08155:                        // was moved over deleted, so the deleted file has to be undone
08156:                        undoContentChanges(dbc, onlineProject, null,
08157:                                onlineResourceByPath,
08158:                                CmsResource.STATE_UNCHANGED, true);
08159:                    }
08160:                }
08161:                // undo content changes
08162:                CmsResourceState newState = CmsResource.STATE_UNCHANGED;
08163:                if (moved && !mode.isUndoMove()) {
08164:                    newState = CmsResource.STATE_CHANGED;
08165:                }
08166:                undoContentChanges(dbc, onlineProject, resource,
08167:                        onlineResource, newState, moved && mode.isUndoMove());
08168:            }
08169:
08170:            /**
08171:             * Unlocks all resources in the given project.<p>
08172:             * 
08173:             * @param project the project to unlock the resources in
08174:             */
08175:            public void unlockProject(CmsProject project) {
08176:
08177:                // unlock all resources in the project
08178:                m_lockManager
08179:                        .removeResourcesInProject(project.getUuid(), false);
08180:                OpenCms.getMemoryMonitor().clearResourceCache();
08181:                OpenCms.getMemoryMonitor().flushProjects();
08182:                // we must also clear the permission cache
08183:                OpenCms.getMemoryMonitor().flushPermissions();
08184:            }
08185:
08186:            /**
08187:             * Unlocks a resource.<p>
08188:             * 
08189:             * @param dbc the current database context
08190:             * @param resource the resource to unlock
08191:             * @param force <code>true</code>, if a resource is forced to get unlocked, no matter by which user and in which project the resource is currently locked
08192:             * @param removeSystemLock <code>true</code>, if you also want to remove system locks
08193:             * 
08194:             * @throws CmsException if something goes wrong
08195:             * 
08196:             * @see CmsObject#unlockResource(String)
08197:             * @see I_CmsResourceType#unlockResource(CmsObject, CmsSecurityManager, CmsResource)
08198:             */
08199:            public void unlockResource(CmsDbContext dbc, CmsResource resource,
08200:                    boolean force, boolean removeSystemLock)
08201:                    throws CmsException {
08202:
08203:                // update the resource cache
08204:                OpenCms.getMemoryMonitor().clearResourceCache();
08205:
08206:                // now update lock status
08207:                m_lockManager.removeResource(dbc, resource, force,
08208:                        removeSystemLock);
08209:
08210:                // we must also clear the permission cache
08211:                OpenCms.getMemoryMonitor().flushPermissions();
08212:
08213:                // fire resource modification event
08214:                HashMap data = new HashMap(2);
08215:                data.put("resource", resource);
08216:                data.put("change", new Integer(NOTHING_CHANGED));
08217:                OpenCms.fireCmsEvent(new CmsEvent(
08218:                        I_CmsEventListener.EVENT_RESOURCE_MODIFIED, data));
08219:            }
08220:
08221:            /**
08222:             * Update the export points.<p>
08223:             * 
08224:             * All files and folders "inside" an export point are written.<p>
08225:             * 
08226:             * @param dbc the current database context
08227:             */
08228:            public void updateExportPoints(CmsDbContext dbc) {
08229:
08230:                try {
08231:                    // read the export points and return immediately if there are no export points at all         
08232:                    Set exportPoints = new HashSet();
08233:                    exportPoints.addAll(OpenCms.getExportPoints());
08234:                    exportPoints.addAll(OpenCms.getModuleManager()
08235:                            .getExportPoints());
08236:                    if (exportPoints.size() == 0) {
08237:                        if (LOG.isWarnEnabled()) {
08238:                            LOG
08239:                                    .warn(Messages
08240:                                            .get()
08241:                                            .getBundle()
08242:                                            .key(
08243:                                                    Messages.LOG_NO_EXPORT_POINTS_CONFIGURED_0));
08244:                        }
08245:                        return;
08246:                    }
08247:
08248:                    // create the driver to write the export points
08249:                    CmsExportPointDriver exportPointDriver = new CmsExportPointDriver(
08250:                            exportPoints);
08251:
08252:                    // the export point hash table contains RFS export paths keyed by their internal VFS paths
08253:                    Iterator i = exportPointDriver.getExportPointPaths()
08254:                            .iterator();
08255:                    while (i.hasNext()) {
08256:                        String currentExportPoint = (String) i.next();
08257:
08258:                        // print some report messages
08259:                        if (LOG.isInfoEnabled()) {
08260:                            LOG.info(Messages.get().getBundle().key(
08261:                                    Messages.LOG_WRITE_EXPORT_POINT_1,
08262:                                    currentExportPoint));
08263:                        }
08264:
08265:                        try {
08266:                            CmsResourceFilter filter = CmsResourceFilter.DEFAULT;
08267:                            List resources = m_vfsDriver
08268:                                    .readResourceTree(
08269:                                            dbc,
08270:                                            CmsProject.ONLINE_PROJECT_ID,
08271:                                            currentExportPoint,
08272:                                            filter.getType(),
08273:                                            filter.getState(),
08274:                                            filter.getModifiedAfter(),
08275:                                            filter.getModifiedBefore(),
08276:                                            filter.getReleaseAfter(),
08277:                                            filter.getReleaseBefore(),
08278:                                            filter.getExpireAfter(),
08279:                                            filter.getExpireBefore(),
08280:                                            CmsDriverManager.READMODE_INCLUDE_TREE
08281:                                                    | (filter.excludeType() ? CmsDriverManager.READMODE_EXCLUDE_TYPE
08282:                                                            : 0)
08283:                                                    | (filter.excludeState() ? CmsDriverManager.READMODE_EXCLUDE_STATE
08284:                                                            : 0));
08285:
08286:                            Iterator j = resources.iterator();
08287:                            while (j.hasNext()) {
08288:                                CmsResource currentResource = (CmsResource) j
08289:                                        .next();
08290:
08291:                                if (currentResource.isFolder()) {
08292:                                    // export the folder                        
08293:                                    exportPointDriver.createFolder(
08294:                                            currentResource.getRootPath(),
08295:                                            currentExportPoint);
08296:                                } else {
08297:                                    // try to create the exportpoint folder
08298:                                    exportPointDriver.createFolder(
08299:                                            currentExportPoint,
08300:                                            currentExportPoint);
08301:                                    byte[] onlineContent = getVfsDriver()
08302:                                            .readContent(
08303:                                                    dbc,
08304:                                                    CmsProject.ONLINE_PROJECT_ID,
08305:                                                    currentResource
08306:                                                            .getResourceId());
08307:                                    // export the file content online
08308:                                    exportPointDriver.writeFile(currentResource
08309:                                            .getRootPath(), currentExportPoint,
08310:                                            onlineContent);
08311:                                }
08312:                            }
08313:                        } catch (CmsException e) {
08314:                            // there might exist export points without corresponding resources in the VFS
08315:                            // -> ignore exceptions which are not "resource not found" exception quiet here
08316:                            if (e instanceof  CmsVfsResourceNotFoundException) {
08317:                                if (LOG.isErrorEnabled()) {
08318:                                    LOG
08319:                                            .error(
08320:                                                    Messages
08321:                                                            .get()
08322:                                                            .getBundle()
08323:                                                            .key(
08324:                                                                    Messages.LOG_UPDATE_EXORT_POINTS_ERROR_0),
08325:                                                    e);
08326:                                }
08327:                            }
08328:                        }
08329:                    }
08330:                } catch (Exception e) {
08331:                    if (LOG.isErrorEnabled()) {
08332:                        LOG.error(Messages.get().getBundle().key(
08333:                                Messages.LOG_UPDATE_EXORT_POINTS_ERROR_0), e);
08334:                    }
08335:                }
08336:            }
08337:
08338:            /**
08339:             * Updates/Creates the given relations for the given resource.<p>
08340:             * 
08341:             * @param dbc the db context
08342:             * @param resource the resource to update the relations for
08343:             * @param links the links to consider for updating
08344:             * 
08345:             * @throws CmsException if something goes wrong
08346:             * 
08347:             * @see CmsSecurityManager#updateRelationsForResource(CmsRequestContext, CmsResource, List)
08348:             */
08349:            public void updateRelationsForResource(CmsDbContext dbc,
08350:                    CmsResource resource, List links) throws CmsException {
08351:
08352:                deleteRelationsWithSiblings(dbc, resource);
08353:
08354:                // build the links again only if needed
08355:                if ((links == null) || links.isEmpty()) {
08356:                    return;
08357:                }
08358:                // the set of written relations
08359:                Set writtenRelations = new HashSet();
08360:
08361:                // create new relation information
08362:                Iterator itLinks = links.iterator();
08363:                while (itLinks.hasNext()) {
08364:                    CmsLink link = (CmsLink) itLinks.next();
08365:                    if (link.isInternal()) { // only update internal links
08366:                        if (CmsStringUtil.isEmptyOrWhitespaceOnly(link
08367:                                .getTarget())) {
08368:                            // only an anchor
08369:                            continue;
08370:                        }
08371:                        CmsRelation originalRelation;
08372:                        try {
08373:                            // get the target resource
08374:                            CmsResource target = readResource(dbc, link
08375:                                    .getTarget(), CmsResourceFilter.ALL);
08376:                            originalRelation = new CmsRelation(resource,
08377:                                    target, link.getType());
08378:                        } catch (Exception e) {
08379:                            // if link is broken maintain name and default time window
08380:                            originalRelation = new CmsRelation(resource
08381:                                    .getStructureId(), resource.getRootPath(),
08382:                                    CmsUUID.getNullUUID(), link.getTarget(),
08383:                                    link.getType());
08384:                        }
08385:                        // do not write twice the same relation
08386:                        if (writtenRelations.contains(originalRelation)) {
08387:                            continue;
08388:                        }
08389:                        writtenRelations.add(originalRelation);
08390:
08391:                        // create the relations in content for all siblings 
08392:                        Iterator itSiblings = readSiblings(dbc, resource,
08393:                                CmsResourceFilter.ALL).iterator();
08394:                        while (itSiblings.hasNext()) {
08395:                            CmsResource sibling = (CmsResource) itSiblings
08396:                                    .next();
08397:                            CmsRelation relation = new CmsRelation(sibling
08398:                                    .getStructureId(), sibling.getRootPath(),
08399:                                    originalRelation.getTargetId(),
08400:                                    originalRelation.getTargetPath(), link
08401:                                            .getType());
08402:                            m_vfsDriver.createRelation(dbc, dbc
08403:                                    .currentProject().getUuid(), relation);
08404:                        }
08405:                    }
08406:                }
08407:            }
08408:
08409:            /**
08410:             * Returns <code>true</code> if a user is member of the given group.<p>
08411:             * 
08412:             * @param dbc the current database context
08413:             * @param username the name of the user to check
08414:             * @param groupname the name of the group to check
08415:             * @param readRoles if to read roles or groups
08416:             *
08417:             * @return <code>true</code>, if the user is in the group, <code>false</code> otherwise
08418:             * 
08419:             * @throws CmsException if something goes wrong
08420:             */
08421:            public boolean userInGroup(CmsDbContext dbc, String username,
08422:                    String groupname, boolean readRoles) throws CmsException {
08423:
08424:                List groups = getGroupsOfUser(dbc, username, readRoles);
08425:                for (int i = 0; i < groups.size(); i++) {
08426:                    CmsGroup group = (CmsGroup) groups.get(i);
08427:                    if (groupname.equals(group.getName())
08428:                            || groupname.substring(1).equals(group.getName())) {
08429:                        return true;
08430:                    }
08431:                }
08432:                return false;
08433:            }
08434:
08435:            /**
08436:             * This method checks if a new password follows the rules for
08437:             * new passwords, which are defined by a Class implementing the 
08438:             * <code>{@link org.opencms.security.I_CmsPasswordHandler}</code> 
08439:             * interface and configured in the opencms.properties file.<p>
08440:             * 
08441:             * If this method throws no exception the password is valid.<p>
08442:             *
08443:             * @param password the new password that has to be checked
08444:             * 
08445:             * @throws CmsSecurityException if the password is not valid
08446:             */
08447:            public void validatePassword(String password)
08448:                    throws CmsSecurityException {
08449:
08450:                OpenCms.getPasswordHandler().validatePassword(password);
08451:            }
08452:
08453:            /**
08454:             * Validates the relations for the given resources.<p>
08455:             * 
08456:             * @param dbc the database context
08457:             * @param publishList the resources to validate during publishing 
08458:             * @param report a report to write the messages to
08459:             * 
08460:             * @return a map with lists of invalid links 
08461:             *          (<code>{@link org.opencms.relations.CmsRelation}}</code> objects) 
08462:             *          keyed by root paths
08463:             * 
08464:             * @throws Exception if something goes wrong
08465:             */
08466:            public Map validateRelations(CmsDbContext dbc,
08467:                    CmsPublishList publishList, I_CmsReport report)
08468:                    throws Exception {
08469:
08470:                return m_htmlLinkValidator.validateResources(dbc, publishList,
08471:                        report);
08472:            }
08473:
08474:            /**
08475:             * Writes an access control entries to a given resource.<p>
08476:             * 
08477:             * @param dbc the current database context
08478:             * @param resource the resource
08479:             * @param ace the entry to write
08480:             * 
08481:             * @throws CmsException if something goes wrong
08482:             */
08483:            public void writeAccessControlEntry(CmsDbContext dbc,
08484:                    CmsResource resource, CmsAccessControlEntry ace)
08485:                    throws CmsException {
08486:
08487:                // write the new ace
08488:                m_userDriver.writeAccessControlEntry(dbc, dbc.currentProject(),
08489:                        ace);
08490:
08491:                // update the "last modified" information
08492:                setDateLastModified(dbc, resource, resource
08493:                        .getDateLastModified());
08494:
08495:                // clear the cache
08496:                OpenCms.getMemoryMonitor().clearAccessControlListCache();
08497:
08498:                // fire a resource modification event
08499:                HashMap data = new HashMap(2);
08500:                data.put("resource", resource);
08501:                data.put("change", new Integer(CHANGED_ACCESSCONTROL));
08502:                OpenCms.fireCmsEvent(new CmsEvent(
08503:                        I_CmsEventListener.EVENT_RESOURCE_MODIFIED, data));
08504:            }
08505:
08506:            /**
08507:             * Writes all export points into the file system for the publish task 
08508:             * specified by trhe given publish history ID.<p>
08509:             * 
08510:             * @param dbc the current database context
08511:             * @param report an I_CmsReport instance to print output message, or null to write messages to the log file
08512:             * @param publishHistoryId ID to identify the publish task in the publish history
08513:             */
08514:            public void writeExportPoints(CmsDbContext dbc, I_CmsReport report,
08515:                    CmsUUID publishHistoryId) {
08516:
08517:                boolean printReportHeaders = false;
08518:                List publishedResources = null;
08519:                try {
08520:                    // read the "published resources" for the specified publish history ID
08521:                    publishedResources = m_projectDriver
08522:                            .readPublishedResources(dbc, publishHistoryId);
08523:                } catch (CmsException e) {
08524:                    if (LOG.isErrorEnabled()) {
08525:                        LOG.error(Messages.get().getBundle().key(
08526:                                Messages.ERR_READ_PUBLISHED_RESOURCES_FOR_ID_1,
08527:                                publishHistoryId), e);
08528:                    }
08529:                }
08530:                if ((publishedResources == null)
08531:                        || publishedResources.isEmpty()) {
08532:                    if (LOG.isWarnEnabled()) {
08533:                        LOG.warn(Messages.get().getBundle().key(
08534:                                Messages.LOG_EMPTY_PUBLISH_HISTORY_1,
08535:                                publishHistoryId));
08536:                    }
08537:                    return;
08538:                }
08539:
08540:                // read the export points and return immediately if there are no export points at all         
08541:                Set exportPoints = new HashSet();
08542:                exportPoints.addAll(OpenCms.getExportPoints());
08543:                exportPoints.addAll(OpenCms.getModuleManager()
08544:                        .getExportPoints());
08545:                if (exportPoints.size() == 0) {
08546:                    if (LOG.isWarnEnabled()) {
08547:                        LOG.warn(Messages.get().getBundle().key(
08548:                                Messages.LOG_NO_EXPORT_POINTS_CONFIGURED_0));
08549:                    }
08550:                    return;
08551:                }
08552:
08553:                // create the driver to write the export points
08554:                CmsExportPointDriver exportPointDriver = new CmsExportPointDriver(
08555:                        exportPoints);
08556:
08557:                // the report may be null if the export point write was started by an event
08558:                if (report == null) {
08559:                    if (dbc.getRequestContext() != null) {
08560:                        report = new CmsLogReport(dbc.getRequestContext()
08561:                                .getLocale(), getClass());
08562:                    } else {
08563:                        report = new CmsLogReport(CmsLocaleManager
08564:                                .getDefaultLocale(), getClass());
08565:                    }
08566:                }
08567:
08568:                // iterate over all published resources to export them
08569:                Iterator i = publishedResources.iterator();
08570:                while (i.hasNext()) {
08571:                    CmsPublishedResource currentPublishedResource = (CmsPublishedResource) i
08572:                            .next();
08573:                    String currentExportPoint = exportPointDriver
08574:                            .getExportPoint(currentPublishedResource
08575:                                    .getRootPath());
08576:
08577:                    if (currentExportPoint != null) {
08578:                        if (!printReportHeaders) {
08579:                            report.println(Messages.get().container(
08580:                                    Messages.RPT_EXPORT_POINTS_WRITE_BEGIN_0),
08581:                                    I_CmsReport.FORMAT_HEADLINE);
08582:                            printReportHeaders = true;
08583:                        }
08584:
08585:                        // print report message
08586:                        if (currentPublishedResource.getState().isDeleted()) {
08587:                            report.print(Messages.get().container(
08588:                                    Messages.RPT_EXPORT_POINTS_DELETE_0),
08589:                                    I_CmsReport.FORMAT_NOTE);
08590:                        } else {
08591:                            report.print(Messages.get().container(
08592:                                    Messages.RPT_EXPORT_POINTS_WRITE_0),
08593:                                    I_CmsReport.FORMAT_NOTE);
08594:                        }
08595:                        report
08596:                                .print(org.opencms.report.Messages
08597:                                        .get()
08598:                                        .container(
08599:                                                org.opencms.report.Messages.RPT_ARGUMENT_1,
08600:                                                currentPublishedResource
08601:                                                        .getRootPath()));
08602:                        report
08603:                                .print(org.opencms.report.Messages
08604:                                        .get()
08605:                                        .container(
08606:                                                org.opencms.report.Messages.RPT_DOTS_0));
08607:
08608:                        if (currentPublishedResource.isFolder()) {
08609:                            // export the folder                        
08610:                            if (currentPublishedResource.getState().isDeleted()) {
08611:                                exportPointDriver.deleteResource(
08612:                                        currentPublishedResource.getRootPath(),
08613:                                        currentExportPoint);
08614:                            } else {
08615:                                exportPointDriver.createFolder(
08616:                                        currentPublishedResource.getRootPath(),
08617:                                        currentExportPoint);
08618:                            }
08619:                            report
08620:                                    .println(
08621:                                            org.opencms.report.Messages
08622:                                                    .get()
08623:                                                    .container(
08624:                                                            org.opencms.report.Messages.RPT_OK_0),
08625:                                            I_CmsReport.FORMAT_OK);
08626:                        } else {
08627:                            // export the file            
08628:                            try {
08629:                                if (currentPublishedResource.getState()
08630:                                        .isDeleted()) {
08631:                                    exportPointDriver.deleteResource(
08632:                                            currentPublishedResource
08633:                                                    .getRootPath(),
08634:                                            currentExportPoint);
08635:                                } else {
08636:                                    // read the file content online
08637:                                    byte[] onlineContent = getVfsDriver()
08638:                                            .readContent(
08639:                                                    dbc,
08640:                                                    CmsProject.ONLINE_PROJECT_ID,
08641:                                                    currentPublishedResource
08642:                                                            .getResourceId());
08643:                                    exportPointDriver.writeFile(
08644:                                            currentPublishedResource
08645:                                                    .getRootPath(),
08646:                                            currentExportPoint, onlineContent);
08647:                                }
08648:                                report
08649:                                        .println(
08650:                                                org.opencms.report.Messages
08651:                                                        .get()
08652:                                                        .container(
08653:                                                                org.opencms.report.Messages.RPT_OK_0),
08654:                                                I_CmsReport.FORMAT_OK);
08655:                            } catch (CmsException e) {
08656:                                if (LOG.isErrorEnabled()) {
08657:                                    LOG
08658:                                            .error(
08659:                                                    Messages
08660:                                                            .get()
08661:                                                            .getBundle()
08662:                                                            .key(
08663:                                                                    Messages.LOG_WRITE_EXPORT_POINT_ERROR_1,
08664:                                                                    currentPublishedResource
08665:                                                                            .getRootPath()),
08666:                                                    e);
08667:                                }
08668:                                report
08669:                                        .println(
08670:                                                org.opencms.report.Messages
08671:                                                        .get()
08672:                                                        .container(
08673:                                                                org.opencms.report.Messages.RPT_FAILED_0),
08674:                                                I_CmsReport.FORMAT_ERROR);
08675:                            }
08676:                        }
08677:                    }
08678:                }
08679:                if (printReportHeaders) {
08680:                    report.println(Messages.get().container(
08681:                            Messages.RPT_EXPORT_POINTS_WRITE_END_0),
08682:                            I_CmsReport.FORMAT_HEADLINE);
08683:                }
08684:            }
08685:
08686:            /**
08687:             * Writes a resource to the OpenCms VFS, including it's content.<p>
08688:             * 
08689:             * Applies only to resources of type <code>{@link CmsFile}</code>
08690:             * i.e. resources that have a binary content attached.<p>
08691:             * 
08692:             * Certain resource types might apply content validation or transformation rules 
08693:             * before the resource is actually written to the VFS. The returned result
08694:             * might therefore be a modified version from the provided original.<p>
08695:             * 
08696:             * @param dbc the current database context
08697:             * @param resource the resource to apply this operation to
08698:             * 
08699:             * @return the written resource (may have been modified)
08700:             *
08701:             * @throws CmsException if something goes wrong
08702:             * 
08703:             * @see CmsObject#writeFile(CmsFile)
08704:             * @see I_CmsResourceType#writeFile(CmsObject, CmsSecurityManager, CmsFile)
08705:             */
08706:            public CmsFile writeFile(CmsDbContext dbc, CmsFile resource)
08707:                    throws CmsException {
08708:
08709:                resource.setUserLastModified(dbc.currentUser().getId());
08710:                resource.setContents(resource.getContents()); // to be sure the content date is updated
08711:
08712:                m_vfsDriver.writeResource(dbc, dbc.currentProject().getUuid(),
08713:                        resource, UPDATE_RESOURCE_STATE);
08714:
08715:                byte[] contents = resource.getContents();
08716:                m_vfsDriver.writeContent(dbc, resource.getResourceId(),
08717:                        contents);
08718:
08719:                // read the file back from db
08720:                resource = new CmsFile(readResource(dbc, resource
08721:                        .getStructureId(), CmsResourceFilter.ALL));
08722:                resource.setContents(contents);
08723:
08724:                deleteRelationsWithSiblings(dbc, resource);
08725:
08726:                // update the cache
08727:                OpenCms.getMemoryMonitor().clearResourceCache();
08728:
08729:                HashMap data = new HashMap(2);
08730:                data.put("resource", resource);
08731:                data.put("change", new Integer(CHANGED_CONTENT));
08732:                OpenCms.fireCmsEvent(new CmsEvent(
08733:                        I_CmsEventListener.EVENT_RESOURCE_MODIFIED, data));
08734:
08735:                return resource;
08736:            }
08737:
08738:            /**
08739:             * Writes an already existing group.<p>
08740:             *
08741:             * The group id has to be a valid OpenCms group id.<br>
08742:             * 
08743:             * The group with the given id will be completely overridden
08744:             * by the given data.<p>
08745:             * 
08746:             * @param dbc the current database context
08747:             * @param group the group that should be written
08748:             * 
08749:             * @throws CmsException if operation was not successful
08750:             */
08751:            public void writeGroup(CmsDbContext dbc, CmsGroup group)
08752:                    throws CmsException {
08753:
08754:                OpenCms.getMemoryMonitor().uncacheGroup(group);
08755:                m_userDriver.writeGroup(dbc, group);
08756:                OpenCms.getMemoryMonitor().cacheGroup(group);
08757:            }
08758:
08759:            /**
08760:             * Creates an historical entry of the current project.<p>
08761:             * 
08762:             * @param dbc the current database context
08763:             * @param publishTag the version
08764:             * @param publishDate the date of publishing
08765:             *
08766:             * @throws CmsDataAccessException if operation was not successful
08767:             */
08768:            public void writeHistoryProject(CmsDbContext dbc, int publishTag,
08769:                    long publishDate) throws CmsDataAccessException {
08770:
08771:                m_historyDriver.writeProject(dbc, publishTag, publishDate);
08772:            }
08773:
08774:            /**
08775:             * Writes the locks that are currently stored in-memory to the database to allow restoring them  
08776:             * in future server startups.<p> 
08777:             * 
08778:             * This overwrites the locks previously stored in the underlying database table.<p>
08779:             * 
08780:             * @param dbc the current database context 
08781:             * 
08782:             * @throws CmsException if something goes wrong 
08783:             */
08784:            public void writeLocks(CmsDbContext dbc) throws CmsException {
08785:
08786:                m_lockManager.writeLocks(dbc);
08787:            }
08788:
08789:            /**
08790:             * Writes an already existing organizational unit.<p>
08791:             *
08792:             * The organizational unit id has to be a valid OpenCms organizational unit id.<br>
08793:             * 
08794:             * The organizational unit with the given id will be completely overridden
08795:             * by the given data.<p>
08796:             *
08797:             * @param dbc the current db context
08798:             * @param organizationalUnit the organizational unit that should be written
08799:             * 
08800:             * @throws CmsException if operation was not successful
08801:             * 
08802:             * @see org.opencms.security.CmsOrgUnitManager#writeOrganizationalUnit(CmsObject, CmsOrganizationalUnit)
08803:             */
08804:            public void writeOrganizationalUnit(CmsDbContext dbc,
08805:                    CmsOrganizationalUnit organizationalUnit)
08806:                    throws CmsException {
08807:
08808:                OpenCms.getMemoryMonitor().uncacheOrgUnit(organizationalUnit);
08809:                m_userDriver.writeOrganizationalUnit(dbc, organizationalUnit);
08810:                OpenCms.getMemoryMonitor().cacheOrgUnit(organizationalUnit);
08811:            }
08812:
08813:            /**
08814:             * Writes an already existing project.<p>
08815:             *
08816:             * The project id has to be a valid OpenCms project id.<br>
08817:             * 
08818:             * The project with the given id will be completely overridden
08819:             * by the given data.<p>
08820:             *
08821:             * @param dbc the current database context
08822:             * @param project the project that should be written
08823:             * 
08824:             * @throws CmsException if operation was not successful
08825:             */
08826:            public void writeProject(CmsDbContext dbc, CmsProject project)
08827:                    throws CmsException {
08828:
08829:                OpenCms.getMemoryMonitor().uncacheProject(project);
08830:                m_projectDriver.writeProject(dbc, project);
08831:                OpenCms.getMemoryMonitor().cacheProject(project);
08832:            }
08833:
08834:            /**
08835:             * Writes a property for a specified resource.<p>
08836:             * 
08837:             * @param dbc the current database context
08838:             * @param resource the resource to write the property for
08839:             * @param property the property to write
08840:             * 
08841:             * @throws CmsException if something goes wrong
08842:             * 
08843:             * @see CmsObject#writePropertyObject(String, CmsProperty)
08844:             * @see I_CmsResourceType#writePropertyObject(CmsObject, CmsSecurityManager, CmsResource, CmsProperty)
08845:             */
08846:            public void writePropertyObject(CmsDbContext dbc,
08847:                    CmsResource resource, CmsProperty property)
08848:                    throws CmsException {
08849:
08850:                try {
08851:                    if (property == CmsProperty.getNullProperty()) {
08852:                        // skip empty or null properties
08853:                        return;
08854:                    }
08855:
08856:                    // test if and what state should be updated
08857:                    // 0: none, 1: structure, 2: resource
08858:                    int updateState = getUpdateState(dbc, resource, Collections
08859:                            .singletonList(property));
08860:
08861:                    // write the property
08862:                    m_vfsDriver.writePropertyObject(dbc, dbc.currentProject(),
08863:                            resource, property);
08864:
08865:                    if (updateState > 0) {
08866:                        updateState(dbc, resource, updateState == 2);
08867:                    }
08868:                } finally {
08869:                    // update the driver manager cache
08870:                    OpenCms.getMemoryMonitor().clearResourceCache();
08871:                    OpenCms.getMemoryMonitor().flushProperties();
08872:                    OpenCms.getMemoryMonitor().flushPropertyLists();
08873:
08874:                    // fire an event that a property of a resource has been modified
08875:                    Map data = new HashMap();
08876:                    data.put("resource", resource);
08877:                    data.put("property", property);
08878:                    OpenCms.fireCmsEvent(new CmsEvent(
08879:                            I_CmsEventListener.EVENT_PROPERTY_MODIFIED, data));
08880:                }
08881:            }
08882:
08883:            /**
08884:             * Writes a list of properties for a specified resource.<p>
08885:             * 
08886:             * Code calling this method has to ensure that the no properties 
08887:             * <code>a, b</code> are contained in the specified list so that <code>a.equals(b)</code>, 
08888:             * otherwise an exception is thrown.<p>
08889:             * 
08890:             * @param dbc the current database context
08891:             * @param resource the resource to write the properties for
08892:             * @param properties the list of properties to write
08893:             * @param updateState if <code>true</code> the state of the resource will be updated
08894:             * 
08895:             * @throws CmsException if something goes wrong
08896:             * 
08897:             * @see CmsObject#writePropertyObjects(String, List)
08898:             * @see I_CmsResourceType#writePropertyObjects(CmsObject, CmsSecurityManager, CmsResource, List)
08899:             */
08900:            public void writePropertyObjects(CmsDbContext dbc,
08901:                    CmsResource resource, List properties, boolean updateState)
08902:                    throws CmsException {
08903:
08904:                if ((properties == null) || (properties.size() == 0)) {
08905:                    // skip empty or null lists
08906:                    return;
08907:                }
08908:
08909:                try {
08910:
08911:                    // the specified list must not contain two or more equal property objects
08912:                    for (int i = 0, n = properties.size(); i < n; i++) {
08913:                        Set keyValidationSet = new HashSet();
08914:                        CmsProperty property = (CmsProperty) properties.get(i);
08915:                        if (!keyValidationSet.contains(property.getName())) {
08916:                            keyValidationSet.add(property.getName());
08917:                        } else {
08918:                            throw new CmsVfsException(Messages.get().container(
08919:                                    Messages.ERR_VFS_INVALID_PROPERTY_LIST_1,
08920:                                    property.getName()));
08921:                        }
08922:                    }
08923:
08924:                    // test if and what state should be updated
08925:                    // 0: none, 1: structure, 2: resource
08926:                    int updateStateValue = 0;
08927:                    if (updateState) {
08928:                        updateStateValue = getUpdateState(dbc, resource,
08929:                                properties);
08930:                    }
08931:
08932:                    for (int i = 0; i < properties.size(); i++) {
08933:                        // write the property
08934:                        CmsProperty property = (CmsProperty) properties.get(i);
08935:                        m_vfsDriver.writePropertyObject(dbc, dbc
08936:                                .currentProject(), resource, property);
08937:                    }
08938:
08939:                    if (updateStateValue > 0) {
08940:                        updateState(dbc, resource, (updateStateValue == 2));
08941:                    }
08942:                } finally {
08943:                    // update the driver manager cache
08944:                    OpenCms.getMemoryMonitor().clearResourceCache();
08945:                    OpenCms.getMemoryMonitor().flushProperties();
08946:                    OpenCms.getMemoryMonitor().flushPropertyLists();
08947:
08948:                    // fire an event that the properties of a resource have been modified
08949:                    OpenCms
08950:                            .fireCmsEvent(new CmsEvent(
08951:                                    I_CmsEventListener.EVENT_RESOURCE_AND_PROPERTIES_MODIFIED,
08952:                                    Collections.singletonMap("resource",
08953:                                            resource)));
08954:                }
08955:            }
08956:
08957:            /**
08958:             * Updates a publish job.<p>
08959:             * 
08960:             * @param dbc the current database context
08961:             * @param publishJob the publish job to update
08962:             * 
08963:             * @throws CmsException if something goes wrong
08964:             */
08965:            public void writePublishJob(CmsDbContext dbc,
08966:                    CmsPublishJobInfoBean publishJob) throws CmsException {
08967:
08968:                m_projectDriver.writePublishJob(dbc, publishJob);
08969:            }
08970:
08971:            /**
08972:             * Writes the publish report for a publish job.<p>
08973:             * 
08974:             * @param dbc the current database context
08975:             * @param publishJob the publish job 
08976:             * @throws CmsException if something goes wrong
08977:             */
08978:            public void writePublishReport(CmsDbContext dbc,
08979:                    CmsPublishJobInfoBean publishJob) throws CmsException {
08980:
08981:                CmsPublishReport report = (CmsPublishReport) publishJob
08982:                        .removePublishReport();
08983:
08984:                if (report != null) {
08985:                    m_projectDriver.writePublishReport(dbc, publishJob
08986:                            .getPublishHistoryId(), report.getContents());
08987:                }
08988:            }
08989:
08990:            /**
08991:             * Writes a resource to the OpenCms VFS.<p>
08992:             * 
08993:             * @param dbc the current database context
08994:             * @param resource the resource to write
08995:             *
08996:             * @throws CmsException if something goes wrong
08997:             */
08998:            public void writeResource(CmsDbContext dbc, CmsResource resource)
08999:                    throws CmsException {
09000:
09001:                // access was granted - write the resource
09002:                resource.setUserLastModified(dbc.currentUser().getId());
09003:
09004:                m_vfsDriver.writeResource(dbc, dbc.currentProject().getUuid(),
09005:                        resource, UPDATE_RESOURCE_STATE);
09006:
09007:                // make sure the written resource has the state correctly set
09008:                if (resource.getState().isUnchanged()) {
09009:                    resource.setState(CmsResource.STATE_CHANGED);
09010:                }
09011:
09012:                // delete in content relations if the new type is not parseable
09013:                if (!(OpenCms.getResourceManager().getResourceType(
09014:                        resource.getTypeId()) instanceof  I_CmsLinkParseable)) {
09015:                    deleteRelationsWithSiblings(dbc, resource);
09016:                }
09017:
09018:                // update the cache
09019:                OpenCms.getMemoryMonitor().clearResourceCache();
09020:                HashMap data = new HashMap(2);
09021:                data.put("resource", resource);
09022:                data.put("change", new Integer(CHANGED_RESOURCE));
09023:                OpenCms.fireCmsEvent(new CmsEvent(
09024:                        I_CmsEventListener.EVENT_RESOURCE_MODIFIED, data));
09025:            }
09026:
09027:            /**
09028:             * Inserts an entry in the published resource table.<p>
09029:             * 
09030:             * This is done during static export.<p>
09031:             * 
09032:             * @param dbc the current database context
09033:             * @param resourceName The name of the resource to be added to the static export
09034:             * @param linkType the type of resource exported (0= non-parameter, 1=parameter)
09035:             * @param linkParameter the parameters added to the resource
09036:             * @param timestamp a time stamp for writing the data into the db
09037:             * 
09038:             * @throws CmsException if something goes wrong
09039:             */
09040:            public void writeStaticExportPublishedResource(CmsDbContext dbc,
09041:                    String resourceName, int linkType, String linkParameter,
09042:                    long timestamp) throws CmsException {
09043:
09044:                m_projectDriver.writeStaticExportPublishedResource(dbc,
09045:                        resourceName, linkType, linkParameter, timestamp);
09046:            }
09047:
09048:            /**
09049:             * Updates the user information. <p>
09050:             * 
09051:             * The user id has to be a valid OpenCms user id.<br>
09052:             * 
09053:             * The user with the given id will be completely overridden
09054:             * by the given data.<p>
09055:             *
09056:             * @param dbc the current database context
09057:             * @param user the user to be updated
09058:             *
09059:             * @throws CmsException if operation was not successful
09060:             */
09061:            public void writeUser(CmsDbContext dbc, CmsUser user)
09062:                    throws CmsException {
09063:
09064:                OpenCms.getMemoryMonitor().clearUserCache(user);
09065:                m_userDriver.writeUser(dbc, user);
09066:            }
09067:
09068:            /** 
09069:             * Converts a resource to a folder (if possible).<p>
09070:             * 
09071:             * @param resource the resource to convert
09072:             * @return the converted resource 
09073:             * 
09074:             * @throws CmsVfsResourceNotFoundException if the resource is not a folder
09075:             */
09076:            protected CmsFolder convertResourceToFolder(CmsResource resource)
09077:                    throws CmsVfsResourceNotFoundException {
09078:
09079:                if (resource.isFolder()) {
09080:                    return new CmsFolder(resource);
09081:                }
09082:
09083:                throw new CmsVfsResourceNotFoundException(Messages.get()
09084:                        .container(Messages.ERR_ACCESS_FILE_AS_FOLDER_1,
09085:                                resource.getRootPath()));
09086:            }
09087:
09088:            /**
09089:             * Deletes all relations for the given resource and all its siblings.<p>
09090:             * 
09091:             * @param dbc the current database context
09092:             * @param resource the resource to delete the resource for
09093:             * 
09094:             * @throws CmsException if something goes wrong 
09095:             */
09096:            protected void deleteRelationsWithSiblings(CmsDbContext dbc,
09097:                    CmsResource resource) throws CmsException {
09098:
09099:                // get all siblings
09100:                List siblings;
09101:                if (resource.getSiblingCount() > 1) {
09102:                    siblings = readSiblings(dbc, resource,
09103:                            CmsResourceFilter.ALL);
09104:                } else {
09105:                    siblings = new ArrayList();
09106:                    siblings.add(resource);
09107:                }
09108:                // clean the relations in content for all siblings 
09109:                Iterator it = siblings.iterator();
09110:                while (it.hasNext()) {
09111:                    CmsResource sibling = (CmsResource) it.next();
09112:                    // clean the relation information for this sibling
09113:                    m_vfsDriver.deleteRelations(dbc, dbc.currentProject()
09114:                            .getUuid(), sibling, CmsRelationFilter.TARGETS
09115:                            .filterDefinedInContent());
09116:                }
09117:            }
09118:
09119:            /**
09120:             * Returns the lock manager instance.<p>
09121:             * 
09122:             * @return the lock manager instance
09123:             */
09124:            protected CmsLockManager getLockManager() {
09125:
09126:                return m_lockManager;
09127:            }
09128:
09129:            /**
09130:             * Checks the parent of a resource during publishing.<p> 
09131:             * 
09132:             * @param dbc the current database context
09133:             * @param deletedFolders a list of deleted folders
09134:             * @param res a resource to check the parent for
09135:             * 
09136:             * @return <code>true</code> if the parent resource will be deleted during publishing
09137:             */
09138:            private boolean checkDeletedParentFolder(CmsDbContext dbc,
09139:                    List deletedFolders, CmsResource res) {
09140:
09141:                String parentPath = CmsResource.getParentFolder(res
09142:                        .getRootPath());
09143:
09144:                if (parentPath == null) {
09145:                    // resource has no parent
09146:                    return false;
09147:                }
09148:
09149:                CmsResource parent;
09150:                try {
09151:                    parent = readResource(dbc, parentPath,
09152:                            CmsResourceFilter.ALL);
09153:                } catch (Exception e) {
09154:                    // failure: if we cannot read the parent, we should not publish the resource
09155:                    return false;
09156:                }
09157:
09158:                if (!parent.getState().isDeleted()) {
09159:                    // parent is not deleted
09160:                    return false;
09161:                }
09162:
09163:                for (int j = 0; j < deletedFolders.size(); j++) {
09164:                    if (((CmsResource) deletedFolders.get(j)).getStructureId()
09165:                            .equals(parent.getStructureId())) {
09166:                        // parent is deleted, and it will get published
09167:                        return true;
09168:                    }
09169:                }
09170:
09171:                // parent is new, but it will not get published
09172:                return false;
09173:            }
09174:
09175:            /**
09176:             * Checks that no one of the resources to be published has a 'new' parent (that has not been published yet).<p> 
09177:             * 
09178:             * @param dbc the db context
09179:             * @param publishList the publish list to check
09180:             * 
09181:             * @throws CmsVfsException if there is a resource to be published with a 'new' parent
09182:             */
09183:            private void checkParentFolders(CmsDbContext dbc,
09184:                    CmsPublishList publishList) throws CmsVfsException {
09185:
09186:                boolean directPublish = publishList.isDirectPublish();
09187:                // if we direct publish a file, check if all parent folders are already published
09188:                if (directPublish) {
09189:                    // first get the names of all parent folders
09190:                    Iterator it = publishList.getDirectPublishResources()
09191:                            .iterator();
09192:                    List parentFolderNames = new ArrayList();
09193:                    while (it.hasNext()) {
09194:                        CmsResource res = (CmsResource) it.next();
09195:                        String parentFolderName = CmsResource
09196:                                .getParentFolder(res.getRootPath());
09197:                        if (parentFolderName != null) {
09198:                            parentFolderNames.add(parentFolderName);
09199:                        }
09200:                    }
09201:                    // remove duplicate parent folder names
09202:                    parentFolderNames = CmsFileUtil
09203:                            .removeRedundancies(parentFolderNames);
09204:                    String parentFolderName = null;
09205:                    try {
09206:                        // now check all folders if they exist in the online project
09207:                        Iterator parentIt = parentFolderNames.iterator();
09208:                        while (parentIt.hasNext()) {
09209:                            parentFolderName = (String) parentIt.next();
09210:                            getVfsDriver().readFolder(dbc,
09211:                                    CmsProject.ONLINE_PROJECT_ID,
09212:                                    parentFolderName);
09213:                        }
09214:                    } catch (CmsException e) {
09215:                        throw new CmsVfsException(Messages.get().container(
09216:                                Messages.RPT_PARENT_FOLDER_NOT_PUBLISHED_1,
09217:                                parentFolderName));
09218:                    }
09219:                }
09220:            }
09221:
09222:            /**
09223:             * Checks the parent of a resource during publishing.<p> 
09224:             * 
09225:             * @param dbc the current database context
09226:             * @param folderList a list of folders
09227:             * @param res a resource to check the parent for
09228:             * 
09229:             * @return true if the resource should be published
09230:             */
09231:            private boolean checkParentResource(CmsDbContext dbc,
09232:                    List folderList, CmsResource res) {
09233:
09234:                String parentPath = CmsResource.getParentFolder(res
09235:                        .getRootPath());
09236:
09237:                if (parentPath == null) {
09238:                    // resource has no parent
09239:                    return true;
09240:                }
09241:
09242:                CmsResource parent;
09243:                try {
09244:                    parent = readResource(dbc, parentPath,
09245:                            CmsResourceFilter.ALL);
09246:                } catch (Exception e) {
09247:                    // failure: if we cannot read the parent, we should not publish the resource
09248:                    return false;
09249:                }
09250:
09251:                if (!parent.getState().isNew()) {
09252:                    // parent is already published
09253:                    return true;
09254:                }
09255:
09256:                for (int j = 0; j < folderList.size(); j++) {
09257:                    if (((CmsResource) folderList.get(j)).getStructureId()
09258:                            .equals(parent.getStructureId())) {
09259:                        // parent is new, but it will get published
09260:                        return true;
09261:                    }
09262:                }
09263:
09264:                // parent is new, but it will not get published
09265:                return false;
09266:            }
09267:
09268:            /**
09269:             * Filters the given list of resources, removes all resources where the current user
09270:             * does not have READ permissions, plus the filter is applied.<p>
09271:             * 
09272:             * @param dbc the current database context
09273:             * @param resourceList a list of CmsResources
09274:             * @param filter the resource filter to use
09275:             * 
09276:             * @return the filtered list of resources
09277:             * 
09278:             * @throws CmsException in case errors testing the permissions
09279:             */
09280:            private List filterPermissions(CmsDbContext dbc, List resourceList,
09281:                    CmsResourceFilter filter) throws CmsException {
09282:
09283:                if (filter.requireTimerange()) {
09284:                    // never check time range here - this must be done later in #updateContextDates(...)
09285:                    filter = filter.addExcludeTimerange();
09286:                }
09287:                ArrayList result = new ArrayList(resourceList.size());
09288:                for (int i = 0; i < resourceList.size(); i++) {
09289:                    // check the permission of all resources
09290:                    CmsResource currentResource = (CmsResource) resourceList
09291:                            .get(i);
09292:                    if (m_securityManager.hasPermissions(dbc, currentResource,
09293:                            CmsPermissionSet.ACCESS_READ, true, filter)
09294:                            .isAllowed()) {
09295:                        // only return resources where permission was granted
09296:                        result.add(currentResource);
09297:                    }
09298:                }
09299:                // return the result
09300:                return result;
09301:            }
09302:
09303:            /**
09304:             * Returns a filtered list of resources for publishing.<p>
09305:             * Contains all resources, which are not locked 
09306:             * and which have a parent folder that is already published or will be published, too.
09307:             * 
09308:             * @param dbc the current database context
09309:             * @param publishList the filling publish list
09310:             * @param resourceList the list of resources to filter
09311:             * @return a filtered list of resources
09312:             */
09313:            private List filterResources(CmsDbContext dbc,
09314:                    CmsPublishList publishList, List resourceList) {
09315:
09316:                List result = new ArrayList();
09317:
09318:                // local folder list for adding new publishing subfolders
09319:                // this solves the {@link org.opencms.file.TestPublishIssues#testPublishScenarioD} problem.
09320:                List newFolderList = new ArrayList(
09321:                        publishList == null ? resourceList : publishList
09322:                                .getFolderList());
09323:
09324:                for (int i = 0; i < resourceList.size(); i++) {
09325:                    CmsResource res = (CmsResource) resourceList.get(i);
09326:                    try {
09327:                        CmsLock lock = getLock(dbc, res);
09328:                        if (lock.isPublish()) {
09329:                            // if already enqueued
09330:                            continue;
09331:                        }
09332:                        if (!lock.isLockableBy(dbc.currentUser())) {
09333:                            // checks if there is a shared lock and if the resource is deleted
09334:                            // this solves the {@link org.opencms.file.TestPublishIssues#testPublishScenarioE} problem.
09335:                            if (lock.isShared() && (publishList != null)) {
09336:                                if (!res.getState().isDeleted()
09337:                                        || !checkDeletedParentFolder(
09338:                                                dbc,
09339:                                                publishList
09340:                                                        .getDeletedFolderList(),
09341:                                                res)) {
09342:                                    continue;
09343:                                }
09344:                            } else {
09345:                                // don't add locked resources
09346:                                continue;
09347:                            }
09348:                        }
09349:                        if (!"/".equals(res.getRootPath())
09350:                                && !checkParentResource(dbc, newFolderList, res)) {
09351:                            continue;
09352:                        }
09353:                        // check permissions
09354:                        try {
09355:                            m_securityManager.checkPermissions(dbc, res,
09356:                                    CmsPermissionSet.ACCESS_DIRECT_PUBLISH,
09357:                                    false, CmsResourceFilter.ALL);
09358:                        } catch (CmsException e) {
09359:                            // skip if not enough permissions
09360:                            continue;
09361:                        }
09362:                        if (res.isFolder()) {
09363:                            newFolderList.add(res);
09364:                        }
09365:                        result.add(res);
09366:                    } catch (Exception e) {
09367:                        // should never happen
09368:                        LOG.error(e.getLocalizedMessage(), e);
09369:                    }
09370:                }
09371:                return result;
09372:            }
09373:
09374:            /**
09375:             * Returns a filtered list of sibling resources for publishing.<p>
09376:             * 
09377:             * Contains all siblings of the given resources, which are not locked
09378:             * and which have a parent folder that is already published or will be published, too.<p>
09379:             * 
09380:             * @param dbc the current database context 
09381:             * @param publishList the unfinished publish list
09382:             * @param resourceList the list of siblings to filter
09383:             * 
09384:             * @return a filtered list of sibling resources for publishing
09385:             */
09386:            private List filterSiblings(CmsDbContext dbc,
09387:                    CmsPublishList publishList, Collection resourceList) {
09388:
09389:                List result = new ArrayList();
09390:
09391:                // removed internal extendible folder list, since iterated (sibling) resources are files in any case, never folders
09392:
09393:                for (Iterator i = resourceList.iterator(); i.hasNext();) {
09394:                    CmsResource res = (CmsResource) i.next();
09395:                    try {
09396:                        CmsLock lock = getLock(dbc, res);
09397:                        if (lock.isPublish()) {
09398:                            // if already enqueued
09399:                            continue;
09400:                        }
09401:                        if (!lock.isLockableBy(dbc.currentUser())) {
09402:                            // checks if there is a shared lock and if the resource is deleted
09403:                            // this solves the {@link org.opencms.file.TestPublishIssues#testPublishScenarioE} problem.
09404:                            if (lock.isShared() && (publishList != null)) {
09405:                                if (!res.getState().isDeleted()
09406:                                        || !checkDeletedParentFolder(
09407:                                                dbc,
09408:                                                publishList
09409:                                                        .getDeletedFolderList(),
09410:                                                res)) {
09411:                                    continue;
09412:                                }
09413:                            } else {
09414:                                // don't add locked resources
09415:                                continue;
09416:                            }
09417:                        }
09418:                        if (!"/".equals(res.getRootPath())
09419:                                && !checkParentResource(dbc, publishList
09420:                                        .getFolderList(), res)) {
09421:                            // don't add resources that have no parent in the online project
09422:                            continue;
09423:                        }
09424:                        // check permissions
09425:                        try {
09426:                            m_securityManager.checkPermissions(dbc, res,
09427:                                    CmsPermissionSet.ACCESS_DIRECT_PUBLISH,
09428:                                    false, CmsResourceFilter.ALL);
09429:                        } catch (CmsException e) {
09430:                            // skip if not enough permissions
09431:                            continue;
09432:                        }
09433:                        result.add(res);
09434:                    } catch (Exception e) {
09435:                        // should never happen
09436:                        LOG.error(e.getLocalizedMessage(), e);
09437:                    }
09438:                }
09439:                return result;
09440:            }
09441:
09442:            /**
09443:             * Returns the access control list of a given resource.<p>
09444:             * 
09445:             * @param dbc the current database context
09446:             * @param resource the resource
09447:             * @param forFolder should be true if resource is a folder
09448:             * @param depth the depth to include non-inherited access entries, also
09449:             * @param inheritedOnly flag indicates to collect inherited permissions only
09450:             * 
09451:             * @return the access control list of the resource
09452:             * 
09453:             * @throws CmsException if something goes wrong
09454:             */
09455:            private CmsAccessControlList getAccessControlList(CmsDbContext dbc,
09456:                    CmsResource resource, boolean inheritedOnly,
09457:                    boolean forFolder, int depth) throws CmsException {
09458:
09459:                String cacheKey = getCacheKey(new String[] {
09460:                        inheritedOnly ? "+" : "-", forFolder ? "+" : "-",
09461:                        Integer.toString(depth),
09462:                        resource.getStructureId().toString() }, dbc
09463:                        .currentProject());
09464:
09465:                CmsAccessControlList acl = OpenCms.getMemoryMonitor()
09466:                        .getCachedACL(cacheKey);
09467:
09468:                // return the cached acl if already available
09469:                if (acl != null) {
09470:                    return acl;
09471:                }
09472:
09473:                List aces = m_userDriver.readAccessControlEntries(dbc, dbc
09474:                        .currentProject(), resource.getResourceId(),
09475:                        (depth > 1) || ((depth > 0) && forFolder));
09476:
09477:                // sort the list of aces
09478:                boolean overwriteAll = sortAceList(aces);
09479:
09480:                // if no 'overwrite all' ace was found
09481:                if (!overwriteAll) {
09482:                    // get the acl of the parent
09483:                    CmsResource parentResource = null;
09484:                    try {
09485:                        // try to recurse over the id
09486:                        parentResource = m_vfsDriver.readParentFolder(dbc, dbc
09487:                                .currentProject().getUuid(), resource
09488:                                .getStructureId());
09489:                    } catch (CmsVfsResourceNotFoundException e) {
09490:                        // should never happen, but try with the path
09491:                        String parentPath = CmsResource
09492:                                .getParentFolder(resource.getRootPath());
09493:                        if (parentPath != null) {
09494:                            parentResource = m_vfsDriver.readFolder(dbc, dbc
09495:                                    .currentProject().getUuid(), parentPath);
09496:                        }
09497:                    }
09498:                    if (parentResource != null) {
09499:                        acl = (CmsAccessControlList) getAccessControlList(dbc,
09500:                                parentResource, inheritedOnly, forFolder,
09501:                                depth + 1).clone();
09502:                    }
09503:                }
09504:                if (acl == null) {
09505:                    acl = new CmsAccessControlList();
09506:                }
09507:
09508:                if (!((depth == 0) && inheritedOnly)) {
09509:                    Iterator itAces = aces.iterator();
09510:                    while (itAces.hasNext()) {
09511:                        CmsAccessControlEntry acEntry = (CmsAccessControlEntry) itAces
09512:                                .next();
09513:                        if (depth > 0) {
09514:                            acEntry
09515:                                    .setFlags(CmsAccessControlEntry.ACCESS_FLAGS_INHERITED);
09516:                        }
09517:
09518:                        acl.add(acEntry);
09519:
09520:                        // if the overwrite flag is set, reset the allowed permissions to the permissions of this entry
09521:                        // denied permissions are kept or extended
09522:                        if ((acEntry.getFlags() & CmsAccessControlEntry.ACCESS_FLAGS_OVERWRITE) > 0) {
09523:                            acl.setAllowedPermissions(acEntry);
09524:                        }
09525:                    }
09526:                }
09527:                OpenCms.getMemoryMonitor().cacheACL(cacheKey, acl);
09528:                return acl;
09529:            }
09530:
09531:            /**
09532:             * Return a cache key build from the provided information.<p>
09533:             * 
09534:             * @param prefix a prefix for the key
09535:             * @param flag a boolean flag for the key (only used if prefix is not null)
09536:             * @param projectId the project for which to generate the key
09537:             * @param resource the resource for which to generate the key
09538:             * 
09539:             * @return String a cache key build from the provided information
09540:             */
09541:            private String getCacheKey(String prefix, boolean flag,
09542:                    CmsUUID projectId, String resource) {
09543:
09544:                StringBuffer b = new StringBuffer(64);
09545:                if (prefix != null) {
09546:                    b.append(prefix);
09547:                    b.append(flag ? '+' : '-');
09548:                }
09549:                b.append(CmsProject.isOnlineProject(projectId) ? '+' : '-');
09550:                return b.append(resource).toString();
09551:            }
09552:
09553:            /**
09554:             * Return a cache key build from the provided information.<p>
09555:             * 
09556:             * @param keys an array of keys to generate the cache key from
09557:             * @param project the project for which to generate the key
09558:             *
09559:             * @return String a cache key build from the provided information
09560:             */
09561:            private String getCacheKey(String[] keys, CmsProject project) {
09562:
09563:                StringBuffer b = new StringBuffer(64);
09564:                int len = keys.length;
09565:                if (len > 0) {
09566:                    for (int i = 0; i < len; i++) {
09567:                        b.append(keys[i]);
09568:                        b.append('_');
09569:                    }
09570:                }
09571:                if (project != null) {
09572:                    b.append(project.isOnlineProject() ? '+' : '-');
09573:                }
09574:                return b.toString();
09575:            }
09576:
09577:            /**
09578:             * Returns if and what state needs to be updated.<p>
09579:             * 
09580:             * @param dbc the db context
09581:             * @param resource the resource
09582:             * @param properties the properties to check
09583:             * 
09584:             * @return 0: none, 1: structure, 2: resource
09585:             * 
09586:             * @throws CmsDataAccessException if something goes wrong
09587:             */
09588:            private int getUpdateState(CmsDbContext dbc, CmsResource resource,
09589:                    List properties) throws CmsDataAccessException {
09590:
09591:                int updateState = 0;
09592:                Iterator it = properties.iterator();
09593:                while (it.hasNext() && (updateState < 2)) {
09594:                    CmsProperty property = (CmsProperty) it.next();
09595:
09596:                    // read existing property
09597:                    CmsProperty existingProperty = m_vfsDriver
09598:                            .readPropertyObject(dbc, property.getName(), dbc
09599:                                    .currentProject(), resource);
09600:
09601:                    // check the shared property
09602:                    if (property.getResourceValue() != null) {
09603:                        if (property.isDeleteResourceValue()) {
09604:                            if (existingProperty.getResourceValue() != null) {
09605:                                updateState = 2; // deleted
09606:                            }
09607:                        } else {
09608:                            if (existingProperty.getResourceValue() == null) {
09609:                                updateState = 2; // created
09610:                            } else {
09611:                                if (!property.getResourceValue().equals(
09612:                                        existingProperty.getResourceValue())) {
09613:                                    updateState = 2; // updated
09614:                                }
09615:                            }
09616:                        }
09617:                    }
09618:                    if (updateState == 0) {
09619:                        // check the individual property only if needed
09620:                        if (property.getStructureValue() != null) {
09621:                            if (property.isDeleteStructureValue()) {
09622:                                if (existingProperty.getStructureValue() != null) {
09623:                                    updateState = 1; // deleted
09624:                                }
09625:                            } else {
09626:                                if (existingProperty.getStructureValue() == null) {
09627:                                    updateState = 1; // created
09628:                                } else {
09629:                                    if (!property.getStructureValue().equals(
09630:                                            existingProperty
09631:                                                    .getStructureValue())) {
09632:                                        updateState = 1; // updated
09633:                                    }
09634:                                }
09635:                            }
09636:                        }
09637:                    }
09638:                }
09639:                return updateState;
09640:            }
09641:
09642:            /**
09643:             * Returns all groups that are virtualizing the given role in the given ou.<p>
09644:             * 
09645:             * @param dbc the database context
09646:             * @param role the role
09647:             * 
09648:             * @return all groups that are virtualizing the given role (or a child of it)
09649:             * 
09650:             * @throws CmsException if something goes wrong 
09651:             */
09652:            private List getVirtualGroupsForRole(CmsDbContext dbc, CmsRole role)
09653:                    throws CmsException {
09654:
09655:                Set roleFlags = new HashSet();
09656:                // add role flag
09657:                Integer flags = new Integer(role.getVirtualGroupFlags());
09658:                roleFlags.add(flags);
09659:                // collect all child role flags
09660:                Iterator itChildRoles = role.getChildren(true).iterator();
09661:                while (itChildRoles.hasNext()) {
09662:                    CmsRole child = (CmsRole) itChildRoles.next();
09663:                    flags = new Integer(child.getVirtualGroupFlags());
09664:                    roleFlags.add(flags);
09665:                }
09666:                // iterate all groups matching the flags
09667:                List groups = new ArrayList();
09668:                Iterator it = getGroups(dbc,
09669:                        readOrganizationalUnit(dbc, role.getOuFqn()), false,
09670:                        false).iterator();
09671:                while (it.hasNext()) {
09672:                    CmsGroup group = (CmsGroup) it.next();
09673:                    if (group.isVirtual()) {
09674:                        CmsRole r = CmsRole.valueOf(group);
09675:                        if (roleFlags.contains(new Integer(r
09676:                                .getVirtualGroupFlags()))) {
09677:                            groups.add(group);
09678:                        }
09679:                    }
09680:                }
09681:                return groups;
09682:            }
09683:
09684:            /**
09685:             * Returns a list of users in a group.<p>
09686:             *
09687:             * @param dbc the current database context
09688:             * @param ouFqn the organizational unit to get the users from 
09689:             * @param groupname the name of the group to list users from
09690:             * @param includeOtherOuUsers include users of other organizational units
09691:             * @param directUsersOnly if set only the direct assigned users will be returned, 
09692:             *                        if not also indirect users, ie. members of parent roles, 
09693:             *                        this parameter only works with roles
09694:             * @param readRoles if to read roles or groups
09695:             * 
09696:             * @return all <code>{@link CmsUser}</code> objects in the group
09697:             * 
09698:             * @throws CmsException if operation was not successful
09699:             */
09700:            private List internalUsersOfGroup(CmsDbContext dbc, String ouFqn,
09701:                    String groupname, boolean includeOtherOuUsers,
09702:                    boolean directUsersOnly, boolean readRoles)
09703:                    throws CmsException {
09704:
09705:                CmsGroup group = readGroup(dbc, groupname); // check that the group really exists
09706:                if ((group != null)
09707:                        && ((!readRoles && !group.isRole()) || (readRoles && group
09708:                                .isRole()))) {
09709:                    String prefix = "_" + includeOtherOuUsers + "_"
09710:                            + directUsersOnly + "_" + ouFqn;
09711:                    String cacheKey = m_keyGenerator.getCacheKeyForGroupUsers(
09712:                            prefix, dbc, group);
09713:                    List allUsers = OpenCms.getMemoryMonitor()
09714:                            .getCachedUserGroups(cacheKey);
09715:                    if (allUsers == null) {
09716:                        Set users = new HashSet(m_userDriver.readUsersOfGroup(
09717:                                dbc, groupname, includeOtherOuUsers));
09718:                        if (readRoles && !directUsersOnly) {
09719:                            CmsRole role = CmsRole.valueOf(group);
09720:                            if (role.getParentRole() != null) {
09721:                                try {
09722:                                    String parentGroup = role.getParentRole()
09723:                                            .getGroupName();
09724:                                    readGroup(dbc, parentGroup);
09725:                                    // iterate the parent roles
09726:                                    users.addAll(internalUsersOfGroup(dbc,
09727:                                            ouFqn, parentGroup,
09728:                                            includeOtherOuUsers,
09729:                                            directUsersOnly, readRoles));
09730:                                } catch (CmsDbEntryNotFoundException e) {
09731:                                    // ignore, this may happen while deleting an orgunit
09732:                                    if (LOG.isDebugEnabled()) {
09733:                                        LOG.debug(e.getLocalizedMessage(), e);
09734:                                    }
09735:                                }
09736:                            }
09737:                            String parentOu = CmsOrganizationalUnit
09738:                                    .getParentFqn(group.getOuFqn());
09739:                            if (parentOu != null) {
09740:                                // iterate the parent ou's
09741:                                users.addAll(internalUsersOfGroup(dbc, ouFqn,
09742:                                        parentOu + group.getSimpleName(),
09743:                                        includeOtherOuUsers, directUsersOnly,
09744:                                        readRoles));
09745:                            }
09746:                            // filter users from other ous
09747:                            if (!includeOtherOuUsers) {
09748:                                Iterator itUsers = users.iterator();
09749:                                while (itUsers.hasNext()) {
09750:                                    CmsUser user = (CmsUser) itUsers.next();
09751:                                    if (!user.getOuFqn().equals(ouFqn)) {
09752:                                        itUsers.remove();
09753:                                    }
09754:                                }
09755:                            }
09756:                        }
09757:                        // make user list unmodifiable for caching
09758:                        allUsers = Collections.unmodifiableList(new ArrayList(
09759:                                users));
09760:                        OpenCms.getMemoryMonitor().cacheUserGroups(cacheKey,
09761:                                allUsers);
09762:                    }
09763:                    return allUsers;
09764:                } else {
09765:                    throw new CmsDbEntryNotFoundException(Messages.get()
09766:                            .container(Messages.ERR_UNKNOWN_GROUP_1, groupname));
09767:                }
09768:            }
09769:
09770:            /**
09771:             * Reads all resources that are inside and changed in a specified project.<p>
09772:             * 
09773:             * @param dbc the current database context
09774:             * @param projectId the ID of the project
09775:             * @param mode one of the {@link CmsReadChangedProjectResourceMode} constants
09776:             * 
09777:             * @return a List with all resources inside the specified project
09778:             * 
09779:             * @throws CmsException if something goes wrong
09780:             */
09781:            private List readChangedResourcesInsideProject(CmsDbContext dbc,
09782:                    CmsUUID projectId, CmsReadChangedProjectResourceMode mode)
09783:                    throws CmsException {
09784:
09785:                String cacheKey = projectId + "_" + mode.toString();
09786:                List result = OpenCms.getMemoryMonitor()
09787:                        .getCachedProjectResources(cacheKey);
09788:                if (result != null) {
09789:                    return result;
09790:                }
09791:                List projectResources = readProjectResources(dbc, readProject(
09792:                        dbc, projectId));
09793:                result = new ArrayList();
09794:                String currentProjectResource = null;
09795:                List resources = new ArrayList();
09796:                CmsResource currentResource = null;
09797:                CmsLock currentLock = null;
09798:
09799:                for (int i = 0; i < projectResources.size(); i++) {
09800:                    // read all resources that are inside the project by visiting each project resource
09801:                    currentProjectResource = (String) projectResources.get(i);
09802:
09803:                    try {
09804:                        currentResource = readResource(dbc,
09805:                                currentProjectResource, CmsResourceFilter.ALL);
09806:
09807:                        if (currentResource.isFolder()) {
09808:                            resources.addAll(readResources(dbc,
09809:                                    currentResource, CmsResourceFilter.ALL,
09810:                                    true));
09811:                        } else {
09812:                            resources.add(currentResource);
09813:                        }
09814:                    } catch (CmsException e) {
09815:                        // the project resource probably doesn't exist (anymore)...
09816:                        if (!(e instanceof  CmsVfsResourceNotFoundException)) {
09817:                            throw e;
09818:                        }
09819:                    }
09820:                }
09821:
09822:                for (int j = 0; j < resources.size(); j++) {
09823:                    currentResource = (CmsResource) resources.get(j);
09824:                    currentLock = getLock(dbc, currentResource)
09825:                            .getEditionLock();
09826:
09827:                    if (!currentResource.getState().isUnchanged()) {
09828:                        if ((currentLock.isNullLock() && (currentResource
09829:                                .getProjectLastModified().equals(projectId)))
09830:                                || (currentLock.isOwnedBy(dbc.currentUser()) && (currentLock
09831:                                        .getProjectId().equals(projectId)))) {
09832:                            // add only resources that are 
09833:                            // - inside the project,
09834:                            // - changed in the project,
09835:                            // - either unlocked, or locked for the current user in the project
09836:                            if ((mode == RCPRM_FILES_AND_FOLDERS_MODE)
09837:                                    || (currentResource.isFolder() && (mode == RCPRM_FOLDERS_ONLY_MODE))
09838:                                    || (currentResource.isFile() && (mode == RCPRM_FILES_ONLY_MODE))) {
09839:                                result.add(currentResource);
09840:                            }
09841:                        }
09842:                    }
09843:                }
09844:
09845:                resources.clear();
09846:                resources = null;
09847:
09848:                OpenCms.getMemoryMonitor().cacheProjectResources(cacheKey,
09849:                        result);
09850:                return result;
09851:            }
09852:
09853:            /**
09854:             * Sorts the given list of {@link CmsAccessControlEntry} objects.<p>
09855:             * 
09856:             * The the 'all others' ace in first place, the 'overwrite all' ace in second.<p>
09857:             * 
09858:             * @param aces the list of ACEs to sort
09859:             * 
09860:             * @return <code>true</code> if the list contains the 'overwrite all' ace
09861:             */
09862:            private boolean sortAceList(List aces) {
09863:
09864:                // sort the list of entries 
09865:                Collections.sort(aces, CmsAccessControlEntry.COMPARATOR_ACE);
09866:                // after sorting just the first 2 positions come in question
09867:                for (int i = 0; i < Math.min(aces.size(), 2); i++) {
09868:                    CmsAccessControlEntry acEntry = (CmsAccessControlEntry) aces
09869:                            .get(i);
09870:                    if (acEntry.getPrincipal().equals(
09871:                            CmsAccessControlEntry.PRINCIPAL_OVERWRITE_ALL_ID)) {
09872:                        return true;
09873:                    }
09874:                }
09875:                return false;
09876:            }
09877:
09878:            /**
09879:             * All permissions and resources attributes of the principal
09880:             * are transfered to a replacement principal.<p>
09881:             *
09882:             * @param dbc the current database context
09883:             * @param project the current project
09884:             * @param principalId the id of the principal to be replaced
09885:             * @param replacementId the user to be transfered
09886:             * @param withACEs flag to signal if the ACEs should also be transfered or just deleted
09887:             * 
09888:             * @throws CmsException if operation was not successful
09889:             */
09890:            private void transferPrincipalResources(CmsDbContext dbc,
09891:                    CmsProject project, CmsUUID principalId,
09892:                    CmsUUID replacementId, boolean withACEs)
09893:                    throws CmsException {
09894:
09895:                // get all resources for the given user including resources associated by ACEs or attributes
09896:                List resources = getResourcesForPrincipal(dbc, project,
09897:                        principalId, null, true);
09898:                Iterator it = resources.iterator();
09899:                while (it.hasNext()) {
09900:                    CmsResource resource = (CmsResource) it.next();
09901:                    // check resource attributes
09902:                    boolean attrModified = false;
09903:                    CmsUUID createdUser = null;
09904:                    if (resource.getUserCreated().equals(principalId)) {
09905:                        createdUser = replacementId;
09906:                        attrModified = true;
09907:                    }
09908:                    CmsUUID lastModUser = null;
09909:                    if (resource.getUserLastModified().equals(principalId)) {
09910:                        lastModUser = replacementId;
09911:                        attrModified = true;
09912:                    }
09913:                    if (attrModified) {
09914:                        m_vfsDriver.transferResource(dbc, project, resource,
09915:                                createdUser, lastModUser);
09916:                        // clear the cache
09917:                        OpenCms.getMemoryMonitor().clearResourceCache();
09918:                    }
09919:                    boolean aceModified = false;
09920:                    // check aces
09921:                    if (withACEs) {
09922:                        Iterator itAces = m_userDriver
09923:                                .readAccessControlEntries(dbc, project,
09924:                                        resource.getResourceId(), false)
09925:                                .iterator();
09926:                        while (itAces.hasNext()) {
09927:                            CmsAccessControlEntry ace = (CmsAccessControlEntry) itAces
09928:                                    .next();
09929:                            if (ace.getPrincipal().equals(principalId)) {
09930:                                CmsAccessControlEntry newAce = new CmsAccessControlEntry(
09931:                                        ace.getResource(), replacementId, ace
09932:                                                .getAllowedPermissions(), ace
09933:                                                .getDeniedPermissions(), ace
09934:                                                .getFlags());
09935:                                // write the new ace
09936:                                m_userDriver.writeAccessControlEntry(dbc,
09937:                                        project, newAce);
09938:                                aceModified = true;
09939:                            }
09940:                        }
09941:                        if (aceModified) {
09942:                            // clear the cache
09943:                            OpenCms.getMemoryMonitor()
09944:                                    .clearAccessControlListCache();
09945:                        }
09946:                    }
09947:                    if (attrModified || aceModified) {
09948:                        // fire the event
09949:                        HashMap data = new HashMap(2);
09950:                        data.put("resource", resource);
09951:                        data
09952:                                .put(
09953:                                        "change",
09954:                                        new Integer(
09955:                                                ((attrModified) ? CHANGED_RESOURCE
09956:                                                        : 0)
09957:                                                        | ((aceModified) ? CHANGED_ACCESSCONTROL
09958:                                                                : 0)));
09959:                        OpenCms.fireCmsEvent(new CmsEvent(
09960:                                I_CmsEventListener.EVENT_RESOURCE_MODIFIED,
09961:                                data));
09962:                    }
09963:                }
09964:            }
09965:
09966:            /**
09967:             * Undoes all content changes of a resource.<p>
09968:             * 
09969:             * @param dbc the database context
09970:             * @param onlineProject the online project
09971:             * @param offlineResource the offline resource, or <code>null</code> if deleted
09972:             * @param onlineResource the online resource
09973:             * @param newState the new resource state
09974:             * @param moveUndone is a move operation on the same resource has been made
09975:             * 
09976:             * @throws CmsException if something goes wrong
09977:             */
09978:            private void undoContentChanges(CmsDbContext dbc,
09979:                    CmsProject onlineProject, CmsResource offlineResource,
09980:                    CmsResource onlineResource, CmsResourceState newState,
09981:                    boolean moveUndone) throws CmsException {
09982:
09983:                String path = ((moveUndone || (offlineResource == null)) ? onlineResource
09984:                        .getRootPath()
09985:                        : offlineResource.getRootPath());
09986:
09987:                // change folder or file?
09988:                if (onlineResource.isFolder()) {
09989:                    CmsFolder restoredFolder = new CmsFolder(onlineResource
09990:                            .getStructureId(), onlineResource.getResourceId(),
09991:                            path, onlineResource.getTypeId(), onlineResource
09992:                                    .getFlags(),
09993:                            dbc.currentProject().getUuid(), newState,
09994:                            onlineResource.getDateCreated(), onlineResource
09995:                                    .getUserCreated(), onlineResource
09996:                                    .getDateLastModified(), onlineResource
09997:                                    .getUserLastModified(), onlineResource
09998:                                    .getDateReleased(), onlineResource
09999:                                    .getDateExpired(), onlineResource
10000:                                    .getVersion()); // version number does not matter since it will be computed later
10001:
10002:                    // write the folder in the offline project
10003:                    // this sets a flag so that the folder date is not set to the current time
10004:                    restoredFolder.setDateLastModified(onlineResource
10005:                            .getDateLastModified());
10006:
10007:                    // write the folder
10008:                    m_vfsDriver.writeResource(dbc, dbc.currentProject()
10009:                            .getUuid(), restoredFolder, NOTHING_CHANGED);
10010:
10011:                    // restore the properties from the online project
10012:                    m_vfsDriver
10013:                            .deletePropertyObjects(
10014:                                    dbc,
10015:                                    dbc.currentProject().getUuid(),
10016:                                    restoredFolder,
10017:                                    CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES);
10018:
10019:                    List propertyInfos = m_vfsDriver.readPropertyObjects(dbc,
10020:                            onlineProject, onlineResource);
10021:                    m_vfsDriver.writePropertyObjects(dbc, dbc.currentProject(),
10022:                            restoredFolder, propertyInfos);
10023:
10024:                    // restore the access control entries from the online project
10025:                    m_userDriver.removeAccessControlEntries(dbc, dbc
10026:                            .currentProject(), onlineResource.getResourceId());
10027:                    ListIterator aceList = m_userDriver
10028:                            .readAccessControlEntries(dbc, onlineProject,
10029:                                    onlineResource.getResourceId(), false)
10030:                            .listIterator();
10031:
10032:                    while (aceList.hasNext()) {
10033:                        CmsAccessControlEntry ace = (CmsAccessControlEntry) aceList
10034:                                .next();
10035:                        m_userDriver.createAccessControlEntry(dbc, dbc
10036:                                .currentProject(), onlineResource
10037:                                .getResourceId(), ace.getPrincipal(), ace
10038:                                .getPermissions().getAllowedPermissions(), ace
10039:                                .getPermissions().getDeniedPermissions(), ace
10040:                                .getFlags());
10041:                    }
10042:                } else {
10043:                    byte[] onlineContent = m_vfsDriver.readContent(dbc,
10044:                            CmsProject.ONLINE_PROJECT_ID, onlineResource
10045:                                    .getResourceId());
10046:
10047:                    CmsFile restoredFile = new CmsFile(onlineResource
10048:                            .getStructureId(), onlineResource.getResourceId(),
10049:                            path, onlineResource.getTypeId(), onlineResource
10050:                                    .getFlags(),
10051:                            dbc.currentProject().getUuid(), newState,
10052:                            onlineResource.getDateCreated(), onlineResource
10053:                                    .getUserCreated(), onlineResource
10054:                                    .getDateLastModified(), onlineResource
10055:                                    .getUserLastModified(), onlineResource
10056:                                    .getDateReleased(), onlineResource
10057:                                    .getDateExpired(), 0, onlineResource
10058:                                    .getLength(), onlineResource
10059:                                    .getDateContent(), onlineResource
10060:                                    .getVersion(), // version number does not matter since it will be computed later
10061:                            onlineContent);
10062:
10063:                    // write the file in the offline project
10064:                    // this sets a flag so that the file date is not set to the current time
10065:                    restoredFile.setDateLastModified(onlineResource
10066:                            .getDateLastModified());
10067:
10068:                    // collect the old properties
10069:                    List properties = m_vfsDriver.readPropertyObjects(dbc,
10070:                            onlineProject, onlineResource);
10071:
10072:                    if (offlineResource != null) {
10073:                        // bug fix 1020: delete all properties (included shared), 
10074:                        // shared properties will be recreated by the next call of #createResource(...)
10075:                        m_vfsDriver
10076:                                .deletePropertyObjects(
10077:                                        dbc,
10078:                                        dbc.currentProject().getUuid(),
10079:                                        onlineResource,
10080:                                        CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES);
10081:
10082:                        // implementation notes: 
10083:                        // undo changes can become complex e.g. if a resource was deleted, and then 
10084:                        // another resource was copied over the deleted file as a sibling
10085:                        // therefore we must "clean" delete the offline resource, and then create 
10086:                        // an new resource with the create method
10087:                        // note that this does NOT apply to folders, since a folder cannot be replaced
10088:                        // like a resource anyway
10089:                        deleteResource(dbc, offlineResource,
10090:                                CmsResource.DELETE_PRESERVE_SIBLINGS);
10091:
10092:                    }
10093:                    CmsResource res = createResource(dbc, restoredFile
10094:                            .getRootPath(), restoredFile, restoredFile
10095:                            .getContents(), properties, false);
10096:
10097:                    // copy the access control entries from the online project
10098:                    if (offlineResource != null) {
10099:                        m_userDriver.removeAccessControlEntries(dbc, dbc
10100:                                .currentProject(), onlineResource
10101:                                .getResourceId());
10102:                    }
10103:                    ListIterator aceList = m_userDriver
10104:                            .readAccessControlEntries(dbc, onlineProject,
10105:                                    onlineResource.getResourceId(), false)
10106:                            .listIterator();
10107:
10108:                    while (aceList.hasNext()) {
10109:                        CmsAccessControlEntry ace = (CmsAccessControlEntry) aceList
10110:                                .next();
10111:                        m_userDriver.createAccessControlEntry(dbc, dbc
10112:                                .currentProject(), res.getResourceId(), ace
10113:                                .getPrincipal(), ace.getPermissions()
10114:                                .getAllowedPermissions(), ace.getPermissions()
10115:                                .getDeniedPermissions(), ace.getFlags());
10116:                    }
10117:
10118:                    // restore the state to unchanged 
10119:                    res.setState(newState);
10120:                    m_vfsDriver.writeResourceState(dbc, dbc.currentProject(),
10121:                            res, UPDATE_ALL, false);
10122:                }
10123:
10124:                // delete all offline relations
10125:                m_vfsDriver.deleteRelations(dbc,
10126:                        dbc.currentProject().getUuid(), offlineResource,
10127:                        CmsRelationFilter.TARGETS);
10128:                // get online relations
10129:                List relations = m_vfsDriver.readRelations(dbc,
10130:                        CmsProject.ONLINE_PROJECT_ID, onlineResource,
10131:                        CmsRelationFilter.TARGETS);
10132:                // write offline relations
10133:                Iterator itRelations = relations.iterator();
10134:                while (itRelations.hasNext()) {
10135:                    CmsRelation relation = (CmsRelation) itRelations.next();
10136:                    m_vfsDriver.createRelation(dbc, dbc.currentProject()
10137:                            .getUuid(), relation);
10138:                }
10139:
10140:                // update the cache
10141:                OpenCms.getMemoryMonitor().clearResourceCache();
10142:                OpenCms.getMemoryMonitor().flushProperties();
10143:                OpenCms.getMemoryMonitor().flushPropertyLists();
10144:
10145:                if (offlineResource != null) {
10146:                    OpenCms
10147:                            .fireCmsEvent(new CmsEvent(
10148:                                    I_CmsEventListener.EVENT_RESOURCE_AND_PROPERTIES_MODIFIED,
10149:                                    Collections.singletonMap("resource",
10150:                                            offlineResource)));
10151:                } else {
10152:                    OpenCms
10153:                            .fireCmsEvent(new CmsEvent(
10154:                                    I_CmsEventListener.EVENT_RESOURCE_AND_PROPERTIES_MODIFIED,
10155:                                    Collections.singletonMap("resource",
10156:                                            onlineResource)));
10157:                }
10158:            }
10159:
10160:            /**
10161:             * Updates the current users context dates with the given resource.<p>
10162:             * 
10163:             * This checks the date information of the resource based on
10164:             * {@link CmsResource#getDateLastModified()} as well as 
10165:             * {@link CmsResource#getDateReleased()} and {@link CmsResource#getDateExpired()}.
10166:             * The current users request context is updated with the the "latest" dates found.<p>
10167:             * 
10168:             * This is required in order to ensure proper setting of <code>"last-modified"</code> http headers
10169:             * and also for expiration of cached elements in the Flex cache.
10170:             * Consider the following use case: Page A is generated from resources x, y and z. 
10171:             * If either x, y or z has an expiration / release date set, then page A must expire at a certain point 
10172:             * in time. This is ensured by the context date check here.<p>
10173:             * 
10174:             * @param dbc the current database context
10175:             * @param resource the resource to get the date information from
10176:             */
10177:            private void updateContextDates(CmsDbContext dbc,
10178:                    CmsResource resource) {
10179:
10180:                CmsFlexRequestContextInfo info = dbc
10181:                        .getFlexRequestContextInfo();
10182:                if (info != null) {
10183:                    info.updateFromResource(resource);
10184:                }
10185:            }
10186:
10187:            /**
10188:             * Updates the current users context dates with each {@link CmsResource} object in the given list.<p>
10189:             * 
10190:             * The given input list is returned unmodified.<p>
10191:             * 
10192:             * Please see {@link #updateContextDates(CmsDbContext, CmsResource)} for an explanation of what this method does.<p>
10193:             * 
10194:             * @param dbc the current database context
10195:             * @param resourceList a list of {@link CmsResource} objects
10196:             * 
10197:             * @return the original list of CmsResources with the full resource name set 
10198:             */
10199:            private List updateContextDates(CmsDbContext dbc, List resourceList) {
10200:
10201:                CmsFlexRequestContextInfo info = dbc
10202:                        .getFlexRequestContextInfo();
10203:                if (info != null) {
10204:                    for (int i = 0; i < resourceList.size(); i++) {
10205:                        CmsResource resource = (CmsResource) resourceList
10206:                                .get(i);
10207:                        info.updateFromResource(resource);
10208:                    }
10209:                }
10210:                return resourceList;
10211:            }
10212:
10213:            /**
10214:             * Returns a List of {@link CmsResource} objects generated when applying the given filter to the given list,
10215:             * also updates the current users context dates with each {@link CmsResource} object in the given list,
10216:             * also applies the selected resource filter to all resources in the list and returns the remaining resources.<p>
10217:             * 
10218:             * Please see {@link #updateContextDates(CmsDbContext, CmsResource)} for an explanation of what this method does.<p>
10219:             * 
10220:             * @param dbc the current database context
10221:             * @param resourceList a list of {@link CmsResource} objects
10222:             * @param filter the resource filter to use
10223:             * 
10224:             * @return a List of {@link CmsResource} objects generated when applying the given filter to the given list
10225:             */
10226:            private List updateContextDates(CmsDbContext dbc,
10227:                    List resourceList, CmsResourceFilter filter) {
10228:
10229:                if (CmsResourceFilter.ALL == filter) {
10230:                    // if there is no filter required, then use the simpler method that does not apply the filter
10231:                    if (resourceList instanceof  ArrayList) {
10232:                        // performance implementation for ArrayLists
10233:                        return (List) ((ArrayList) (updateContextDates(dbc,
10234:                                resourceList))).clone();
10235:                    } else {
10236:                        return new ArrayList(updateContextDates(dbc,
10237:                                resourceList));
10238:                    }
10239:                }
10240:
10241:                CmsFlexRequestContextInfo info = dbc
10242:                        .getFlexRequestContextInfo();
10243:                ArrayList result = new ArrayList(resourceList.size());
10244:                for (int i = 0; i < resourceList.size(); i++) {
10245:                    CmsResource resource = (CmsResource) resourceList.get(i);
10246:                    if (filter.isValid(dbc.getRequestContext(), resource)) {
10247:                        result.add(resource);
10248:                    }
10249:                    // must also include "invalid" resources for the update of context dates
10250:                    // since a resource may be invalid because of release / expiration date
10251:                    if (info != null) {
10252:                        info.updateFromResource(resource);
10253:                    }
10254:                }
10255:                return result;
10256:            }
10257:
10258:            /**
10259:             * Updates the state of a resource, depending on the <code>resourceState</code> parameter.<p>
10260:             * 
10261:             * @param dbc the db context
10262:             * @param resource the resource
10263:             * @param resourceState if <code>true</code> the resource state will be updated, if not just the structure state.
10264:             * 
10265:             * @throws CmsDataAccessException if something goes wrong 
10266:             */
10267:            private void updateState(CmsDbContext dbc, CmsResource resource,
10268:                    boolean resourceState) throws CmsDataAccessException {
10269:
10270:                resource.setUserLastModified(dbc.currentUser().getId());
10271:                if (resourceState) {
10272:                    // update the whole resource state
10273:                    m_vfsDriver.writeResource(dbc, dbc.currentProject()
10274:                            .getUuid(), resource, UPDATE_RESOURCE_STATE);
10275:                } else {
10276:                    // update the structure state
10277:                    m_vfsDriver.writeResource(dbc, dbc.currentProject()
10278:                            .getUuid(), resource, UPDATE_STRUCTURE_STATE);
10279:                }
10280:            }
10281:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.