KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > opencms > db > CmsDriverManager


1 /*
2  * File : $Source: /usr/local/cvs/opencms/src/org/opencms/db/CmsDriverManager.java,v $
3  * Date : $Date: 2006/11/02 13:16:00 $
4  * Version: $Revision: 1.577 $
5  *
6  * This library is part of OpenCms -
7  * the Open Source Content Mananagement System
8  *
9  * Copyright (c) 2005 Alkacon Software GmbH (http://www.alkacon.com)
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * Lesser General Public License for more details.
20  *
21  * For further information about Alkacon Software GmbH, please see the
22  * company website: http://www.alkacon.com
23  *
24  * For further information about OpenCms, please see the
25  * project website: http://www.opencms.org
26  *
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30  */

31
32 package org.opencms.db;
33
34 import org.opencms.configuration.CmsConfigurationManager;
35 import org.opencms.configuration.CmsSystemConfiguration;
36 import org.opencms.file.CmsBackupProject;
37 import org.opencms.file.CmsBackupResource;
38 import org.opencms.file.CmsDataAccessException;
39 import org.opencms.file.CmsFile;
40 import org.opencms.file.CmsFolder;
41 import org.opencms.file.CmsGroup;
42 import org.opencms.file.CmsObject;
43 import org.opencms.file.CmsProject;
44 import org.opencms.file.CmsProperty;
45 import org.opencms.file.CmsPropertyDefinition;
46 import org.opencms.file.CmsRequestContext;
47 import org.opencms.file.CmsResource;
48 import org.opencms.file.CmsResourceFilter;
49 import org.opencms.file.CmsUser;
50 import org.opencms.file.CmsVfsException;
51 import org.opencms.file.CmsVfsResourceAlreadyExistsException;
52 import org.opencms.file.CmsVfsResourceNotFoundException;
53 import org.opencms.file.types.CmsResourceTypeFolder;
54 import org.opencms.file.types.CmsResourceTypeJsp;
55 import org.opencms.file.types.I_CmsResourceType;
56 import org.opencms.flex.CmsFlexRequestContextInfo;
57 import org.opencms.i18n.CmsLocaleManager;
58 import org.opencms.i18n.CmsMessageContainer;
59 import org.opencms.lock.CmsLock;
60 import org.opencms.lock.CmsLockException;
61 import org.opencms.lock.CmsLockManager;
62 import org.opencms.main.CmsEvent;
63 import org.opencms.main.CmsException;
64 import org.opencms.main.CmsIllegalArgumentException;
65 import org.opencms.main.CmsIllegalStateException;
66 import org.opencms.main.CmsInitException;
67 import org.opencms.main.CmsLog;
68 import org.opencms.main.I_CmsEventListener;
69 import org.opencms.main.OpenCms;
70 import org.opencms.module.CmsModule;
71 import org.opencms.report.CmsLogReport;
72 import org.opencms.report.I_CmsReport;
73 import org.opencms.security.CmsAccessControlEntry;
74 import org.opencms.security.CmsAccessControlList;
75 import org.opencms.security.CmsAuthentificationException;
76 import org.opencms.security.CmsPasswordEncryptionException;
77 import org.opencms.security.CmsPermissionSet;
78 import org.opencms.security.CmsPermissionSetCustom;
79 import org.opencms.security.CmsRole;
80 import org.opencms.security.CmsSecurityException;
81 import org.opencms.security.I_CmsPrincipal;
82 import org.opencms.util.CmsFileUtil;
83 import org.opencms.util.CmsStringUtil;
84 import org.opencms.util.CmsUUID;
85 import org.opencms.validation.CmsXmlDocumentLinkValidator;
86 import org.opencms.workflow.CmsTask;
87 import org.opencms.workflow.CmsTaskLog;
88 import org.opencms.workflow.CmsTaskService;
89
90 import java.util.ArrayList JavaDoc;
91 import java.util.Arrays JavaDoc;
92 import java.util.Collections JavaDoc;
93 import java.util.HashMap JavaDoc;
94 import java.util.HashSet JavaDoc;
95 import java.util.Iterator JavaDoc;
96 import java.util.List JavaDoc;
97 import java.util.ListIterator JavaDoc;
98 import java.util.Map JavaDoc;
99 import java.util.Set JavaDoc;
100 import java.util.Stack JavaDoc;
101 import java.util.Vector JavaDoc;
102
103 import org.apache.commons.collections.ExtendedProperties;
104 import org.apache.commons.collections.map.LRUMap;
105 import org.apache.commons.dbcp.PoolingDriver;
106 import org.apache.commons.logging.Log;
107 import org.apache.commons.pool.ObjectPool;
108
109 /**
110  * The OpenCms driver manager.<p>
111  *
112  * @author Alexander Kandzior
113  * @author Thomas Weckert
114  * @author Carsten Weinholz
115  * @author Michael Emmerich
116  * @author Michael Moossen
117  *
118  * @since 6.0.0
119  */

120 public final class CmsDriverManager implements I_CmsEventListener {
121
122     /**
123      * Provides a method to build cache keys for groups and users that depend either on
124      * a name string or an id.<p>
125      *
126      * @author Alexander Kandzior
127      */

128     private class CacheId extends Object JavaDoc {
129
130         /**
131          * Name of the object.
132          */

133         public String JavaDoc m_name;
134
135         /**
136          * Id of the object.
137          */

138         public CmsUUID m_uuid;
139
140         /**
141          * Creates a new CacheId for a CmsGroup.<p>
142          *
143          * @param group the group to create a cache id from
144          */

145         public CacheId(CmsGroup group) {
146
147             m_name = group.getName();
148             m_uuid = group.getId();
149         }
150
151         /**
152          * Creates a new CacheId for a CmsResource.<p>
153          *
154          * @param resource the resource to create a cache id from
155          */

156         public CacheId(CmsResource resource) {
157
158             m_name = resource.getName();
159             m_uuid = resource.getResourceId();
160         }
161
162         /**
163          * Creates a new CacheId for a CmsUser.<p>
164          *
165          * @param user the user to create a cache id from
166          */

167         public CacheId(CmsUser user) {
168
169             m_name = user.getName() + user.getType();
170             m_uuid = user.getId();
171         }
172
173         /**
174          * Creates a new CacheId for a CmsUUID.<p>
175          *
176          * @param uuid the uuid to create a cache id from
177          */

178         public CacheId(CmsUUID uuid) {
179
180             m_uuid = uuid;
181         }
182
183         /**
184          * Creates a new CacheId for a String.<p>
185          *
186          * @param str the string to create a cache id from
187          */

188         public CacheId(String JavaDoc str) {
189
190             m_name = str;
191         }
192
193         /**
194          * Creates a new CacheId for a String and CmsUUID.<p>
195          *
196          * @param name the string to create a cache id from
197          * @param uuid the uuid to create a cache id from
198          */

199         public CacheId(String JavaDoc name, CmsUUID uuid) {
200
201             m_name = name;
202             m_uuid = uuid;
203         }
204
205         /**
206          * @see java.lang.Object#equals(java.lang.Object)
207          */

208         public boolean equals(Object JavaDoc obj) {
209
210             if (obj == this) {
211                 return true;
212             }
213             if (!(obj instanceof CacheId)) {
214                 return false;
215             }
216             CacheId other = (CacheId)obj;
217             boolean result;
218             if (m_uuid != null) {
219                 result = m_uuid.equals(other.m_uuid);
220                 if (result) {
221                     return true;
222                 }
223             }
224             if (m_name != null) {
225                 result = m_name.equals(other.m_name);
226                 if (result) {
227                     return true;
228                 }
229             }
230             return false;
231         }
232
233         /**
234          * @see java.lang.Object#hashCode()
235          */

236         public int hashCode() {
237
238             if (m_uuid == null) {
239                 return 509;
240             } else {
241                 return m_uuid.hashCode();
242             }
243         }
244
245     }
246
247     /** Cache key for all properties. */
248     public static final String JavaDoc CACHE_ALL_PROPERTIES = "_CAP_";
249
250     /** "driver.backup" string in the configuration-file. */
251     public static final String JavaDoc CONFIGURATION_BACKUP = "driver.backup";
252
253     /** "cache" string in the configuration-file. */
254     public static final String JavaDoc CONFIGURATION_CACHE = "cache";
255
256     /** "db" string in the configuration-file. */
257     public static final String JavaDoc CONFIGURATION_DB = "db";
258
259     /** "driver.project" string in the configuration-file. */
260     public static final String JavaDoc CONFIGURATION_PROJECT = "driver.project";
261
262     /** "driver.user" string in the configuration-file. */
263     public static final String JavaDoc CONFIGURATION_USER = "driver.user";
264
265     /** "driver.vfs" string in the configuration-file. */
266     public static final String JavaDoc CONFIGURATION_VFS = "driver.vfs";
267
268     /** "driver.workflow" string in the configuration-file. */
269     public static final String JavaDoc CONFIGURATION_WORKFLOW = "driver.workflow";
270
271     /** The vfs path of the loast and found folder. */
272     public static final String JavaDoc LOST_AND_FOUND_FOLDER = "/system/lost-found";
273
274     /** The maximum length of a VFS resource path. */
275     public static final int MAX_VFS_RESOURCE_PATH_LENGTH = 512;
276
277     /** Key for indicating no changes. */
278     public static final int NOTHING_CHANGED = 0;
279
280     /** Indicates to ignore the resource path when matching resources. */
281     public static final String JavaDoc READ_IGNORE_PARENT = null;
282
283     /** Indicates to ignore the resource state when matching resources. */
284     public static final int READ_IGNORE_STATE = -1;
285
286     /** Indicates to ignore the time value. */
287     public static final long READ_IGNORE_TIME = 0L;
288
289     /** Indicates to ignore the resource type when matching resources. */
290     public static final int READ_IGNORE_TYPE = -1;
291
292     /** Indicates to match resources NOT having the given state. */
293     public static final int READMODE_EXCLUDE_STATE = 8;
294
295     /** Indicates to match immediate children only. */
296     public static final int READMODE_EXCLUDE_TREE = 1;
297
298     /** Indicates to match resources NOT having the given type. */
299     public static final int READMODE_EXCLUDE_TYPE = 4;
300
301     /** Mode for reading project resources from the db. */
302     public static final int READMODE_IGNORESTATE = 0;
303
304     /** Indicates to match resources in given project only. */
305     public static final int READMODE_INCLUDE_PROJECT = 2;
306
307     /** Indicates to match all successors. */
308     public static final int READMODE_INCLUDE_TREE = 0;
309
310     /** Mode for reading project resources from the db. */
311     public static final int READMODE_MATCHSTATE = 1;
312
313     /** Indicates if only file resources should be read. */
314     public static final int READMODE_ONLY_FILES = 128;
315
316     /** Indicates if only folder resources should be read. */
317     public static final int READMODE_ONLY_FOLDERS = 64;
318
319     /** Mode for reading project resources from the db. */
320     public static final int READMODE_UNMATCHSTATE = 2;
321
322     /** Key to indicate complete update. */
323     public static final int UPDATE_ALL = 3;
324
325     /** Key to indicate update of resource record. */
326     public static final int UPDATE_RESOURCE = 4;
327
328     /** Key to indicate update of resource state. */
329     public static final int UPDATE_RESOURCE_STATE = 1;
330
331     /** Key to indicate update of structure record. */
332     public static final int UPDATE_STRUCTURE = 5;
333
334     /** Key to indicate update of structure state. */
335     public static final int UPDATE_STRUCTURE_STATE = 2;
336
337     /** The log object for this class. */
338     private static final Log LOG = CmsLog.getLog(CmsSecurityManager.class);
339
340     /** Separator for user cache. */
341     private static final char USER_CACHE_SEP = '\u0000';
342
343     /** Cache for access control lists. */
344     private Map JavaDoc m_accessControlListCache;
345
346     /** The backup driver. */
347     private I_CmsBackupDriver m_backupDriver;
348
349     /** Temporary concurrent lock list for the "create resource" method. */
350     private List m_concurrentCreateResourceLocks;
351
352     /** The configuration of the property-file. */
353     private Map JavaDoc m_configuration;
354
355     /** The list of initialized JDBC pools. */
356     private List m_connectionPools;
357
358     /** Cache for groups. */
359     private Map JavaDoc m_groupCache;
360
361     /** The HTML link validator. */
362     private CmsXmlDocumentLinkValidator m_htmlLinkValidator;
363
364     /** The class used for cache key generation. */
365     private I_CmsCacheKey m_keyGenerator;
366
367     /** The lock manager. */
368     private CmsLockManager m_lockManager = OpenCms.getLockManager();
369
370     /** Cache for offline projects. */
371     private Map JavaDoc m_projectCache;
372
373     /** The project driver. */
374     private I_CmsProjectDriver m_projectDriver;
375
376     /** Cache for properties. */
377     private Map JavaDoc m_propertyCache;
378
379     /** Cache for resources. */
380     private Map JavaDoc m_resourceCache;
381
382     /** Cache for resource lists. */
383     private Map JavaDoc m_resourceListCache;
384
385     /** The security manager (for access checks). */
386     private CmsSecurityManager m_securityManager;
387
388     /** The sql manager. */
389     private CmsSqlManager m_sqlManager;
390
391     /** Cache for user data. */
392     private Map JavaDoc m_userCache;
393
394     /** The user driver. */
395     private I_CmsUserDriver m_userDriver;
396
397     /** Cache for user groups. */
398     private Map JavaDoc m_userGroupsCache;
399
400     /** The VFS driver. */
401     private I_CmsVfsDriver m_vfsDriver;
402
403     /** The workflow driver. */
404     private I_CmsWorkflowDriver m_workflowDriver;
405
406     /**
407      * Private constructor, initializes some required member variables.<p>
408      */

409     private CmsDriverManager() {
410
411         m_connectionPools = new ArrayList JavaDoc();
412     }
413
414     /**
415      * Reads the required configurations from the opencms.properties file and creates
416      * the various drivers to access the cms resources.<p>
417      *
418      * The initialization process of the driver manager and its drivers is split into
419      * the following phases:
420      * <ul>
421      * <li>the database pool configuration is read</li>
422      * <li>a plain and empty driver manager instance is created</li>
423      * <li>an instance of each driver is created</li>
424      * <li>the driver manager is passed to each driver during initialization</li>
425      * <li>finally, the driver instances are passed to the driver manager during initialization</li>
426      * </ul>
427      *
428      * @param configurationManager the configuration manager
429      * @param securityManager the security manager
430      * @param runtimeInfoFactory the initialized OpenCms runtime info factory
431      *
432      * @return CmsDriverManager the instanciated driver manager
433      * @throws CmsInitException if the driver manager couldn't be instanciated
434      */

435     public static CmsDriverManager newInstance(
436         CmsConfigurationManager configurationManager,
437         CmsSecurityManager securityManager,
438         I_CmsDbContextFactory runtimeInfoFactory) throws CmsInitException {
439
440         Map JavaDoc configuration = configurationManager.getConfiguration();
441
442         ExtendedProperties config;
443         if (configuration instanceof ExtendedProperties) {
444             config = (ExtendedProperties)configuration;
445         } else {
446             config = new ExtendedProperties();
447             config.putAll(configuration);
448         }
449
450         // initialize static hashtables
451
CmsDbUtil.init();
452
453         List drivers = null;
454         String JavaDoc driverName = null;
455
456         I_CmsVfsDriver vfsDriver = null;
457         I_CmsUserDriver userDriver = null;
458         I_CmsProjectDriver projectDriver = null;
459         I_CmsWorkflowDriver workflowDriver = null;
460         I_CmsBackupDriver backupDriver = null;
461
462         CmsDriverManager driverManager = null;
463         try {
464             // create a driver manager instance
465
driverManager = new CmsDriverManager();
466             if (CmsLog.INIT.isInfoEnabled()) {
467                 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_DRIVER_MANAGER_START_PHASE1_0));
468             }
469             if ((runtimeInfoFactory == null) && CmsLog.INIT.isDebugEnabled()) {
470                 CmsLog.INIT.debug(Messages.get().getBundle().key(Messages.INIT_DRIVER_MANAGER_START_RT_0));
471             }
472         } catch (Exception JavaDoc exc) {
473             CmsMessageContainer message = Messages.get().container(Messages.LOG_ERR_DRIVER_MANAGER_START_0);
474             if (LOG.isFatalEnabled()) {
475                 LOG.fatal(message.key(), exc);
476             }
477             throw new CmsInitException(message, exc);
478         }
479
480         // set the security manager
481
driverManager.m_securityManager = securityManager;
482
483         // create and set the sql manager
484
driverManager.m_sqlManager = new CmsSqlManager(driverManager);
485
486         if (CmsLog.INIT.isInfoEnabled()) {
487             CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_DRIVER_MANAGER_START_PHASE2_0));
488         }
489
490         // read the pool names to initialize
491
String JavaDoc[] driverPoolNames = config.getStringArray(CmsDriverManager.CONFIGURATION_DB + ".pools");
492         if (CmsLog.INIT.isInfoEnabled()) {
493             String JavaDoc names = "";
494             for (int p = 0; p < driverPoolNames.length; p++) {
495                 names += driverPoolNames[p] + " ";
496             }
497             CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_DRIVER_MANAGER_START_POOLS_1, names));
498         }
499
500         // initialize each pool
501
for (int p = 0; p < driverPoolNames.length; p++) {
502             driverManager.newPoolInstance(config, driverPoolNames[p]);
503         }
504
505         // initialize the runtime info factory with the generated driver manager
506
if (runtimeInfoFactory != null) {
507             runtimeInfoFactory.initialize(driverManager);
508         }
509
510         if (CmsLog.INIT.isInfoEnabled()) {
511             CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_DRIVER_MANAGER_START_PHASE3_0));
512         }
513
514         // read the vfs driver class properties and initialize a new instance
515
drivers = Arrays.asList(config.getStringArray(CmsDriverManager.CONFIGURATION_VFS));
516         driverName = config.getString((String JavaDoc)drivers.get(0) + ".vfs.driver");
517         drivers = (drivers.size() > 1) ? drivers.subList(1, drivers.size()) : null;
518         vfsDriver = (I_CmsVfsDriver)driverManager.newDriverInstance(configurationManager, driverName, drivers);
519
520         // read the user driver class properties and initialize a new instance
521
drivers = Arrays.asList(config.getStringArray(CmsDriverManager.CONFIGURATION_USER));
522         driverName = config.getString((String JavaDoc)drivers.get(0) + ".user.driver");
523         drivers = (drivers.size() > 1) ? drivers.subList(1, drivers.size()) : null;
524         userDriver = (I_CmsUserDriver)driverManager.newDriverInstance(configurationManager, driverName, drivers);
525
526         // read the project driver class properties and initialize a new instance
527
drivers = Arrays.asList(config.getStringArray(CmsDriverManager.CONFIGURATION_PROJECT));
528         driverName = config.getString((String JavaDoc)drivers.get(0) + ".project.driver");
529         drivers = (drivers.size() > 1) ? drivers.subList(1, drivers.size()) : null;
530         projectDriver = (I_CmsProjectDriver)driverManager.newDriverInstance(configurationManager, driverName, drivers);
531
532         // read the workflow driver class properties and initialize a new instance
533
drivers = Arrays.asList(config.getStringArray(CmsDriverManager.CONFIGURATION_WORKFLOW));
534         driverName = config.getString((String JavaDoc)drivers.get(0) + ".workflow.driver");
535         drivers = (drivers.size() > 1) ? drivers.subList(1, drivers.size()) : null;
536         workflowDriver = (I_CmsWorkflowDriver)driverManager.newDriverInstance(configurationManager, driverName, drivers);
537
538         // read the backup driver class properties and initialize a new instance
539
drivers = Arrays.asList(config.getStringArray(CmsDriverManager.CONFIGURATION_BACKUP));
540         driverName = config.getString((String JavaDoc)drivers.get(0) + ".backup.driver");
541         drivers = (drivers.size() > 1) ? drivers.subList(1, drivers.size()) : null;
542         backupDriver = (I_CmsBackupDriver)driverManager.newDriverInstance(configurationManager, driverName, drivers);
543
544         try {
545             // invoke the init method of the driver manager
546
driverManager.init(
547                 configurationManager,
548                 config,
549                 vfsDriver,
550                 userDriver,
551                 projectDriver,
552                 workflowDriver,
553                 backupDriver);
554             if (CmsLog.INIT.isInfoEnabled()) {
555                 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_DRIVER_MANAGER_START_PHASE4_OK_0));
556             }
557         } catch (Exception JavaDoc exc) {
558             CmsMessageContainer message = Messages.get().container(Messages.LOG_ERR_DRIVER_MANAGER_START_0);
559             if (LOG.isFatalEnabled()) {
560                 LOG.fatal(message.key(), exc);
561             }
562             throw new CmsInitException(message, exc);
563         }
564
565         // register the driver manager for required events
566
org.opencms.main.OpenCms.addCmsEventListener(driverManager, new int[] {
567             I_CmsEventListener.EVENT_UPDATE_EXPORTS,
568             I_CmsEventListener.EVENT_CLEAR_CACHES,
569             I_CmsEventListener.EVENT_CLEAR_PRINCIPAL_CACHES,
570             I_CmsEventListener.EVENT_PUBLISH_PROJECT});
571
572         // return the configured driver manager
573
return driverManager;
574     }
575
576     /**
577      * Updates the state of the given task as accepted by the current user.<p>
578      *
579      * @param dbc the current database context
580      * @param taskId the Id of the task to accept
581      *
582      * @throws CmsException if something goes wrong
583      */

584     public void acceptTask(CmsDbContext dbc, int taskId) throws CmsException {
585
586         CmsTask task = m_workflowDriver.readTask(dbc, taskId);
587         task.setPercentage(1);
588         task = m_workflowDriver.writeTask(dbc, task);
589         // currently don't localize workflow logs (this log goes to the database)
590
m_workflowDriver.writeSystemTaskLog(dbc, taskId, "Task was accepted from "
591             + dbc.currentUser().getFirstname()
592             + " "
593             + dbc.currentUser().getLastname()
594             + '.');
595     }
596
597     /**
598      * Adds a user to a group.<p>
599      *
600      * @param dbc the current database context
601      * @param username the name of the user that is to be added to the group
602      * @param groupname the name of the group
603      *
604      * @throws CmsException if operation was not succesfull
605      * @throws CmsDbEntryNotFoundException if the given user or the given group was not found
606      */

607     public void addUserToGroup(CmsDbContext dbc, String JavaDoc username, String JavaDoc groupname)
608     throws CmsException, CmsDbEntryNotFoundException {
609
610         if (!userInGroup(dbc, username, groupname)) {
611             CmsUser user;
612             CmsGroup group;
613             try {
614                 user = readUser(dbc, username);
615             } catch (CmsDbEntryNotFoundException e) {
616                 user = readWebUser(dbc, username);
617             }
618             //check if the user exists
619
if (user != null) {
620                 // web user can not be members of:
621
// Administrators, Projectmanagers or Users
622
if (user.getType() == CmsUser.USER_TYPE_WEBUSER) {
623                     List forbidden = new ArrayList JavaDoc();
624                     forbidden.add(OpenCms.getDefaultUsers().getGroupAdministrators());
625                     forbidden.add(OpenCms.getDefaultUsers().getGroupProjectmanagers());
626                     forbidden.add(OpenCms.getDefaultUsers().getGroupUsers());
627                     if (forbidden.contains(groupname)) {
628                         throw new CmsSecurityException(
629                             Messages.get().container(Messages.ERR_WEBUSER_GROUP_1, forbidden));
630                     }
631                 }
632
633                 group = readGroup(dbc, groupname);
634                 //check if group exists
635
if (group != null) {
636                     //add this user to the group
637
m_userDriver.createUserInGroup(dbc, user.getId(), group.getId(), null);
638                     // update the cache
639
m_userGroupsCache.clear();
640                 } else {
641                     throw new CmsDbEntryNotFoundException(Messages.get().container(
642                         Messages.ERR_UNKNOWN_GROUP_1,
643                         groupname));
644                 }
645             } else {
646                 throw new CmsDbEntryNotFoundException(Messages.get().container(
647                     Messages.ERR_UNKNOWN_USER_1,
648                     user.getName()));
649             }
650         }
651     }
652
653     /**
654      * Creates a new web user.<p>
655      *
656      * A web user has no access to the workplace but is able to access personalized
657      * functions controlled by the OpenCms.<br>
658      *
659      * Moreover, a web user can be created by any user, the intention being that
660      * a "Guest" user can create a personalized account for himself.<p>
661      *
662      * @param dbc the current database context
663      * @param name the new name for the user
664      * @param password the new password for the user
665      * @param group the default groupname for the user
666      * @param description the description for the user
667      * @param additionalInfos a <code>{@link Map}</code> with additional infos for the user
668      * Infos may be stored into the Usertables (depending on the implementation).
669      *
670      * @return the new user will be returned
671      *
672      * @throws CmsException if operation was not succesfull
673      * @throws CmsSecurityException if the password is not valid
674      * @throws CmsIllegalArgumentException if the provided name has an illegal format (length == 0)
675      * @throws CmsDbEntryNotFoundException if the user for the given name or the given group was not found
676      */

677     public CmsUser addWebUser(
678         CmsDbContext dbc,
679         String JavaDoc name,
680         String JavaDoc password,
681         String JavaDoc group,
682         String JavaDoc description,
683         Map JavaDoc additionalInfos)
684     throws CmsException, CmsSecurityException, CmsIllegalArgumentException, CmsDbEntryNotFoundException {
685
686         return addWebUser(dbc, name, password, group, null, description, additionalInfos);
687     }
688
689     /**
690      * Adds a web user to the Cms.<p>
691      *
692      * A web user has no access to the workplace but is able to access personalized
693      * functions controlled by the OpenCms.<p>
694      *
695      * @param dbc the current database context
696      * @param name the new name for the user
697      * @param password the new password for the user
698      * @param group the default groupname for the user
699      * @param additionalGroup an additional group for the user
700      * @param description the description for the user
701      * @param additionalInfos a Hashtable with additional infos for the user, these
702      * Infos may be stored into the Usertables (depending on the implementation)
703      *
704      * @return the new user will be returned
705      *
706      * @throws CmsException if operation was not succesfull
707      * @throws CmsSecurityException if the password is not valid
708      * @throws CmsIllegalArgumentException if the provided name has an illegal format (length == 0)
709      * @throws CmsDbEntryNotFoundException if the user for the given name or the given group was not found
710      */

711     public CmsUser addWebUser(
712         CmsDbContext dbc,
713         String JavaDoc name,
714         String JavaDoc password,
715         String JavaDoc group,
716         String JavaDoc additionalGroup,
717         String JavaDoc description,
718         Map JavaDoc additionalInfos)
719     throws CmsException, CmsDbEntryNotFoundException, CmsIllegalArgumentException, CmsSecurityException {
720
721         CmsUser newUser = createUser(dbc, name, password, description, additionalInfos, CmsUser.USER_TYPE_WEBUSER);
722         CmsUser user = m_userDriver.readUser(dbc, newUser.getName(), CmsUser.USER_TYPE_WEBUSER);
723         //check if the user exists
724
if (user != null) {
725             CmsGroup usergroup = readGroup(dbc, group);
726             //check if group exists
727
if (usergroup != null && isWebgroup(dbc, usergroup)) {
728                 //add this user to the group
729
m_userDriver.createUserInGroup(dbc, user.getId(), usergroup.getId(), null);
730                 // update the cache
731
m_userGroupsCache.clear();
732             } else {
733                 throw new CmsDbEntryNotFoundException(Messages.get().container(Messages.ERR_UNKNOWN_GROUP_1, group));
734             }
735             // if an additional groupname is given and the group does not belong to
736
// Users, Administrators or Projectmanager add the user to this group
737
if (CmsStringUtil.isNotEmpty(additionalGroup)) {
738                 CmsGroup addGroup = readGroup(dbc, additionalGroup);
739                 if (addGroup != null && isWebgroup(dbc, addGroup)) {
740                     //add this user to the group
741
m_userDriver.createUserInGroup(dbc, user.getId(), addGroup.getId(), null);
742                     // update the cache
743
m_userGroupsCache.clear();
744                 } else {
745                     throw new CmsDbEntryNotFoundException(Messages.get().container(Messages.ERR_UNKNOWN_GROUP_1, group));
746                 }
747             }
748         } else {
749             throw new CmsDbEntryNotFoundException(Messages.get().container(Messages.ERR_UNKNOWN_USER_1, user.getName()));
750         }
751         return newUser;
752     }
753
754     /**
755      * Creates a backup of the current project.<p>
756      *
757      * @param dbc the current database context
758      * @param tagId the version of the backup
759      * @param publishDate the date of publishing
760      *
761      * @throws CmsDataAccessException if operation was not succesful
762      */

763     public void backupProject(CmsDbContext dbc, int tagId, long publishDate) throws CmsDataAccessException {
764
765         m_backupDriver.writeBackupProject(dbc, tagId, publishDate);
766     }
767
768     /**
769      * Changes the project id of the resource to the current project, indicating that
770      * the resource was last modified in this project.<p>
771      *
772      * @param dbc the current database context
773      * @param resource theresource to apply this operation to
774      *
775      * @throws CmsException if something goes wrong
776      *
777      * @see CmsObject#changeLastModifiedProjectId(String)
778      * @see I_CmsResourceType#changeLastModifiedProjectId(CmsObject, CmsSecurityManager, CmsResource)
779      */

780     public void changeLastModifiedProjectId(CmsDbContext dbc, CmsResource resource) throws CmsException {
781
782         // update the project id of a modified resource as "modified inside the current project"
783
m_vfsDriver.writeLastModifiedProjectId(dbc, dbc.currentProject(), dbc.currentProject().getId(), resource);
784
785         clearResourceCache();
786
787         OpenCms.fireCmsEvent(new CmsEvent(I_CmsEventListener.EVENT_RESOURCE_MODIFIED, Collections.singletonMap(
788             "resource",
789             resource)));
790     }
791
792     /**
793      * Changes the lock of a resource to the current user,
794      * that is "steals" the lock from another user.<p>
795      *
796      * @param dbc the current database context
797      * @param resource the resource to change the lock for
798      *
799      * @throws CmsException if something goes wrong
800      * @throws CmsSecurityException if something goes wrong
801      *
802      *
803      * @see CmsObject#changeLock(String)
804      * @see I_CmsResourceType#changeLock(CmsObject, CmsSecurityManager, CmsResource)
805      *
806      * @see CmsSecurityManager#hasPermissions(CmsRequestContext, CmsResource, CmsPermissionSet, boolean, CmsResourceFilter)
807      */

808     public void changeLock(CmsDbContext dbc, CmsResource resource) throws CmsException, CmsSecurityException {
809
810         // get the current lock
811
CmsLock currentLock = getLock(dbc, resource);
812         // check if the resource is locked at all
813
if (currentLock.isNullLock()) {
814             throw new CmsLockException(Messages.get().container(
815                 Messages.ERR_CHANGE_LOCK_UNLOCKED_RESOURCE_1,
816                 dbc.getRequestContext().getSitePath(resource)));
817         } else if (currentLock.getUserId().equals(dbc.currentUser().getId())
818             && (currentLock.getProjectId() == dbc.currentProject().getId())
819             && (currentLock.getType() == CmsLock.TYPE_EXCLUSIVE)) {
820             // the current lock requires no change
821
return;
822         }
823
824         // duplicate logic from CmsSecurityManager#hasPermissions() because lock state can't be ignored
825
// if another user has locked the file, the current user can never get WRITE permissions with the default check
826
int denied = 0;
827         // check if the current user is admin
828
boolean canIgnorePermissions = m_securityManager.hasRole(dbc, CmsRole.VFS_MANAGER);
829         // if the resource type is jsp
830
// write is only allowed for administrators
831
if (!canIgnorePermissions && (resource.getTypeId() == CmsResourceTypeJsp.getStaticTypeId())) {
832             if (!m_securityManager.hasRole(dbc, CmsRole.DEVELOPER)) {
833                 denied |= CmsPermissionSet.PERMISSION_WRITE;
834             }
835         }
836         CmsPermissionSetCustom permissions;
837         if (canIgnorePermissions) {
838             // if the current user is administrator, anything is allowed
839
permissions = new CmsPermissionSetCustom(~0);
840         } else {
841             // otherwise, get the permissions from the access control list
842
permissions = getPermissions(dbc, resource, dbc.currentUser());
843         }
844         // revoke the denied permissions
845
permissions.denyPermissions(denied);
846         // now check if write permission is granted
847
if ((CmsPermissionSet.ACCESS_WRITE.getPermissions() & permissions.getPermissions()) != CmsPermissionSet.ACCESS_WRITE.getPermissions()) {
848             // check failed, throw exception
849
m_securityManager.checkPermissions(
850                 dbc.getRequestContext(),
851                 resource,
852                 CmsPermissionSet.ACCESS_WRITE,
853                 CmsSecurityManager.PERM_DENIED);
854         }
855         // if we got here write permission is granted on the target
856

857         // remove the old lock
858
m_lockManager.removeResource(this, dbc, resource, true);
859         // apply the new lock
860
lockResource(dbc, resource, CmsLock.COMMON);
861     }
862
863     /**
864      * Changes the user type of the user.<p>
865      *
866      * @param dbc the current database context
867      * @param user the user to change
868      * @param userType the new usertype of the user
869      *
870      * @throws CmsDataAccessException if something goes wrong
871      */

872     public void changeUserType(CmsDbContext dbc, CmsUser user, int userType) throws CmsDataAccessException {
873
874         // try to remove user from cache
875
clearUserCache(user);
876         m_userDriver.writeUserType(dbc, user.getId(), userType);
877     }
878
879     /**
880      * Changes the user type of the user.<p>
881      *
882      * @param dbc the current database context
883      * @param userId the id of the user to change
884      * @param userType the new usertype of the user
885      *
886      * @throws CmsDataAccessException if something goes wrong
887      * @throws CmsDataAccessException if an underlying <code>Exception</code> related to runtime type instantiation (<code>IOException</code>, <code>ClassCastException</code>) occurs.
888      * @throws CmsDbSqlException if an underlying <code>Exception</code> related to data retrieval (<code>SQLException</code>) occurs.
889      * @throws CmsDbEntryNotFoundException if the user corresponding to the given id does not exist in the database
890      *
891      */

892     public void changeUserType(CmsDbContext dbc, CmsUUID userId, int userType)
893     throws CmsDataAccessException, CmsDbEntryNotFoundException, CmsDbSqlException {
894
895         CmsUser theUser = m_userDriver.readUser(dbc, userId);
896         changeUserType(dbc, theUser, userType);
897     }
898
899     /**
900      * Changes the user type of the user.<p>
901
902      * Only the administrator can change the type.<p>
903      *
904      * @param dbc the current database context
905      * @param username the name of the user to change
906      * @param userType the new usertype of the user
907      *
908      * @throws CmsException if something goes wrong
909      */

910     public void changeUserType(CmsDbContext dbc, String JavaDoc username, int userType) throws CmsException {
911
912         CmsUser theUser = null;
913         try {
914             // try to read the webuser
915
theUser = readWebUser(dbc, username);
916         } catch (CmsDbEntryNotFoundException confe) {
917             // try to read the systemuser
918
theUser = readUser(dbc, username);
919         }
920         changeUserType(dbc, theUser, userType);
921     }
922
923     /**
924      * Changes the resource flags of a resource.<p>
925      *
926      * The resource flags are used to indicate various "special" conditions
927      * for a resource. Most notably, the "internal only" setting which signals
928      * that a resource can not be directly requested with it's URL.<p>
929      *
930      * @param dbc the current database context
931      * @param resource the resource to change the flags for
932      * @param flags the new resource flags for this resource
933      *
934      * @throws CmsException if something goes wrong
935      *
936      * @see CmsObject#chflags(String, int)
937      * @see I_CmsResourceType#chflags(CmsObject, CmsSecurityManager, CmsResource, int)
938      */

939     public void chflags(CmsDbContext dbc, CmsResource resource, int flags) throws CmsException {
940
941         // must operate on a clone to ensure resource is not modified in case permissions are not granted
942
CmsResource clone = (CmsResource)resource.clone();
943         clone.setFlags(flags);
944         writeResource(dbc, clone);
945     }
946
947     /**
948      * Changes the resource type of a resource.<p>
949      *
950      * OpenCms handles resources according to the resource type,
951      * not the file suffix. This is e.g. why a JSP in OpenCms can have the
952      * suffix ".html" instead of ".jsp" only. Changing the resource type
953      * makes sense e.g. if you want to make a plain text file a JSP resource,
954      * or a binary file an image, etc.<p>
955      *
956      * @param dbc the current database context
957      * @param resource the resource to change the type for
958      * @param type the new resource type for this resource
959      *
960      * @throws CmsException if something goes wrong
961      *
962      * @see CmsObject#chtype(String, int)
963      * @see I_CmsResourceType#chtype(CmsObject, CmsSecurityManager, CmsResource, int)
964      */

965     public void chtype(CmsDbContext dbc, CmsResource resource, int type) throws CmsException {
966
967         // must operate on a clone to ensure resource is not modified in case permissions are not granted
968
CmsResource clone = (CmsResource)resource.clone();
969         I_CmsResourceType newType = OpenCms.getResourceManager().getResourceType(type);
970         clone.setType(newType.getTypeId());
971         writeResource(dbc, clone);
972     }
973
974     /**
975      * @see org.opencms.main.I_CmsEventListener#cmsEvent(org.opencms.main.CmsEvent)
976      */

977     public void cmsEvent(CmsEvent event) {
978
979         if (LOG.isDebugEnabled()) {
980             LOG.debug(Messages.get().getBundle().key(Messages.LOG_CMS_EVENT_1, new Integer JavaDoc(event.getType())));
981         }
982
983         I_CmsReport report;
984         CmsDbContext dbc;
985
986         switch (event.getType()) {
987
988             case I_CmsEventListener.EVENT_UPDATE_EXPORTS:
989                 report = (I_CmsReport)event.getData().get(I_CmsEventListener.KEY_REPORT);
990                 dbc = (CmsDbContext)event.getData().get(I_CmsEventListener.KEY_DBCONTEXT);
991                 updateExportPoints(dbc, report);
992                 break;
993
994             case I_CmsEventListener.EVENT_PUBLISH_PROJECT:
995                 CmsUUID publishHistoryId = new CmsUUID((String JavaDoc)event.getData().get(I_CmsEventListener.KEY_PUBLISHID));
996                 report = (I_CmsReport)event.getData().get(I_CmsEventListener.KEY_REPORT);
997                 dbc = (CmsDbContext)event.getData().get(I_CmsEventListener.KEY_DBCONTEXT);
998                 int projectId = ((Integer JavaDoc)event.getData().get(I_CmsEventListener.KEY_PROJECTID)).intValue();
999                 writeExportPoints(dbc, projectId, report, publishHistoryId);
1000                break;
1001
1002            case I_CmsEventListener.EVENT_CLEAR_CACHES:
1003                clearcache(false);
1004                break;
1005            case I_CmsEventListener.EVENT_CLEAR_PRINCIPAL_CACHES:
1006                clearcache(true);
1007                break;
1008            default:
1009                // noop
1010
}
1011    }
1012
1013    /**
1014     * Copies the access control entries of a given resource to a destination resorce.<p>
1015     *
1016     * Already existing access control entries of the destination resource are removed.<p>
1017     * @param dbc the current database context
1018     * @param source the resource to copy the access control entries from
1019     * @param destination the resource to which the access control entries are copied
1020     * @param updateLastModifiedInfo if true, user and date "last modified" information on the target resource will be updated
1021     *
1022     * @throws CmsException if something goes wrong
1023     */

1024    public void copyAccessControlEntries(
1025        CmsDbContext dbc,
1026        CmsResource source,
1027        CmsResource destination,
1028        boolean updateLastModifiedInfo) throws CmsException {
1029
1030        // get the entries to copy
1031
ListIterator JavaDoc aceList = m_userDriver.readAccessControlEntries(
1032            dbc,
1033            dbc.currentProject(),
1034            source.getResourceId(),
1035            false).listIterator();
1036
1037        // remove the current entries from the destination
1038
m_userDriver.removeAccessControlEntries(dbc, dbc.currentProject(), destination.getResourceId());
1039
1040        // now write the new entries
1041
while (aceList.hasNext()) {
1042            CmsAccessControlEntry ace = (CmsAccessControlEntry)aceList.next();
1043            m_userDriver.createAccessControlEntry(
1044                dbc,
1045                dbc.currentProject(),
1046                destination.getResourceId(),
1047                ace.getPrincipal(),
1048                ace.getPermissions().getAllowedPermissions(),
1049                ace.getPermissions().getDeniedPermissions(),
1050                ace.getFlags());
1051        }
1052
1053        // update the "last modified" information
1054
if (updateLastModifiedInfo) {
1055            setDateLastModified(dbc, destination, destination.getDateLastModified());
1056        }
1057
1058        // clear the cache
1059
clearAccessControlListCache();
1060
1061        // fire a resource modification event
1062
OpenCms.fireCmsEvent(new CmsEvent(I_CmsEventListener.EVENT_RESOURCE_MODIFIED, Collections.singletonMap(
1063            "resource",
1064            destination)));
1065    }
1066
1067    /**
1068     * Copies a resource.<p>
1069     *
1070     * You must ensure that the destination path is anabsolute, vaild and
1071     * existing VFS path. Relative paths from the source are currently not supported.<p>
1072     *
1073     * In case the target resource already exists, it is overwritten with the
1074     * source resource.<p>
1075     *
1076     * The <code>siblingMode</code> parameter controls how to handle siblings
1077     * during the copy operation.
1078     * Possible values for this parameter are:
1079     * <ul>
1080     * <li><code>{@link org.opencms.file.CmsResource#COPY_AS_NEW}</code></li>
1081     * <li><code>{@link org.opencms.file.CmsResource#COPY_AS_SIBLING}</code></li>
1082     * <li><code>{@link org.opencms.file.CmsResource#COPY_PRESERVE_SIBLING}</code></li>
1083     * </ul><p>
1084     *
1085     * @param dbc the current database context
1086     * @param source the resource to copy
1087     * @param destination the name of the copy destination with complete path
1088     * @param siblingMode indicates how to handle siblings during copy
1089     *
1090     * @throws CmsException if something goes wrong
1091     * @throws CmsIllegalArgumentException if the <code>source</code> argument is null or of length 0
1092     *
1093     * @see CmsObject#copyResource(String, String, int)
1094     * @see I_CmsResourceType#copyResource(CmsObject, CmsSecurityManager, CmsResource, String, int)
1095     */

1096    public void copyResource(CmsDbContext dbc, CmsResource source, String JavaDoc destination, int siblingMode)
1097    throws CmsException, CmsIllegalArgumentException {
1098
1099        // check the sibling mode to see if this resource has to be copied as a sibling
1100
boolean copyAsSibling = false;
1101
1102        // siblings of folders are not supported
1103
if (!source.isFolder()) {
1104            // if the "copy as sibling" mode is used, set the flag to true
1105
if (siblingMode == CmsResource.COPY_AS_SIBLING) {
1106                copyAsSibling = true;
1107            }
1108            // if the mode is "preserve siblings", we have to check the sibling counter
1109
if (siblingMode == CmsResource.COPY_PRESERVE_SIBLING) {
1110                if (source.getSiblingCount() > 1) {
1111                    copyAsSibling = true;
1112                }
1113            }
1114        }
1115
1116        // read the source properties
1117
List properties = readPropertyObjects(dbc, source, false);
1118
1119        if (copyAsSibling) {
1120            // create a sibling of the source file at the destination
1121
createSibling(dbc, source, destination, properties);
1122            // after the sibling is created the copy operation is finished
1123
return;
1124        }
1125
1126        // prepare the content if required
1127
byte[] content = null;
1128        if (source.isFile()) {
1129            CmsFile file;
1130            if (source instanceof CmsFile) {
1131                // resource already is a file
1132
file = (CmsFile)source;
1133                content = file.getContents();
1134            }
1135            if ((content == null) || (content.length < 1)) {
1136                // no known content yet - read from database
1137
file = m_vfsDriver.readFile(dbc, dbc.currentProject().getId(), false, source.getStructureId());
1138                content = file.getContents();
1139            }
1140        }
1141
1142        // determine desitnation folder and resource name
1143
String JavaDoc destinationFoldername = CmsResource.getParentFolder(destination);
1144        String JavaDoc destinationResourceName = destination.substring(destinationFoldername.length());
1145
1146        if (CmsResource.isFolder(destinationResourceName)) {
1147            // must cut of trailing '/' on destination folders
1148
destinationResourceName = destinationResourceName.substring(0, destinationResourceName.length() - 1);
1149        }
1150
1151        // read the destination folder (will also check read permissions)
1152
CmsFolder destinationFolder = m_securityManager.readFolder(
1153            dbc,
1154            destinationFoldername,
1155            CmsResourceFilter.IGNORE_EXPIRATION);
1156
1157        // no further permission check required here, will be done in createResource()
1158

1159        // set user and creation timestamps
1160
long currentTime = System.currentTimeMillis();
1161        long dateLastModified;
1162        CmsUUID userLastModified;
1163        if (source.isFolder()) {
1164            // folders always get a new date and uswer when they are copied
1165
dateLastModified = currentTime;
1166            userLastModified = dbc.currentUser().getId();
1167        } else {
1168            // files keep the date and user last modified from the source
1169
dateLastModified = source.getDateLastModified();
1170            userLastModified = source.getUserLastModified();
1171        }
1172
1173        // check the resource flags
1174
int flags = source.getFlags();
1175        if (source.isLabeled()) {
1176            // reset "labeled" link flag for new resource
1177
flags &= ~CmsResource.FLAG_LABELED;
1178        }
1179
1180        // create the new resource
1181
CmsResource newResource = new CmsResource(
1182            new CmsUUID(),
1183            new CmsUUID(),
1184            destination,
1185            source.getTypeId(),
1186            source.isFolder(),
1187            flags,
1188            dbc.currentProject().getId(),
1189            CmsResource.STATE_NEW,
1190            currentTime,
1191            dbc.currentUser().getId(),
1192            dateLastModified,
1193            userLastModified,
1194            source.getDateReleased(),
1195            source.getDateExpired(),
1196            1,
1197            source.getLength());
1198
1199        // trigger "is touched" state on resource (will ensure modification date is kept unchanged)
1200
newResource.setDateLastModified(dateLastModified);
1201
1202        // create the resource
1203
newResource = createResource(dbc, destination, newResource, content, properties, false);
1204
1205        // copy the access control entries to the created resource
1206
copyAccessControlEntries(dbc, source, newResource, false);
1207
1208        // clear the cache
1209
clearAccessControlListCache();
1210
1211        List modifiedResources = new ArrayList JavaDoc();
1212        modifiedResources.add(source);
1213        modifiedResources.add(newResource);
1214        modifiedResources.add(destinationFolder);
1215        OpenCms.fireCmsEvent(new CmsEvent(I_CmsEventListener.EVENT_RESOURCE_COPIED, Collections.singletonMap(
1216            "resources",
1217            modifiedResources)));
1218
1219    }
1220
1221    /**
1222     * Copies a resource to the current project of the user.<p>
1223     *
1224     * @param dbc the current database context
1225     * @param resource the resource to apply this operation to
1226     *
1227     * @throws CmsException if something goes wrong
1228     *
1229     * @see CmsObject#copyResourceToProject(String)
1230     * @see I_CmsResourceType#copyResourceToProject(CmsObject, CmsSecurityManager, CmsResource)
1231     */

1232    public void copyResourceToProject(CmsDbContext dbc, CmsResource resource) throws CmsException {
1233
1234        // copy the resource to the project only if the resource is not already in the project
1235
if (!isInsideCurrentProject(dbc, resource.getRootPath())) {
1236            // check if there are already any subfolders of this resource
1237
if (resource.isFolder()) {
1238                List projectResources = m_projectDriver.readProjectResources(dbc, dbc.currentProject());
1239                for (int i = 0; i < projectResources.size(); i++) {
1240                    String JavaDoc resname = (String JavaDoc)projectResources.get(i);
1241                    if (resname.startsWith(resource.getRootPath())) {
1242                        // delete the existing project resource first
1243
m_projectDriver.deleteProjectResource(dbc, dbc.currentProject().getId(), resname);
1244                    }
1245                }
1246            }
1247            try {
1248                m_projectDriver.createProjectResource(dbc, dbc.currentProject().getId(), resource.getRootPath(), null);
1249            } catch (CmsException exc) {
1250                // if the subfolder exists already - all is ok
1251
} finally {
1252                OpenCms.fireCmsEvent(new CmsEvent(I_CmsEventListener.EVENT_PROJECT_MODIFIED, Collections.singletonMap(
1253                    "project",
1254                    dbc.currentProject())));
1255            }
1256        }
1257    }
1258
1259    /**
1260     * Counts the locked resources in a given folder.<p>
1261     *
1262     * @param dbc the current database context
1263     * @param foldername the folder to search in
1264     *
1265     * @return the amount of locked resources in this project
1266     *
1267     * @throws CmsLockException if the current project is locked
1268     */

1269    public int countLockedResources(CmsDbContext dbc, String JavaDoc foldername) throws CmsLockException {
1270
1271        // check the security
1272
if (dbc.currentProject().getFlags() == CmsProject.PROJECT_STATE_UNLOCKED) {
1273            // count locks
1274
return m_lockManager.countExclusiveLocksInFolder(foldername);
1275        } else {
1276            throw new CmsLockException(org.opencms.lock.Messages.get().container(
1277                org.opencms.lock.Messages.ERR_RESOURCE_LOCKED_1,
1278                dbc.currentProject().getName()));
1279        }
1280    }
1281
1282    /**
1283     * Counts the locked resources in this project.<p>
1284     *
1285     * @param project the project to count the locked resources in
1286     *
1287     * @return the amount of locked resources in this project
1288     *
1289     * @throws CmsLockException if the given project itself is locked
1290     */

1291    public int countLockedResources(CmsProject project) throws CmsLockException {
1292
1293        // check the security
1294
if (project.getFlags() == CmsProject.PROJECT_STATE_UNLOCKED) {
1295            // count locks
1296
return m_lockManager.countExclusiveLocksInProject(project);
1297        } else {
1298            throw new CmsLockException(org.opencms.lock.Messages.get().container(
1299                org.opencms.lock.Messages.ERR_RESOURCE_LOCKED_1,
1300                project.getName()));
1301        }
1302    }
1303
1304    /**
1305     * Add a new group to the Cms.<p>
1306     *
1307     * Only the admin can do this.
1308     * Only users, which are in the group "administrators" are granted.<p>
1309     *
1310     * @param dbc the current database context
1311     * @param id the id of the new group
1312     * @param name the name of the new group
1313     * @param description the description for the new group
1314     * @param flags the flags for the new group
1315     * @param parent the name of the parent group (or null)
1316     *
1317     * @return new created group
1318     *
1319     * @throws CmsDataAccessException if the creation of the group failed
1320     * @throws CmsIllegalArgumentException if the length of the given name was below 1
1321     */

1322    public CmsGroup createGroup(CmsDbContext dbc, CmsUUID id, String JavaDoc name, String JavaDoc description, int flags, String JavaDoc parent)
1323    throws CmsIllegalArgumentException, CmsDataAccessException {
1324
1325        // check the groupname
1326
OpenCms.getValidationHandler().checkGroupName(name);
1327        // trim the name
1328
name = name.trim();
1329        // create the group
1330
return m_userDriver.createGroup(dbc, id, name, description, flags, parent, null);
1331    }
1332
1333    /**
1334     * Creates a new task for project creation.<p>
1335     *
1336     * @param dbc the current database context
1337     * @param projectName name of the project
1338     * @param roleName usergroup for the project
1339     * @param timeout time when the Project must finished
1340     * @param priority priority for the Project
1341     *
1342     * @return the new task project
1343     *
1344     * @throws CmsDataAccessException if something goes wrong
1345     */

1346    public CmsTask createProject(CmsDbContext dbc, String JavaDoc projectName, String JavaDoc roleName, long timeout, int priority)
1347    throws CmsDataAccessException {
1348
1349        CmsGroup role = null;
1350
1351        // read the role
1352
if (CmsStringUtil.isNotEmpty(roleName)) {
1353            role = readGroup(dbc, roleName);
1354        }
1355        // create the timestamp
1356
java.sql.Timestamp JavaDoc timestamp = new java.sql.Timestamp JavaDoc(timeout);
1357        java.sql.Timestamp JavaDoc now = new java.sql.Timestamp JavaDoc(System.currentTimeMillis());
1358
1359        return m_workflowDriver.createTask(dbc, 0, 0, 1, // standard project type,
1360
dbc.currentUser().getId(),
1361            dbc.currentUser().getId(),
1362            role.getId(),
1363            projectName,
1364            now,
1365            timestamp,
1366            priority);
1367    }
1368
1369    /**
1370     * Creates a project.<p>
1371     *
1372     * @param dbc the current database context
1373     * @param name the name of the project to create
1374     * @param description the description of the project
1375     * @param groupname the project user group to be set
1376     * @param managergroupname the project manager group to be set
1377     * @param projecttype the type of the project
1378     *
1379     * @return the created project
1380     *
1381     * @throws CmsIllegalArgumentException if the chosen <code>name</code> is already used
1382     * by the online project
1383     * @throws CmsDataAccessException if something goes wrong
1384     */

1385    public CmsProject createProject(
1386        CmsDbContext dbc,
1387        String JavaDoc name,
1388        String JavaDoc description,
1389        String JavaDoc groupname,
1390        String JavaDoc managergroupname,
1391        int projecttype) throws CmsIllegalArgumentException, CmsDataAccessException {
1392
1393        if (CmsProject.ONLINE_PROJECT_NAME.equals(name)) {
1394            throw new CmsIllegalArgumentException(Messages.get().container(
1395                Messages.ERR_CREATE_PROJECT_ONLINE_PROJECT_NAME_1,
1396                CmsProject.ONLINE_PROJECT_NAME));
1397        }
1398        // read the needed groups from the cms
1399
CmsGroup group = readGroup(dbc, groupname);
1400        CmsGroup managergroup = readGroup(dbc, managergroupname);
1401
1402        // create a new task for the project
1403
CmsTask task = createProject(
1404            dbc,
1405            name,
1406            group.getName(),
1407            System.currentTimeMillis(),
1408            CmsTaskService.TASK_PRIORITY_NORMAL);
1409
1410        return m_projectDriver.createProject(
1411            dbc,
1412            dbc.currentUser(),
1413            group,
1414            managergroup,
1415            task,
1416            name,
1417            description,
1418            CmsProject.PROJECT_STATE_UNLOCKED,
1419            projecttype,
1420            null);
1421    }
1422
1423    /**
1424     * Creates a property definition.<p>
1425     *
1426     * Property definitions are valid for all resource types.<p>
1427     *
1428     * @param dbc the current database context
1429     * @param name the name of the property definition to create
1430     *
1431     * @return the created property definition
1432     *
1433     * @throws CmsException if something goes wrong
1434     */

1435    public CmsPropertyDefinition createPropertyDefinition(CmsDbContext dbc, String JavaDoc name) throws CmsException {
1436
1437        CmsPropertyDefinition propertyDefinition = null;
1438
1439        name = name.trim();
1440        // validate the property name
1441
CmsPropertyDefinition.checkPropertyName(name);
1442
1443        try {
1444            try {
1445                propertyDefinition = m_vfsDriver.readPropertyDefinition(dbc, name, dbc.currentProject().getId());
1446            } catch (CmsException e) {
1447                propertyDefinition = m_vfsDriver.createPropertyDefinition(dbc, dbc.currentProject().getId(), name);
1448            }
1449
1450            try {
1451                m_vfsDriver.readPropertyDefinition(dbc, name, CmsProject.ONLINE_PROJECT_ID);
1452            } catch (CmsException e) {
1453                m_vfsDriver.createPropertyDefinition(dbc, CmsProject.ONLINE_PROJECT_ID, name);
1454            }
1455
1456            try {
1457                m_backupDriver.readBackupPropertyDefinition(dbc, name);
1458            } catch (CmsException e) {
1459                m_backupDriver.createBackupPropertyDefinition(dbc, name);
1460            }
1461        } finally {
1462
1463            // fire an event that a property of a resource has been deleted
1464
OpenCms.fireCmsEvent(new CmsEvent(
1465                I_CmsEventListener.EVENT_PROPERTY_DEFINITION_CREATED,
1466                Collections.singletonMap("propertyDefinition", propertyDefinition)));
1467
1468        }
1469
1470        return propertyDefinition;
1471    }
1472
1473    /**
1474     * Creates a new resource with the provided content and properties.<p>
1475     *
1476     * The <code>content</code> parameter may be null if the resource id already exists.
1477     * If so, the created resource will be made a sibling of the existing resource,
1478     * the existing content will remain unchanged.
1479     * This is used during file import for import of siblings as the
1480     * <code>manifest.xml</code> only contains one binary copy per file.
1481     * If the resource id exists but the <code>content</code> is not null,
1482     * the created resource will be made a sibling of the existing resource,
1483     * and both will share the new content.<p>
1484     *
1485     * Note: the id used to identify the content record (pk of the record) is generated
1486     * on each call of this method (with valid content) !
1487     *
1488     * @param dbc the current database context
1489     * @param resourcePath the name of the resource to create (full path)
1490     * @param resource the new resource to create
1491     * @param content the content for the new resource
1492     * @param properties the properties for the new resource
1493     * @param importCase if true, signals that this operation is done while importing resource,
1494     * causing different lock behaviour and potential "lost and found" usage
1495     *
1496     * @return the created resource
1497     *
1498     * @throws CmsException if something goes wrong
1499     */

1500    public CmsResource createResource(
1501        CmsDbContext dbc,
1502        String JavaDoc resourcePath,
1503        CmsResource resource,
1504        byte[] content,
1505        List properties,
1506        boolean importCase) throws CmsException {
1507
1508        CmsResource newResource = null;
1509
1510        if (m_concurrentCreateResourceLocks.contains(resourcePath)) {
1511            // since this method is a long-runner, we must make sure to avoid concurrent creation of the same resource
1512
throw new CmsVfsResourceAlreadyExistsException(org.opencms.db.generic.Messages.get().container(
1513                org.opencms.db.generic.Messages.ERR_RESOURCE_WITH_NAME_CURRENTLY_CREATED_1,
1514                dbc.removeSiteRoot(resourcePath)));
1515            // potential issue with this solution:
1516
// in theory, someone _without_ write permissions could "block" the concurrent creation of a resource
1517
// for someone _with_ permissions this way since the permissions have not been checked yet
1518
}
1519
1520        try {
1521            // avoid concurrent creation issues
1522
m_concurrentCreateResourceLocks.add(resourcePath);
1523
1524            // check import configuration of "lost and found" folder
1525
boolean useLostAndFound = importCase && !OpenCms.getImportExportManager().overwriteCollidingResources();
1526
1527            // check if the resource already exists
1528
CmsResource currentResource = null;
1529
1530            try {
1531                currentResource = readResource(dbc, resourcePath, CmsResourceFilter.ALL);
1532            } catch (CmsVfsResourceNotFoundException e) {
1533                // if the resource does exist, we need to either overwrite it,
1534
// or create a sibling - this will be handled later
1535
}
1536
1537            CmsResource parentFolder;
1538            String JavaDoc parentFolderName;
1539            String JavaDoc createdResourceName = resourcePath;
1540            int contentLength;
1541
1542            if (currentResource != null) {
1543                if (currentResource.getState() == CmsResource.STATE_DELETED) {
1544                    if (!currentResource.isFolder()) {
1545                        // if a non-folder resource was deleted it's treated like a new resource
1546
currentResource = null;
1547                    }
1548                } else {
1549                    if (!importCase) {
1550                        // direct "overwrite" of a resource is possible only during import,
1551
// or if the resource has been deleted
1552
throw new CmsVfsResourceAlreadyExistsException(org.opencms.db.generic.Messages.get().container(
1553                            org.opencms.db.generic.Messages.ERR_RESOURCE_WITH_NAME_ALREADY_EXISTS_1,
1554                            dbc.removeSiteRoot(resource.getRootPath())));
1555                    }
1556                    // the resource already exists
1557
if (!resource.isFolder()
1558                        && useLostAndFound
1559                        && (!currentResource.getResourceId().equals(resource.getResourceId()))) {
1560                        // new resource must be created in "lost and found"
1561
createdResourceName = moveToLostAndFound(dbc, resourcePath, false);
1562                        // current resource must remain unchanged, new will be created in "lost and found"
1563
currentResource = null;
1564                    }
1565                }
1566            }
1567
1568            // need to provide the parent folder id for resource creation
1569
parentFolderName = CmsResource.getParentFolder(createdResourceName);
1570            parentFolder = readFolder(dbc, parentFolderName, CmsResourceFilter.IGNORE_EXPIRATION);
1571
1572            // check the permissions
1573
if (currentResource == null) {
1574                // resource does not exist - check parent folder
1575
m_securityManager.checkPermissions(
1576                    dbc,
1577                    parentFolder,
1578                    CmsPermissionSet.ACCESS_WRITE,
1579                    false,
1580                    CmsResourceFilter.IGNORE_EXPIRATION);
1581            } else {
1582                // resource already exists - check existing resource
1583
m_securityManager.checkPermissions(
1584                    dbc,
1585                    currentResource,
1586                    CmsPermissionSet.ACCESS_WRITE,
1587                    !importCase,
1588                    CmsResourceFilter.ALL);
1589            }
1590
1591            // extract the name (without path)
1592
String JavaDoc targetName = CmsResource.getName(createdResourceName);
1593
1594            // modify target name and content length in case of folder creation
1595
if (resource.isFolder()) {
1596                // folders never have any content
1597
contentLength = -1;
1598                // must cut of trailing '/' for folder creation (or name check fails)
1599
if (CmsResource.isFolder(targetName)) {
1600                    targetName = targetName.substring(0, targetName.length() - 1);
1601                }
1602            } else {
1603                // otherwise ensure content and content length are set correctly
1604
if (content != null) {
1605                    // if a content is provided, in each case the length is the length of this content
1606
contentLength = content.length;
1607                } else if (currentResource != null) {
1608                    // we have no content, but an already existing resource - length remains unchanged
1609
contentLength = currentResource.getLength();
1610                } else {
1611                    // we have no content - length is used as set in the resource
1612
contentLength = resource.getLength();
1613                }
1614            }
1615
1616            // check if the target name is valid (forbitten chars etc.),
1617
// if not throw an exception
1618
// must do this here since targetName is modified in folder case (see above)
1619
CmsResource.checkResourceName(targetName);
1620
1621            // set strcuture and resource ids
1622
CmsUUID structureId;
1623            CmsUUID resourceId;
1624            if (currentResource != null) {
1625                // resource exists, re-use existing ids
1626
structureId = currentResource.getStructureId();
1627                resourceId = currentResource.getResourceId();
1628            } else {
1629                // new resource always gets a new structure id
1630
structureId = new CmsUUID();
1631                if (!resource.getResourceId().isNullUUID()) {
1632                    // re-use existing resource id
1633
resourceId = resource.getResourceId();
1634                } else {
1635                    // need a new resource id
1636
resourceId = new CmsUUID();
1637                }
1638            }
1639
1640            // now create a resource object with all informations
1641
newResource = new CmsResource(
1642                structureId,
1643                resourceId,
1644                createdResourceName,
1645                resource.getTypeId(),
1646                resource.isFolder(),
1647                resource.getFlags(),
1648                dbc.currentProject().getId(),
1649                resource.getState(),
1650                resource.getDateCreated(),
1651                resource.getUserCreated(),
1652                resource.getDateLastModified(),
1653                resource.getUserLastModified(),
1654                resource.getDateReleased(),
1655                resource.getDateExpired(),
1656                1,
1657                contentLength);
1658
1659            // ensure date is updated only if required
1660
if (resource.isTouched()) {
1661                // this will trigger the internal "is touched" state on the new resource
1662
newResource.setDateLastModified(resource.getDateLastModified());
1663            }
1664
1665            if (resource.isFile()) {
1666                // check if a sibling to the imported resource lies in a marked site
1667
if (labelResource(dbc, resource, resourcePath, 2)) {
1668                    int flags = resource.getFlags();
1669                    flags |= CmsResource.FLAG_LABELED;
1670                    resource.setFlags(flags);
1671                }
1672                // ensure siblings don't overwrite existing resource records
1673
if (content == null) {
1674                    newResource.setState(CmsResource.STATE_KEEP);
1675                }
1676            }
1677
1678            if (currentResource == null) {
1679
1680                // resource does not exist.
1681
newResource = m_vfsDriver.createResource(dbc, dbc.currentProject(), newResource, content);
1682
1683            } else {
1684
1685                // resource already exists.
1686
// probably the resource is a merged page file that gets overwritten during import, or it gets
1687
// overwritten by a copy operation. if so, the structure & resource state are not modified to changed.
1688
int updateStates = (currentResource.getState() == CmsResource.STATE_NEW) ? CmsDriverManager.NOTHING_CHANGED
1689                : CmsDriverManager.UPDATE_ALL;
1690                m_vfsDriver.writeResource(dbc, dbc.currentProject(), newResource, updateStates);
1691
1692                if ((content != null) && resource.isFile()) {
1693                    // also update file content if required
1694
m_vfsDriver.writeContent(dbc, dbc.currentProject(), currentResource.getResourceId(), content);
1695                }
1696
1697            }
1698
1699            // write the properties (internal operation, no events or duplicate permission checks)
1700
writePropertyObjects(dbc, newResource, properties);
1701
1702            // lock the created resource
1703
lockResource(dbc, newResource, CmsLock.COMMON);
1704
1705        } finally {
1706            // remove the create lock
1707
m_concurrentCreateResourceLocks.remove(resourcePath);
1708
1709            // clear the internal caches
1710
clearAccessControlListCache();
1711            m_propertyCache.clear();
1712
1713            if (newResource != null) {
1714                // fire an event that a new resource has been created
1715
OpenCms.fireCmsEvent(new CmsEvent(I_CmsEventListener.EVENT_RESOURCE_CREATED, Collections.singletonMap(
1716                    "resource",
1717                    newResource)));
1718            }
1719        }
1720
1721        return newResource;
1722    }
1723
1724    /**
1725     * Creates a new resource of the given resource type
1726     * with the provided content and properties.<p>
1727     *
1728     * If the provided content is null and the resource is not a folder,
1729     * the content will be set to an empty byte array.<p>
1730     *
1731     * @param dbc the current database context
1732     * @param resourcename the name of the resource to create (full path)
1733     * @param type the type of the resource to create
1734     * @param content the content for the new resource
1735     * @param properties the properties for the new resource
1736     *
1737     * @return the created resource
1738     *
1739     * @throws CmsException if something goes wrong
1740     * @throws CmsIllegalArgumentException if the <code>resourcename</code> argument is null or of length 0
1741     *
1742     * @see CmsObject#createResource(String, int, byte[], List)
1743     * @see CmsObject#createResource(String, int)
1744     * @see I_CmsResourceType#createResource(CmsObject, CmsSecurityManager, String, byte[], List)
1745     */

1746    public CmsResource createResource(CmsDbContext dbc, String JavaDoc resourcename, int type, byte[] content, List properties)
1747    throws CmsException, CmsIllegalArgumentException {
1748
1749        String JavaDoc targetName = resourcename;
1750
1751        if (content == null) {
1752            // name based resource creation MUST have a content
1753
content = new byte[0];
1754        }
1755        int size;
1756
1757        if (CmsFolder.isFolderType(type)) {
1758            // must cut of trailing '/' for folder creation
1759
if (CmsResource.isFolder(targetName)) {
1760                targetName = targetName.substring(0, targetName.length() - 1);
1761            }
1762            size = -1;
1763        } else {
1764            size = content.length;
1765        }
1766
1767        // create a new resource
1768
CmsResource newResource = new CmsResource(CmsUUID.getNullUUID(), // uuids will be "corrected" later
1769
CmsUUID.getNullUUID(),
1770            targetName,
1771            type,
1772            CmsFolder.isFolderType(type),
1773            0,
1774            dbc.currentProject().getId(),
1775            CmsResource.STATE_NEW,
1776            0,
1777            dbc.currentUser().getId(),
1778            0,
1779            dbc.currentUser().getId(),
1780            CmsResource.DATE_RELEASED_DEFAULT,
1781            CmsResource.DATE_EXPIRED_DEFAULT,
1782            1,
1783            size);
1784
1785        return createResource(dbc, targetName, newResource, content, properties, false);
1786    }
1787
1788    /**
1789     * Creates a new sibling of the source resource.<p>
1790     *
1791     * @param dbc the current database context
1792     * @param source the resource to create a sibling for
1793     * @param destination the name of the sibling to create with complete path
1794     * @param properties the individual properties for the new sibling
1795     *
1796     * @throws CmsException if something goes wrong
1797     *
1798     * @see CmsObject#createSibling(String, String, List)
1799     * @see I_CmsResourceType#createSibling(CmsObject, CmsSecurityManager, CmsResource, String, List)
1800     */

1801    public void createSibling(CmsDbContext dbc, CmsResource source, String JavaDoc destination, List properties)
1802    throws CmsException {
1803
1804        if (source.isFolder()) {
1805            throw new CmsVfsException(Messages.get().container(Messages.ERR_VFS_FOLDERS_DONT_SUPPORT_SIBLINGS_0));
1806        }
1807
1808        // determine desitnation folder and resource name
1809
String JavaDoc destinationFoldername = CmsResource.getParentFolder(destination);
1810
1811        // read the destination folder (will also check read permissions)
1812
CmsFolder destinationFolder = readFolder(dbc, destinationFoldername, CmsResourceFilter.IGNORE_EXPIRATION);
1813
1814        // no further permission check required here, will be done in createResource()
1815

1816        // check the resource flags
1817
int flags = source.getFlags();
1818        if (labelResource(dbc, source, destination, 1)) {
1819            // set "labeled" link flag for new resource
1820
flags |= CmsResource.FLAG_LABELED;
1821        }
1822
1823        // create the new resource
1824
CmsResource newResource = new CmsResource(
1825            new CmsUUID(),
1826            source.getResourceId(),
1827            destination,
1828            source.getTypeId(),
1829            source.isFolder(),
1830            flags,
1831            dbc.currentProject().getId(),
1832            CmsResource.STATE_KEEP,
1833            source.getDateCreated(), // ensures current resource record remains untouched
1834
source.getUserCreated(),
1835            source.getDateLastModified(),
1836            source.getUserLastModified(),
1837            source.getDateReleased(),
1838            source.getDateExpired(),
1839            source.getSiblingCount() + 1,
1840            source.getLength());
1841
1842        // trigger "is touched" state on resource (will ensure modification date is kept unchanged)
1843
newResource.setDateLastModified(newResource.getDateLastModified());
1844
1845        // create the resource (null content signals creation of sibling)
1846
newResource = createResource(dbc, destination, newResource, null, properties, false);
1847
1848        // clear the caches
1849
clearAccessControlListCache();
1850
1851        List modifiedResources = new ArrayList JavaDoc();
1852        modifiedResources.add(source);
1853        modifiedResources.add(newResource);
1854        modifiedResources.add(destinationFolder);
1855        OpenCms.fireCmsEvent(new CmsEvent(
1856            I_CmsEventListener.EVENT_RESOURCES_AND_PROPERTIES_MODIFIED,
1857            Collections.singletonMap("resources", modifiedResources)));
1858    }
1859
1860    /**
1861     * Creates a new task.<p>
1862     *
1863     * @param dbc the current database context
1864     * @param currentUser the current user
1865     * @param projectid the current project id
1866     * @param agentName user who will edit the task
1867     * @param roleName usergroup for the task
1868     * @param taskName name of the task
1869     * @param taskType type of the task
1870     * @param taskComment description of the task
1871     * @param timeout time when the task must finished
1872     * @param priority Id for the priority
1873     *
1874     * @return a new task object
1875     *
1876     * @throws CmsException if something goes wrong
1877     */

1878    public CmsTask createTask(
1879        CmsDbContext dbc,
1880        CmsUser currentUser,
1881        int projectid,
1882        String JavaDoc agentName,
1883        String JavaDoc roleName,
1884        String JavaDoc taskName,
1885        String JavaDoc taskComment,
1886        int taskType,
1887        long timeout,
1888        int priority) throws CmsException {
1889
1890        CmsUser agent = readUser(dbc, agentName, CmsUser.USER_TYPE_SYSTEMUSER);
1891        CmsGroup role = m_userDriver.readGroup(dbc, roleName);
1892        java.sql.Timestamp JavaDoc timestamp = new java.sql.Timestamp JavaDoc(timeout);
1893        java.sql.Timestamp JavaDoc now = new java.sql.Timestamp JavaDoc(System.currentTimeMillis());
1894
1895        // validate the task name
1896
CmsTask.checkTaskName(taskName);
1897
1898        CmsTask task = m_workflowDriver.createTask(
1899            dbc,
1900            projectid,
1901            projectid,
1902            taskType,
1903            currentUser.getId(),
1904            agent.getId(),
1905            role.getId(),
1906            taskName,
1907            now,
1908            timestamp,
1909            priority);
1910
1911        if (CmsStringUtil.isNotEmpty(taskComment)) {
1912            m_workflowDriver.writeTaskLog(dbc, task.getId(), currentUser.getId(), new java.sql.Timestamp JavaDoc(
1913                System.currentTimeMillis()), taskComment, CmsTaskService.TASKLOG_USER);
1914        }
1915
1916        return task;
1917    }
1918
1919    /**
1920     * Creates a new task.<p>
1921     *
1922     * This is just a more limited version of the
1923     * <code>{@link #createTask(CmsDbContext, CmsUser, int, String, String, String, String, int, long, int)}</code>
1924     * method, where: <br>
1925     * <ul>
1926     * <il>the project id is the current project id.</il>
1927     * <il>the task type is the standard task type <b>1</b>.</il>
1928     * <il>with no comments</il>
1929     * </ul><p>
1930     *
1931     * @param dbc the current database context
1932     * @param agentName the user who will edit the task
1933     * @param roleName a usergroup for the task
1934     * @param taskname the name of the task
1935     * @param timeout the time when the task must finished
1936     * @param priority the id for the priority of the task
1937     *
1938     * @return the created task
1939     *
1940     * @throws CmsException if something goes wrong
1941     */

1942    public CmsTask createTask(
1943        CmsDbContext dbc,
1944        String JavaDoc agentName,
1945        String JavaDoc roleName,
1946        String JavaDoc taskname,
1947        long timeout,
1948        int priority) throws CmsException {
1949
1950        CmsGroup role = m_userDriver.readGroup(dbc, roleName);
1951        java.sql.Timestamp JavaDoc timestamp = new java.sql.Timestamp JavaDoc(timeout);
1952        java.sql.Timestamp JavaDoc now = new java.sql.Timestamp JavaDoc(System.currentTimeMillis());
1953        CmsUUID agentId = CmsUUID.getNullUUID();
1954        // validate the task name
1955
CmsTask.checkTaskName(taskname);
1956        try {
1957            agentId = readUser(dbc, agentName, CmsUser.USER_TYPE_SYSTEMUSER).getId();
1958        } catch (Exception JavaDoc e) {
1959            // ignore that this user doesn't exist and create a task for the role
1960
}
1961        return m_workflowDriver.createTask(dbc, dbc.currentProject().getTaskId(), dbc.currentProject().getTaskId(), 1, // standart Task Type
1962
dbc.currentUser().getId(),
1963            agentId,
1964            role.getId(),
1965            taskname,
1966            now,
1967            timestamp,
1968            priority);
1969    }
1970
1971    /**
1972     * Creates the project for the temporary workplace files.<p>
1973     *
1974     * @param dbc the current database context
1975     *
1976     * @return the created project for the temporary workplace files
1977     *
1978     * @throws CmsException if something goes wrong
1979     */

1980    public CmsProject createTempfileProject(CmsDbContext dbc) throws CmsException {
1981
1982        // read the needed groups from the cms
1983
CmsGroup projectUserGroup = readGroup(dbc, OpenCms.getDefaultUsers().getGroupUsers());
1984        CmsGroup projectManagerGroup = readGroup(dbc, OpenCms.getDefaultUsers().getGroupAdministrators());
1985
1986        // create a new task for the project
1987
CmsTask task = createProject(
1988            dbc,
1989            I_CmsProjectDriver.TEMP_FILE_PROJECT_NAME,
1990            projectUserGroup.getName(),
1991            System.currentTimeMillis(),
1992            CmsTaskService.TASK_PRIORITY_NORMAL);
1993
1994        CmsProject tempProject = m_projectDriver.createProject(
1995            dbc,
1996            dbc.currentUser(),
1997            projectUserGroup,
1998            projectManagerGroup,
1999            task,
2000            I_CmsProjectDriver.TEMP_FILE_PROJECT_NAME,
2001            Messages.get().getBundle(dbc.getRequestContext().getLocale()).key(
2002                Messages.GUI_WORKPLACE_TEMPFILE_PROJECT_DESC_0),
2003            CmsProject.PROJECT_STATE_INVISIBLE,
2004            CmsProject.PROJECT_STATE_INVISIBLE,
2005            null);
2006        m_projectDriver.createProjectResource(dbc, tempProject.getId(), "/", null);
2007
2008        OpenCms.fireCmsEvent(new CmsEvent(I_CmsEventListener.EVENT_PROJECT_MODIFIED, Collections.singletonMap(
2009            "project",
2010            tempProject)));
2011
2012        return tempProject;
2013    }
2014
2015    /**
2016     * Creates a new user.<p>
2017     *
2018     * @param dbc the current database context
2019     * @param name the name for the new user
2020     * @param password the password for the new user
2021     * @param description the description for the new user
2022     * @param additionalInfos the additional infos for the user
2023     *
2024     * @return the created user
2025     *
2026     * @see CmsObject#createUser(String, String, String, Map)
2027     *
2028     * @throws CmsException if something goes wrong
2029     * @throws CmsIllegalArgumentException if the name for the user is not valid
2030     */

2031    public CmsUser createUser(CmsDbContext dbc, String JavaDoc name, String JavaDoc password, String JavaDoc description, Map JavaDoc additionalInfos)
2032    throws CmsException, CmsIllegalArgumentException {
2033
2034        return createUser(dbc, name, password, description, additionalInfos, CmsUser.USER_TYPE_SYSTEMUSER);
2035    }
2036
2037    /**
2038     * Deletes all property values of a file or folder.<p>
2039     *
2040     * If there are no other siblings than the specified resource,
2041     * both the structure and resource property values get deleted.
2042     * If the specified resource has siblings, only the structure
2043     * property values get deleted.<p>
2044     *
2045     * @param dbc the current database context
2046     * @param resourcename the name of the resource for which all properties should be deleted
2047     *
2048     * @throws CmsException if operation was not successful
2049     */

2050    public void deleteAllProperties(CmsDbContext dbc, String JavaDoc resourcename) throws CmsException {
2051
2052        CmsResource resource = null;
2053        List resources = new ArrayList JavaDoc();
2054
2055        try {
2056            // read the resource
2057
resource = readResource(dbc, resourcename, CmsResourceFilter.IGNORE_EXPIRATION);
2058
2059            // check the security
2060
m_securityManager.checkPermissions(
2061                dbc,
2062                resource,
2063                CmsPermissionSet.ACCESS_WRITE,
2064                true,
2065                CmsResourceFilter.ALL);
2066
2067            // delete the property values
2068
if (resource.getSiblingCount() > 1) {
2069                // the resource has siblings- delete only the (structure) properties of this sibling
2070
m_vfsDriver.deletePropertyObjects(
2071                    dbc,
2072                    dbc.currentProject().getId(),
2073                    resource,
2074                    CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_VALUES);
2075                resources.addAll(readSiblings(dbc, resource, CmsResourceFilter.ALL));
2076
2077            } else {
2078                // the resource has no other siblings- delete all (structure+resource) properties
2079
m_vfsDriver.deletePropertyObjects(
2080                    dbc,
2081                    dbc.currentProject().getId(),
2082                    resource,
2083                    CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES);
2084                resources.add(resource);
2085            }
2086        } finally {
2087            // clear the driver manager cache
2088
m_propertyCache.clear();
2089
2090            // fire an event that all properties of a resource have been deleted
2091
OpenCms.fireCmsEvent(new CmsEvent(
2092                I_CmsEventListener.EVENT_RESOURCES_AND_PROPERTIES_MODIFIED,
2093                Collections.singletonMap("resources", resources)));
2094        }
2095    }
2096
2097    /**
2098     * Deletes all entries in the published resource table.<p>
2099     *
2100     * @param dbc the current database context
2101     * @param linkType the type of resource deleted (0= non-paramter, 1=parameter)
2102     *
2103     * @throws CmsException if something goes wrong
2104     */

2105    public void deleteAllStaticExportPublishedResources(CmsDbContext dbc, int linkType) throws CmsException {
2106
2107        m_projectDriver.deleteAllStaticExportPublishedResources(dbc, dbc.currentProject(), linkType);
2108    }
2109
2110    /**
2111     * Deletes all backup versions of a single resource.<p>
2112     *
2113     * @param dbc the current database context
2114     * @param res the resource to delete all backups from
2115     *
2116     * @throws CmsDataAccessException if operation was not succesful
2117     */

2118    public void deleteBackup(CmsDbContext dbc, CmsResource res) throws CmsDataAccessException {
2119
2120        // we need a valid CmsBackupResource, so get all backup file headers of the
2121
// requested resource
2122
List backupFileHeaders = m_backupDriver.readBackupFileHeaders(dbc, res.getRootPath(), res.getResourceId());
2123        // check if we have some results
2124
if (backupFileHeaders.size() > 0) {
2125            // get the first backup resource
2126
CmsBackupResource backupResource = (CmsBackupResource)backupFileHeaders.get(0);
2127            // create a timestamp slightly in the future
2128
long timestamp = System.currentTimeMillis() + 100000;
2129            // get the maximum tag id and add ne to include the current publish process as well
2130
int maxTag = m_backupDriver.readBackupProjectTag(dbc, timestamp) + 1;
2131            int resVersions = m_backupDriver.readBackupMaxVersion(dbc, res.getResourceId());
2132            // delete the backups
2133
m_backupDriver.deleteBackup(dbc, backupResource, maxTag, resVersions);
2134        }
2135    }
2136
2137    /**
2138     * Deletes the versions from the backup tables that are older then the given timestamp and/or number of remaining versions.<p>
2139     *
2140     * The number of verions always wins, i.e. if the given timestamp would delete more versions than given in the
2141     * versions parameter, the timestamp will be ignored.<p>
2142     *
2143     * Deletion will delete file header, content and properties.<p>
2144     *
2145     * @param dbc the current database context
2146     * @param timestamp timestamp which defines the date after which backup resources must be deleted
2147     * @param versions the number of versions per file which should kept in the system
2148     * @param report the report for output logging
2149     *
2150     * @throws CmsException if operation was not succesful
2151     */

2152    public void deleteBackups(CmsDbContext dbc, long timestamp, int versions, I_CmsReport report) throws CmsException {
2153
2154        // get all resources from the backup table
2155
// do only get one version per resource
2156
List allBackupFiles = m_backupDriver.readBackupFileHeaders(dbc);
2157        int counter = 1;
2158        int size = allBackupFiles.size();
2159        // get the tagId of the oldest Backupproject which will be kept in the database
2160
int maxTag = m_backupDriver.readBackupProjectTag(dbc, timestamp);
2161        Iterator JavaDoc i = allBackupFiles.iterator();
2162        while (i.hasNext()) {
2163            // now check get a single backup resource
2164
CmsBackupResource res = (CmsBackupResource)i.next();
2165
2166            report.print(org.opencms.report.Messages.get().container(
2167                org.opencms.report.Messages.RPT_SUCCESSION_2,
2168                String.valueOf(counter),
2169                String.valueOf(size)), I_CmsReport.FORMAT_NOTE);
2170            report.print(Messages.get().container(Messages.RPT_CHECKING_0), I_CmsReport.FORMAT_NOTE);
2171            report.print(org.opencms.report.Messages.get().container(
2172                org.opencms.report.Messages.RPT_ARGUMENT_1,
2173                res.getRootPath()));
2174
2175            // now delete all versions of this resource that have more than the maximun number
2176
// of allowed versions and which are older then the maximum backup date
2177
int resVersions = m_backupDriver.readBackupMaxVersion(dbc, res.getResourceId());
2178            int versionsToDelete = resVersions - versions;
2179
2180            // now we know which backup versions must be deleted, so remove them now
2181
if (versionsToDelete > 0) {
2182                report.print(Messages.get().container(Messages.RPT_DELETE_VERSIONS_0), I_CmsReport.FORMAT_NOTE);
2183                report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0));
2184                m_backupDriver.deleteBackup(dbc, res, maxTag, versionsToDelete);
2185            } else {
2186                report.print(Messages.get().container(Messages.RPT_DELETE_NOTHING_0), I_CmsReport.FORMAT_NOTE);
2187                report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0));
2188            }
2189
2190            report.println(
2191                org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0),
2192                I_CmsReport.FORMAT_OK);
2193            counter++;
2194
2195            // TODO: delete the old backup projects as well
2196
int todo = 0;
2197            m_projectDriver.deletePublishHistory(dbc, dbc.currentProject().getId(), maxTag);
2198        }
2199    }
2200
2201    /**
2202     * Deletes a group, where all permissions, users and childs of the group
2203     * are transfered to a replacement group.<p>
2204     *
2205     * @param dbc the current request context
2206     * @param group the id of the group to be deleted
2207     * @param replacementId the id of the group to be transfered, can be <code>null</code>
2208     *
2209     * @throws CmsException if operation was not succesfull
2210     * @throws CmsDataAccessException if group to be deleted contains user
2211     */

2212    public void deleteGroup(CmsDbContext dbc, CmsGroup group, CmsUUID replacementId)
2213    throws CmsDataAccessException, CmsException {
2214
2215        CmsGroup replacementGroup = null;
2216        if (replacementId != null) {
2217            replacementGroup = readGroup(dbc, replacementId);
2218        }
2219        // get all child groups of the group
2220
List childs = getChild(dbc, group.getName());
2221        // get all users in this group
2222
List users = getUsersOfGroup(dbc, group.getName());
2223        // get online project
2224
CmsProject onlineProject = readProject(dbc, CmsProject.ONLINE_PROJECT_ID);
2225        if (replacementGroup == null) {
2226            // remove users
2227
Iterator JavaDoc itUsers = users.iterator();
2228            while (itUsers.hasNext()) {
2229                CmsUser user = (CmsUser)itUsers.next();
2230                removeUserFromGroup(dbc, user.getName(), group.getName());
2231            }
2232            // transfer childs to grandfather if possible
2233
CmsUUID parentId = group.getParentId();
2234            if (parentId == null) {
2235                parentId = CmsUUID.getNullUUID();
2236            }
2237            Iterator JavaDoc itChilds = childs.iterator();
2238            while (itChilds.hasNext()) {
2239                CmsGroup child = (CmsGroup)itChilds.next();
2240                child.setParentId(parentId);
2241                writeGroup(dbc, child);
2242            }
2243        } else {
2244            // move childs
2245
Iterator JavaDoc itChilds = childs.iterator();
2246            while (itChilds.hasNext()) {
2247                CmsGroup child = (CmsGroup)itChilds.next();
2248                child.setParentId(replacementId);
2249                writeGroup(dbc, child);
2250            }
2251            // move users
2252
Iterator JavaDoc itUsers = users.iterator();
2253            while (itUsers.hasNext()) {
2254                CmsUser user = (CmsUser)itUsers.next();
2255                addUserToGroup(dbc, user.getName(), replacementGroup.getName());
2256                removeUserFromGroup(dbc, user.getName(), group.getName());
2257            }
2258            // transfer for offline
2259
transferPrincipalResources(dbc, dbc.currentProject(), group.getId(), replacementId, true);
2260            // transfer for online
2261
transferPrincipalResources(dbc, onlineProject, group.getId(), replacementId, true);
2262        }
2263        // remove the group
2264
m_userDriver.removeAccessControlEntriesForPrincipal(dbc, dbc.currentProject(), onlineProject, group.getId());
2265        m_userDriver.deleteGroup(dbc, group.getName());
2266        m_groupCache.remove(new CacheId(group.getName()));
2267    }
2268
2269    /**
2270     * Deletes a user group.<p>
2271     *
2272     * Only groups that contain no subgroups can be deleted.<p>
2273     *
2274     * @param dbc the current database context
2275     * @param name the name of the group that is to be deleted
2276     *
2277     * @throws CmsException if operation was not succesfull
2278     * @throws CmsDataAccessException if group to be deleted contains user
2279     */

2280    public void deleteGroup(CmsDbContext dbc, String JavaDoc name) throws CmsDataAccessException, CmsException {
2281
2282        deleteGroup(dbc, readGroup(dbc, name), null);
2283    }
2284
2285    /**
2286     * Deletes a project.<p>
2287     *
2288     * Only the admin or the owner of the project can do this.
2289     *
2290     * @param dbc the current database context
2291     * @param deleteProject the project to be deleted
2292     *
2293     * @throws CmsException if something goes wrong
2294     */

2295    public void deleteProject(CmsDbContext dbc, CmsProject deleteProject) throws CmsException {
2296
2297        int projectId = deleteProject.getId();
2298
2299        // changed/new/deleted files in the specified project
2300
List modifiedFiles = readChangedResourcesInsideProject(dbc, projectId, 1);
2301
2302        // changed/new/deleted folders in the specified project
2303
List modifiedFolders = readChangedResourcesInsideProject(dbc, projectId, CmsResourceTypeFolder.RESOURCE_TYPE_ID);
2304
2305        // all resources inside the project have to be be reset to their online state.
2306

2307        // 1. step: delete all new files
2308
for (int i = 0; i < modifiedFiles.size(); i++) {
2309
2310            CmsResource currentFile = (CmsResource)modifiedFiles.get(i);
2311
2312            if (currentFile.getState() == CmsResource.STATE_NEW) {
2313
2314                CmsLock lock = getLock(dbc, currentFile);
2315                if (lock.isNullLock()) {
2316                    // lock the resource
2317
lockResource(dbc, currentFile, CmsLock.COMMON);
2318                } else if (!lock.getUserId().equals(dbc.currentUser().getId())
2319                    || lock.getProjectId() != dbc.currentProject().getId()) {
2320                    changeLock(dbc, currentFile);
2321                }
2322
2323                // delete the properties
2324
m_vfsDriver.deletePropertyObjects(
2325                    dbc,
2326                    projectId,
2327                    currentFile,
2328                    CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES);
2329
2330                // delete the file
2331
m_vfsDriver.removeFile(dbc, dbc.currentProject(), currentFile, true);
2332
2333                // remove the access control entries
2334
m_userDriver.removeAccessControlEntries(dbc, dbc.currentProject(), currentFile.getResourceId());
2335
2336                OpenCms.fireCmsEvent(new CmsEvent(
2337                    I_CmsEventListener.EVENT_RESOURCE_AND_PROPERTIES_MODIFIED,
2338                    Collections.singletonMap("resource", currentFile)));
2339            }
2340        }
2341
2342        // 2. step: delete all new folders
2343
for (int i = 0; i < modifiedFolders.size(); i++) {
2344
2345            CmsResource currentFolder = (CmsResource)modifiedFolders.get(i);
2346            if (currentFolder.getState() == CmsResource.STATE_NEW) {
2347
2348                // delete the properties
2349
m_vfsDriver.deletePropertyObjects(
2350                    dbc,
2351                    projectId,
2352                    currentFolder,
2353                    CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES);
2354
2355                m_vfsDriver.removeFolder(dbc, dbc.currentProject(), currentFolder);
2356
2357                // remove the access control entries
2358
m_userDriver.removeAccessControlEntries(dbc, dbc.currentProject(), currentFolder.getResourceId());
2359
2360                OpenCms.fireCmsEvent(new CmsEvent(
2361                    I_CmsEventListener.EVENT_RESOURCE_AND_PROPERTIES_MODIFIED,
2362                    Collections.singletonMap("resource", currentFolder)));
2363            }
2364        }
2365
2366        // 3. step: undo changes on all changed or deleted folders
2367
for (int i = 0; i < modifiedFolders.size(); i++) {
2368
2369            CmsResource currentFolder = (CmsResource)modifiedFolders.get(i);
2370
2371            if ((currentFolder.getState() == CmsResource.STATE_CHANGED)
2372                || (currentFolder.getState() == CmsResource.STATE_DELETED)) {
2373                CmsLock lock = getLock(dbc, currentFolder);
2374                if (lock.isNullLock()) {
2375                    // lock the resource
2376
lockResource(dbc, currentFolder, CmsLock.COMMON);
2377                } else if (!lock.getUserId().equals(dbc.currentUser().getId())
2378                    || lock.getProjectId() != dbc.currentProject().getId()) {
2379                    changeLock(dbc, currentFolder);
2380                }
2381
2382                // undo all changes in the folder
2383
undoChanges(dbc, currentFolder);
2384
2385                OpenCms.fireCmsEvent(new CmsEvent(
2386                    I_CmsEventListener.EVENT_RESOURCE_AND_PROPERTIES_MODIFIED,
2387                    Collections.singletonMap("resource", currentFolder)));
2388            }
2389        }
2390
2391        // 4. step: undo changes on all changed or deleted files
2392
for (int i = 0; i < modifiedFiles.size(); i++) {
2393
2394            CmsResource currentFile = (CmsResource)modifiedFiles.get(i);
2395
2396            if ((currentFile.getState() == CmsResource.STATE_CHANGED)
2397                || (currentFile.getState() == CmsResource.STATE_DELETED)) {
2398
2399                CmsLock lock = getLock(dbc, currentFile);
2400                if (lock.isNullLock()) {
2401                    // lock the resource
2402
lockResource(dbc, currentFile, CmsLock.COMMON);
2403                } else if (!lock.getUserId().equals(dbc.currentUser().getId())
2404                    || lock.getProjectId() != dbc.currentProject().getId()) {
2405                    changeLock(dbc, currentFile);
2406                }
2407
2408                // undo all changes in the file
2409
undoChanges(dbc, currentFile);
2410
2411                OpenCms.fireCmsEvent(new CmsEvent(
2412                    I_CmsEventListener.EVENT_RESOURCE_AND_PROPERTIES_MODIFIED,
2413                    Collections.singletonMap("resource", currentFile)));
2414            }
2415        }
2416
2417        // unlock all resources in the project
2418
m_lockManager.removeResourcesInProject(deleteProject.getId());
2419        clearAccessControlListCache();
2420        clearResourceCache();
2421
2422        // set project to online project if current project is the one which will be deleted
2423
if (projectId == dbc.currentProject().getId()) {
2424            dbc.getRequestContext().setCurrentProject(readProject(dbc, CmsProject.ONLINE_PROJECT_ID));
2425        }
2426
2427        // delete the project itself
2428
m_projectDriver.deleteProject(dbc, deleteProject);
2429        m_projectCache.remove(new Integer JavaDoc(projectId));
2430        m_projectCache.remove(deleteProject.getName());
2431
2432        OpenCms.fireCmsEvent(new CmsEvent(I_CmsEventListener.EVENT_PROJECT_MODIFIED, Collections.singletonMap(
2433            "project",
2434            deleteProject)));
2435
2436    }
2437
2438    /**
2439     * Deletes a property definition.<p>
2440     *
2441     * @param dbc the current database context
2442     * @param name the name of the property definition to delete
2443     *
2444     * @throws CmsException if something goes wrong
2445     */

2446    public void deletePropertyDefinition(CmsDbContext dbc, String JavaDoc name) throws CmsException {
2447
2448        CmsPropertyDefinition propertyDefinition = null;
2449
2450        try {
2451            // first read and then delete the metadefinition.
2452
propertyDefinition = readPropertyDefinition(dbc, name);
2453            m_vfsDriver.deletePropertyDefinition(dbc, propertyDefinition);
2454            m_backupDriver.deleteBackupPropertyDefinition(dbc, propertyDefinition);
2455        } finally {
2456
2457            // fire an event that a property of a resource has been deleted
2458
OpenCms.fireCmsEvent(new CmsEvent(
2459                I_CmsEventListener.EVENT_PROPERTY_DEFINITION_MODIFIED,
2460                Collections.singletonMap("propertyDefinition", propertyDefinition)));
2461        }
2462    }
2463
2464    /**
2465     * Deletes a resource.<p>
2466     *
2467     * The <code>siblingMode</code> parameter controls how to handle siblings
2468     * during the delete operation.
2469     * Possible values for this parameter are:
2470     * <ul>
2471     * <li><code>{@link org.opencms.file.CmsResource#DELETE_REMOVE_SIBLINGS}</code></li>
2472     * <li><code>{@link org.opencms.file.CmsResource#DELETE_PRESERVE_SIBLINGS}</code></li>
2473     * </ul><p>
2474     *
2475     * @param dbc the current database context
2476     * @param resource the name of the resource to delete (full path)
2477     * @param siblingMode indicates how to handle siblings of the deleted resource
2478     *
2479     * @throws CmsException if something goes wrong
2480     *
2481     * @see CmsObject#deleteResource(String, int)
2482     * @see I_CmsResourceType#deleteResource(CmsObject, CmsSecurityManager, CmsResource, int)
2483     */

2484    public void deleteResource(CmsDbContext dbc, CmsResource resource, int siblingMode) throws CmsException {
2485
2486        // upgrade a potential inherited, non-shared lock into a common lock
2487
CmsLock currentLock = getLock(dbc, resource);
2488        if (currentLock.getType() == CmsLock.TYPE_INHERITED) {
2489            // upgrade the lock status if required
2490
lockResource(dbc, resource, CmsLock.COMMON);
2491        }
2492
2493        // check if siblings of the resource exist and must be deleted as well
2494

2495        if (resource.isFolder()) {
2496            // folder can have no siblings
2497
siblingMode = CmsResource.DELETE_PRESERVE_SIBLINGS;
2498        }
2499
2500        // if selected, add all siblings of this resource to the list of resources to be deleted
2501
boolean allSiblingsRemoved;
2502        List resources;
2503        if (siblingMode == CmsResource.DELETE_REMOVE_SIBLINGS) {
2504            resources = new ArrayList JavaDoc(readSiblings(dbc, resource, CmsResourceFilter.ALL));
2505            allSiblingsRemoved = true;
2506
2507            // ensure that the resource requested to be deleted is the last resource that gets actually deleted
2508
// to keep the shared locks of the siblings while those get deleted.
2509
resources.remove(resource);
2510            resources.add(resource);
2511        } else {
2512            // only delete the resource, no siblings
2513
resources = Collections.singletonList(resource);
2514            allSiblingsRemoved = false;
2515        }
2516
2517        int size = resources.size();
2518        // if we have only one resource no further check is required
2519
if (size > 1) {
2520            // ensure that each sibling is unlocked or locked by the current user
2521
for (int i = 0; i < size; i++) {
2522
2523                CmsResource currentResource = (CmsResource)resources.get(i);
2524                currentLock = getLock(dbc, currentResource);
2525
2526                if (!currentLock.equals(CmsLock.getNullLock())
2527                    && !currentLock.getUserId().equals(dbc.currentUser().getId())) {
2528                    // the resource is locked by a user different from the current user
2529
CmsRequestContext context = dbc.getRequestContext();
2530                    throw new CmsLockException(org.opencms.lock.Messages.get().container(
2531                        org.opencms.lock.Messages.ERR_SIBLING_LOCKED_2,
2532                        context.getSitePath(currentResource),
2533                        context.getSitePath(resource)));
2534                }
2535            }
2536        }
2537
2538        boolean removeAce = true;
2539
2540        // delete all collected resources
2541
for (int i = 0; i < size; i++) {
2542            CmsResource currentResource = (CmsResource)resources.get(i);
2543
2544            // try to delete/remove the resource only if the user has write access to the resource
2545
if (CmsSecurityManager.PERM_ALLOWED != m_securityManager.hasPermissions(
2546                dbc,
2547                currentResource,
2548                CmsPermissionSet.ACCESS_WRITE,
2549                true,
2550                CmsResourceFilter.ALL)) {
2551
2552                // no write access to sibling - must keep ACE (see below)
2553
allSiblingsRemoved = false;
2554
2555            } else {
2556
2557                // write access to sibling granted
2558
boolean existsOnline = m_vfsDriver.validateStructureIdExists(
2559                    dbc,
2560                    CmsProject.ONLINE_PROJECT_ID,
2561                    currentResource.getStructureId());
2562
2563                if (!existsOnline) {
2564                    // the resource does not exist online => remove the resource
2565
// this means the resoruce is "new" (blue) in the offline project
2566

2567                    // delete all properties of this resource
2568
deleteAllProperties(dbc, currentResource.getRootPath());
2569
2570                    if (currentResource.isFolder()) {
2571                        m_vfsDriver.removeFolder(dbc, dbc.currentProject(), currentResource);
2572                    } else {
2573                        // check lables
2574
if (currentResource.isLabeled() && !labelResource(dbc, currentResource, null, 2)) {
2575                            // update the resource flags to "unlabel" the other siblings
2576
int flags = currentResource.getFlags();
2577                            flags &= ~CmsResource.FLAG_LABELED;
2578                            currentResource.setFlags(flags);
2579                        }
2580                        m_vfsDriver.removeFile(dbc, dbc.currentProject(), currentResource, true);
2581                    }
2582
2583                    // ensure an exclusive lock is removed in the lock manager for a deleted new resource,
2584
// otherwise it would "stick" in the lock manager, preventing other users from creating
2585
// a file with the same name (issue with tempfiles in editor)
2586
m_lockManager.removeDeletedResource(this, dbc, currentResource.getRootPath());
2587
2588                } else {
2589                    // the resource exists online => mark the resource as deleted
2590
// structure record is removed during next publish
2591
// if one (or more) siblings are not removed, the ACE can not be removed
2592
removeAce = false;
2593
2594                    // set resource state to deleted
2595
currentResource.setState(CmsResource.STATE_DELETED);
2596                    m_vfsDriver.writeResourceState(dbc, dbc.currentProject(), currentResource, UPDATE_STRUCTURE_STATE);
2597
2598                    // add the project id as a property, this is later used for publishing
2599
m_vfsDriver.writePropertyObject(dbc, dbc.currentProject(), currentResource, new CmsProperty(
2600                        CmsPropertyDefinition.PROPERTY_INTERNAL,
2601                        String.valueOf(dbc.currentProject().getId()),
2602                        null));
2603
2604                    // update the project ID
2605
m_vfsDriver.writeLastModifiedProjectId(
2606                        dbc,
2607                        dbc.currentProject(),
2608                        dbc.currentProject().getId(),
2609                        currentResource);
2610                }
2611            }
2612        }
2613
2614        if ((resource.getSiblingCount() <= 1) || allSiblingsRemoved) {
2615            if (removeAce) {
2616                // remove the access control entries
2617
m_userDriver.removeAccessControlEntries(dbc, dbc.currentProject(), resource.getResourceId());
2618            } else {
2619                // mark access control entries as deleted
2620
m_userDriver.deleteAccessControlEntries(dbc, dbc.currentProject(), resource.getResourceId());
2621            }
2622        }
2623
2624        // flush all caches
2625
clearAccessControlListCache();
2626        m_propertyCache.clear();
2627
2628        OpenCms.fireCmsEvent(new CmsEvent(I_CmsEventListener.EVENT_RESOURCE_DELETED, Collections.singletonMap(
2629            "resources",
2630            resources)));
2631    }
2632
2633    /**
2634     * Deletes an entry in the published resource table.<p>
2635     *
2636     * @param dbc the current database context
2637     * @param resourceName The name of the resource to be deleted in the static export
2638     * @param linkType the type of resource deleted (0= non-paramter, 1=parameter)
2639     * @param linkParameter the parameters ofthe resource
2640     *
2641     * @throws CmsException if something goes wrong
2642     */

2643    public void deleteStaticExportPublishedResource(
2644        CmsDbContext dbc,
2645        String JavaDoc resourceName,
2646        int linkType,
2647        String JavaDoc linkParameter) throws CmsException {
2648
2649        m_projectDriver.deleteStaticExportPublishedResource(
2650            dbc,
2651            dbc.currentProject(),
2652            resourceName,
2653            linkType,
2654            linkParameter);
2655    }
2656
2657    /**
2658     * Deletes a user, where all permissions and resources attributes of the user
2659     * were transfered to a replacement user, if given.<p>
2660     *
2661     * Only users, which are in the group "administrators" are granted.<p>
2662     *
2663     * @param dbc the current database context
2664     * @param project the current project
2665     * @param username the name of the user to be deleted
2666     * @param replacementUsername the name of the user to be transfered, can be <code>null</code>
2667     *
2668     * @throws CmsException if operation was not succesfull
2669     */

2670    public void deleteUser(CmsDbContext dbc, CmsProject project, String JavaDoc username, String JavaDoc replacementUsername)
2671    throws CmsException {
2672
2673        // Test if the users exists
2674
CmsUser user = readUser(dbc, username);
2675        CmsUser replacementUser = null;
2676        if (replacementUsername != null) {
2677            replacementUser = readUser(dbc, replacementUsername);
2678        }
2679
2680        CmsProject onlineProject = readProject(dbc, CmsProject.ONLINE_PROJECT_ID);
2681        boolean withACEs = true;
2682        if (replacementUser == null) {
2683            withACEs = false;
2684            replacementUser = readUser(dbc, OpenCms.getDefaultUsers().getUserDeletedResource());
2685        }
2686        Iterator JavaDoc itGroups = getGroupsOfUser(dbc, username).iterator();
2687        while (itGroups.hasNext()) {
2688            CmsGroup group = (CmsGroup)itGroups.next();
2689            if (!m_securityManager.hasRole(dbc, replacementUser, CmsRole.VFS_MANAGER)) {
2690                // add replacement user to user groups
2691
if (!userInGroup(dbc, replacementUser.getName(), group.getName())) {
2692                    addUserToGroup(dbc, replacementUser.getName(), group.getName());
2693                }
2694            }
2695            // remove user from groups
2696
if (userInGroup(dbc, username, group.getName())) {
2697                removeUserFromGroup(dbc, username, group.getName());
2698            }
2699        }
2700        
2701        // offline
2702
transferPrincipalResources(dbc, project, user.getId(), replacementUser.getId(), withACEs);
2703        // online
2704
transferPrincipalResources(dbc, onlineProject, user.getId(), replacementUser.getId(), withACEs);
2705        m_userDriver.removeAccessControlEntriesForPrincipal(dbc, project, onlineProject, user.getId());
2706        m_userDriver.deleteUser(dbc, username);
2707        // delete user from cache
2708
clearUserCache(user);
2709    }
2710
2711    /**
2712     * Deletes a web user from the Cms.<p>
2713     *
2714     * @param dbc the current database context
2715     * @param userId the Id of the user to be deleted
2716     *
2717     * @throws CmsException if operation was not succesfull
2718     */

2719    public void deleteWebUser(CmsDbContext dbc, CmsUUID userId) throws CmsException {
2720
2721        CmsUser user = readUser(dbc, userId);
2722        m_userDriver.deleteUser(dbc, user.getName());
2723        // delete user from cache
2724
clearUserCache(user);
2725    }
2726
2727    /**
2728     * Destroys this driver manager.<p>
2729     *
2730     * @throws Throwable if something goes wrong
2731     */

2732    public void destroy() throws Throwable JavaDoc {
2733
2734        finalize();
2735        if (CmsLog.INIT.isInfoEnabled()) {
2736            CmsLog.INIT.info(Messages.get().getBundle().key(
2737                Messages.INIT_DRIVER_MANAGER_DESTROY_1,
2738                getClass().getName()));
2739        }
2740    }
2741
2742    /**
2743     * Ends a task.<p>
2744     *
2745     * @param dbc the current databsae context
2746     * @param taskid the ID of the task to end
2747     *
2748     * @throws CmsException if something goes wrong
2749     */

2750    public void endTask(CmsDbContext dbc, int taskid) throws CmsException {
2751
2752        m_workflowDriver.endTask(dbc, taskid);
2753        if (dbc.currentUser() == null) {
2754            m_workflowDriver.writeSystemTaskLog(dbc, taskid, "Task finished.");
2755
2756        } else {
2757            m_workflowDriver.writeSystemTaskLog(dbc, taskid, "Task finished by "
2758                + dbc.currentUser().getFirstname()
2759                + " "
2760                + dbc.currentUser().getLastname()
2761                + '.');
2762        }
2763    }
2764
2765    /**
2766     * Tests if a resource with the given resourceId does already exist in the Database.<p>
2767     *
2768     * @param dbc the current database context
2769     * @param resourceId the resource id to test for
2770     * @return true if a resource with the given id was found, false otherweise
2771     * @throws CmsException if something goes wrong
2772     */

2773    public boolean existsResourceId(CmsDbContext dbc, CmsUUID resourceId) throws CmsException {
2774
2775        return m_vfsDriver.validateResourceIdExists(dbc, dbc.currentProject().getId(), resourceId);
2776    }
2777
2778    /**
2779     * Fills the given publish list with the the VFS resources that actually get published.<p>
2780     *
2781     * Please refer to the source code of this method for the rules on how to decide whether a
2782     * new/changed/deleted <code>{@link CmsResource}</code> object can be published or not.<p>
2783     *
2784     * @param dbc the current database context
2785     * @param publishList must be initialized with basic publish information (Project or direct publish operation)
2786     *
2787     * @return the given publish list filled with all new/changed/deleted files from the current (offline) project
2788     * that will be published actually
2789     *
2790     * @throws CmsException if something goes wrong
2791     *
2792     * @see org.opencms.db.CmsPublishList
2793     */

2794    public CmsPublishList fillPublishList(CmsDbContext dbc, CmsPublishList publishList) throws CmsException {
2795
2796        if (!publishList.isDirectPublish()) {
2797            // when publishing a project,
2798
// all modified resources with the last change done in the current project are candidates if unlocked
2799

2800            List folderList = m_vfsDriver.readResourceTree(
2801                dbc,
2802                dbc.currentProject().getId(),
2803                CmsDriverManager.READ_IGNORE_PARENT,
2804                CmsDriverManager.READ_IGNORE_TYPE,
2805                CmsResource.STATE_UNCHANGED,
2806                CmsDriverManager.READ_IGNORE_TIME,
2807                CmsDriverManager.READ_IGNORE_TIME,
2808                CmsDriverManager.READ_IGNORE_TIME,
2809                CmsDriverManager.READ_IGNORE_TIME,
2810                CmsDriverManager.READ_IGNORE_TIME,
2811                CmsDriverManager.READ_IGNORE_TIME,
2812                CmsDriverManager.READMODE_INCLUDE_TREE
2813                    | CmsDriverManager.READMODE_INCLUDE_PROJECT
2814                    | CmsDriverManager.READMODE_EXCLUDE_STATE
2815                    | CmsDriverManager.READMODE_ONLY_FOLDERS);
2816
2817            publishList.addFolders(filterResources(dbc, folderList, folderList));
2818
2819            List fileList = m_vfsDriver.readResourceTree(
2820                dbc,
2821                dbc.currentProject().getId(),
2822                CmsDriverManager.READ_IGNORE_PARENT,
2823                CmsDriverManager.READ_IGNORE_TYPE,
2824                CmsResource.STATE_UNCHANGED,
2825                CmsDriverManager.READ_IGNORE_TIME,
2826                CmsDriverManager.READ_IGNORE_TIME,
2827                CmsDriverManager.READ_IGNORE_TIME,
2828                CmsDriverManager.READ_IGNORE_TIME,
2829                CmsDriverManager.READ_IGNORE_TIME,
2830                CmsDriverManager.READ_IGNORE_TIME,
2831                CmsDriverManager.READMODE_INCLUDE_TREE
2832                    | CmsDriverManager.READMODE_INCLUDE_PROJECT
2833                    | CmsDriverManager.READMODE_EXCLUDE_STATE
2834                    | CmsDriverManager.READMODE_ONLY_FILES);
2835
2836            publishList.addFiles(filterResources(dbc, publishList.getFolderList(), fileList));
2837
2838        } else {
2839            // this is a direct publish
2840
Iterator JavaDoc it = publishList.getDirectPublishResources().iterator();
2841            while (it.hasNext()) {
2842                // iterate all resources in the direct publish list
2843
CmsResource directPublishResource = (CmsResource)it.next();
2844                if (directPublishResource.isFolder()) {
2845
2846                    // when publishing a folder directly,
2847
// the folder and all modified resources within the tree below this folder
2848
// and with the last change done in the current project are candidates if unlocked
2849

2850                    if (CmsResource.STATE_UNCHANGED != directPublishResource.getState()
2851                        && getLock(dbc, directPublishResource).isNullLock()) {
2852                        publishList.addFolder(directPublishResource);
2853                    }
2854
2855                    if (publishList.isPublishSubResources()) {
2856                        // add all sub resources of the folder
2857

2858                        List folderList = m_vfsDriver.readResourceTree(
2859                            dbc,
2860                            dbc.currentProject().getId(),
2861                            directPublishResource.getRootPath(),
2862                            CmsDriverManager.READ_IGNORE_TYPE,
2863                            CmsResource.STATE_UNCHANGED,
2864                            CmsDriverManager.READ_IGNORE_TIME,
2865                            CmsDriverManager.READ_IGNORE_TIME,
2866                            CmsDriverManager.READ_IGNORE_TIME,
2867                            CmsDriverManager.READ_IGNORE_TIME,
2868                            CmsDriverManager.READ_IGNORE_TIME,
2869                            CmsDriverManager.READ_IGNORE_TIME,
2870                            CmsDriverManager.READMODE_INCLUDE_TREE
2871                                | CmsDriverManager.READMODE_INCLUDE_PROJECT
2872                                | CmsDriverManager.READMODE_EXCLUDE_STATE
2873                                | CmsDriverManager.READMODE_ONLY_FOLDERS);
2874
2875                        publishList.addFolders(filterResources(dbc, publishList.getFolderList(), folderList));
2876
2877                        List fileList = m_vfsDriver.readResourceTree(
2878                            dbc,
2879                            dbc.currentProject().getId(),
2880                            directPublishResource.getRootPath(),
2881                            CmsDriverManager.READ_IGNORE_TYPE,
2882                            CmsResource.STATE_UNCHANGED,
2883                            CmsDriverManager.READ_IGNORE_TIME,
2884                            CmsDriverManager.READ_IGNORE_TIME,
2885                            CmsDriverManager.READ_IGNORE_TIME,
2886                            CmsDriverManager.READ_IGNORE_TIME,
2887                            CmsDriverManager.READ_IGNORE_TIME,
2888                            CmsDriverManager.READ_IGNORE_TIME,
2889                            CmsDriverManager.READMODE_INCLUDE_TREE
2890                                | CmsDriverManager.READMODE_INCLUDE_PROJECT
2891                                | CmsDriverManager.READMODE_EXCLUDE_STATE
2892                                | CmsDriverManager.READMODE_ONLY_FILES);
2893
2894                        publishList.addFiles(filterResources(dbc, publishList.getFolderList(), fileList));
2895                    }
2896                } else if (directPublishResource.isFile()
2897                    && CmsResource.STATE_UNCHANGED != directPublishResource.getState()) {
2898
2899                    // when publishing a file directly this file is the only candidate
2900
// if it is modified and unlocked
2901

2902                    if (getLock(dbc, directPublishResource).isNullLock()) {
2903                        publishList.addFile(directPublishResource);
2904                    }
2905                }
2906            }
2907        }
2908
2909        // Step 2: if desired, extend the list of files to publish with related siblings
2910
if (publishList.isPublishSiblings()) {
2911
2912            List publishFiles = publishList.getFileList();
2913            int size = publishFiles.size();
2914
2915            for (int i = 0; i < size; i++) {
2916                CmsResource currentFile = (CmsResource)publishFiles.get(i);
2917                if (currentFile.getSiblingCount() > 1) {
2918                    publishList.addFiles(filterSiblings(dbc, currentFile, publishList.getFolderList(), readSiblings(
2919                        dbc,
2920                        currentFile,
2921                        CmsResourceFilter.ALL_MODIFIED)));
2922                }
2923            }
2924        }
2925
2926        publishList.initialize();
2927        return publishList;
2928    }
2929
2930    /**
2931     * Forwards a task to a new user.<p>
2932     *
2933     * @param dbc the current database context
2934     * @param taskid the Id of the task to forward
2935     * @param newRoleName the new group name for the task
2936     * @param newUserName the new user who gets the task. if it is empty, a new agent will automatic selected
2937     *
2938     * @throws CmsException if something goes wrong
2939     */

2940    public void forwardTask(CmsDbContext dbc, int taskid, String JavaDoc newRoleName, String JavaDoc newUserName) throws CmsException {
2941
2942        CmsGroup newRole = m_userDriver.readGroup(dbc, newRoleName);
2943        CmsUser newUser = null;
2944        if (CmsStringUtil.isEmpty(newUserName)) {
2945            newUser = readUser(dbc, m_workflowDriver.readAgent(dbc, newRole.getId()));
2946        } else {
2947            newUser = readUser(dbc, newUserName, CmsUser.USER_TYPE_SYSTEMUSER);
2948        }
2949
2950        m_workflowDriver.forwardTask(dbc, taskid, newRole.getId(), newUser.getId());
2951        m_workflowDriver.writeSystemTaskLog(dbc, taskid, "Task fowarded from "
2952            + dbc.currentUser().getFirstname()
2953            + " "
2954            + dbc.currentUser().getLastname()
2955            + " to "
2956            + newUser.getFirstname()
2957            + " "
2958            + newUser.getLastname()
2959            + '.');
2960    }
2961
2962    /**
2963     * Returns the list of access control entries of a resource given its name.<p>
2964     *
2965     * @param dbc the current database context
2966     * @param resource the resource to read the access control entries for
2967     * @param getInherited true if the result should include all access control entries inherited by parent folders
2968     *
2969     * @return a list of <code>{@link CmsAccessControlEntry}</code> objects defining all permissions for the given resource
2970     *
2971     * @throws CmsException if something goes wrong
2972     */

2973    public List getAccessControlEntries(CmsDbContext dbc, CmsResource resource, boolean getInherited)
2974    throws CmsException {
2975
2976        // get the ACE of the resource itself
2977
List ace = m_userDriver.readAccessControlEntries(dbc, dbc.currentProject(), resource.getResourceId(), false);
2978
2979        // get the ACE of each parent folder
2980
// Note: for the immediate parent, get non-inherited access control entries too,
2981
// if the resource is not a folder
2982
String JavaDoc parentPath = CmsResource.getParentFolder(resource.getRootPath());
2983        int d = (resource.isFolder()) ? 1 : 0;
2984
2985        while (getInherited && parentPath != null) {
2986            resource = m_vfsDriver.readFolder(dbc, dbc.currentProject().getId(), parentPath);
2987            List entries = m_userDriver.readAccessControlEntries(
2988                dbc,
2989                dbc.currentProject(),
2990                resource.getResourceId(),
2991                d > 0);
2992
2993            for (Iterator JavaDoc i = entries.iterator(); i.hasNext();) {
2994                CmsAccessControlEntry e = (CmsAccessControlEntry)i.next();
2995                e.setFlags(CmsAccessControlEntry.ACCESS_FLAGS_INHERITED);
2996            }
2997
2998            ace.addAll(entries);
2999            parentPath = CmsResource.getParentFolder(resource.getRootPath());
3000            d++;
3001        }
3002
3003        return ace;
3004    }
3005
3006    /**
3007     * Returns the full access control list of a given resource.<p>
3008     *
3009     * @param dbc the current database context
3010     * @param resource the resource
3011     *
3012     * @return the access control list of the resource
3013     *
3014     * @throws CmsException if something goes wrong
3015     */

3016    public CmsAccessControlList getAccessControlList(CmsDbContext dbc, CmsResource resource) throws CmsException {
3017
3018        return getAccessControlList(dbc, resource, false);
3019    }
3020
3021    /**
3022     * Returns the access control list of a given resource.<p>
3023     *
3024     * If <code>inheritedOnly</code> is set, only inherited access control entries
3025     * are returned.<p>
3026     *
3027     * Note: For file resources, *all* permissions set at the immediate parent folder are inherited,
3028     * not only these marked to inherit.
3029     *
3030     * @param dbc the current database context
3031     * @param resource the resource
3032     * @param inheritedOnly skip non-inherited entries if set
3033     *
3034     * @return the access control list of the resource
3035     *
3036     * @throws CmsException if something goes wrong
3037     */

3038    public CmsAccessControlList getAccessControlList(CmsDbContext dbc, CmsResource resource, boolean inheritedOnly)
3039    throws CmsException {
3040
3041        return getAccessControlList(dbc, resource, inheritedOnly, resource.isFolder(), 0);
3042    }
3043
3044    /**
3045     * Returns the number of active connections managed by a pool.<p>
3046     *
3047     * @param dbPoolUrl the url of a pool
3048     * @return the number of active connections
3049     * @throws CmsDbException if something goes wrong
3050     */

3051    public int getActiveConnections(String JavaDoc dbPoolUrl) throws CmsDbException {
3052
3053        try {
3054            for (Iterator JavaDoc i = m_connectionPools.iterator(); i.hasNext();) {
3055                PoolingDriver d = (PoolingDriver)i.next();
3056                ObjectPool p = d.getConnectionPool(dbPoolUrl);
3057                return p.getNumActive();
3058            }
3059        } catch (Exception JavaDoc exc) {
3060            CmsMessageContainer message = Messages.get().container(Messages.ERR_ACCESSING_POOL_1, dbPoolUrl);
3061            throw new CmsDbException(message, exc);
3062        }
3063
3064        CmsMessageContainer message = Messages.get().container(Messages.ERR_UNKNOWN_POOL_URL_1, dbPoolUrl);
3065        throw new CmsDbException(message);
3066    }
3067
3068    /**
3069     * Returns all projects which are owned by the current user or which are
3070     * accessible by the current user.<p>
3071     *
3072     * @param dbc the current database context
3073     *
3074     * @return a list of objects of type <code>{@link CmsProject}</code>
3075     *
3076     * @throws CmsException if something goes wrong
3077     */

3078    public List getAllAccessibleProjects(CmsDbContext dbc) throws CmsException {
3079
3080        if (m_securityManager.hasRole(dbc, CmsRole.PROJECT_MANAGER)) {
3081            // user is allowed to access all existing projects
3082
return m_projectDriver.readProjects(dbc, CmsProject.PROJECT_STATE_UNLOCKED);
3083        }
3084
3085        // get all groups of the user
3086
List groups = getGroupsOfUser(dbc, dbc.currentUser().getName());
3087
3088        // add all projects which are owned by the user
3089
Set projects = new HashSet JavaDoc(m_projectDriver.readProjectsForUser(dbc, dbc.currentUser()));
3090
3091        // add all projects, that the user can access with his groups
3092
for (int i = 0, n = groups.size(); i < n; i++) {
3093            projects.addAll(m_projectDriver.readProjectsForGroup(dbc, (CmsGroup)groups.get(i)));
3094        }
3095
3096        // return the list of projects
3097
ArrayList JavaDoc accessibleProjects = new ArrayList JavaDoc(projects);
3098        Collections.sort(accessibleProjects);
3099        return accessibleProjects;
3100    }
3101
3102    /**
3103     * Returns a Vector with all projects from history.<p>
3104     *
3105     * @param dbc the current database context
3106     *
3107     * @return list of <code>{@link CmsBackupProject}</code> objects
3108     * with all projects from history.
3109     *
3110     * @throws CmsException if operation was not succesful
3111     */

3112    public List getAllBackupProjects(CmsDbContext dbc) throws CmsException {
3113
3114        return m_backupDriver.readBackupProjects(dbc);
3115    }
3116
3117    /**
3118     * Returns all projects which are owned by the current user or which are manageable
3119     * for the group of the user.<p>
3120     *
3121     * @param dbc the current database context
3122     *
3123     * @return a list of objects of type <code>{@link CmsProject}</code>
3124     *
3125     * @throws CmsException if operation was not succesful
3126     */

3127    public List getAllManageableProjects(CmsDbContext dbc) throws CmsException {
3128
3129        // the result set
3130
Set projects = new HashSet JavaDoc();
3131
3132        if (m_securityManager.hasRole(dbc, CmsRole.PROJECT_MANAGER)) {
3133
3134            // user is allowed to access all existing projects
3135
projects.addAll(m_projectDriver.readProjects(dbc, CmsProject.PROJECT_STATE_UNLOCKED));
3136        } else {
3137
3138            // add all projects which are owned by the user
3139
projects.addAll(m_projectDriver.readProjectsForUser(dbc, dbc.currentUser()));
3140
3141            // get all groups of the user
3142
List groups = getGroupsOfUser(dbc, dbc.currentUser().getName());
3143
3144            // add all projects, that the user can access with his groups
3145
for (int i = 0, n = groups.size(); i < n; i++) {
3146                projects.addAll(m_projectDriver.readProjectsForManagerGroup(dbc, (CmsGroup)groups.get(i)));
3147            }
3148        }
3149
3150        // remove the online-project, it is not manageable!
3151
projects.remove(readProject(dbc, CmsProject.ONLINE_PROJECT_ID));
3152
3153        // return the list of projects
3154
return new ArrayList JavaDoc(projects);
3155    }
3156
3157    /**
3158     * Returns the backup driver.<p>
3159     *
3160     * @return the backup driver
3161     */

3162    public I_CmsBackupDriver getBackupDriver() {
3163
3164        return m_backupDriver;
3165    }
3166
3167    /**
3168     * Returns the next version id for the published backup resources.<p>
3169     *
3170     * @param dbc the current database context
3171     *
3172     * @return the new version id
3173     */

3174    public int getBackupTagId(CmsDbContext dbc) {
3175
3176        return m_backupDriver.readNextBackupTagId(dbc);
3177    }
3178
3179    /**
3180     * Returns all child groups of a group.<p>
3181     *
3182     * @param dbc the current database context
3183     * @param groupname the name of the group
3184     *
3185     * @return a list of all child <code>{@link CmsGroup}</code> objects
3186     *
3187     * @throws CmsException if operation was not succesful
3188     */

3189    public List getChild(CmsDbContext dbc, String JavaDoc groupname) throws CmsException {
3190
3191        return m_userDriver.readChildGroups(dbc, groupname);
3192    }
3193
3194    /**
3195     * Returns all child groups of a group.<p>
3196     *
3197     * This method also returns all sub-child groups of the current group.
3198     *
3199     * @param dbc the current database context
3200     * @param groupname the name of the group
3201     *
3202     * @return a list of all child <code>{@link CmsGroup}</code> objects or <code>null</code>
3203     *
3204     * @throws CmsException if operation was not succesful
3205     */

3206    public List getChilds(CmsDbContext dbc, String JavaDoc groupname) throws CmsException {
3207
3208        Set allChilds = new HashSet JavaDoc();
3209        // iterate all child groups
3210
Iterator JavaDoc it = m_userDriver.readChildGroups(dbc, groupname).iterator();
3211        while (it.hasNext()) {
3212            CmsGroup group = (CmsGroup)it.next();
3213            // add the group itself
3214
allChilds.add(group);
3215            // now get all subchilds for each group
3216
allChilds.addAll(getChilds(dbc, group.getName()));
3217        }
3218        return new ArrayList JavaDoc(allChilds);
3219    }
3220
3221    /**
3222     * Method to access the configurations of the properties-file.<p>
3223     *
3224     * All users are granted.
3225     *
3226     * @return the Configurations of the properties-file
3227     */

3228    public Map JavaDoc getConfigurations() {
3229
3230        return m_configuration;
3231    }
3232
3233    /**
3234     * Returns the list of groups to which the user directly belongs to.<p>
3235     *
3236     * @param dbc the current database context
3237     * @param username The name of the user
3238     *
3239     * @return a list of <code>{@link CmsGroup}</code> objects
3240     *
3241     * @throws CmsException Throws CmsException if operation was not succesful
3242     */

3243    public List getDirectGroupsOfUser(CmsDbContext dbc, String JavaDoc username) throws CmsException {
3244
3245        CmsUser user = readUser(dbc, username);
3246        return m_userDriver.readGroupsOfUser(dbc, user.getId(), dbc.getRequestContext().getRemoteAddress());
3247    }
3248
3249    /**
3250     * Returns all available groups.<p>
3251     *
3252     * @param dbc the current database context
3253     *
3254     * @return a list of all available <code>{@link CmsGroup}</code> objects
3255     *
3256     * @throws CmsException if operation was not succesful
3257     */

3258    public List getGroups(CmsDbContext dbc) throws CmsException {
3259
3260        return m_userDriver.readGroups(dbc);
3261    }
3262
3263    /**
3264     * Returns the groups of a user.<p>
3265     *
3266     * @param dbc the current database context
3267     * @param username the name of the user
3268     *
3269     * @return a list of <code>{@link CmsGroup}</code> objects
3270     *
3271     * @throws CmsException if operation was not succesful
3272     */

3273    public List getGroupsOfUser(CmsDbContext dbc, String JavaDoc username) throws CmsException {
3274
3275        return getGroupsOfUser(dbc, username, dbc.getRequestContext().getRemoteAddress());
3276    }
3277
3278    /**
3279     * Returns the groups of a Cms user filtered by the specified IP address.<p>
3280     *
3281     * @param dbc the current database context
3282     * @param username the name of the user
3283     * @param remoteAddress the IP address to filter the groups in the result list
3284     *
3285     * @return a list of <code>{@link CmsGroup}</code> objects
3286     *
3287     * @throws CmsException if operation was not succesful
3288     */

3289    public List getGroupsOfUser(CmsDbContext dbc, String JavaDoc username, String JavaDoc remoteAddress) throws CmsException {
3290
3291        CmsUser user = readUser(dbc, username);
3292        String JavaDoc cacheKey = m_keyGenerator.getCacheKeyForUserGroups(remoteAddress, dbc, user);
3293
3294        List allGroups = (List)m_userGroupsCache.get(cacheKey);
3295        if (allGroups == null) {
3296
3297            // get all groups of the user
3298
List groups = m_userDriver.readGroupsOfUser(dbc, user.getId(), remoteAddress);
3299            allGroups = new ArrayList JavaDoc(groups);
3300            // now get all parents of the groups
3301
for (int i = 0; i < groups.size(); i++) {
3302
3303                CmsGroup parent = getParent(dbc, ((CmsGroup)groups.get(i)).getName());
3304                while ((parent != null) && (!allGroups.contains(parent))) {
3305
3306                    allGroups.add(parent);
3307                    // read next parent group
3308
parent = getParent(dbc, parent.getName());
3309                }
3310            }
3311            // make group list unmodifiable for caching
3312
allGroups = Collections.unmodifiableList(allGroups);
3313            m_userGroupsCache.put(cacheKey, allGroups);
3314        }
3315
3316        return allGroups;
3317    }
3318
3319    /**
3320     * Returns the HTML link validator.<p>
3321     *
3322     * @return the HTML link validator
3323     * @see CmsXmlDocumentLinkValidator
3324     */

3325    public CmsXmlDocumentLinkValidator getHtmlLinkValidator() {
3326
3327        return m_htmlLinkValidator;
3328    }
3329
3330    /**
3331     * Returns the number of idle connections managed by a pool.<p>
3332     *
3333     * @param dbPoolUrl the url of a pool
3334     * @return the number of idle connections
3335     * @throws CmsDbException if something goes wrong
3336     */

3337    public int getIdleConnections(String JavaDoc dbPoolUrl) throws CmsDbException {
3338
3339        try {
3340            for (Iterator JavaDoc i = m_connectionPools.iterator(); i.hasNext();) {
3341                PoolingDriver d = (PoolingDriver)i.next();
3342                ObjectPool p = d.getConnectionPool(dbPoolUrl);
3343                return p.getNumIdle();
3344            }
3345        } catch (Exception JavaDoc exc) {
3346            CmsMessageContainer message = Messages.get().container(Messages.ERR_ACCESSING_POOL_1, dbPoolUrl);
3347            throw new CmsDbException(message, exc);
3348        }
3349
3350        CmsMessageContainer message = Messages.get().container(Messages.ERR_UNKNOWN_POOL_URL_1, dbPoolUrl);
3351        throw new CmsDbException(message);
3352    }
3353
3354    /**
3355     * Returns the lock state of a resource.<p>
3356     *
3357     * @param dbc the current database context
3358     * @param resource the resource to return the lock state for
3359     *
3360     * @return the lock state of the resource
3361     *
3362     * @throws CmsException if something goes wrong
3363     */

3364    public CmsLock getLock(CmsDbContext dbc, CmsResource resource) throws CmsException {
3365
3366        return m_lockManager.getLock(this, dbc, resource);
3367    }
3368
3369    /**
3370     * Returns the parent group of a group.<p>
3371     *
3372     * @param dbc the current database context
3373     * @param groupname the name of the group
3374     *
3375     * @return group the parent group or <code>null</code>
3376     *
3377     * @throws CmsException if operation was not succesful
3378     */

3379    public CmsGroup getParent(CmsDbContext dbc, String JavaDoc groupname) throws CmsException {
3380
3381        CmsGroup group = readGroup(dbc, groupname);
3382        if (group.getParentId().isNullUUID()) {
3383            return null;
3384        }
3385
3386        // try to read from cache
3387
CmsGroup parent = (CmsGroup)m_groupCache.get(new CacheId(group.getParentId()));
3388        if (parent == null) {
3389            parent = m_userDriver.readGroup(dbc, group.getParentId());
3390            m_groupCache.put(new CacheId(parent), parent);
3391        }
3392        return parent;
3393    }
3394
3395    /**
3396     * Returns the set of permissions of the current user for a given resource.<p>
3397     *
3398     * @param dbc the current database context
3399     * @param resource the resource
3400     * @param user the user
3401     *
3402     * @return bitset with allowed permissions
3403     *
3404     * @throws CmsException if something goes wrong
3405     */

3406    public CmsPermissionSetCustom getPermissions(CmsDbContext dbc, CmsResource resource, CmsUser user)
3407    throws CmsException {
3408
3409        CmsAccessControlList acList = getAccessControlList(dbc, resource, false);
3410        return acList.getPermissions(user, getGroupsOfUser(dbc, user.getName()));
3411    }
3412
3413    /**
3414     * Returns the project driver.<p>
3415     *
3416     * @return the project driver
3417     */

3418    public I_CmsProjectDriver getProjectDriver() {
3419
3420        return m_projectDriver;
3421    }
3422
3423    /**
3424     * Returns all resources associated to a given principal via an ACE with the given permissions.<p>
3425     *
3426     * If the <code>includeAttr</code> flag is set it returns also all resources associated to
3427     * a given principal through some of following attributes.<p>
3428     *
3429     * <ul>
3430     * <li>User Created</li>
3431     * <li>User Last Modified</li>
3432     * </ul><p>
3433     *
3434     * @param dbc the current database context
3435     * @param project the to read the entries from
3436     * @param principalId the id of the principal
3437     * @param permissions a set of permissions to match, can be <code>null</code> for all ACEs
3438     * @param includeAttr a flag to include resources associated by attributes
3439     *
3440     * @return a list of <code>{@link CmsResource}</code> objects
3441     *
3442     * @throws CmsException if something goes wrong
3443     */

3444    public List getResourcesForPrincipal(
3445        CmsDbContext dbc,
3446        CmsProject project,
3447        CmsUUID principalId,
3448        CmsPermissionSet permissions,
3449        boolean includeAttr) throws CmsException {
3450
3451        List resources = m_vfsDriver.readResourcesForPrincipalACE(dbc, project, principalId);
3452        if (permissions != null) {
3453            Iterator JavaDoc itRes = resources.iterator();
3454            while (itRes.hasNext()) {
3455                CmsAccessControlEntry ace = readAccessControlEntry(dbc, (CmsResource)itRes.next(), principalId);
3456                if ((ace.getPermissions().getPermissions() & permissions.getPermissions()) != permissions.getPermissions()) {
3457                    // remove if permissions does not match
3458
itRes.remove();
3459                }
3460            }
3461        }
3462        if (includeAttr) {
3463            resources.addAll(m_vfsDriver.readResourcesForPrincipalAttr(dbc, project, principalId));
3464        }
3465        // remove duplicated
3466
Set resNames = new HashSet JavaDoc();
3467        Iterator JavaDoc itRes = resources.iterator();
3468        while (itRes.hasNext()) {
3469            String JavaDoc resName = ((CmsResource)itRes.next()).getRootPath();
3470            if (resNames.contains(resName)) {
3471                itRes.remove();
3472            } else {
3473                resNames.add(resName);
3474            }
3475        }
3476        return resources;
3477    }
3478
3479    /**
3480     * Returns an instance of the common sql manager.<p>
3481     *
3482     * @return an instance of the common sql manager
3483     */

3484    public CmsSqlManager getSqlManager() {
3485
3486        return m_sqlManager;
3487    }
3488
3489    /**
3490     * Returns the value of the given parameter for the given task.<p>
3491     *
3492     * @param dbc the current database context
3493     * @param taskId the Id of the task
3494     * @param parName name of the parameter
3495     *
3496     * @return task parameter value
3497     *
3498     * @throws CmsException if something goes wrong
3499     */

3500    public String JavaDoc getTaskPar(CmsDbContext dbc, int taskId, String JavaDoc parName) throws CmsException {
3501
3502        return m_workflowDriver.readTaskParameter(dbc, taskId, parName);
3503    }
3504
3505    /**
3506     * Returns the template task id for a given taskname.<p>
3507     *
3508     * @param dbc the current database context
3509     * @param taskName the name of the task
3510     *
3511     * @return the id of the task template
3512     *
3513     * @throws CmsException if operation was not successful
3514     */

3515    public int getTaskType(CmsDbContext dbc, String JavaDoc taskName) throws CmsException {
3516
3517        return m_workflowDriver.readTaskType(dbc, taskName);
3518    }
3519
3520    /**
3521     * Returns the user driver.<p>
3522     *
3523     * @return the user driver
3524     */

3525    public I_CmsUserDriver getUserDriver() {
3526
3527        return m_userDriver;
3528    }
3529
3530    /**
3531     * Returns all available users.<p>
3532     *
3533     * @param dbc the current database context
3534     *
3535     * @return a list of all available <code>{@link CmsUser}</code> objects
3536     *
3537     * @throws CmsException if operation was not succesful
3538     */

3539    public List getUsers(CmsDbContext dbc) throws CmsException {
3540
3541        return m_userDriver.readUsers(dbc, CmsUser.USER_TYPE_SYSTEMUSER);
3542    }
3543
3544    /**
3545     * Returns all users from a given type.<p>
3546     *
3547     * @param dbc the current database context
3548     * @param type the type of the users
3549     *
3550     * @return a list of all <code>{@link CmsUser}</code> objects of the given type
3551     *
3552     * @throws CmsException if operation was not succesful
3553     */

3554    public List getUsers(CmsDbContext dbc, int type) throws CmsException {
3555
3556        return m_userDriver.readUsers(dbc, type);
3557    }
3558
3559    /**
3560     * Returns a list of users in a group.<p>
3561     *
3562     * @param dbc the current database context
3563     * @param groupname the name of the group to list users from
3564     *
3565     * @return all <code>{@link CmsUser}</code> objects in the group
3566     *
3567     * @throws CmsException if operation was not succesful
3568     */

3569    public List getUsersOfGroup(CmsDbContext dbc, String JavaDoc groupname) throws CmsException {
3570
3571        return m_userDriver.readUsersOfGroup(dbc, groupname, CmsUser.USER_TYPE_SYSTEMUSER);
3572    }
3573
3574    /**
3575     * Returns the VFS driver.<p>
3576     *
3577     * @return the VFS driver
3578     */

3579    public I_CmsVfsDriver getVfsDriver() {
3580
3581        return m_vfsDriver;
3582    }
3583
3584    /**
3585     * Returns the workflow driver.<p>
3586     *
3587     * @return the workflow driver
3588     */

3589    public I_CmsWorkflowDriver getWorkflowDriver() {
3590
3591        return m_workflowDriver;
3592    }
3593
3594    /**
3595     * Writes a vector of access control entries as new access control entries of a given resource.<p>
3596     *
3597     * Already existing access control entries of this resource are removed before.
3598     * Access is granted, if:<p>
3599     * <ul>
3600     * <li>the current user has control permission on the resource</li>
3601     * </ul>
3602     *
3603     * @param dbc the current database context
3604     * @param resource the resource
3605     * @param acEntries a list of <code>{@link CmsAccessControlEntry}</code> objects
3606     *
3607     * @throws CmsException if something goes wrong
3608     */

3609    public void importAccessControlEntries(CmsDbContext dbc, CmsResource resource, List acEntries) throws CmsException {
3610
3611        m_userDriver.removeAccessControlEntries(dbc, dbc.currentProject(), resource.getResourceId());
3612
3613        Iterator JavaDoc i = acEntries.iterator();
3614        while (i.hasNext()) {
3615            m_userDriver.writeAccessControlEntry(dbc, dbc.currentProject(), (CmsAccessControlEntry)i.next());
3616        }
3617        clearAccessControlListCache();
3618    }
3619
3620    /**
3621     * Creates a new user by import.<p>
3622     *
3623     * @param dbc the current database context
3624     * @param id the id of the user
3625     * @param name the new name for the user
3626     * @param password the new password for the user
3627     * @param description the description for the user
3628     * @param firstname the firstname of the user
3629     * @param lastname the lastname of the user
3630     * @param email the email of the user
3631     * @param address the address of the user
3632     * @param flags the flags for a user (for example <code>{@link I_CmsPrincipal#FLAG_ENABLED}</code>)
3633     * @param type the type of the user
3634     * @param additionalInfos the additional user infos
3635     *
3636     * @return the imported user
3637     *
3638     * @throws CmsException if something goes wrong
3639     */

3640    public CmsUser importUser(
3641        CmsDbContext dbc,
3642        String JavaDoc id,
3643        String JavaDoc name,
3644        String JavaDoc password,
3645        String JavaDoc description,
3646        String JavaDoc firstname,
3647        String JavaDoc lastname,
3648        String JavaDoc email,
3649        String JavaDoc address,
3650        int flags,
3651        int type,
3652        Map JavaDoc additionalInfos) throws CmsException {
3653
3654        // no space before or after the name
3655
name = name.trim();
3656        // check the username
3657
OpenCms.getValidationHandler().checkUserName(name);
3658
3659        CmsUser newUser = m_userDriver.importUser(
3660            dbc,
3661            new CmsUUID(id),
3662            name,
3663            password,
3664            description,
3665            firstname,
3666            lastname,
3667            email,
3668            0,
3669            flags,
3670            additionalInfos,
3671            address,
3672            type,
3673            null);
3674        return newUser;
3675    }
3676
3677    /**
3678     * Initializes the driver and sets up all required modules and connections.<p>
3679     *
3680     * @param configurationManager the configuration manager
3681     * @param configuration the OpenCms configuration
3682     * @param vfsDriver the vfsdriver
3683     * @param userDriver the userdriver
3684     * @param projectDriver the projectdriver
3685     * @param workflowDriver the workflowdriver
3686     * @param backupDriver the backupdriver
3687     *
3688     * @throws CmsException if something goes wrong
3689     * @throws Exception if something goes wrong
3690     */

3691    public void init(
3692        CmsConfigurationManager configurationManager,
3693        Map JavaDoc configuration,
3694        I_CmsVfsDriver vfsDriver,
3695        I_CmsUserDriver userDriver,
3696        I_CmsProjectDriver projectDriver,
3697        I_CmsWorkflowDriver workflowDriver,
3698        I_CmsBackupDriver backupDriver) throws CmsException, Exception JavaDoc {
3699
3700        // initialize the access-module.
3701
if (CmsLog.INIT.isInfoEnabled()) {
3702            CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_DRIVER_MANAGER_START_PHASE4_0));
3703        }
3704
3705        // store the access objects
3706
m_vfsDriver = vfsDriver;
3707        m_userDriver = userDriver;
3708        m_projectDriver = projectDriver;
3709        m_workflowDriver = workflowDriver;
3710        m_backupDriver = backupDriver;
3711
3712        m_configuration = configuration;
3713
3714        ExtendedProperties config;
3715        if (configuration instanceof ExtendedProperties) {
3716            config = (ExtendedProperties)configuration;
3717        } else {
3718            config = new ExtendedProperties();
3719            config.putAll(configuration);
3720        }
3721
3722        CmsSystemConfiguration systemConfiguation = (CmsSystemConfiguration)configurationManager.getConfiguration(CmsSystemConfiguration.class);
3723        CmsCacheSettings settings = systemConfiguation.getCacheSettings();
3724
3725        // initialize the key generator
3726
m_keyGenerator = (I_CmsCacheKey)Class.forName(settings.getCacheKeyGenerator()).newInstance();
3727
3728        // initalize the caches
3729
LRUMap lruMap = new LRUMap(settings.getUserCacheSize());
3730        m_userCache = Collections.synchronizedMap(lruMap);
3731        if (OpenCms.getMemoryMonitor().enabled()) {
3732            OpenCms.getMemoryMonitor().register(this.getClass().getName() + ".m_userCache", lruMap);
3733        }
3734
3735        lruMap = new LRUMap(settings.getGroupCacheSize());
3736        m_groupCache = Collections.synchronizedMap(lruMap);
3737        if (OpenCms.getMemoryMonitor().enabled()) {
3738            OpenCms.getMemoryMonitor().register(this.getClass().getName() + ".m_groupCache", lruMap);
3739        }
3740
3741        lruMap = new LRUMap(settings.getUserGroupsCacheSize());
3742        m_userGroupsCache = Collections.synchronizedMap(lruMap);
3743        if (OpenCms.getMemoryMonitor().enabled()) {
3744            OpenCms.getMemoryMonitor().register(this.getClass().getName() + ".m_userGroupsCache", lruMap);
3745        }
3746
3747        lruMap = new LRUMap(settings.getProjectCacheSize());
3748        m_projectCache = Collections.synchronizedMap(lruMap);
3749        if (OpenCms.getMemoryMonitor().enabled()) {
3750            OpenCms.getMemoryMonitor().register(this.getClass().getName() + ".m_projectCache", lruMap);
3751        }
3752
3753        lruMap = new LRUMap(settings.getResourceCacheSize());
3754        m_resourceCache = Collections.synchronizedMap(lruMap);
3755        if (OpenCms.getMemoryMonitor().enabled()) {
3756            OpenCms.getMemoryMonitor().register(this.getClass().getName() + ".m_resourceCache", lruMap);
3757        }
3758
3759        lruMap = new LRUMap(settings.getResourcelistCacheSize());
3760        m_resourceListCache = Collections.synchronizedMap(lruMap);
3761        if (OpenCms.getMemoryMonitor().enabled()) {
3762            OpenCms.getMemoryMonitor().register(this.getClass().getName() + ".m_resourceListCache", lruMap);
3763        }
3764
3765        lruMap = new LRUMap(settings.getPropertyCacheSize());
3766        m_propertyCache = Collections.synchronizedMap(lruMap);
3767        if (OpenCms.getMemoryMonitor().enabled()) {
3768            OpenCms.getMemoryMonitor().register(this.getClass().getName() + ".m_propertyCache", lruMap);
3769        }
3770
3771        lruMap = new LRUMap(settings.getAclCacheSize());
3772        m_accessControlListCache = Collections.synchronizedMap(lruMap);
3773        if (OpenCms.getMemoryMonitor().enabled()) {
3774            OpenCms.getMemoryMonitor().register(this.getClass().getName() + ".m_accessControlListCache", lruMap);
3775        }
3776
3777        getProjectDriver().fillDefaults(new CmsDbContext());
3778
3779        // initialize the HTML link validator
3780
m_htmlLinkValidator = new CmsXmlDocumentLinkValidator(this);
3781        // initialize the lock list for the "CreateResource" method, use Vector for most efficient synchronization
3782
m_concurrentCreateResourceLocks = new Vector JavaDoc();
3783    }
3784
3785    /**
3786     * Checks if the specified resource is inside the current project.<p>
3787     *
3788     * The project "view" is determined by a set of path prefixes.
3789     * If the resource starts with any one of this prefixes, it is considered to
3790     * be "inside" the project.<p>
3791     *
3792     * @param dbc the current database context
3793     * @param resourcename the specified resource name (full path)
3794     *
3795     * @return <code>true</code>, if the specified resource is inside the current project
3796     */

3797    public boolean isInsideCurrentProject(CmsDbContext dbc, String JavaDoc resourcename) {
3798
3799        List projectResources = null;
3800
3801        try {
3802            projectResources = readProjectResources(dbc, dbc.currentProject());
3803        } catch (CmsException e) {
3804            if (LOG.isErrorEnabled()) {
3805                LOG.error(Messages.get().getBundle().key(
3806                    Messages.LOG_CHECK_RESOURCE_INSIDE_CURRENT_PROJECT_1,
3807                    resourcename), e);
3808            }
3809            return false;
3810        }
3811        return CmsProject.isInsideProject(projectResources, resourcename);
3812    }
3813
3814    /**
3815     *
3816     * Proves if a resource is locked.<p>
3817     *
3818     * @see org.opencms.lock.CmsLockManager#isLocked(org.opencms.db.CmsDriverManager, CmsDbContext, CmsResource)
3819     *
3820     * @param dbc the current database context
3821     * @param resource the resource
3822     *
3823     * @return true, if and only if the resource is currently locked
3824     * @throws CmsException if something goes wrong
3825     */

3826    public boolean isLocked(CmsDbContext dbc, CmsResource resource) throws CmsException {
3827
3828        return m_lockManager.isLocked(this, dbc, resource);
3829    }
3830
3831    /**
3832     * Checks if a project is the tempfile project.<p>
3833     * @param project the project to test
3834     * @return true if the project is the tempfile project
3835     */

3836    public boolean isTempfileProject(CmsProject project) {
3837
3838        return project.getName().equals("tempFileProject");
3839    }
3840
3841    /**
3842     * Determines if the user is a member of the default users group.<p>
3843     *
3844     * All users are granted.
3845     *
3846     * @param dbc the current database context
3847     * @return true, if the users current group is the projectleader-group, else it returns false
3848     * @throws CmsException if operation was not succesful
3849     */

3850    public boolean isUser(CmsDbContext dbc) throws CmsException {
3851
3852        return userInGroup(dbc, dbc.currentUser().getName(), OpenCms.getDefaultUsers().getGroupUsers());
3853    }
3854
3855    /**
3856     * Checks if one of the resources (except the resource itself)
3857     * is a sibling in a "labeled" site folder.<p>
3858     *
3859     * This method is used when creating a new sibling
3860     * (use the newResource parameter & action = 1)
3861     * or deleting/importing a resource (call with action = 2).<p>
3862     *
3863     * @param dbc the current database context
3864     * @param resource the resource
3865     * @param newResource absolute path for a resource sibling which will be created
3866     * @param action the action which has to be performed (1 = create VFS link, 2 all other actions)
3867     * @return true if the flag should be set for the resource, otherwise false
3868     * @throws CmsDataAccessException if something goes wrong
3869     */

3870    public boolean labelResource(CmsDbContext dbc, CmsResource resource, String JavaDoc newResource, int action)
3871    throws CmsDataAccessException {
3872
3873        // get the list of labeled site folders from the runtime property
3874
List labeledSites = OpenCms.getWorkplaceManager().getLabelSiteFolders();
3875
3876        if (labeledSites.size() == 0) {
3877            // no labeled sites defined, just return false
3878
return false;
3879        }
3880
3881        if (action == 1) {
3882            // CASE 1: a new resource is created, check the sites
3883
if (!resource.isLabeled()) {
3884                // source isn't labeled yet, so check!
3885
boolean linkInside = false;
3886                boolean sourceInside = false;
3887                for (int i = 0; i < labeledSites.size(); i++) {
3888                    String JavaDoc curSite = (String JavaDoc)labeledSites.get(i);
3889                    if (newResource.startsWith(curSite)) {
3890                        // the link lies in a labeled site
3891
linkInside = true;
3892                    }
3893                    if (resource.getRootPath().startsWith(curSite)) {
3894                        // the source lies in a labeled site
3895
sourceInside = true;
3896                    }
3897                    if (linkInside && sourceInside) {
3898                        break;
3899                    }
3900                }
3901                // return true when either source or link is in labeled site, otherwise false
3902
return (linkInside != sourceInside);
3903            }
3904            // resource is already labeled
3905
return false;
3906
3907        } else {
3908            // CASE 2: the resource will be deleted or created (import)
3909
// check if at least one of the other siblings resides inside a "labeled site"
3910
// and if at least one of the other siblings resides outside a "labeled site"
3911
boolean isInside = false;
3912            boolean isOutside = false;
3913            // check if one of the other vfs links lies in a labeled site folder
3914
List siblings = m_vfsDriver.readSiblings(dbc, dbc.currentProject(), resource, false);
3915            updateContextDates(dbc, siblings);
3916            Iterator JavaDoc i = siblings.iterator();
3917            while (i.hasNext() && (!isInside || !isOutside)) {
3918                CmsResource currentResource = (CmsResource)i.next();
3919                if (currentResource.equals(resource)) {
3920                    // dont't check the resource itself!
3921
continue;
3922                }
3923                String JavaDoc curPath = currentResource.getRootPath();
3924                boolean curInside = false;
3925                for (int k = 0; k < labeledSites.size(); k++) {
3926                    if (curPath.startsWith((String JavaDoc)labeledSites.get(k))) {
3927                        // the link is in the labeled site
3928
isInside = true;
3929                        curInside = true;
3930                        break;
3931                    }
3932                }
3933                if (!curInside) {
3934                    // the current link was not found in labeled site, so it is outside
3935
isOutside = true;
3936                }
3937            }
3938            // now check the new resource name if present
3939
if (newResource != null) {
3940                boolean curInside = false;
3941                for (int k = 0; k < labeledSites.size(); k++) {
3942                    if (newResource.startsWith((String JavaDoc)labeledSites.get(k))) {
3943                        // the new resource is in the labeled site
3944
isInside = true;
3945                        curInside = true;
3946                        break;
3947                    }
3948                }
3949                if (!curInside) {
3950                    // the new resource was not found in labeled site, so it is outside
3951
isOutside = true;
3952                }
3953            }
3954            return (isInside && isOutside);
3955        }
3956    }
3957
3958    /**
3959     * Returns the user, who had locked the resource.<p>
3960     *
3961     * A user can lock a resource, so he is the only one who can write this
3962     * resource. This methods checks, if a resource was locked.
3963     *
3964     * @param dbc the current database context
3965     * @param resource the resource
3966     *
3967     * @return the user, who had locked the resource
3968     *
3969     * @throws CmsException will be thrown, if the user has not the rights for this resource
3970     */

3971    public CmsUser lockedBy(CmsDbContext dbc, CmsResource resource) throws CmsException {
3972
3973        return readUser(dbc, m_lockManager.getLock(this, dbc, resource).getUserId());
3974    }
3975
3976    /**
3977     * Locks a resource.<p>
3978     *
3979     * The <code>mode</code> parameter controls what kind of lock is used.
3980     * Possible values for this parameter are:
3981     * <ul>
3982     * <li><code>{@link org.opencms.lock.CmsLock#COMMON}</code></li>
3983     * <li><code>{@link org.opencms.lock.CmsLock#TEMPORARY}</code></li>
3984     * </ul><p>
3985     *
3986     * @param dbc the current database context
3987     * @param resource the resource to lock
3988     * @param mode flag indicating the mode for the lock
3989     *
3990     * @throws CmsException if something goes wrong
3991     *
3992     * @see CmsObject#lockResource(String, int)
3993     * @see I_CmsResourceType#lockResource(CmsObject, CmsSecurityManager, CmsResource, int)
3994     */

3995    public void lockResource(CmsDbContext dbc, CmsResource resource, int mode) throws CmsException {
3996
3997        // update the resource cache
3998
clearResourceCache();
3999
4000        // add the resource to the lock dispatcher
4001
m_lockManager.addResource(this, dbc, resource, dbc.currentUser().getId(), dbc.currentProject().getId(), mode);
4002
4003        if ((resource.getState() != CmsResource.STATE_UNCHANGED) && (resource.getState() != CmsResource.STATE_KEEP)) {
4004            // update the project flag of a modified resource as "last modified inside the current project"
4005
m_vfsDriver.writeLastModifiedProjectId(dbc, dbc.currentProject(), dbc.currentProject().getId(), resource);
4006        }
4007
4008        // we must also clear the permission cache
4009
m_securityManager.clearPermissionCache();
4010
4011        // fire resource modification event
4012
OpenCms.fireCmsEvent(new CmsEvent(I_CmsEventListener.EVENT_RESOURCE_MODIFIED, Collections.singletonMap(
4013            "resource",
4014            resource)));
4015    }
4016
4017    /**
4018     * Attempts to authenticate a user into OpenCms with the given password.<p>
4019     *
4020     * @param dbc the current database context
4021     * @param userName the name of the user to be logged in
4022     * @param password the password of the user
4023     * @param remoteAddress the ip address of the request
4024     * @param userType the user type to log in (System user or Web user)
4025     *
4026     * @return the logged in user
4027     *
4028     * @throws CmsAuthentificationException if the login was not successful
4029     * @throws CmsDataAccessException in case of errors accessing the database
4030     * @throws CmsPasswordEncryptionException in case of errors encrypting the users password
4031     */

4032    public CmsUser loginUser(CmsDbContext dbc, String JavaDoc userName, String JavaDoc password, String JavaDoc remoteAddress, int userType)
4033    throws CmsAuthentificationException, CmsDataAccessException, CmsPasswordEncryptionException {
4034
4035        if (CmsStringUtil.isEmptyOrWhitespaceOnly(password)) {
4036            throw new CmsDbEntryNotFoundException(Messages.get().container(Messages.ERR_UNKNOWN_USER_1, userName));
4037        }
4038        CmsUser newUser;
4039        try {
4040            // read the user from the driver to avoid the cache
4041
newUser = m_userDriver.readUser(dbc, userName, password, remoteAddress, userType);
4042        } catch (CmsDbEntryNotFoundException e) {
4043            // this indicates that the username / password combination does not exist
4044
// any other exception indicates database issues, these are not catched here
4045

4046            // check if a user with this name exists at all
4047
boolean userExists = true;
4048            try {
4049                readUser(dbc, userName, userType);
4050            } catch (CmsDataAccessException e2) {
4051                // apparently this user does not exist in the database
4052
userExists = false;
4053            }
4054
4055            if (userExists) {
4056                if (dbc.currentUser().isGuestUser()) {
4057                    // add an invalid login attempt for this user to the storage
4058
OpenCms.getLoginManager().addInvalidLogin(userName, userType, remoteAddress);
4059                }
4060                throw new CmsAuthentificationException(org.opencms.security.Messages.get().container(
4061                    org.opencms.security.Messages.ERR_LOGIN_FAILED_3,
4062                    userName,
4063                    new Integer JavaDoc(userType),
4064                    remoteAddress), e);
4065            } else {
4066                throw new CmsAuthentificationException(org.opencms.security.Messages.get().container(
4067                    org.opencms.security.Messages.ERR_LOGIN_FAILED_NO_USER_3,
4068                    userName,
4069                    new Integer JavaDoc(userType),
4070                    remoteAddress), e);
4071            }
4072        }
4073        // check if the "enabled" flag is set for the user
4074
if (!newUser.isEnabled()) {
4075            // user is disabled, throw a securiy exception
4076
throw new CmsAuthentificationException(org.opencms.security.Messages.get().container(
4077                org.opencms.security.Messages.ERR_LOGIN_FAILED_DISABLED_3,
4078                userName,
4079                new Integer JavaDoc(userType),
4080                remoteAddress));
4081        }
4082
4083        if (dbc.currentUser().isGuestUser()) {
4084            // check if this account is temporarily disabled because of too many invalid login attempts
4085
// this will throw an exception if the test fails
4086
OpenCms.getLoginManager().checkInvalidLogins(userName, userType, remoteAddress);
4087            // test successful, remove all previous invalid login attempts for this user from the storage
4088
OpenCms.getLoginManager().removeInvalidLogins(userName, userType, remoteAddress);
4089        }
4090
4091        if (!m_securityManager.hasRole(dbc, newUser, CmsRole.ADMINISTRATOR)) {
4092            // new user is not Administrator, check if login is currently allowed
4093
OpenCms.getLoginManager().checkLoginAllowed();
4094        }
4095
4096        // set the last login time to the current time
4097
newUser.setLastlogin(System.currentTimeMillis());
4098
4099        // write the changed user object back to the user driver
4100
m_userDriver.writeUser(dbc, newUser);
4101
4102        // update cache
4103
putUserInCache(newUser);
4104
4105        // invalidate all user dependent caches
4106
m_accessControlListCache.clear();
4107        m_groupCache.clear();
4108        m_userGroupsCache.clear();
4109        m_resourceListCache.clear();
4110        m_securityManager.clearPermissionCache();
4111
4112        // return the user object read from the driver
4113
return newUser;
4114    }
4115
4116    /**
4117     * Lookup and read the user or group with the given UUID.<p>
4118     *
4119     * @param dbc the current database context
4120     * @param principalId the UUID of the principal to lookup
4121     *
4122     * @return the principal (group or user) if found, otherwise <code>null</code>
4123     */

4124    public I_CmsPrincipal lookupPrincipal(CmsDbContext dbc, CmsUUID principalId) {
4125
4126        try {
4127            CmsGroup group = m_userDriver.readGroup(dbc, principalId);
4128            if (group != null) {
4129                return group;
4130            }
4131        } catch (Exception JavaDoc e) {
4132            // ignore this exception
4133
}
4134
4135        try {
4136            CmsUser user = readUser(dbc, principalId);
4137            if (user != null) {
4138                return user;
4139            }
4140        } catch (Exception JavaDoc e) {
4141            // ignore this exception
4142
}
4143
4144        return null;
4145    }
4146
4147    /**
4148     * Lookup and read the user or group with the given name.<p>
4149     *
4150     * @param dbc the current database context
4151     * @param principalName the name of the principal to lookup
4152     *
4153     * @return the principal (group or user) if found, otherwise <code>null</code>
4154     */

4155    public I_CmsPrincipal lookupPrincipal(CmsDbContext dbc, String JavaDoc principalName) {
4156
4157        try {
4158            CmsGroup group = m_userDriver.readGroup(dbc, principalName);
4159            if (group != null) {
4160                return group;
4161            }
4162        } catch (Exception JavaDoc e) {
4163            // ignore this exception
4164
}
4165
4166        try {
4167            CmsUser user = readUser(dbc, principalName, CmsUser.USER_TYPE_SYSTEMUSER);
4168            if (user != null) {
4169                return user;
4170            }
4171        } catch (Exception JavaDoc e) {
4172            // ignore this exception
4173
}
4174
4175        return null;
4176    }
4177
4178    /**
4179     * Moves a resource to the "lost and found" folder.<p>
4180     *
4181     * The method can also be used to check get the name of a resource
4182     * in the "lost and found" folder only without actually moving the
4183     * the resource. To do this, the <code>returnNameOnly</code> flag
4184     * must be set to <code>true</code>.<p>
4185     *
4186     * @param dbc the current database context
4187     * @param resourcename the name of the resource to apply this operation to
4188     * @param returnNameOnly if <code>true</code>, only the name of the resource in the "lost and found"
4189     * folder is returned, the move operation is not really performed
4190     *
4191     * @return the name of the resource inside the "lost and found" folder
4192     *
4193     * @throws CmsException if something goes wrong
4194     * @throws CmsIllegalArgumentException if the <code>resourcename</code> argument is null or of length 0
4195     *
4196     * @see CmsObject#moveToLostAndFound(String)
4197     * @see CmsObject#getLostAndFoundName(String)
4198     */

4199    public String JavaDoc moveToLostAndFound(CmsDbContext dbc, String JavaDoc resourcename, boolean returnNameOnly)
4200    throws CmsException, CmsIllegalArgumentException {
4201
4202        CmsRequestContext context = dbc.getRequestContext();
4203        String JavaDoc siteRoot = context.getSiteRoot();
4204        Stack JavaDoc storage = new Stack JavaDoc();
4205        context.setSiteRoot("/");
4206        String JavaDoc destination = CmsDriverManager.LOST_AND_FOUND_FOLDER + resourcename;
4207        // create the require folders if nescessary
4208
String JavaDoc des = destination;
4209        // collect all folders...
4210
try {
4211            while (des.indexOf('/') == 0) {
4212                des = des.substring(0, des.lastIndexOf('/'));
4213                storage.push(des.concat("/"));
4214            }
4215            // ...now create them....
4216
while (storage.size() != 0) {
4217                des = (String JavaDoc)storage.pop();
4218                try {
4219                    readFolder(dbc, des, CmsResourceFilter.IGNORE_EXPIRATION);
4220                } catch (Exception JavaDoc e1) {
4221                    // the folder is not existing, so create it
4222
createResource(dbc, des, CmsResourceTypeFolder.RESOURCE_TYPE_ID, null, Collections.EMPTY_LIST);
4223                }
4224            }
4225            // check if this resource name does already exist
4226
// if so add a psotfix to the name
4227
des = destination;
4228            int postfix = 1;
4229            boolean found = true;
4230            while (found) {
4231                try {
4232                    // try to read the file.....
4233
found = true;
4234                    readResource(dbc, des, CmsResourceFilter.ALL);
4235                    // ....it's there, so add a postfix and try again
4236
String JavaDoc path = destination.substring(0, destination.lastIndexOf('/') + 1);
4237                    String JavaDoc filename = destination.substring(destination.lastIndexOf('/') + 1, destination.length());
4238
4239                    des = path;
4240
4241                    if (filename.lastIndexOf('.') > 0) {
4242                        des += filename.substring(0, filename.lastIndexOf('.'));
4243                    } else {
4244                        des += filename;
4245                    }
4246                    des += "_" + postfix;
4247                    if (filename.lastIndexOf('.') > 0) {
4248                        des += filename.substring(filename.lastIndexOf('.'), filename.length());
4249                    }
4250                    postfix++;
4251                } catch (CmsException e3) {
4252                    // the file does not exist, so we can use this filename
4253
found = false;
4254                }
4255            }
4256            destination = des;
4257
4258            if (!returnNameOnly) {
4259                // move the existing resource to the lost and foud folder
4260
CmsResource resource = readResource(dbc, resourcename, CmsResourceFilter.ALL);
4261                copyResource(dbc, resource, destination, CmsResource.COPY_AS_SIBLING);
4262                deleteResource(dbc, resource, CmsResource.DELETE_PRESERVE_SIBLINGS);
4263            }
4264        } catch (CmsException e2) {
4265            throw e2;
4266        } finally {
4267            // set the site root to the old value again
4268
context.setSiteRoot(siteRoot);
4269        }
4270        return destination;
4271    }
4272
4273    /**
4274     * Gets a new driver instance.<p>
4275     *
4276     * @param configurationManager the configuration manager
4277     * @param driverName the driver name
4278     * @param successiveDrivers the list of successive drivers
4279     *
4280     * @return the driver object
4281     * @throws CmsInitException if the selected driver could not be initialized
4282     */

4283    public Object JavaDoc newDriverInstance(
4284        CmsConfigurationManager configurationManager,
4285        String JavaDoc driverName,
4286        List successiveDrivers) throws CmsInitException {
4287
4288        Class JavaDoc driverClass = null;
4289        I_CmsDriver driver = null;
4290        CmsDbContext dbc = new CmsDbContext();
4291
4292        try {
4293            // try to get the class
4294
driverClass = Class.forName(driverName);
4295            if (CmsLog.INIT.isInfoEnabled()) {
4296                CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_DRIVER_START_1, driverName));
4297            }
4298
4299            // try to create a instance
4300
driver = (I_CmsDriver)driverClass.newInstance();
4301            if (CmsLog.INIT.isInfoEnabled()) {
4302                CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_DRIVER_INITIALIZING_1, driverName));
4303            }
4304
4305            // invoke the init-method of this access class
4306
driver.init(dbc, configurationManager, successiveDrivers, this);
4307            if (CmsLog.INIT.isInfoEnabled()) {
4308                CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_DRIVER_INIT_FINISHED_0));
4309            }
4310
4311        } catch (Throwable JavaDoc t) {
4312            CmsMessageContainer message = Messages.get().container(Messages.ERR_ERROR_INITIALIZING_DRIVER_1, driverName);
4313            if (LOG.isErrorEnabled()) {
4314                LOG.error(message.key(), t);
4315            }
4316            throw new CmsInitException(message, t);
4317        }
4318
4319        return driver;
4320    }
4321
4322    /**
4323     * Method to create a new instance of a driver.<p>
4324     *
4325     * @param configuration the configurations from the propertyfile
4326     * @param driverName the class name of the driver
4327     * @param driverPoolUrl the pool url for the driver
4328     * @return an initialized instance of the driver
4329     * @throws CmsException if something goes wrong
4330     */

4331    public Object JavaDoc newDriverInstance(ExtendedProperties configuration, String JavaDoc driverName, String JavaDoc driverPoolUrl)
4332    throws CmsException {
4333
4334        Class JavaDoc[] initParamClasses = {ExtendedProperties.class, String JavaDoc.class, CmsDriverManager.class};
4335        Object JavaDoc[] initParams = {configuration, driverPoolUrl, this};
4336
4337        Class JavaDoc driverClass = null;
4338        Object JavaDoc driver = null;
4339
4340        try {
4341            // try to get the class
4342
driverClass = Class.forName(driverName);
4343            if (CmsLog.INIT.isInfoEnabled()) {
4344                CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_DRIVER_START_1, driverName));
4345            }
4346
4347            // try to create a instance
4348
driver = driverClass.newInstance();
4349            if (CmsLog.INIT.isInfoEnabled()) {
4350                CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_DRIVER_INITIALIZING_1, driverName));
4351            }
4352
4353            // invoke the init-method of this access class
4354
driver.getClass().getMethod("init", initParamClasses).invoke(driver, initParams);
4355            if (CmsLog.INIT.isInfoEnabled()) {
4356                CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_DRIVER_INIT_FINISHED_1, driverPoolUrl));
4357            }
4358
4359        } catch (Exception JavaDoc exc) {
4360
4361            CmsMessageContainer message = Messages.get().container(Messages.ERR_INIT_DRIVER_MANAGER_1);
4362            if (LOG.isFatalEnabled()) {
4363                LOG.fatal(message.key(), exc);
4364            }
4365            throw new CmsDbException(message, exc);
4366
4367        }
4368
4369        return driver;
4370    }
4371
4372    /**
4373     * Method to create a new instance of a pool.<p>
4374     *
4375     * @param configuration the configurations from the propertyfile
4376     * @param poolName the configuration name of the pool
4377     *
4378     * @throws CmsInitException if the pools could not be initialized
4379     */

4380    public void newPoolInstance(Map JavaDoc configuration, String JavaDoc poolName) throws CmsInitException {
4381
4382        PoolingDriver driver;
4383
4384        try {
4385            driver = CmsDbPool.createDriverManagerConnectionPool(configuration, poolName);
4386        } catch (Exception JavaDoc e) {
4387
4388            CmsMessageContainer message = Messages.get().container(Messages.ERR_INIT_CONN_POOL_1, poolName);
4389            if (LOG.isErrorEnabled()) {
4390                LOG.error(message.key(), e);
4391            }
4392            throw new CmsInitException(message, e);
4393        }
4394
4395        m_connectionPools.add(driver);
4396    }
4397
4398    /**
4399     * Publishes the resources of a specified publish list.<p>
4400     *
4401     * @param cms the current request context
4402     * @param dbc the current database context
4403     * @param publishList a publish list
4404     * @param report an instance of <code>{@link I_CmsReport}</code> to print messages
4405     *
4406     * @throws CmsException if something goes wrong
4407     * @see #fillPublishList(CmsDbContext, CmsPublishList)
4408     */

4409    public void publishProject(CmsObject cms, CmsDbContext dbc, CmsPublishList publishList, I_CmsReport report)
4410    throws CmsException {
4411
4412        int publishProjectId = dbc.currentProject().getId();
4413        boolean temporaryProject = (dbc.currentProject().getType() == CmsProject.PROJECT_TYPE_TEMPORARY);
4414        boolean backupEnabled = OpenCms.getSystemInfo().isVersionHistoryEnabled();
4415        boolean directPublish = publishList.isDirectPublish();
4416        int backupTagId = 0;
4417
4418        if (backupEnabled) {
4419            backupTagId = getBackupTagId(dbc);
4420        } else {
4421            backupTagId = 0;
4422        }
4423
4424        int maxVersions = OpenCms.getSystemInfo().getVersionHistoryMaxCount();
4425
4426        // if we direct publish a file, check if all parent folders are already published
4427
if (directPublish) {
4428            // first get the names of all parent folders
4429
Iterator JavaDoc it = publishList.getDirectPublishResources().iterator();
4430            List parentFolderNames = new ArrayList JavaDoc();
4431            while (it.hasNext()) {
4432                CmsResource res = (CmsResource)it.next();
4433                String JavaDoc parentFolderName = CmsResource.getParentFolder(res.getRootPath());
4434                if (parentFolderName != null) {
4435                    parentFolderNames.add(parentFolderName);
4436                }
4437            }
4438            // remove duplicate parent folder names
4439
parentFolderNames = CmsFileUtil.removeRedundancies(parentFolderNames);
4440            String JavaDoc parentFolderName = null;
4441            try {
4442                // now check all folders if they exist in the online project
4443
Iterator JavaDoc parentIt = parentFolderNames.iterator();
4444                while (parentIt.hasNext()) {
4445                    parentFolderName = (String JavaDoc)parentIt.next();
4446                    getVfsDriver().readFolder(dbc, CmsProject.ONLINE_PROJECT_ID, parentFolderName);
4447                }
4448            } catch (CmsException e) {
4449                report.println(
4450                    Messages.get().container(Messages.RPT_PARENT_FOLDER_NOT_PUBLISHED_1, parentFolderName),
4451                    I_CmsReport.FORMAT_ERROR);
4452                return;
4453            }
4454        }
4455
4456        synchronized (this) {
4457            // only one publish cycle is allowed at a time
4458
try {
4459
4460                // fire an event that a project is to be published
4461
Map JavaDoc eventData = new HashMap JavaDoc();
4462                eventData.put(I_CmsEventListener.KEY_REPORT, report);
4463                eventData.put(I_CmsEventListener.KEY_PUBLISHLIST, publishList);
4464                eventData.put(I_CmsEventListener.KEY_PROJECTID, new Integer JavaDoc(publishProjectId));
4465                eventData.put(I_CmsEventListener.KEY_DBCONTEXT, dbc);
4466                CmsEvent beforePublishEvent = new CmsEvent(I_CmsEventListener.EVENT_BEFORE_PUBLISH_PROJECT, eventData);
4467                OpenCms.fireCmsEvent(beforePublishEvent);
4468
4469                // clear the cache
4470
clearcache(false);
4471
4472                m_projectDriver.publishProject(
4473                    dbc,
4474                    report,
4475                    readProject(dbc, CmsProject.ONLINE_PROJECT_ID),
4476                    publishList,
4477                    OpenCms.getSystemInfo().isVersionHistoryEnabled(),
4478                    backupTagId,
4479                    maxVersions);
4480
4481                // iterate the initialized module action instances
4482
Iterator JavaDoc i = OpenCms.getModuleManager().getModuleNames().iterator();
4483                while (i.hasNext()) {
4484                    CmsModule module = OpenCms.getModuleManager().getModule(i.next().toString());
4485                    if (module != null && module.getActionInstance() != null) {
4486                        module.getActionInstance().publishProject(cms, publishList, backupTagId, report);
4487                    }
4488                }
4489
4490                // the project was stored in the backuptables for history
4491
// it will be deleted if the project_flag is PROJECT_TYPE_TEMPORARY
4492
if ((temporaryProject) && (!directPublish)) {
4493                    try {
4494                        m_projectDriver.deleteProject(dbc, dbc.currentProject());
4495                    } catch (CmsException e) {
4496                        LOG.error(Messages.get().getBundle().key(
4497                            Messages.LOG_DELETE_TEMP_PROJECT_FAILED_1,
4498                            new Integer JavaDoc(publishProjectId)));
4499                    }
4500                    // if project was temporary set context to online project
4501
cms.getRequestContext().setCurrentProject(readProject(dbc, CmsProject.ONLINE_PROJECT_ID));
4502                }
4503            } finally {
4504                // clear the cache again
4505
clearcache(false);
4506
4507                // fire an event that a project has been published
4508
Map JavaDoc eventData = new HashMap JavaDoc();
4509                eventData.put(I_CmsEventListener.KEY_REPORT, report);
4510                eventData.put(I_CmsEventListener.KEY_PUBLISHID, publishList.getPublishHistoryId().toString());
4511                eventData.put(I_CmsEventListener.KEY_PROJECTID, new Integer JavaDoc(publishProjectId));
4512                eventData.put(I_CmsEventListener.KEY_DBCONTEXT, dbc);
4513                CmsEvent afterPublishEvent = new CmsEvent(I_CmsEventListener.EVENT_PUBLISH_PROJECT, eventData);
4514                OpenCms.fireCmsEvent(afterPublishEvent);
4515            }
4516        }
4517    }
4518
4519    /**
4520     * Reactivates a task.<p>
4521     *
4522     * Setting its state to <code>{@link CmsTaskService#TASK_STATE_STARTED}</code> and
4523     * the percentage to <b>zero</b>.<p>
4524     *
4525     * @param dbc the current database context
4526     * @param taskId the id of the task to reactivate
4527     *
4528     * @throws CmsException if something goes wrong
4529     */

4530    public void reactivateTask(CmsDbContext dbc, int taskId) throws CmsException {
4531
4532        CmsTask task = m_workflowDriver.readTask(dbc, taskId);
4533        task.setState(CmsTaskService.TASK_STATE_STARTED);
4534        task.setPercentage(0);
4535        task = m_workflowDriver.writeTask(dbc, task);
4536        m_workflowDriver.writeSystemTaskLog(dbc, taskId, "Task was reactivated from "
4537            + dbc.currentUser().getFirstname()
4538            + " "
4539            + dbc.currentUser().getLastname()
4540            + '.');
4541    }
4542
4543    /**
4544     * Reads an access control entry from the cms.<p>
4545     *
4546     * The access control entries of a resource are readable by everyone.
4547     *
4548     * @param dbc the current database context
4549     * @param resource the resource
4550     * @param principal the id of a group or a user any other entity
4551     * @return an access control entry that defines the permissions of the entity for the given resource
4552     * @throws CmsException if something goes wrong
4553     */

4554    public CmsAccessControlEntry readAccessControlEntry(CmsDbContext dbc, CmsResource resource, CmsUUID principal)
4555    throws CmsException {
4556
4557        return m_userDriver.readAccessControlEntry(dbc, dbc.currentProject(), resource.getResourceId(), principal);
4558    }
4559
4560    /**
4561     * Reads the agent of a task.<p>
4562     *
4563     * @param dbc the current database context
4564     * @param task the task to read the agent from
4565     *
4566     * @return the owner of a task
4567     *
4568     * @throws CmsException if something goes wrong
4569     */

4570    public CmsUser readAgent(CmsDbContext dbc, CmsTask task) throws CmsException {
4571
4572        return readUser(dbc, task.getAgentUser());
4573    }
4574
4575    /**
4576     * Reads all file headers of a file.<br>
4577     *
4578     * This method returns a list with the history of all file headers, i.e.
4579     * the file headers of a file, independent of the project they were attached to.<br>
4580     *
4581     * The reading excludes the file content.<p>
4582     *
4583     * @param dbc the current database context
4584     * @param resource the resource to read the backup resources for
4585     *
4586     * @return a list of file headers, as <code>{@link CmsBackupResource}</code> objects, read from the Cms
4587     *
4588     * @throws CmsException if something goes wrong
4589     */

4590    public List readAllBackupFileHeaders(CmsDbContext dbc, CmsResource resource) throws CmsException {
4591
4592        // read the backup resources
4593
List backupFileHeaders = m_backupDriver.readBackupFileHeaders(
4594            dbc,
4595            resource.getRootPath(),
4596            resource.getResourceId());
4597
4598        if (backupFileHeaders != null && backupFileHeaders.size() > 1) {
4599            // change the order of the list
4600
Collections.reverse(backupFileHeaders);
4601        }
4602
4603        return backupFileHeaders;
4604    }
4605
4606    /**
4607     * Reads all property definitions for the given mapping type.<p>
4608     *
4609     * @param dbc the current database context
4610     *
4611     * @return a list with the <code>{@link CmsPropertyDefinition}</code> objects (may be empty)
4612     *
4613     * @throws CmsException if something goes wrong
4614     */

4615    public List readAllPropertyDefinitions(CmsDbContext dbc) throws CmsException {
4616
4617        List returnValue = m_vfsDriver.readPropertyDefinitions(dbc, dbc.currentProject().getId());
4618        Collections.sort(returnValue);
4619        return returnValue;
4620    }
4621
4622    /**
4623     * Returns a file from the history.<br>
4624     *
4625     * The reading includes the file content.<p>
4626     *
4627     * @param dbc the current database context
4628     * @param tagId the desired tag ID of the file
4629     * @param resource the resource to read the historic version of
4630     * @return the file read
4631     * @throws CmsException if operation was not succesful
4632     */

4633    public CmsBackupResource readBackupFile(CmsDbContext dbc, int tagId, CmsResource resource) throws CmsException {
4634
4635        return m_backupDriver.readBackupFile(dbc, tagId, resource.getRootPath());
4636    }
4637
4638    /**
4639     * Returns a backup project.<p>
4640     *
4641     * @param dbc the current database context
4642     * @param tagId the tagId of the project
4643     *
4644     * @return the requested backup project
4645     *
4646     * @throws CmsException if something goes wrong
4647     */

4648    public CmsBackupProject readBackupProject(CmsDbContext dbc, int tagId) throws CmsException {
4649
4650        return m_backupDriver.readBackupProject(dbc, tagId);
4651    }
4652
4653    /**
4654     * Reads the list of <code>{@link CmsProperty}</code> objects that belong the the given backup resource.<p>
4655     *
4656     * @param dbc the current database context
4657     * @param resource the backup resource to read the properties from
4658     *
4659     * @return the list of <code>{@link CmsProperty}</code> objects that belong the the given backup resource
4660     *
4661     * @throws CmsException if something goes wrong
4662     */

4663    public List readBackupPropertyObjects(CmsDbContext dbc, CmsBackupResource resource) throws CmsException {
4664
4665        return m_backupDriver.readBackupProperties(dbc, resource);
4666    }
4667
4668    /**
4669     * Reads all resources that are inside and changed in a specified project.<p>
4670     *
4671     * @param dbc the current database context
4672     * @param projectId the ID of the project
4673     * @param resourceType &lt;0 if files and folders should be read, 0 if only folders should be read, &gt;0 if only files should be read
4674     * @return a List with all resources inside the specified project
4675     * @throws CmsException if somethong goes wrong
4676     */

4677    public List readChangedResourcesInsideProject(CmsDbContext dbc, int projectId, int resourceType)
4678    throws CmsException {
4679
4680        List projectResources = readProjectResources(dbc, readProject(dbc, projectId));
4681        List result = new ArrayList JavaDoc();
4682        String JavaDoc currentProjectResource = null;
4683        List resources = new ArrayList JavaDoc();
4684        CmsResource currentResource = null;
4685        CmsLock currentLock = null;
4686
4687        for (int i = 0; i < projectResources.size(); i++) {
4688            // read all resources that are inside the project by visiting each project resource
4689
currentProjectResource = (String JavaDoc)projectResources.get(i);
4690
4691            try {
4692                currentResource = readResource(dbc, currentProjectResource, CmsResourceFilter.ALL);
4693
4694                if (currentResource.isFolder()) {
4695                    resources.addAll(readResources(dbc, currentResource, CmsResourceFilter.ALL, true));
4696                } else {
4697                    resources.add(currentResource);
4698                }
4699            } catch (CmsException e) {
4700                // the project resource probably doesnt exist (anymore)...
4701
if (!(e instanceof CmsVfsResourceNotFoundException)) {
4702                    throw e;
4703                }
4704            }
4705        }
4706
4707        for (int j = 0; j < resources.size(); j++) {
4708            currentResource = (CmsResource)resources.get(j);
4709            currentLock = getLock(dbc, currentResource);
4710
4711            if (currentResource.getState() != CmsResource.STATE_UNCHANGED) {
4712                if ((currentLock.isNullLock() && currentResource.getProjectLastModified() == projectId)
4713                    || (currentLock.getUserId().equals(dbc.currentUser().getId()) && currentLock.getProjectId() == projectId)) {
4714                    // add only resources that are
4715
// - inside the project,
4716
// - changed in the project,
4717
// - either unlocked, or locked for the current user in the project
4718
if ((currentResource.isFolder() && resourceType <= 0)
4719                        || (currentResource.isFile() && resourceType != 0)) {
4720                        result.add(currentResource);
4721                    }
4722                }
4723            }
4724        }
4725
4726        resources.clear();
4727        resources = null;
4728
4729        // TODO the calculated resource lists should be cached
4730

4731        return result;
4732    }
4733
4734    /**
4735     * Returns the child resources of a resource, that is the resources
4736     * contained in a folder.<p>
4737     *
4738     * With the parameters <code>getFolders</code> and <code>getFiles</code>
4739     * you can control what type of resources you want in the result list:
4740     * files, folders, or both.<p>
4741     *
4742     * This method is mainly used by the workplace explorer.<p>
4743     *
4744     * @param dbc the current database context
4745     * @param resource the resource to return the child resources for
4746     * @param filter the resource filter to use
4747     * @param getFolders if true the child folders are included in the result
4748     * @param getFiles if true the child files are included in the result
4749     *
4750     * @return a list of all child resources
4751     *
4752     * @throws CmsException if something goes wrong
4753     */

4754    public List readChildResources(
4755        CmsDbContext dbc,
4756        CmsResource resource,
4757        CmsResourceFilter filter,
4758        boolean getFolders,
4759        boolean getFiles) throws CmsException {
4760
4761        // try to get the sub resources from the cache
4762
String JavaDoc cacheKey = getCacheKey(new String JavaDoc[] {
4763            dbc.currentUser().getName(),
4764            getFolders ? (getFiles ? CmsCacheKey.CACHE_KEY_SUBALL : CmsCacheKey.CACHE_KEY_SUBFOLDERS)
4765            : CmsCacheKey.CACHE_KEY_SUBFILES,
4766            filter.getCacheId(),
4767            resource.getRootPath()}, dbc.currentProject());
4768
4769        List subResources = (List)m_resourceListCache.get(cacheKey);
4770
4771        if (subResources != null && subResources.size() > 0) {
4772            // the parent folder is not deleted, and the sub resources were cached, no further operations required
4773
// we must however still apply the result filter and update the context dates
4774
return updateContextDates(dbc, subResources, filter);
4775        }
4776
4777        // read the result form the database
4778
subResources = m_vfsDriver.readChildResources(dbc, dbc.currentProject(), resource, getFolders, getFiles);
4779
4780        for (int i = 0; i < subResources.size(); i++) {
4781            CmsResource currentResource = (CmsResource)subResources.get(i);
4782            int perms = m_securityManager.hasPermissions(
4783                dbc,
4784                currentResource,
4785                CmsPermissionSet.ACCESS_READ,
4786                true,
4787                filter);
4788            if (CmsSecurityManager.PERM_DENIED == perms) {
4789                subResources.remove(i--);
4790            }
4791        }
4792
4793        // cache the sub resources
4794
m_resourceListCache.put(cacheKey, subResources);
4795
4796        // apply the result filter and update the context dates
4797
return updateContextDates(dbc, subResources, filter);
4798    }
4799
4800    /**
4801     * Reads a file resource (including it's binary content) from the VFS,
4802     * using the specified resource filter.<p>
4803     *
4804     * In case you do not need the file content,
4805     * use <code>{@link #readResource(CmsDbContext, String, CmsResourceFilter)}</code> instead.<p>
4806     *
4807     * The specified filter controls what kind of resources should be "found"
4808     * during the read operation. This will depend on the application. For example,
4809     * using <code>{@link CmsResourceFilter#DEFAULT}</code> will only return currently
4810     * "valid" resources, while using <code>{@link CmsResourceFilter#IGNORE_EXPIRATION}</code>
4811     * will ignore the date release / date expired information of the resource.<p>
4812     *
4813     * @param dbc the current database context
4814     * @param resource the base file resource (without content)
4815     * @param filter the filter object
4816     * @return the file read from the VFS
4817     * @throws CmsException if operation was not succesful
4818     */

4819    public CmsFile readFile(CmsDbContext dbc, CmsResource resource, CmsResourceFilter filter) throws CmsException {
4820
4821        if (resource.isFolder()) {
4822            throw new CmsVfsResourceNotFoundException(Messages.get().container(
4823                Messages.ERR_ACCESS_FOLDER_AS_FILE_1,
4824                dbc.removeSiteRoot(resource.getRootPath())));
4825        }
4826
4827        CmsFile file = m_vfsDriver.readFile(
4828            dbc,
4829            dbc.currentProject().getId(),
4830            filter.includeDeleted(),
4831            resource.getStructureId());
4832
4833        return file;
4834    }
4835
4836    /**
4837     * Reads a folder from the VFS,
4838     * using the specified resource filter.<p>
4839     *
4840     * @param dbc the current database context
4841     * @param resourcename the name of the folder to read (full path)
4842     * @param filter the resource filter to use while reading
4843     *
4844     * @return the folder that was read
4845     *
4846     * @throws CmsDataAccessException if something goes wrong
4847     *
4848     * @see #readResource(CmsDbContext, String, CmsResourceFilter)
4849     * @see CmsObject#readFolder(String)
4850     * @see CmsObject#readFolder(String, CmsResourceFilter)
4851     */

4852    public CmsFolder readFolder(CmsDbContext dbc, String JavaDoc resourcename, CmsResourceFilter filter)
4853    throws CmsDataAccessException {
4854
4855        CmsResource resource = readResource(dbc, resourcename, filter);
4856
4857        return convertResourceToFolder(resource);
4858    }
4859
4860    /**
4861     * Reads all given tasks from a user for a project.<p>
4862     *
4863     * The <code>tasktype</code> parameter will filter the tasks.
4864     * The possible values for this parameter are:<br>
4865     * <ul>
4866     * <il><code>{@link CmsTaskService#TASKS_ALL}</code>: Reads all tasks</il>
4867     * <il><code>{@link CmsTaskService#TASKS_OPEN}</code>: Reads all open tasks</il>
4868     * <il><code>{@link CmsTaskService#TASKS_DONE}</code>: Reads all finished tasks</il>
4869     * <il><code>{@link CmsTaskService#TASKS_NEW}</code>: Reads all new tasks</il>
4870     * </ul>
4871     *
4872     * @param dbc the current database context
4873     * @param projectId the id of the project in which the tasks are defined
4874     * @param ownerName the owner of the task
4875     * @param taskType the type of task you want to read
4876     * @param orderBy specifies how to order the tasks
4877     * @param sort sorting of the tasks
4878     *
4879     * @return a list of given <code>{@link CmsTask}</code> objects for a user for a project
4880     *
4881     * @throws CmsException if operation was not successful
4882     */

4883    public List readGivenTasks(
4884        CmsDbContext dbc,
4885        int projectId,
4886        String JavaDoc ownerName,
4887        int taskType,
4888        String JavaDoc orderBy,
4889        String JavaDoc sort) throws CmsException {
4890
4891        CmsProject project = null;
4892
4893        CmsUser owner = null;
4894
4895        if (ownerName != null) {
4896            owner = readUser(dbc, ownerName);
4897        }
4898
4899        if (projectId != CmsDbUtil.UNKNOWN_ID) {
4900            project = readProject(dbc, projectId);
4901        }
4902
4903        return m_workflowDriver.readTasks(dbc, project, null, owner, null, taskType, orderBy, sort);
4904    }
4905
4906    /**
4907     * Reads the group of a project.<p>
4908     *
4909     * @param dbc the current database context
4910     * @param project the project to read from
4911     *
4912     * @return the group of a resource
4913     */

4914    public CmsGroup readGroup(CmsDbContext dbc, CmsProject project) {
4915
4916        // try to read group form cache
4917
CmsGroup group = (CmsGroup)m_groupCache.get(new CacheId(project.getGroupId()));
4918        if (group == null) {
4919            try {
4920                group = m_userDriver.readGroup(dbc, project.getGroupId());
4921            } catch (CmsDataAccessException exc) {
4922                return new CmsGroup(
4923                    CmsUUID.getNullUUID(),
4924                    CmsUUID.getNullUUID(),
4925                    project.getGroupId() + "",
4926                    "deleted group",
4927                    0);
4928            }
4929            m_groupCache.put(new CacheId(group), group);
4930        }
4931
4932        return group;
4933    }
4934
4935    /**
4936     * Reads the group (role) of a task.<p>
4937     *
4938     * @param dbc the current database context
4939     * @param task the task to read from
4940     *
4941     * @return the group of a resource
4942     *
4943     * @throws CmsException if operation was not succesful
4944     */

4945    public CmsGroup readGroup(CmsDbContext dbc, CmsTask task) throws CmsException {
4946
4947        return m_userDriver.readGroup(dbc, task.getRole());
4948    }
4949
4950    /**
4951     * Reads a group based on its id.<p>
4952     *
4953     * @param dbc the current database context
4954     * @param groupId the id of the group that is to be read
4955     *
4956     * @return the requested group
4957     *
4958     * @throws CmsException if operation was not succesful
4959     */

4960    public CmsGroup readGroup(CmsDbContext dbc, CmsUUID groupId) throws CmsException {
4961
4962        return m_userDriver.readGroup(dbc, groupId);
4963    }
4964
4965    /**
4966     * Reads a group based on its name.<p>
4967     *
4968     * @param dbc the current database context
4969     * @param groupname the name of the group that is to be read
4970     *
4971     * @return the requested group
4972     *
4973     * @throws CmsDataAccessException if operation was not succesful
4974     */

4975    public CmsGroup readGroup(CmsDbContext dbc, String JavaDoc groupname) throws CmsDataAccessException {
4976
4977        CmsGroup group = null;
4978        // try to read group form cache
4979
group = (CmsGroup)m_groupCache.get(new CacheId(groupname));
4980        if (group == null) {
4981            group = m_userDriver.readGroup(dbc, groupname);
4982            m_groupCache.put(new CacheId(group), group);
4983        }
4984        return group;
4985    }
4986
4987    /**
4988     * Reads the manager group of a project.<p>
4989     *
4990     * @param dbc the current database context
4991     * @param project the project to read from
4992     *
4993     * @return the group of a resource
4994     */

4995    public CmsGroup readManagerGroup(CmsDbContext dbc, CmsProject project) {
4996
4997        CmsGroup group = null;
4998        // try to read group form cache
4999
group = (CmsGroup)m_groupCache.get(new CacheId(project.getManagerGroupId()));
5000        if (group == null) {
5001            try {
5002                group = m_userDriver.readGroup(dbc, project.getManagerGroupId());
5003            } catch (CmsDataAccessException exc) {
5004                // the group does not exist any more - return a dummy-group
5005
return new CmsGroup(
5006                    CmsUUID.getNullUUID(),
5007                    CmsUUID.getNullUUID(),
5008                    project.getManagerGroupId() + "",
5009                    "deleted group",
5010                    0);
5011            }
5012            m_groupCache.put(new CacheId(group), group);
5013        }
5014        return group;
5015    }
5016
5017    /**
5018     * Reads the original agent of a task.<p>
5019     *
5020     * @param dbc the current database context
5021     * @param task the task to read the original agent from
5022     *
5023     * @return the owner of a task
5024     *
5025     * @throws CmsException if something goes wrong
5026     */

5027    public CmsUser readOriginalAgent(CmsDbContext dbc, CmsTask task) throws CmsException {
5028
5029        return readUser(dbc, task.getOriginalUser());
5030    }
5031
5032    /**
5033     * Reads the owner of a project.<p>
5034     *
5035     * @param dbc the current database context
5036     * @param project the project to get the owner from
5037     *
5038     * @return the owner of a resource
5039     * @throws CmsException if something goes wrong
5040     */

5041    public CmsUser readOwner(CmsDbContext dbc, CmsProject project) throws CmsException {
5042
5043        return readUser(dbc, project.getOwnerId());
5044    }
5045
5046    /**
5047     * Reads the owner (initiator) of a task.<p>
5048     *
5049     * @param dbc the current database context
5050     * @param task the task to read the owner from
5051     *
5052     * @return the owner of a task
5053     *
5054     * @throws CmsException if something goes wrong
5055     */

5056    public CmsUser readOwner(CmsDbContext dbc, CmsTask task) throws CmsException {
5057
5058        return readUser(dbc, task.getInitiatorUser());
5059    }
5060
5061    /**
5062     * Reads the owner of a tasklog.<p>
5063     *
5064     * @param dbc the current database context
5065     * @param log the tasklog
5066     *
5067     * @return the owner of a resource
5068     *
5069     * @throws CmsException if something goes wrong
5070     */

5071    public CmsUser readOwner(CmsDbContext dbc, CmsTaskLog log) throws CmsException {
5072
5073        return readUser(dbc, log.getUser());
5074    }
5075
5076    /**
5077     * Builds a list of resources for a given path.<p>
5078     *
5079     * @param dbc the current database context
5080     * @param projectId the project to lookup the resource
5081     * @param path the requested path
5082     * @param filter a filter object (only "includeDeleted" information is used!)
5083     *
5084     * @return list of <code>{@link CmsResource}</code>s
5085     *
5086     * @throws CmsException if something goes wrong
5087     */

5088    public List readPath(CmsDbContext dbc, int projectId, String JavaDoc path, CmsResourceFilter filter) throws CmsException {
5089
5090        // # of folders in the path
5091
int folderCount = 0;
5092        // true if the path doesn't end with a folder
5093
boolean lastResourceIsFile = false;
5094        // holds the CmsResource instances in the path
5095
List pathList = null;
5096        // the current path token
5097
String JavaDoc currentResourceName = null;
5098        // the current resource
5099
CmsResource currentResource = null;
5100        // this is a comment. i love comments!
5101
int i = 0, count = 0;
5102        // key to cache the resources
5103
String JavaDoc cacheKey = null;
5104
5105        // splits the path into folder and filename tokens
5106
List tokens = CmsStringUtil.splitAsList(path, '/');
5107
5108        // the root folder is no token in the path but a resource which has to be added to the path
5109
count = tokens.size() + 1;
5110        pathList = new ArrayList JavaDoc(count);
5111
5112        folderCount = count;
5113        if (!path.endsWith("/")) {
5114            folderCount--;
5115            lastResourceIsFile = true;
5116        }
5117
5118        // read the root folder, coz it's ID is required to read any sub-resources
5119
currentResourceName = "/";
5120        StringBuffer JavaDoc currentPath = new StringBuffer JavaDoc(64);
5121        currentPath.append('/');
5122
5123        String JavaDoc cp = currentPath.toString();
5124        cacheKey = getCacheKey(null, false, projectId, cp);
5125        currentResource = (CmsResource)m_resourceCache.get(cacheKey);
5126        if (currentResource == null) {
5127            currentResource = m_vfsDriver.readFolder(dbc, projectId, cp);
5128            m_resourceCache.put(cacheKey, currentResource);
5129        }
5130
5131        pathList.add(0, currentResource);
5132
5133        if (count == 1) {
5134            // the root folder was requested- no further operations required
5135
return pathList;
5136        }
5137
5138        Iterator JavaDoc it = tokens.iterator();
5139        currentResourceName = (String JavaDoc)it.next();
5140
5141        // read the folder resources in the path /a/b/c/
5142
for (i = 1; i < folderCount; i++) {
5143            currentPath.append(currentResourceName);
5144            currentPath.append('/');
5145            // read the folder
5146
cp = currentPath.toString();
5147            cacheKey = getCacheKey(null, false, projectId, cp);
5148            currentResource = (CmsResource)m_resourceCache.get(cacheKey);
5149            if (currentResource == null) {
5150                currentResource = m_vfsDriver.readFolder(dbc, projectId, cp);
5151                m_resourceCache.put(cacheKey, currentResource);
5152            }
5153
5154            pathList.add(i, currentResource);
5155
5156            if (i < folderCount - 1) {
5157                currentResourceName = (String JavaDoc)it.next();
5158            }
5159        }
5160
5161        // read the (optional) last file resource in the path /x.html
5162
if (lastResourceIsFile) {
5163            if (it.hasNext()) {
5164                // this will only be false if a resource in the
5165
// top level root folder (e.g. "/index.html") was requested
5166
currentResourceName = (String JavaDoc)it.next();
5167            }
5168            currentPath.append(currentResourceName);
5169
5170            // read the file
5171
cp = currentPath.toString();
5172            cacheKey = getCacheKey(null, false, projectId, cp);
5173            currentResource = (CmsResource)m_resourceCache.get(cacheKey);
5174            if (currentResource == null) {
5175                currentResource = m_vfsDriver.readResource(dbc, projectId, cp, filter.includeDeleted());
5176                m_resourceCache.put(cacheKey, currentResource);
5177            }
5178
5179            pathList.add(i, currentResource);
5180        }
5181
5182        return pathList;
5183    }
5184
5185    /**
5186     * Reads a project of a given task.<p>
5187     *
5188     * @param dbc the current database context
5189     * @param task the task to read the project of
5190     *
5191     * @return the project of the task
5192     *
5193     * @throws CmsException if something goes wrong
5194     */

5195    public CmsProject readProject(CmsDbContext dbc, CmsTask task) throws CmsException {
5196
5197        // read the parent of the task, until it has no parents.
5198
while (task.getParent() != 0) {
5199            task = readTask(dbc, task.getParent());
5200        }
5201        return m_workflowDriver.readProject(dbc, task);
5202    }
5203
5204    /**
5205     * Reads a project given the projects id.<p>
5206     *
5207     * @param dbc the current database context
5208     * @param id the id of the project
5209     *
5210     * @return the project read
5211     *
5212     * @throws CmsDataAccessException if something goes wrong
5213     */

5214    public CmsProject readProject(CmsDbContext dbc, int id) throws CmsDataAccessException {
5215
5216        CmsProject project = null;
5217        project = (CmsProject)m_projectCache.get(new Integer JavaDoc(id));
5218        if (project == null) {
5219            project = m_projectDriver.readProject(dbc, id);
5220            m_projectCache.put(new Integer JavaDoc(id), project);
5221        }
5222        return project;
5223    }
5224
5225    /**
5226     * Reads a project.<p>
5227     *
5228     * Important: Since a project name can be used multiple times, this is NOT the most efficient
5229     * way to read the project. This is only a convenience for front end developing.
5230     * Reading a project by name will return the first project with that name.
5231     * All core classes must use the id version {@link #readProject(CmsDbContext, int)} to ensure the right project is read.<p>
5232     *
5233     * @param dbc the current database context
5234     * @param name the name of the project
5235     *
5236     * @return the project read
5237     *
5238     * @throws CmsException if something goes wrong
5239     */

5240    public CmsProject readProject(CmsDbContext dbc, String JavaDoc name) throws CmsException {
5241
5242        CmsProject project = null;
5243        project = (CmsProject)m_projectCache.get(name);
5244        if (project == null) {
5245            project = m_projectDriver.readProject(dbc, name);
5246            m_projectCache.put(name, project);
5247        }
5248        return project;
5249    }
5250
5251    /**
5252     * Reads all task log entries for a project.
5253     *
5254     * @param dbc the current database context
5255     * @param projectId the id of the project for which the tasklog will be read
5256     *
5257     * @return a list of <code>{@link CmsTaskLog}</code> objects
5258     *
5259     * @throws CmsException if something goes wrong
5260     */

5261    public List readProjectLogs(CmsDbContext dbc, int projectId) throws CmsException {
5262
5263        return m_workflowDriver.readProjectLogs(dbc, projectId);
5264    }
5265
5266    /**
5267     * Returns the list of all resource names that define the "view" of the given project.<p>
5268     *
5269     * @param dbc the current database context
5270     * @param project the project to get the project resources for
5271     *
5272     * @return the list of all resources, as <code>{@link String}</code> objects
5273     * that define the "view" of the given project.
5274     *
5275     * @throws CmsException if something goes wrong
5276     */

5277    public List readProjectResources(CmsDbContext dbc, CmsProject project) throws CmsException {
5278
5279        return m_projectDriver.readProjectResources(dbc, project);
5280    }
5281
5282    /**
5283     * Reads all resources of a project that match a given state from the VFS.<p>
5284     *
5285     * Possible values for the <code>state</code> parameter are:<br>
5286     * <ul>
5287     * <li><code>{@link CmsResource#STATE_CHANGED}</code>: Read all "changed" resources in the project</li>
5288     * <li><code>{@link CmsResource#STATE_NEW}</code>: Read all "new" resources in the project</li>
5289     * <li><code>{@link CmsResource#STATE_DELETED}</code>: Read all "deleted" resources in the project</li>
5290     * <li><code>{@link CmsResource#STATE_KEEP}</code>: Read all resources either "changed", "new" or "deleted" in the project</li>
5291     * </ul><p>
5292     *
5293     * @param dbc the current database context
5294     * @param projectId the id of the project to read the file resources for
5295     * @param state the resource state to match
5296     *
5297     * @return a list of <code>{@link CmsResource}</code> objects matching the filter criteria
5298     *
5299     * @throws CmsException if something goes wrong
5300     *
5301     * @see CmsObject#readProjectView(int, int)
5302     */

5303    public List readProjectView(CmsDbContext dbc, int projectId, int state) throws CmsException {
5304
5305        List resources;
5306        if ((state == CmsResource.STATE_NEW)
5307            || (state == CmsResource.STATE_CHANGED)
5308            || (state == CmsResource.STATE_DELETED)) {
5309            // get all resources form the database that match the selected state
5310
resources = m_vfsDriver.readResources(dbc, projectId, state, CmsDriverManager.READMODE_MATCHSTATE);
5311        } else {
5312            // get all resources form the database that are somehow changed (i.e. not unchanged)
5313
resources = m_vfsDriver.readResources(
5314                dbc,
5315                projectId,
5316                CmsResource.STATE_UNCHANGED,
5317                CmsDriverManager.READMODE_UNMATCHSTATE);
5318        }
5319
5320        // filter the permissions
5321
List result = filterPermissions(dbc, resources, CmsResourceFilter.ALL);
5322        // sort the result
5323
Collections.sort(result);
5324        // set the full resource names
5325
return updateContextDates(dbc, result);
5326    }
5327
5328    /**
5329     * Reads a property definition.<p>
5330     *
5331     * If no property definition with the given name is found,
5332     * <code>null</code> is returned.<p>
5333     *
5334     * @param dbc the current database context
5335     * @param name the name of the property definition to read
5336     *
5337     * @return the property definition that was read,
5338     * or <code>null</code> if there is no property definition with the given name.
5339     *
5340     * @throws CmsException if something goes wrong
5341     */

5342    public CmsPropertyDefinition readPropertyDefinition(CmsDbContext dbc, String JavaDoc name) throws CmsException {
5343
5344        return m_vfsDriver.readPropertyDefinition(dbc, name, dbc.currentProject().getId());
5345    }
5346
5347    /**
5348     * Reads a property object from a resource specified by a property name.<p>
5349     *
5350     * Returns <code>{@link CmsProperty#getNullProperty()}</code> if the property is not found.<p>
5351     *
5352     * @param dbc the current database context
5353     * @param resource the resource where the property is read from
5354     * @param key the property key name
5355     * @param search if <code>true</code>, the property is searched on all parent folders of the resource.
5356     * if it's not found attached directly to the resource.
5357     *
5358     * @return the required property, or <code>{@link CmsProperty#getNullProperty()}</code> if the property was not found
5359     *
5360     * @throws CmsException if something goes wrong
5361     */

5362    public CmsProperty readPropertyObject(CmsDbContext dbc, CmsResource resource, String JavaDoc key, boolean search)
5363    throws CmsException {
5364
5365        // check if we have the result already cached
5366
String JavaDoc cacheKey = getCacheKey(key, search, dbc.currentProject().getId(), resource.getRootPath());
5367        CmsProperty value = (CmsProperty)m_propertyCache.get(cacheKey);
5368
5369        if (value == null) {
5370            // check if the map of all properties for this resource is already cached
5371
String JavaDoc cacheKey2 = getCacheKey(
5372                CACHE_ALL_PROPERTIES,
5373                search,
5374                dbc.currentProject().getId(),
5375                resource.getRootPath());
5376
5377            List allProperties = (List)m_propertyCache.get(cacheKey2);
5378
5379            if (allProperties != null) {
5380                // list of properties already read, look up value there
5381
for (int i = 0; i < allProperties.size(); i++) {
5382                    CmsProperty property = (CmsProperty)allProperties.get(i);
5383                    if (property.getName().equals(key)) {
5384                        value = property;
5385                        break;
5386                    }
5387                }
5388            } else if (search) {
5389                // result not cached, look it up recursivly with search enabled
5390
String JavaDoc cacheKey3 = getCacheKey(key, search, dbc.currentProject().getId(), resource.getRootPath());
5391                value = (CmsProperty)m_propertyCache.get(cacheKey3);
5392
5393                if ((value == null) || value.isNullProperty()) {
5394                    boolean cont;
5395                    do {
5396                        try {
5397                            value = readPropertyObject(dbc, resource, key, false);
5398                            cont = value.isNullProperty() && (resource.getRootPath().length() > 1);
5399                        } catch (CmsSecurityException se) {
5400                            // a security exception (probably no read permission) we return the current result
5401
cont = false;
5402                        }
5403                        if (cont) {
5404                            // no permission check on parent folder is required since we must have "read"
5405
// permissions to read the child resource anyway
5406
resource = readResource(
5407                                dbc,
5408                                CmsResource.getParentFolder(resource.getRootPath()),
5409                                CmsResourceFilter.ALL);
5410                        }
5411                    } while (cont);
5412                }
5413            } else {
5414                // result not cached, look it up in the DB without search
5415
value = m_vfsDriver.readPropertyObject(dbc, key, dbc.currentProject(), resource);
5416            }
5417            if (value == null) {
5418                value = CmsProperty.getNullProperty();
5419            }
5420
5421            // freeze the value
5422
value.setFrozen(true);
5423            // store the result in the cache
5424
m_propertyCache.put(cacheKey, value);
5425        }
5426
5427        // ensure the result value is not frozen
5428
return value.cloneAsProperty();
5429    }
5430
5431    /**
5432     * Reads all property objects mapped to a specified resource from the database.<p>
5433     *
5434     * All properties in the result List will be in frozen (read only) state, so you can't change the values.<p>
5435     *
5436     * Returns an empty list if no properties are found at all.<p>
5437     *
5438     * @param dbc the current database context
5439     * @param resource the resource where the properties are read from
5440     * @param search true, if the properties should be searched on all parent folders if not found on the resource
5441     *
5442     * @return a list of CmsProperty objects containing the structure and/or resource value
5443     *
5444     * @throws CmsException if something goes wrong
5445     *
5446     * @see CmsObject#readPropertyObjects(String, boolean)
5447     */

5448    public List readPropertyObjects(CmsDbContext dbc, CmsResource resource, boolean search) throws CmsException {
5449
5450        // check if we have the result already cached
5451
String JavaDoc cacheKey = getCacheKey(
5452            CACHE_ALL_PROPERTIES,
5453            search,
5454            dbc.currentProject().getId(),
5455            resource.getRootPath());
5456
5457        List properties = (List)m_propertyCache.get(cacheKey);
5458
5459        if (properties == null) {
5460            // result not cached, let's look it up in the DB
5461
if (search) {
5462                boolean cont;
5463                properties = new ArrayList JavaDoc();
5464                List parentProperties = null;
5465
5466                do {
5467                    try {
5468                        parentProperties = readPropertyObjects(dbc, resource, false);
5469
5470                        // make sure properties from lower folders "overwrite" properties from upper folders
5471
parentProperties.removeAll(properties);
5472                        parentProperties.addAll(properties);
5473
5474                        properties.clear();
5475                        properties.addAll(parentProperties);
5476
5477                        cont = resource.getRootPath().length() > 1;
5478                    } catch (CmsSecurityException se) {
5479                        // a security exception (probably no read permission) we return the current result
5480
cont = false;
5481                    }
5482                    if (cont) {
5483                        // no permission check on parent folder is required since we must have "read"
5484
// permissions to read the child resource anyway
5485
resource = readResource(
5486                            dbc,
5487                            CmsResource.getParentFolder(resource.getRootPath()),
5488                            CmsResourceFilter.ALL);
5489                    }
5490                } while (cont);
5491            } else {
5492                properties = m_vfsDriver.readPropertyObjects(dbc, dbc.currentProject(), resource);
5493            }
5494
5495            // set all properties in the result lisst as frozen
5496
CmsProperty.setFrozen(properties);
5497            // store the result in the driver manager's cache
5498
m_propertyCache.put(cacheKey, properties);
5499        }
5500
5501        return new ArrayList JavaDoc(properties);
5502    }
5503
5504    /**
5505     * Reads the resources that were published in a publish task for a given publish history ID.<p>
5506     *
5507     * @param dbc the current database context
5508     * @param publishHistoryId unique int ID to identify each publish task in the publish history
5509     *
5510     * @return a list of <code>{@link org.opencms.db.CmsPublishedResource}</code> objects
5511     *
5512     * @throws CmsException if something goes wrong
5513     */

5514    public List readPublishedResources(CmsDbContext dbc, CmsUUID publishHistoryId) throws CmsException {
5515
5516        return m_projectDriver.readPublishedResources(dbc, dbc.currentProject().getId(), publishHistoryId);
5517    }
5518
5519    /**
5520     * Reads all project resources that belong to a given view criteria. <p>
5521     *
5522     * A view criteria can be "new", "changed" and "deleted" and the result
5523     * contains those resources in the project whose
5524     * state is equal to the selected value.
5525     *
5526     * @param dbc the current database context
5527     * @param projectId the preoject to read from
5528     * @param criteria the view criteria, can be "new", "changed" or "deleted"
5529     *
5530     * @return all project resources that belong to the given view criteria
5531     * @throws CmsException if something goes wrong
5532     */

5533    public List readPublishProjectView(CmsDbContext dbc, int projectId, String JavaDoc criteria) throws CmsException {
5534
5535        List retValue = new ArrayList JavaDoc();
5536        List resources = m_projectDriver.readProjectView(dbc, projectId, criteria);
5537        boolean onlyLocked = false;
5538
5539        // check if only locked resources should be displayed
5540
if ("locked".equalsIgnoreCase(criteria)) {
5541            onlyLocked = true;
5542        }
5543
5544        // check the security
5545
Iterator JavaDoc i = resources.iterator();
5546        while (i.hasNext()) {
5547            CmsResource currentResource = (CmsResource)i.next();
5548            if (CmsSecurityManager.PERM_ALLOWED == m_securityManager.hasPermissions(
5549                dbc,
5550                currentResource,
5551                CmsPermissionSet.ACCESS_READ,
5552                true,
5553                CmsResourceFilter.ALL)) {
5554
5555                if (onlyLocked) {
5556                    // check if resource is locked
5557
CmsLock lock = getLock(dbc, currentResource);
5558                    if (!lock.isNullLock()) {
5559                        retValue.add(currentResource);
5560                    }
5561                } else {
5562                    // add all resources with correct permissions
5563
retValue.add(currentResource);
5564                }
5565            }
5566        }
5567
5568        return retValue;
5569
5570    }
5571
5572    /**
5573     * Reads a resource from the VFS, using the specified resource filter.<p>
5574     *
5575     * @param dbc the current database context
5576     * @param resourcePath the name of the resource to read (full path)
5577     * @param filter the resource filter to use while reading
5578     *
5579     * @return the resource that was read
5580     *
5581     * @throws CmsDataAccessException if something goes wrong
5582     *
5583     * @see CmsObject#readResource(String, CmsResourceFilter)
5584     * @see CmsObject#readResource(String)
5585     * @see CmsFile#upgrade(CmsResource, CmsObject)
5586     */

5587    public CmsResource readResource(CmsDbContext dbc, String JavaDoc resourcePath, CmsResourceFilter filter)
5588    throws CmsDataAccessException {
5589
5590        CmsResource resource = m_vfsDriver.readResource(
5591            dbc,
5592            dbc.currentProject().getId(),
5593            resourcePath,
5594            filter.includeDeleted());
5595
5596        // context dates need to be updated even if filter was applied
5597
updateContextDates(dbc, resource);
5598
5599        // return the resource
5600
return resource;
5601    }
5602
5603    /**
5604     * Reads all resources below the given path matching the filter criteria,
5605     * including the full tree below the path only in case the <code>readTree</code>
5606     * parameter is <code>true</code>.<p>
5607     *
5608     * @param dbc the current database context
5609     * @param parent the parent path to read the resources from
5610     * @param filter the filter
5611     * @param readTree <code>true</code> to read all subresources
5612     *
5613     * @return a list of <code>{@link CmsResource}</code> objects matching the filter criteria
5614     *
5615     * @throws CmsDataAccessException if the bare reading of the resources fails
5616     * @throws CmsException if security and permission checks for the resources read fail
5617     */

5618    public List readResources(CmsDbContext dbc, CmsResource parent, CmsResourceFilter filter, boolean readTree)
5619    throws CmsException, CmsDataAccessException {
5620
5621        // try to get the sub resources from the cache
5622
String JavaDoc cacheKey = getCacheKey(new String JavaDoc[] {
5623            dbc.currentUser().getName(),
5624            filter.getCacheId(),
5625            readTree ? "+" : "-",
5626            parent.getRootPath()}, dbc.currentProject());
5627
5628        List resourceList = (List)m_resourceListCache.get(cacheKey);
5629        if (resourceList == null) {
5630            // read the result from the database
5631
resourceList = m_vfsDriver.readResourceTree(
5632                dbc,
5633                dbc.currentProject().getId(),
5634                (readTree ? parent.getRootPath() : parent.getStructureId().toString()),
5635                filter.getType(),
5636                filter.getState(),
5637                filter.getModifiedAfter(),
5638                filter.getModifiedBefore(),
5639                filter.getReleaseAfter(),
5640                filter.getReleaseBefore(),
5641                filter.getExpireAfter(),
5642                filter.getExpireBefore(),
5643                (readTree ? CmsDriverManager.READMODE_INCLUDE_TREE : CmsDriverManager.READMODE_EXCLUDE_TREE)
5644                    | (filter.excludeType() ? CmsDriverManager.READMODE_EXCLUDE_TYPE : 0)
5645                    | (filter.excludeState() ? CmsDriverManager.READMODE_EXCLUDE_STATE : 0)
5646                    | ((filter.getOnlyFolders() != null) ? (filter.getOnlyFolders().booleanValue() ? CmsDriverManager.READMODE_ONLY_FOLDERS
5647                    : CmsDriverManager.READMODE_ONLY_FILES)
5648                    : 0));
5649
5650            // apply permission filter
5651
resourceList = filterPermissions(dbc, resourceList, filter);
5652            // store the result in the resourceList cache
5653
m_resourceListCache.put(cacheKey, resourceList);
5654        }
5655        // apply the result filter and update the context dates
5656
return updateContextDates(dbc, resourceList, filter);
5657    }
5658
5659    /**
5660     * Reads all resources that have a value set for the specified property (definition) in the given path.<p>
5661     *
5662     * Both individual and shared properties of a resource are checked.<p>
5663     *
5664     * @param dbc the current database context
5665     * @param path the folder to get the resources with the property from
5666     * @param propertyDefinition the name of the property (definition) to check for
5667     *
5668     * @return a list of all <code>{@link CmsResource}</code> objects
5669     * that have a value set for the specified property.
5670     *
5671     * @throws CmsException if something goes wrong
5672     */

5673    public List readResourcesWithProperty(CmsDbContext dbc, String JavaDoc path, String JavaDoc propertyDefinition) throws CmsException {
5674
5675        String JavaDoc cacheKey = getCacheKey(
5676            new String JavaDoc[] {dbc.currentUser().getName(), path, propertyDefinition},
5677            dbc.currentProject());
5678        List resourceList = (List)m_resourceListCache.get(cacheKey);
5679        if (resourceList == null) {
5680            // first read the property definition
5681
CmsPropertyDefinition propDef = readPropertyDefinition(dbc, propertyDefinition);
5682            // now read the list of resources that have a value set for the property definition
5683
resourceList = m_vfsDriver.readResourcesWithProperty(
5684                dbc,
5685                dbc.currentProject().getId(),
5686                propDef.getId(),
5687                path);
5688            // apply permission filter
5689
resourceList = filterPermissions(dbc, resourceList, CmsResourceFilter.ALL);
5690            // store the result in the resourceList cache
5691
m_resourceListCache.put(cacheKey, resourceList);
5692        }
5693        return resourceList;
5694    }
5695
5696    /**
5697     * Reads all resources that have a value (containing the given value string) set
5698     * for the specified property (definition) in the given path.<p>
5699     *
5700     * Both individual and shared properties of a resource are checked.<p>
5701     *
5702     * @param dbc the current database context
5703     * @param path the folder to get the resources with the property from
5704     * @param propertyDefinition the name of the property (definition) to check for
5705     * @param value the string to search in the value of the property
5706     *
5707     * @return a list of all <code>{@link CmsResource}</code> objects
5708     * that have a value set for the specified property.
5709     *
5710     * @throws CmsException if something goes wrong
5711     */

5712    public List readResourcesWithProperty(CmsDbContext dbc, String JavaDoc path, String JavaDoc propertyDefinition, String JavaDoc value)
5713    throws CmsException {
5714
5715        String JavaDoc cacheKey = getCacheKey(
5716            new String JavaDoc[] {dbc.currentUser().getName(), path, propertyDefinition, value},
5717            dbc.currentProject());
5718        List resourceList = (List)m_resourceListCache.get(cacheKey);
5719        if (resourceList == null) {
5720            // first read the property definition
5721
CmsPropertyDefinition propDef = readPropertyDefinition(dbc, propertyDefinition);
5722            // now read the list of resources that have a value set for the property definition
5723
resourceList = m_vfsDriver.readResourcesWithProperty(
5724                dbc,
5725                dbc.currentProject().getId(),
5726                propDef.getId(),
5727                path,
5728                value);
5729            // apply permission filter
5730
resourceList = filterPermissions(dbc, resourceList, CmsResourceFilter.ALL);
5731            // store the result in the resourceList cache
5732
m_resourceListCache.put(cacheKey, resourceList);
5733        }
5734        return resourceList;
5735    }
5736
5737    /**
5738     * Returns the set of users that are responsible for a specific resource.<p>
5739     *
5740     * @param dbc the current database context
5741     * @param resource the resource to get the responsible users from
5742     *
5743     * @return the set of users that are responsible for a specific resource
5744     *
5745     * @throws CmsException if something goes wrong
5746     */

5747    public Set readResponsiblePrincipals(CmsDbContext dbc, CmsResource resource) throws CmsException {
5748
5749        Set result = new HashSet JavaDoc();
5750        Iterator JavaDoc aces = getAccessControlEntries(dbc, resource, true).iterator();
5751        while (aces.hasNext()) {
5752            CmsAccessControlEntry ace = (CmsAccessControlEntry)aces.next();
5753            if (ace.isResponsible()) {
5754                result.add(lookupPrincipal(dbc, ace.getPrincipal()));
5755            }
5756        }
5757        return result;
5758    }
5759
5760    /**
5761     * Returns the set of users that are responsible for a specific resource.<p>
5762     *
5763     * @param dbc the current database context
5764     * @param resource the resource to get the responsible users from
5765     *
5766     * @return the set of users that are responsible for a specific resource
5767     *
5768     * @throws CmsException if something goes wrong
5769     */

5770    public Set readResponsibleUsers(CmsDbContext dbc, CmsResource resource) throws CmsException {
5771
5772        Set result = new HashSet JavaDoc();
5773        Iterator JavaDoc principals = readResponsiblePrincipals(dbc, resource).iterator();
5774        while (principals.hasNext()) {
5775            I_CmsPrincipal principal = (I_CmsPrincipal)principals.next();
5776            if (principal instanceof CmsGroup) {
5777                try {
5778                    result.addAll(getUsersOfGroup(dbc, principal.getName()));
5779                } catch (CmsException e) {
5780                    if (LOG.isInfoEnabled()) {
5781                        LOG.info(e);
5782                    }
5783                }
5784            } else {
5785                result.add(principal);
5786            }
5787        }
5788        return result;
5789    }
5790
5791    /**
5792     * Returns a List of all siblings of the specified resource,
5793     * the specified resource being always part of the result set.<p>
5794     *
5795     * The result is a list of <code>{@link CmsResource}</code> objects.<p>
5796     *
5797     * @param dbc the current database context
5798     * @param resource the resource to read the siblings for
5799     * @param filter a filter object
5800     *
5801     * @return a list of <code>{@link CmsResource}</code> Objects that
5802     * are siblings to the specified resource,
5803     * including the specified resource itself
5804     *
5805     * @throws CmsException if something goes wrong
5806     */

5807    public List readSiblings(CmsDbContext dbc, CmsResource resource, CmsResourceFilter filter) throws CmsException {
5808
5809        List siblings = m_vfsDriver.readSiblings(dbc, dbc.currentProject(), resource, filter.includeDeleted());
5810
5811        // important: there is no permission check done on the returned list of siblings
5812
// this is because of possible issues with the "publish all siblings" option,
5813
// moreover the user has read permission for the content through
5814
// the selected sibling anyway
5815

5816        return updateContextDates(dbc, siblings, filter);
5817    }
5818
5819    /**
5820     * Returns the parameters of a resource in the table of all published template resources.<p>
5821     *
5822     * @param dbc the current database context
5823     * @param rfsName the rfs name of the resource
5824     *
5825     * @return the paramter string of the requested resource
5826     *
5827     * @throws CmsException if something goes wrong
5828     */

5829    public String JavaDoc readStaticExportPublishedResourceParameters(CmsDbContext dbc, String JavaDoc rfsName) throws CmsException {
5830
5831        return m_projectDriver.readStaticExportPublishedResourceParameters(dbc, dbc.currentProject(), rfsName);
5832    }
5833
5834    /**
5835     * Returns a list of all template resources which must be processed during a static export.<p>
5836     *
5837     * @param dbc the current database context
5838     * @param parameterResources flag for reading resources with parameters (1) or without (0)
5839     * @param timestamp for reading the data from the db
5840     *
5841     * @return a list of template resources as <code>{@link String}</code> objects
5842     *
5843     * @throws CmsException if something goes wrong
5844     */

5845    public List readStaticExportResources(CmsDbContext dbc, int parameterResources, long timestamp) throws CmsException {
5846
5847        return m_projectDriver.readStaticExportResources(dbc, dbc.currentProject(), parameterResources, timestamp);
5848    }
5849
5850    /**
5851     * Reads the task with the given id.<p>
5852     *
5853     * @param dbc the current database context
5854     * @param id the id for the task to read
5855     *
5856     * @return the task with the given id
5857     *
5858     * @throws CmsException if something goes wrong
5859     */

5860    public CmsTask readTask(CmsDbContext dbc, int id) throws CmsException {
5861
5862        return m_workflowDriver.readTask(dbc, id);
5863    }
5864
5865    /**
5866     * Reads log entries for a task.<p>
5867     *
5868     * @param dbc the current satabase context
5869     * @param taskid the task for the tasklog to read
5870     *
5871     * @return a list of <code>{@link CmsTaskLog}</code> objects
5872     *
5873     * @throws CmsException if something goes wrong
5874     */

5875    public List readTaskLogs(CmsDbContext dbc, int taskid) throws CmsException {
5876
5877        return m_workflowDriver.readTaskLogs(dbc, taskid);
5878    }
5879
5880    /**
5881     * Reads all tasks for a project.<p>
5882     *
5883     * The <code>tasktype</code> parameter will filter the tasks.
5884     * The possible values are:<br>
5885     * <ul>
5886     * <il><code>{@link CmsTaskService#TASKS_ALL}</code>: Reads all tasks</il>
5887     * <il><code>{@link CmsTaskService#TASKS_OPEN}</code>: Reads all open tasks</il>
5888     * <il><code>{@link CmsTaskService#TASKS_DONE}</code>: Reads all finished tasks</il>
5889     * <il><code>{@link CmsTaskService#TASKS_NEW}</code>: Reads all new tasks</il>
5890     * </ul><p>
5891     *
5892     * @param dbc the current database context
5893     * @param projectId the id of the project in which the tasks are defined. Can be null to select all tasks
5894     * @param tasktype the type of task you want to read
5895     * @param orderBy specifies how to order the tasks
5896     * @param sort sort order: C_SORT_ASC, C_SORT_DESC, or null
5897     *
5898     * @return a list of <code>{@link CmsTask}</code> objects for the project
5899     *
5900     * @throws CmsException if operation was not successful
5901     */

5902    public List readTasksForProject(CmsDbContext dbc, int projectId, int tasktype, String JavaDoc orderBy, String JavaDoc sort)
5903    throws CmsException {
5904
5905        CmsProject project = null;
5906
5907        if (projectId != CmsDbUtil.UNKNOWN_ID) {
5908            project = readProject(dbc, projectId);
5909        }
5910        return m_workflowDriver.readTasks(dbc, project, null, null, null, tasktype, orderBy, sort);
5911    }
5912
5913    /**
5914     * Reads all tasks for a role in a project.<p>
5915     *
5916     * The <code>tasktype</code> parameter will filter the tasks.
5917     * The possible values for this parameter are:<br>
5918     * <ul>
5919     * <il><code>{@link CmsTaskService#TASKS_ALL}</code>: Reads all tasks</il>
5920     * <il><code>{@link CmsTaskService#TASKS_OPEN}</code>: Reads all open tasks</il>
5921     * <il><code>{@link CmsTaskService#TASKS_DONE}</code>: Reads all finished tasks</il>
5922     * <il><code>{@link CmsTaskService#TASKS_NEW}</code>: Reads all new tasks</il>
5923     * </ul><p>
5924     *
5925     * @param dbc the current database context
5926     * @param projectId the id of the Project in which the tasks are defined
5927     * @param roleName the role who has to process the task
5928     * @param tasktype the type of task you want to read
5929     * @param orderBy specifies how to order the tasks
5930     * @param sort sort order C_SORT_ASC, C_SORT_DESC, or null
5931     *
5932     * @return list of <code>{@link CmsTask}</code> objects for the role
5933     *
5934     * @throws CmsException if operation was not successful
5935     */

5936    public List readTasksForRole(
5937        CmsDbContext dbc,
5938        int projectId,
5939        String JavaDoc roleName,
5940        int tasktype,
5941        String JavaDoc orderBy,
5942        String JavaDoc sort) throws CmsException {
5943
5944        CmsProject project = null;
5945        CmsGroup role = null;
5946
5947        if (roleName != null) {
5948            role = readGroup(dbc, roleName);
5949        }
5950
5951        if (projectId != CmsDbUtil.UNKNOWN_ID) {
5952            project = readProject(dbc, projectId);
5953        }
5954
5955        return m_workflowDriver.readTasks(dbc, project, null, null, role, tasktype, orderBy, sort);
5956    }
5957
5958    /**
5959     * Reads all tasks for a user in a project.<p>
5960     *
5961     * The <code>tasktype</code> parameter will filter the tasks.
5962     * The possible values for this parameter are:<br>
5963     * <ul>
5964     * <il><code>{@link CmsTaskService#TASKS_ALL}</code>: Reads all tasks</il>
5965     * <il><code>{@link CmsTaskService#TASKS_OPEN}</code>: Reads all open tasks</il>
5966     * <il><code>{@link CmsTaskService#TASKS_DONE}</code>: Reads all finished tasks</il>
5967     * <il><code>{@link CmsTaskService#TASKS_NEW}</code>: Reads all new tasks</il>
5968     * </ul>
5969     *
5970     * @param dbc the current database context
5971     * @param projectId the id of the Project in which the tasks are defined
5972     * @param userName the user who has to process the task
5973     * @param taskType the type of task you want to read
5974     * @param orderBy specifies how to order the tasks
5975     * @param sort sort order C_SORT_ASC, C_SORT_DESC, or null
5976     *
5977     * @return a list of <code>{@link CmsTask}</code> objects for the user
5978     *
5979     * @throws CmsException if operation was not successful
5980     */

5981    public List readTasksForUser(
5982        CmsDbContext dbc,
5983        int projectId,
5984        String JavaDoc userName,
5985        int taskType,
5986        String JavaDoc orderBy,
5987        String JavaDoc sort) throws CmsException {
5988
5989        CmsUser user = readUser(dbc, userName, CmsUser.USER_TYPE_SYSTEMUSER);
5990        CmsProject project = null;
5991        // try to read the project, if projectId == -1 we must return the tasks of all projects
5992
if (projectId != CmsDbUtil.UNKNOWN_ID) {
5993            project = m_projectDriver.readProject(dbc, projectId);
5994        }
5995        return m_workflowDriver.readTasks(dbc, project, user, null, null, taskType, orderBy, sort);
5996    }
5997
5998    /**
5999     * Returns a user object based on the id of a user.<p>
6000     *
6001     * @param dbc the current database context
6002     * @param id the id of the user to read
6003     *
6004     * @return the user read
6005     *
6006     * @throws CmsException if something goes wrong
6007     */

6008    public CmsUser readUser(CmsDbContext dbc, CmsUUID id) throws CmsException {
6009
6010        CmsUser user = null;
6011        user = getUserFromCache(id);
6012        if (user == null) {
6013            user = m_userDriver.readUser(dbc, id);
6014            putUserInCache(user);
6015        }
6016        return user;
6017    }
6018
6019    /**
6020     * Returns a user object.<p>
6021     *
6022     * @param dbc the current database context
6023     * @param username the name of the user that is to be read
6024     *
6025     * @return user read
6026     *
6027     * @throws CmsDataAccessException if operation was not succesful
6028     */

6029    public CmsUser readUser(CmsDbContext dbc, String JavaDoc username) throws CmsDataAccessException {
6030
6031        return readUser(dbc, username, CmsUser.USER_TYPE_SYSTEMUSER);
6032    }
6033
6034    /**
6035     * Returns a user object.<p>
6036     *
6037     * @param dbc the current database context
6038     * @param username the name of the user that is to be read
6039     * @param type the type of the user
6040     *
6041     * @return user read
6042     *
6043     * @throws CmsDataAccessException if an underlying <code>Exception</code> related to runtime type instantiation (<code>IOException</code>, <code>ClassCastException</code>) occurs
6044     * @throws CmsDbSqlException if an underlying <code>Exception</code> related to data retrieval (<code>SQLException</code>) occurs
6045     * @throws CmsDbEntryNotFoundException if the user corresponding to the given id does not exist in the database
6046     */

6047    public CmsUser readUser(CmsDbContext dbc, String JavaDoc username, int type)
6048    throws CmsDataAccessException, CmsDbSqlException, CmsDbEntryNotFoundException {
6049
6050        CmsUser user = getUserFromCache(username, type);
6051        if (user == null) {
6052            user = m_userDriver.readUser(dbc, username, type);
6053            putUserInCache(user);
6054        }
6055        return user;
6056    }
6057
6058    /**
6059     * Returns a user object if the password for the user is correct.<p>
6060     *
6061     * If the user/pwd pair is not valid a <code>{@link CmsException}</code> is thrown.<p>
6062     *
6063     * @param dbc the current database context
6064     * @param username the username of the user that is to be read
6065     * @param password the password of the user that is to be read
6066     *
6067     * @return user read
6068     *
6069     * @throws CmsException if operation was not succesful
6070     */

6071    public CmsUser readUser(CmsDbContext dbc, String JavaDoc username, String JavaDoc password) throws CmsException {
6072
6073        // don't read user from cache here because password may have changed
6074
CmsUser user = m_userDriver.readUser(dbc, username, password, CmsUser.USER_TYPE_SYSTEMUSER);
6075        putUserInCache(user);
6076        return user;
6077    }
6078
6079    /**
6080     * Read a web user from the database.<p>
6081     *
6082     * @param dbc the current database context
6083     * @param username the web user to read
6084     *
6085     * @return the read web user
6086     *
6087     * @throws CmsException if the user could not be read.
6088     */

6089    public CmsUser readWebUser(CmsDbContext dbc, String JavaDoc username) throws CmsException {
6090
6091        return readUser(dbc, username, CmsUser.USER_TYPE_WEBUSER);
6092    }
6093
6094    /**
6095     * Returns a user object if the password for the user is correct.<p>
6096     *
6097     * If the user/pwd pair is not valid a <code>{@link CmsException}</code> is thrown.<p>
6098     *
6099     * @param dbc the current database context
6100     * @param username the username of the user that is to be read
6101     * @param password the password of the user that is to be read
6102     *
6103     * @return the webuser read
6104     *
6105     * @throws CmsException if operation was not succesful
6106     */

6107    public CmsUser readWebUser(CmsDbContext dbc, String JavaDoc username, String JavaDoc password) throws CmsException {
6108
6109        // don't read user from cache here because password may have changed
6110
CmsUser user = m_userDriver.readUser(dbc, username, password, CmsUser.USER_TYPE_WEBUSER);
6111        putUserInCache(user);
6112        return user;
6113    }
6114
6115    /**
6116     * Removes an access control entry for a given resource and principal.<p>
6117     *
6118     * @param dbc the current database context
6119     * @param resource the resource
6120     * @param principal the id of the principal to remove the the access control entry for
6121     *
6122     * @throws CmsException if something goes wrong
6123     */

6124    public void removeAccessControlEntry(CmsDbContext dbc, CmsResource resource, CmsUUID principal) throws CmsException {
6125
6126        // remove the ace
6127
m_userDriver.removeAccessControlEntry(dbc, dbc.currentProject(), resource.getResourceId(), principal);
6128
6129        // update the "last modified" information
6130
setDateLastModified(dbc, resource, resource.getDateLastModified());
6131
6132        // clear the cache
6133
clearAccessControlListCache();
6134
6135        // fire a resource modification event
6136
OpenCms.fireCmsEvent(new CmsEvent(I_CmsEventListener.EVENT_RESOURCE_MODIFIED, Collections.singletonMap(
6137            "resource",
6138            resource)));
6139    }
6140
6141    /**
6142     * Removes a resource from the current project of the user.<p>
6143     *
6144     * @param dbc the current database context
6145     * @param resource the resource to apply this operation to
6146     *
6147     * @throws CmsException if something goes wrong
6148     *
6149     * @see CmsObject#copyResourceToProject(String)
6150     * @see I_CmsResourceType#copyResourceToProject(CmsObject, CmsSecurityManager, CmsResource)
6151     */

6152    public void removeResourceFromProject(CmsDbContext dbc, CmsResource resource) throws CmsException {
6153
6154        // remove the resource to the project only if the resource is already in the project
6155
if (isInsideCurrentProject(dbc, resource.getRootPath())) {
6156            // check if there are already any subfolders of this resource
6157
if (resource.isFolder()) {
6158                List projectResources = m_projectDriver.readProjectResources(dbc, dbc.currentProject());
6159                for (int i = 0; i < projectResources.size(); i++) {
6160                    String JavaDoc resname = (String JavaDoc)projectResources.get(i);
6161                    if (resname.startsWith(resource.getRootPath())) {
6162                        // delete the existing project resource first
6163
m_projectDriver.deleteProjectResource(dbc, dbc.currentProject().getId(), resname);
6164                    }
6165                }
6166            }
6167            try {
6168                m_projectDriver.deleteProjectResource(dbc, dbc.currentProject().getId(), resource.getRootPath());
6169            } catch (CmsException exc) {
6170                // if the subfolder exists already - all is ok
6171
} finally {
6172                OpenCms.fireCmsEvent(new CmsEvent(I_CmsEventListener.EVENT_PROJECT_MODIFIED, Collections.singletonMap(
6173                    "project",
6174                    dbc.currentProject())));
6175            }
6176        }
6177    }
6178
6179    /**
6180     * Removes a user from a group.<p>
6181     *
6182     * @param dbc the current database context
6183     * @param username the name of the user that is to be removed from the group
6184     * @param groupname the name of the group
6185     *
6186     * @throws CmsException if operation was not succesful
6187     * @throws CmsIllegalArgumentException if the given user was not member in the given group
6188     * @throws CmsDbEntryNotFoundException if the given group was not found
6189     * @throws CmsSecurityException if the given user was <b>read as 'null' from the database</b>
6190     */

6191    public void removeUserFromGroup(CmsDbContext dbc, String JavaDoc username, String JavaDoc groupname)
6192    throws CmsException, CmsIllegalArgumentException, CmsDbEntryNotFoundException, CmsSecurityException {
6193
6194        // test if this user is existing in the group
6195
if (!userInGroup(dbc, username, groupname)) {
6196            // user is not in the group, throw exception
6197
throw new CmsIllegalArgumentException(Messages.get().container(
6198                Messages.ERR_USER_NOT_IN_GROUP_2,
6199                username,
6200                groupname));
6201        }
6202
6203        if (username.equals(OpenCms.getDefaultUsers().getUserAdmin())
6204            && groupname.equals(OpenCms.getDefaultUsers().getGroupAdministrators())) {
6205            // the admin user cannot be removed from the administrators group, throw exception
6206
throw new CmsIllegalStateException(Messages.get().container(
6207                Messages.ERR_ADMIN_REMOVED_FROM_ADMINISTRATORS_0));
6208        }
6209        CmsUser user;
6210        CmsGroup group;
6211
6212        user = readUser(dbc, username);
6213
6214        //check if the user exists
6215
if (user != null) {
6216            group = readGroup(dbc, groupname);
6217            //check if group exists
6218
if (group != null) {
6219                m_userDriver.deleteUserInGroup(dbc, user.getId(), group.getId());
6220                m_userGroupsCache.clear();
6221            } else {
6222                throw new CmsDbEntryNotFoundException(Messages.get().container(Messages.ERR_UNKNOWN_GROUP_1, groupname));
6223            }
6224        } else {
6225            throw new CmsIllegalArgumentException(Messages.get().container(
6226                Messages.ERR_USER_NOT_IN_GROUP_2,
6227                username,
6228                groupname));
6229        }
6230    }
6231
6232    /**
6233     * Replaces the content, type and properties of a resource.<p>
6234     *
6235     * @param dbc the current database context
6236     * @param resource the name of the resource to apply this operation to
6237     * @param type the new type of the resource
6238     * @param content the new content of the resource
6239     * @param properties the new properties of the resource
6240     *
6241     * @throws CmsException if something goes wrong
6242     *
6243     * @see CmsObject#replaceResource(String, int, byte[], List)
6244     * @see I_CmsResourceType#replaceResource(CmsObject, CmsSecurityManager, CmsResource, int, byte[], List)
6245     */

6246    public void replaceResource(CmsDbContext dbc, CmsResource resource, int type, byte[] content, List properties)
6247    throws CmsException {
6248
6249        // replace the existing with the new file content
6250
m_vfsDriver.replaceResource(dbc, resource, content, type);
6251
6252        if ((properties != null) && (properties != Collections.EMPTY_LIST)) {
6253            // write the properties
6254
m_vfsDriver.writePropertyObjects(dbc, dbc.currentProject(), resource, properties);
6255            m_propertyCache.clear();
6256        }
6257
6258        // update the resource state
6259
if (resource.getState() == CmsResource.STATE_UNCHANGED) {
6260            resource.setState(CmsResource.STATE_CHANGED);
6261        }
6262        resource.setUserLastModified(dbc.currentUser().getId());
6263
6264        setDateLastModified(dbc, resource, System.currentTimeMillis());
6265
6266        m_vfsDriver.writeResourceState(dbc, dbc.currentProject(), resource, UPDATE_RESOURCE);
6267
6268        // clear the cache
6269
clearResourceCache();
6270        content = null;
6271
6272        OpenCms.fireCmsEvent(new CmsEvent(I_CmsEventListener.EVENT_RESOURCE_MODIFIED, Collections.singletonMap(
6273            "resource",
6274            resource)));
6275    }
6276
6277    /**
6278     * Resets the password for a specified user.<p>
6279     *
6280     * @param dbc the current database context
6281     * @param username the name of the user
6282     * @param oldPassword the old password
6283     * @param newPassword the new password
6284     *
6285     * @throws CmsException if the user data could not be read from the database
6286     * @throws CmsSecurityException if the specified username and old password could not be verified
6287     */

6288    public void resetPassword(CmsDbContext dbc, String JavaDoc username, String JavaDoc oldPassword, String JavaDoc newPassword)
6289    throws CmsException, CmsSecurityException {
6290
6291        if (oldPassword != null && newPassword != null) {
6292
6293            CmsUser user = null;
6294
6295            validatePassword(newPassword);
6296
6297            // read the user as a system user to verify that the specified old password is correct
6298
try {
6299                user = m_userDriver.readUser(dbc, username, oldPassword, CmsUser.USER_TYPE_SYSTEMUSER);
6300            } catch (CmsDbEntryNotFoundException e) {
6301                throw new CmsDataAccessException(Messages.get().container(Messages.ERR_RESET_PASSWORD_1, username), e);
6302            }
6303
6304            // dito as a web user
6305
try {
6306                user = (user != null) ? user : m_userDriver.readUser(
6307                    dbc,
6308                    username,
6309                    oldPassword,
6310                    CmsUser.USER_TYPE_WEBUSER);
6311            } catch (CmsDbEntryNotFoundException e) {
6312                throw new CmsDataAccessException(Messages.get().container(Messages.ERR_RESET_PASSWORD_1, username), e);
6313            }
6314
6315            if (user == null) {
6316                throw new CmsDataAccessException(Messages.get().container(Messages.ERR_RESET_PASSWORD_1, username));
6317            }
6318
6319            m_userDriver.writePassword(dbc, username, user.getType(), oldPassword, newPassword);
6320
6321        } else if (CmsStringUtil.isEmpty(oldPassword)) {
6322            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_PWD_OLD_MISSING_0));
6323        } else if (CmsStringUtil.isEmpty(newPassword)) {
6324            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_PWD_NEW_MISSING_0));
6325        }
6326    }
6327
6328    /**
6329     * Restores a file in the current project with a version from the backup archive.<p>
6330     *
6331     * @param dbc the current database context
6332     * @param resource the resource to restore from the archive
6333     * @param tag the tag (version) id to resource form the archive
6334     *
6335     * @throws CmsException if something goes wrong
6336     *
6337     * @see CmsObject#restoreResourceBackup(String, int)
6338     * @see I_CmsResourceType#restoreResourceBackup(CmsObject, CmsSecurityManager, CmsResource, int)
6339     */

6340    public void restoreResource(CmsDbContext dbc, CmsResource resource, int tag) throws CmsException {
6341
6342        int state = CmsResource.STATE_CHANGED;
6343
6344        CmsBackupResource backupFile = readBackupFile(dbc, tag, resource);
6345        if (resource.getState() == CmsResource.STATE_NEW) {
6346            state = CmsResource.STATE_NEW;
6347        }
6348
6349        if (backupFile != null) {
6350            // get the backed up flags
6351
int flags = backupFile.getFlags();
6352            if (resource.isLabeled()) {
6353                // set the flag for labeled links on the restored file
6354
flags |= CmsResource.FLAG_LABELED;
6355            }
6356
6357            CmsFile newFile = new CmsFile(
6358                resource.getStructureId(),
6359                resource.getResourceId(),
6360                backupFile.getContentId(),
6361                resource.getRootPath(),
6362                backupFile.getTypeId(),
6363                flags,
6364                dbc.currentProject().getId(),
6365                state,
6366                resource.getDateCreated(),
6367                backupFile.getUserCreated(),
6368                resource.getDateLastModified(),
6369                dbc.currentUser().getId(),
6370                backupFile.getDateReleased(),
6371                backupFile.getDateExpired(),
6372                backupFile.getSiblingCount(),
6373                backupFile.getLength(),
6374                backupFile.getContents());
6375
6376            writeFile(dbc, newFile);
6377
6378            // now read the backup properties
6379
List backupProperties = m_backupDriver.readBackupProperties(dbc, backupFile);
6380            // remove all properties
6381
deleteAllProperties(dbc, newFile.getRootPath());
6382            // write them to the restored resource
6383
writePropertyObjects(dbc, newFile, backupProperties);
6384
6385            clearResourceCache();
6386        }
6387
6388        OpenCms.fireCmsEvent(new CmsEvent(I_CmsEventListener.EVENT_RESOURCE_MODIFIED, Collections.singletonMap(
6389            "resource",
6390            resource)));
6391    }
6392
6393    /**
6394     * Changes the "expire" date of a resource.<p>
6395     *
6396     * @param dbc the current database context
6397     * @param resource the resource to touch
6398     * @param dateExpired the new expire date of the resource
6399     *
6400     * @throws CmsDataAccessException if something goes wrong
6401     *
6402     * @see CmsObject#setDateExpired(String, long, boolean)
6403     * @see I_CmsResourceType#setDateExpired(CmsObject, CmsSecurityManager, CmsResource, long, boolean)
6404     */

6405    public void setDateExpired(CmsDbContext dbc, CmsResource resource, long dateExpired) throws CmsDataAccessException {
6406
6407        resource.setDateExpired(dateExpired);
6408        if (resource.getState() == CmsResource.STATE_UNCHANGED) {
6409            resource.setState(CmsResource.STATE_CHANGED);
6410        }
6411        resource.setUserLastModified(dbc.currentUser().getId());
6412
6413        m_vfsDriver.writeResourceState(dbc, dbc.currentProject(), resource, UPDATE_STRUCTURE);
6414
6415        // clear the cache
6416
clearResourceCache();
6417
6418        // fire the event
6419
OpenCms.fireCmsEvent(new CmsEvent(I_CmsEventListener.EVENT_RESOURCE_MODIFIED, Collections.singletonMap(
6420            "resource",
6421            resource)));
6422    }
6423
6424    /**
6425     * Changes the "last modified" timestamp of a resource.<p>
6426     *
6427     * @param dbc the current database context
6428     * @param resource the resource to touch
6429     * @param dateLastModified the new last modified date of the resource
6430     *
6431     * @throws CmsDataAccessException if something goes wrong
6432     *
6433     * @see CmsObject#setDateLastModified(String, long, boolean)
6434     * @see I_CmsResourceType#setDateLastModified(CmsObject, CmsSecurityManager, CmsResource, long, boolean)
6435     */

6436    public void setDateLastModified(CmsDbContext dbc, CmsResource resource, long dateLastModified)
6437    throws CmsDataAccessException {
6438
6439        // modify the last modification date
6440
resource.setDateLastModified(dateLastModified);
6441        if (resource.getState() == CmsResource.STATE_UNCHANGED) {
6442            resource.setState(CmsResource.STATE_CHANGED);
6443        } else if ((resource.getState() == CmsResource.STATE_NEW) && (resource.getSiblingCount() > 1)) {
6444            // in case of new resources with siblings make sure the state is correct
6445
resource.setState(CmsResource.STATE_CHANGED);
6446        }
6447        resource.setUserLastModified(dbc.currentUser().getId());
6448
6449        m_vfsDriver.writeResourceState(dbc, dbc.currentProject(), resource, UPDATE_RESOURCE);
6450
6451        // clear the cache
6452
clearResourceCache();
6453
6454        // fire the event
6455
OpenCms.fireCmsEvent(new CmsEvent(I_CmsEventListener.EVENT_RESOURCE_MODIFIED, Collections.singletonMap(
6456            "resource",
6457            resource)));
6458    }
6459
6460    /**
6461     * Changes the "release" date of a resource.<p>
6462     *
6463     * @param dbc the current database context
6464     * @param resource the resource to touch
6465     * @param dateReleased the new release date of the resource
6466     *
6467     * @throws CmsDataAccessException if something goes wrong
6468     *
6469     * @see CmsObject#setDateReleased(String, long, boolean)
6470     * @see I_CmsResourceType#setDateReleased(CmsObject, CmsSecurityManager, CmsResource, long, boolean)
6471     */

6472    public void setDateReleased(CmsDbContext dbc, CmsResource resource, long dateReleased)
6473    throws CmsDataAccessException {
6474
6475        // modify the last modification date
6476
resource.setDateReleased(dateReleased);
6477        if (resource.getState() == CmsResource.STATE_UNCHANGED) {
6478            resource.setState(CmsResource.STATE_CHANGED);
6479        }
6480        resource.setUserLastModified(dbc.currentUser().getId());
6481
6482        m_vfsDriver.writeResourceState(dbc, dbc.currentProject(), resource, UPDATE_STRUCTURE);
6483
6484        // clear the cache
6485
clearResourceCache();
6486
6487        // fire the event
6488
OpenCms.fireCmsEvent(new CmsEvent(I_CmsEventListener.EVENT_RESOURCE_MODIFIED, Collections.singletonMap(
6489            "resource",
6490            resource)));
6491    }
6492
6493    /**
6494     * Set a new name for a task.<p>
6495     *
6496     * @param dbc the current database context
6497     * @param taskId the Id of the task to set the percentage
6498     * @param name the new name value
6499     *
6500     * @throws CmsException if an error occurs while writing workflow system task logs
6501     * @throws CmsDataAccessException if an error occurs while reading the task from or writing it to the underlying workflow driver
6502     * @throws CmsIllegalArgumentException if argument <code>name</code> is <code>null</code> or has a length of zero
6503     */

6504    public void setName(CmsDbContext dbc, int taskId, String JavaDoc name)
6505    throws CmsException, CmsDataAccessException, CmsIllegalArgumentException {
6506
6507        if ((name == null) || name.length() == 0) {
6508            throw new CmsIllegalArgumentException(org.opencms.main.Messages.get().container(
6509                org.opencms.main.Messages.ERR_ILLEGAL_ARG_2,
6510                "name",
6511                name));
6512        }
6513        CmsTask task = m_workflowDriver.readTask(dbc, taskId);
6514        task.setName(name);
6515        task = m_workflowDriver.writeTask(dbc, task);
6516        m_workflowDriver.writeSystemTaskLog(dbc, taskId, "Name was set to "
6517            + name
6518            + "% from "
6519            + dbc.currentUser().getFirstname()
6520            + " "
6521            + dbc.currentUser().getLastname()
6522            + '.');
6523    }
6524
6525    /**
6526     * Sets a new parent group for an already existing group.<p>
6527     *
6528     * @param dbc the current database context
6529     * @param groupName the name of the group that should be written
6530     * @param parentGroupName the name of the parent group to set,
6531     * or <code>null</code> if the parent
6532     * group should be deleted.
6533     *
6534     * @throws CmsException if operation was not succesfull
6535     * @throws CmsDataAccessException if the group with <code>groupName</code> could not be read from VFS
6536     */

6537    public void setParentGroup(CmsDbContext dbc, String JavaDoc groupName, String JavaDoc parentGroupName)
6538    throws CmsException, CmsDataAccessException {
6539
6540        CmsGroup group = readGroup(dbc, groupName);
6541        CmsUUID parentGroupId = CmsUUID.getNullUUID();
6542
6543        // if the group exists, use its id, else set to unknown.
6544
if (parentGroupName != null) {
6545            parentGroupId = readGroup(dbc, parentGroupName).getId();
6546        }
6547
6548        group.setParentId(parentGroupId);
6549
6550        // write the changes to the cms
6551
writeGroup(dbc, group);
6552    }
6553
6554    /**
6555     * Sets the password for a user.<p>
6556     *
6557     * @param dbc the current database context
6558     * @param username the name of the user
6559     * @param newPassword the new password
6560     *
6561     * @throws CmsException if operation was not succesfull
6562     * @throws CmsIllegalArgumentException if the user with the <code>username</code> was not found
6563     */

6564    public void setPassword(CmsDbContext dbc, String JavaDoc username, String JavaDoc newPassword)
6565    throws CmsException, CmsIllegalArgumentException {
6566
6567        CmsUser user = null;
6568
6569        validatePassword(newPassword);
6570
6571        // read the user as a system user to verify that the specified old password is correct
6572
try {
6573            user = m_userDriver.readUser(dbc, username, CmsUser.USER_TYPE_SYSTEMUSER);
6574        } catch (CmsDbEntryNotFoundException confe) {
6575            // only continue if not found and read user from web might succeed
6576
}
6577
6578        // dito as a web user
6579
// this time don't catch CmsObjectNotFoundException (user not found)
6580
user = (user != null) ? user : m_userDriver.readUser(dbc, username, CmsUser.USER_TYPE_WEBUSER);
6581        m_userDriver.writePassword(dbc, username, user.getType(), null, newPassword);
6582    }
6583
6584    /**
6585     * Set priority of a task.<p>
6586     *
6587     * @param dbc the current database context
6588     * @param taskId the Id of the task to set the percentage
6589     * @param priority the priority value
6590     *
6591     * @throws CmsException if writing to the system task log failed
6592     * @throws CmsDataAccessException if reading or writing of the task failed
6593     */

6594    public void setPriority(CmsDbContext dbc, int taskId, int priority) throws CmsException, CmsDataAccessException {
6595
6596        CmsTask task = m_workflowDriver.readTask(dbc, taskId);
6597        task.setPriority(priority);
6598        task = m_workflowDriver.writeTask(dbc, task);
6599        m_workflowDriver.writeSystemTaskLog(dbc, taskId, "Priority was set to "
6600            + priority
6601            + " from "
6602            + dbc.currentUser().getFirstname()
6603            + " "
6604            + dbc.currentUser().getLastname()
6605            + '.');
6606    }
6607
6608    /**
6609     * Set a Parameter for a task.<p>
6610     *
6611     * @param dbc the current database context
6612     * @param taskId the Id of the task
6613     * @param parName name of the parameter
6614     * @param parValue value if the parameter
6615     *
6616     * @throws CmsDataAccessException if something goes wrong
6617     */

6618    public void setTaskPar(CmsDbContext dbc, int taskId, String JavaDoc parName, String JavaDoc parValue) throws CmsDataAccessException {
6619
6620        m_workflowDriver.writeTaskParameter(dbc, taskId, parName, parValue);
6621    }
6622
6623    /**
6624     * Set the timeout of a task.<p>
6625     *
6626     * @param dbc the current database context
6627     * @param taskId the Id of the task to set the percentage
6628     * @param timeout new timeout value
6629     *
6630     * @throws CmsException if writing to the system task log failed
6631     * @throws CmsDataAccessException if reading or writing of the task failed
6632     */

6633    public void setTimeout(CmsDbContext dbc, int taskId, long timeout) throws CmsException, CmsDataAccessException {
6634
6635        CmsTask task = m_workflowDriver.readTask(dbc, taskId);
6636        java.sql.Timestamp JavaDoc timestamp = new java.sql.Timestamp JavaDoc(timeout);
6637        task.setTimeOut(timestamp);
6638        task = m_workflowDriver.writeTask(dbc, task);
6639        m_workflowDriver.writeSystemTaskLog(dbc, taskId, "Timeout was set to "
6640            + timeout
6641            + " from "
6642            + dbc.currentUser().getFirstname()
6643            + " "
6644            + dbc.currentUser().getLastname()
6645            + '.');
6646    }
6647
6648    /**
6649     * Undos all changes in the resource by restoring the version from the
6650     * online project to the current offline project.<p>
6651     *
6652     * @param dbc the current database context
6653     * @param resource the name of the resource to apply this operation to
6654     *
6655     * @throws CmsException if something goes wrong
6656     *
6657     * @see CmsObject#undoChanges(String, boolean)
6658     * @see I_CmsResourceType#undoChanges(CmsObject, CmsSecurityManager, CmsResource, boolean)
6659     */

6660    public void undoChanges(CmsDbContext dbc, CmsResource resource) throws CmsException {
6661
6662        if (resource.getState() == CmsResource.STATE_NEW) {
6663            // undo changes is impossible on a new resource
6664
throw new CmsVfsException(Messages.get().container(Messages.ERR_UNDO_CHANGES_FOR_RESOURCE_NEW_0));
6665        }
6666
6667        // we need this for later use
6668
CmsProject onlineProject = readProject(dbc, CmsProject.ONLINE_PROJECT_ID);
6669
6670        // change folder or file?
6671
if (resource.isFolder()) {
6672
6673            // read the resource from the online project
6674
CmsFolder onlineFolder = m_vfsDriver.readFolder(dbc, CmsProject.ONLINE_PROJECT_ID, resource.getRootPath());
6675
6676            CmsFolder restoredFolder = new CmsFolder(
6677                resource.getStructureId(),
6678                resource.getResourceId(),
6679                resource.getRootPath(),
6680                onlineFolder.getTypeId(),
6681                onlineFolder.getFlags(),
6682                dbc.currentProject().getId(),
6683                CmsResource.STATE_UNCHANGED,
6684                onlineFolder.getDateCreated(),
6685                onlineFolder.getUserCreated(),
6686                onlineFolder.getDateLastModified(),
6687                onlineFolder.getUserLastModified(),
6688                resource.getSiblingCount(),
6689                onlineFolder.getDateReleased(),
6690                onlineFolder.getDateExpired());
6691
6692            // write the folder in the offline project
6693
// this sets a flag so that the folder date is not set to the current time
6694
restoredFolder.setDateLastModified(onlineFolder.getDateLastModified());
6695
6696            // write the folder
6697
m_vfsDriver.writeResource(dbc, dbc.currentProject(), restoredFolder, NOTHING_CHANGED);
6698
6699            // restore the properties from the online project
6700
m_vfsDriver.deletePropertyObjects(
6701                dbc,
6702                dbc.currentProject().getId(),
6703                restoredFolder,
6704                CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES);
6705
6706            List propertyInfos = m_vfsDriver.readPropertyObjects(dbc, onlineProject, onlineFolder);
6707            m_vfsDriver.writePropertyObjects(dbc, dbc.currentProject(), restoredFolder, propertyInfos);
6708
6709            // restore the access control entries from the online project
6710
m_userDriver.removeAccessControlEntries(dbc, dbc.currentProject(), resource.getResourceId());
6711            ListIterator JavaDoc aceList = m_userDriver.readAccessControlEntries(
6712                dbc,
6713                onlineProject,
6714                resource.getResourceId(),
6715                false).listIterator();
6716
6717            while (aceList.hasNext()) {
6718                CmsAccessControlEntry ace = (CmsAccessControlEntry)aceList.next();
6719                m_userDriver.createAccessControlEntry(
6720                    dbc,
6721                    dbc.currentProject(),
6722                    resource.getResourceId(),
6723                    ace.getPrincipal(),
6724                    ace.getPermissions().getAllowedPermissions(),
6725                    ace.getPermissions().getDeniedPermissions(),
6726                    ace.getFlags());
6727            }
6728        } else {
6729
6730            // read the file from the online project
6731
CmsFile onlineFile = this.m_vfsDriver.readFile(
6732                dbc,
6733                CmsProject.ONLINE_PROJECT_ID,
6734                true,
6735                resource.getStructureId());
6736
6737            CmsFile restoredFile = new CmsFile(
6738                onlineFile.getStructureId(),
6739                onlineFile.getResourceId(),
6740                onlineFile.getContentId(),
6741                resource.getRootPath(),
6742                onlineFile.getTypeId(),
6743                onlineFile.getFlags(),
6744                dbc.currentProject().getId(),
6745                CmsResource.STATE_UNCHANGED,
6746                onlineFile.getDateCreated(),
6747                onlineFile.getUserCreated(),
6748                onlineFile.getDateLastModified(),
6749                onlineFile.getUserLastModified(),
6750                onlineFile.getDateReleased(),
6751                onlineFile.getDateExpired(),
6752                0,
6753                onlineFile.getLength(),
6754                onlineFile.getContents());
6755
6756            // write the file in the offline project
6757
// this sets a flag so that the file date is not set to the current time
6758
restoredFile.setDateLastModified(onlineFile.getDateLastModified());
6759
6760            // collect the old properties
6761
List properties = m_vfsDriver.readPropertyObjects(dbc, onlineProject, onlineFile);
6762
6763            // bugfix 1020: delete all properties (included shared),
6764
// shared properties will be recreated by the next call of #createResource(...)
6765
m_vfsDriver.deletePropertyObjects(
6766                dbc,
6767                dbc.currentProject().getId(),
6768                resource,
6769                CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES);
6770
6771            // implementation notes:
6772
// undo changes can become complex e.g. if a resource was deleted, and then
6773
// another resource was copied over the deleted file as a sibling
6774
// therefore we must "clean" delete the offline resource, and then create
6775
// an new resource with the create method
6776
// note that this does NOT apply to folders, since a folder cannot be replaced
6777
// like a resource anyway
6778
deleteResource(dbc, resource, CmsResource.DELETE_PRESERVE_SIBLINGS);
6779
6780            CmsResource res = createResource(
6781                dbc,
6782                restoredFile.getRootPath(),
6783                restoredFile,
6784                restoredFile.getContents(),
6785                properties,
6786                false);
6787
6788            // copy the access control entries from the online project
6789
m_userDriver.removeAccessControlEntries(dbc, dbc.currentProject(), resource.getResourceId());
6790            ListIterator JavaDoc aceList = m_userDriver.readAccessControlEntries(
6791                dbc,
6792                onlineProject,
6793                onlineFile.getResourceId(),
6794                false).listIterator();
6795
6796            while (aceList.hasNext()) {
6797                CmsAccessControlEntry ace = (CmsAccessControlEntry)aceList.next();
6798                m_userDriver.createAccessControlEntry(
6799                    dbc,
6800                    dbc.currentProject(),
6801                    res.getResourceId(),
6802                    ace.getPrincipal(),
6803                    ace.getPermissions().getAllowedPermissions(),
6804                    ace.getPermissions().getDeniedPermissions(),
6805                    ace.getFlags());
6806            }
6807
6808            // restore the state to unchanged
6809
res.setState(CmsResource.STATE_UNCHANGED);
6810            m_vfsDriver.writeResourceState(dbc, dbc.currentProject(), res, UPDATE_ALL);
6811        }
6812
6813        // update the cache
6814
clearResourceCache();
6815        m_propertyCache.clear();
6816
6817        OpenCms.fireCmsEvent(new CmsEvent(
6818            I_CmsEventListener.EVENT_RESOURCE_AND_PROPERTIES_MODIFIED,
6819            Collections.singletonMap("resource", resource)));
6820    }
6821
6822    /**
6823     * Unlocks all resources in the given project.<p>
6824     * @param project the project to unlock the resources in
6825     *
6826     * @throws CmsLockException if something goes wrong
6827     */

6828    public void unlockProject(CmsProject project) throws CmsLockException {
6829
6830        // check the security
6831
if (project.getFlags() == CmsProject.PROJECT_STATE_UNLOCKED) {
6832
6833            // unlock all resources in the project
6834
m_lockManager.removeResourcesInProject(project.getId());
6835            clearResourceCache();
6836            m_projectCache.clear();
6837            // we must also clear the permission cache
6838
m_securityManager.clearPermissionCache();
6839
6840        } else {
6841            throw new CmsLockException(Messages.get().container(
6842                Messages.ERR_UNLOCK_ALL_PROJECT_LOCKED_1,
6843                project.getName()));
6844        }
6845    }
6846
6847    /**
6848     * Unlocks a resource.<p>
6849     *
6850     * @param dbc the current database context
6851     * @param resource the resource to unlock
6852     *
6853     * @throws CmsException if something goes wrong
6854     *
6855     * @see CmsObject#unlockResource(String)
6856     * @see I_CmsResourceType#unlockResource(CmsObject, CmsSecurityManager, CmsResource)
6857     */

6858    public void unlockResource(CmsDbContext dbc, CmsResource resource) throws CmsException {
6859
6860        // update the resource cache
6861
clearResourceCache();
6862
6863        // now update lock status
6864
m_lockManager.removeResource(this, dbc, resource, false);
6865
6866        // we must also clear the permission cache
6867
m_securityManager.clearPermissionCache();
6868
6869        // fire resource modification event
6870
OpenCms.fireCmsEvent(new CmsEvent(I_CmsEventListener.EVENT_RESOURCE_MODIFIED, Collections.singletonMap(
6871            "resource",
6872            resource)));
6873    }
6874
6875    /**
6876     * Update the export points.<p>
6877     *
6878     * All files and folders "inside" an export point are written.<p>
6879     *
6880     * @param dbc the current database context
6881     * @param report an I_CmsReport instance to print output message, or null to write messages to the log file
6882     */

6883    public void updateExportPoints(CmsDbContext dbc, I_CmsReport report) {
6884
6885        try {
6886            // read the export points and return immediately if there are no export points at all
6887
Set exportPoints = new HashSet JavaDoc();
6888            exportPoints.addAll(OpenCms.getExportPoints());
6889            exportPoints.addAll(OpenCms.getModuleManager().getExportPoints());
6890            if (exportPoints.size() == 0) {
6891                if (LOG.isWarnEnabled()) {
6892                    LOG.warn(Messages.get().getBundle().key(Messages.LOG_NO_EXPORT_POINTS_CONFIGURED_0));
6893                }
6894                return;
6895            }
6896
6897            // create the driver to write the export points
6898
CmsExportPointDriver exportPointDriver = new CmsExportPointDriver(exportPoints);
6899
6900            // the report may be null if the export point update was started by an event on a remote server
6901
if (report == null) {
6902                if (dbc.getRequestContext() != null) {
6903                    report = new CmsLogReport(dbc.getRequestContext().getLocale(), getClass());
6904                } else {
6905                    report = new CmsLogReport(CmsLocaleManager.getDefaultLocale(), getClass());
6906                }
6907            }
6908
6909            // the export point hash table contains RFS export paths keyed by their internal VFS paths
6910
Iterator JavaDoc i = exportPointDriver.getExportPointPaths().iterator();
6911            while (i.hasNext()) {
6912                String JavaDoc currentExportPoint = (String JavaDoc)i.next();
6913
6914                // print some report messages
6915
if (LOG.isInfoEnabled()) {
6916                    LOG.info(Messages.get().getBundle().key(Messages.LOG_WRITE_EXPORT_POINT_1, currentExportPoint));
6917                }
6918
6919                try {
6920                    CmsResourceFilter filter = CmsResourceFilter.DEFAULT;
6921                    List resources = m_vfsDriver.readResourceTree(
6922                        dbc,
6923                        CmsProject.ONLINE_PROJECT_ID,
6924                        currentExportPoint,
6925                        filter.getType(),
6926                        filter.getState(),
6927                        filter.getModifiedAfter(),
6928                        filter.getModifiedBefore(),
6929                        filter.getReleaseAfter(),
6930                        filter.getReleaseBefore(),
6931                        filter.getExpireAfter(),
6932                        filter.getExpireBefore(),
6933                        CmsDriverManager.READMODE_INCLUDE_TREE
6934                            | (filter.excludeType() ? CmsDriverManager.READMODE_EXCLUDE_TYPE : 0)
6935                            | (filter.excludeState() ? CmsDriverManager.READMODE_EXCLUDE_STATE : 0));
6936
6937                    Iterator JavaDoc j = resources.iterator();
6938                    while (j.hasNext()) {
6939                        CmsResource currentResource = (CmsResource)j.next();
6940
6941                        if (currentResource.isFolder()) {
6942                            // export the folder
6943
exportPointDriver.createFolder(currentResource.getRootPath(), currentExportPoint);
6944                        } else {
6945                            // try to create the exportpoint folder
6946
exportPointDriver.createFolder(currentExportPoint, currentExportPoint);
6947                            // export the file content online
6948
CmsFile file = getVfsDriver().readFile(
6949                                dbc,
6950                                CmsProject.ONLINE_PROJECT_ID,
6951                                false,
6952                                currentResource.getStructureId());
6953                            exportPointDriver.writeFile(file.getRootPath(), currentExportPoint, file.getContents());
6954                        }
6955                    }
6956                } catch (CmsException e) {
6957                    // there might exist export points without corresponding resources in the VFS
6958
// -> ignore exceptions which are not "resource not found" exception quiet here
6959
if (e instanceof CmsVfsResourceNotFoundException) {
6960                        if (LOG.isErrorEnabled()) {
6961                            LOG.error(Messages.get().getBundle().key(Messages.LOG_UPDATE_EXORT_POINTS_ERROR_0), e);
6962                        }
6963                    }
6964                }
6965            }
6966        } catch (Exception JavaDoc e) {
6967            if (LOG.isErrorEnabled()) {
6968                LOG.error(Messages.get().getBundle().key(Messages.LOG_UPDATE_EXORT_POINTS_ERROR_0), e);
6969            }
6970        }
6971    }
6972
6973    /**
6974     * Returns <code>true</code> if a user is member of the given group.<p>
6975     *
6976     * @param dbc the current database context
6977     * @param username the name of the user to check
6978     * @param groupname the name of the group to check
6979     *
6980     * @return <code>true</code>, if the user is in the group, <code>false</code> otherwise
6981     *
6982     * @throws CmsException if something goes wrong
6983     */

6984    public boolean userInGroup(CmsDbContext dbc, String JavaDoc username, String JavaDoc groupname) throws CmsException {
6985
6986        List groups = getGroupsOfUser(dbc, username);
6987        for (int i = 0; i < groups.size(); i++) {
6988            if (groupname.equals(((CmsGroup)groups.get(i)).getName())) {
6989                return true;
6990            }
6991        }
6992        return false;
6993    }
6994
6995    /**
6996     * Validates the HTML links in the unpublished files of the specified
6997     * publish list, if a file resource type implements the interface
6998     * <code>{@link org.opencms.validation.I_CmsXmlDocumentLinkValidatable}</code>.<p>
6999     *
7000     * @param cms the current user's Cms object
7001     * @param publishList an OpenCms publish list
7002     * @param report a report to write the messages to
7003     *
7004     * @return a map with lists of invalid links (<code>String</code> objects) keyed by resource names
7005     *
7006     * @throws Exception if something goes wrong
7007     *
7008     * @see #fillPublishList(CmsDbContext, CmsPublishList)
7009     */

7010    public Map JavaDoc validateHtmlLinks(CmsObject cms, CmsPublishList publishList, I_CmsReport report) throws Exception JavaDoc {
7011
7012        return getHtmlLinkValidator().validateResources(cms, publishList.getFileList(), report);
7013    }
7014
7015    /**
7016     * This method checks if a new password follows the rules for
7017     * new passwords, which are defined by a Class implementing the
7018     * <code>{@link org.opencms.security.I_CmsPasswordHandler}</code>
7019     * interface and configured in the opencms.properties file.<p>
7020     *
7021     * If this method throws no exception the password is valid.<p>
7022     *
7023     * @param password the new password that has to be checked
7024     *
7025     * @throws CmsSecurityException if the password is not valid
7026     */

7027    public void validatePassword(String JavaDoc password) throws CmsSecurityException {
7028
7029        OpenCms.getPasswordHandler().validatePassword(password);
7030    }
7031
7032    /**
7033     * Writes an access control entries to a given resource.<p>
7034     *
7035     * @param dbc the current database context
7036     * @param resource the resource
7037     * @param ace the entry to write
7038     *
7039     * @throws CmsException if something goes wrong
7040     */

7041    public void writeAccessControlEntry(CmsDbContext dbc, CmsResource resource, CmsAccessControlEntry ace)
7042    throws CmsException {
7043
7044        // write the new ace
7045
m_userDriver.writeAccessControlEntry(dbc, dbc.currentProject(), ace);
7046
7047        // update the "last modified" information
7048
setDateLastModified(dbc, resource, resource.getDateLastModified());
7049
7050        // clear the cache
7051
clearAccessControlListCache();
7052
7053        // fire a resource modification event
7054
OpenCms.fireCmsEvent(new CmsEvent(I_CmsEventListener.EVENT_RESOURCE_MODIFIED, Collections.singletonMap(
7055            "resource",
7056            resource)));
7057    }
7058
7059    /**
7060     * Writes all export points into the file system for a publish task
7061     * specified by its publish history ID.<p>
7062     *
7063     * @param dbc the current database context
7064     * @param projectId the id of the project that was published
7065     * @param report an I_CmsReport instance to print output message, or null to write messages to the log file
7066     *
7067     * @param publishHistoryId unique int ID to identify each publish task in the publish history
7068     */

7069    public void writeExportPoints(CmsDbContext dbc, int projectId, I_CmsReport report, CmsUUID publishHistoryId) {
7070
7071        boolean printReportHeaders = false;
7072        try {
7073            // read the "published resources" for the specified publish history ID
7074
List publishedResources = m_projectDriver.readPublishedResources(dbc, projectId, publishHistoryId);
7075            if (publishedResources.size() == 0) {
7076                if (LOG.isWarnEnabled()) {
7077                    LOG.warn(Messages.get().getBundle().key(Messages.LOG_EMPTY_PUBLISH_HISTORY_1, publishHistoryId));
7078                }
7079                return;
7080            }
7081
7082            // read the export points and return immediately if there are no export points at all
7083
Set exportPoints = new HashSet JavaDoc();
7084            exportPoints.addAll(OpenCms.getExportPoints());
7085            exportPoints.addAll(OpenCms.getModuleManager().getExportPoints());
7086            if (exportPoints.size() == 0) {
7087                if (LOG.isWarnEnabled()) {
7088                    LOG.warn(Messages.get().getBundle().key(Messages.LOG_NO_EXPORT_POINTS_CONFIGURED_0));
7089                }
7090                return;
7091            }
7092
7093            // create the driver to write the export points
7094
CmsExportPointDriver exportPointDriver = new CmsExportPointDriver(exportPoints);
7095
7096            // the report may be null if the export point write was started by an event
7097
if (report == null) {
7098                if (dbc.getRequestContext() != null) {
7099                    report = new CmsLogReport(dbc.getRequestContext().getLocale(), getClass());
7100                } else {
7101                    report = new CmsLogReport(CmsLocaleManager.getDefaultLocale(), getClass());
7102                }
7103            }
7104
7105            // iterate over all published resources to export them eventually
7106
Iterator JavaDoc i = publishedResources.iterator();
7107            while (i.hasNext()) {
7108                CmsPublishedResource currentPublishedResource = (CmsPublishedResource)i.next();
7109                String JavaDoc currentExportPoint = exportPointDriver.getExportPoint(currentPublishedResource.getRootPath());
7110
7111                if (currentExportPoint != null) {
7112                    if (!printReportHeaders) {
7113                        report.println(
7114                            Messages.get().container(Messages.RPT_EXPORT_POINTS_WRITE_BEGIN_0),
7115                            I_CmsReport.FORMAT_HEADLINE);
7116                        printReportHeaders = true;
7117                    }
7118
7119                    if (currentPublishedResource.isFolder()) {
7120                        // export the folder
7121
if (currentPublishedResource.getState() == CmsResource.STATE_DELETED) {
7122                            exportPointDriver.deleteResource(currentPublishedResource.getRootPath(), currentExportPoint);
7123                        } else {
7124                            exportPointDriver.createFolder(currentPublishedResource.getRootPath(), currentExportPoint);
7125                        }
7126                    } else {
7127                        // export the file
7128
if (currentPublishedResource.getState() == CmsResource.STATE_DELETED) {
7129                            exportPointDriver.deleteResource(currentPublishedResource.getRootPath(), currentExportPoint);
7130                        } else {
7131                            // read the file content online
7132
CmsFile file = getVfsDriver().readFile(
7133                                dbc,
7134                                CmsProject.ONLINE_PROJECT_ID,
7135                                false,
7136                                currentPublishedResource.getStructureId());
7137                            exportPointDriver.writeFile(file.getRootPath(), currentExportPoint, file.getContents());
7138                        }
7139                    }
7140
7141                    // print some report messages
7142
if (currentPublishedResource.getState() == CmsResource.STATE_DELETED) {
7143
7144                        report.print(
7145                            Messages.get().container(Messages.RPT_EXPORT_POINTS_DELETE_0),
7146                            I_CmsReport.FORMAT_NOTE);
7147                        report.print(org.opencms.report.Messages.get().container(
7148                            org.opencms.report.Messages.RPT_ARGUMENT_1,
7149                            currentPublishedResource.getRootPath()));
7150                        report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0));
7151                        report.println(
7152                            org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0),
7153                            I_CmsReport.FORMAT_OK);
7154                    } else {
7155
7156                        report.print(
7157                            Messages.get().container(Messages.RPT_EXPORT_POINTS_WRITE_0),
7158                            I_CmsReport.FORMAT_NOTE);
7159                        report.print(org.opencms.report.Messages.get().container(
7160                            org.opencms.report.Messages.RPT_ARGUMENT_1,
7161                            currentPublishedResource.getRootPath()));
7162                        report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0));
7163                        report.println(
7164                            org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0),
7165                            I_CmsReport.FORMAT_OK);
7166                    }
7167                }
7168            }
7169        } catch (CmsException e) {
7170            if (LOG.isErrorEnabled()) {
7171                LOG.error(Messages.get().getBundle().key(Messages.LOG_WRITE_EXPORT_POINTS_ERROR_0), e);
7172            }
7173        } finally {
7174            if (printReportHeaders) {
7175                report.println(
7176                    Messages.get().container(Messages.RPT_EXPORT_POINTS_WRITE_END_0),
7177                    I_CmsReport.FORMAT_HEADLINE);
7178            }
7179        }
7180    }
7181
7182    /**
7183     * Writes a resource to the OpenCms VFS, including it's content.<p>
7184     *
7185     * Applies only to resources of type <code>{@link CmsFile}</code>
7186     * i.e. resources that have a binary content attached.<p>
7187     *
7188     * Certain resource types might apply content validation or transformation rules
7189     * before the resource is actually written to the VFS. The returned result
7190     * might therefore be a modified version from the provided original.<p>
7191     *
7192     * @param dbc the current database context
7193     * @param resource the resource to apply this operation to
7194     *
7195     * @return the written resource (may have been modified)
7196     *
7197     * @throws CmsException if something goes wrong
7198     *
7199     * @see CmsObject#writeFile(CmsFile)
7200     * @see I_CmsResourceType#writeFile(CmsObject, CmsSecurityManager, CmsFile)
7201     */

7202    public CmsFile writeFile(CmsDbContext dbc, CmsFile resource) throws CmsException {
7203
7204        resource.setUserLastModified(dbc.currentUser().getId());
7205
7206        m_vfsDriver.writeResource(dbc, dbc.currentProject(), resource, UPDATE_RESOURCE_STATE);
7207
7208        m_vfsDriver.writeContent(dbc, dbc.currentProject(), resource.getResourceId(), resource.getContents());
7209
7210        if (resource.getState() == CmsResource.STATE_UNCHANGED) {
7211            resource.setState(CmsResource.STATE_CHANGED);
7212        }
7213
7214        // update the cache
7215
clearResourceCache();
7216
7217        OpenCms.fireCmsEvent(new CmsEvent(I_CmsEventListener.EVENT_RESOURCE_MODIFIED, Collections.singletonMap(
7218            "resource",
7219            resource)));
7220
7221        return resource;
7222    }
7223
7224    /**
7225     * Writes an already existing group.<p>
7226     *
7227     * The group id has to be a valid OpenCms group id.<br>
7228     *
7229     * The group with the given id will be completely overriden
7230     * by the given data.<p>
7231     *
7232     * @param dbc the current database context
7233     * @param group the group that should be written
7234     *
7235     * @throws CmsException if operation was not succesfull
7236     */

7237    public void writeGroup(CmsDbContext dbc, CmsGroup group) throws CmsException {
7238
7239        m_groupCache.remove(new CacheId(group));
7240        m_userDriver.writeGroup(dbc, group);
7241        m_groupCache.put(new CacheId(group), group);
7242    }
7243
7244    /**
7245     * Writes an already existing project.<p>
7246     *
7247     * The project id has to be a valid OpenCms project id.<br>
7248     *
7249     * The project with the given id will be completely overriden
7250     * by the given data.<p>
7251     *
7252     * @param dbc the current database context
7253     * @param project the project that should be written
7254     *
7255     * @throws CmsException if operation was not successful
7256     */

7257    public void writeProject(CmsDbContext dbc, CmsProject project) throws CmsException {
7258
7259        m_projectDriver.writeProject(dbc, project);
7260        m_projectCache.put(project.getName(), project);
7261        m_projectCache.put(new Integer JavaDoc(project.getId()), project);
7262    }
7263
7264    /**
7265     * Writes a property for a specified resource.<p>
7266     *
7267     * @param dbc the current database context
7268     * @param resource the resource to write the property for
7269     * @param property the property to write
7270     *
7271     * @throws CmsException if something goes wrong
7272     *
7273     * @see CmsObject#writePropertyObject(String, CmsProperty)
7274     * @see I_CmsResourceType#writePropertyObject(CmsObject, CmsSecurityManager, CmsResource, CmsProperty)
7275     */

7276    public void writePropertyObject(CmsDbContext dbc, CmsResource resource, CmsProperty property) throws CmsException {
7277
7278        try {
7279            if (property == CmsProperty.getNullProperty()) {
7280                // skip empty or null properties
7281
return;
7282            }
7283
7284            // write the property
7285
m_vfsDriver.writePropertyObject(dbc, dbc.currentProject(), resource, property);
7286
7287            // update the resource state
7288
resource.setUserLastModified(dbc.currentUser().getId());
7289            m_vfsDriver.writeResource(dbc, dbc.currentProject(), resource, UPDATE_RESOURCE_STATE);
7290
7291        } finally {
7292            // update the driver manager cache
7293
clearResourceCache();
7294            m_propertyCache.clear();
7295
7296            // fire an event that a property of a resource has been modified
7297
Map JavaDoc data = new HashMap JavaDoc();
7298            data.put("resource", resource);
7299            data.put("property", property);
7300            OpenCms.fireCmsEvent(new CmsEvent(I_CmsEventListener.EVENT_PROPERTY_MODIFIED, data));
7301        }
7302    }
7303
7304    /**
7305     * Writes a list of properties for a specified resource.<p>
7306     *
7307     * Code calling this method has to ensure that the no properties
7308     * <code>a, b</code> are contained in the specified list so that <code>a.equals(b)</code>,
7309     * otherwise an exception is thrown.<p>
7310     *
7311     * @param dbc the current database context
7312     * @param resource the resource to write the properties for
7313     * @param properties the list of properties to write
7314     *
7315     * @throws CmsException if something goes wrong
7316     *
7317     * @see CmsObject#writePropertyObjects(String, List)
7318     * @see I_CmsResourceType#writePropertyObjects(CmsObject, CmsSecurityManager, CmsResource, List)
7319     */

7320    public void writePropertyObjects(CmsDbContext dbc, CmsResource resource, List properties) throws CmsException {
7321
7322        if ((properties == null) || (properties.size() == 0)) {
7323            // skip empty or null lists
7324
return;
7325        }
7326
7327        try {
7328
7329            // the specified list must not contain two or more equal property objects
7330
for (int i = 0, n = properties.size(); i < n; i++) {
7331                Set keyValidationSet = new HashSet JavaDoc();
7332                CmsProperty property = (CmsProperty)properties.get(i);
7333                if (!keyValidationSet.contains(property.getName())) {
7334                    keyValidationSet.add(property.getName());
7335                } else {
7336                    throw new CmsVfsException(Messages.get().container(
7337                        Messages.ERR_VFS_INVALID_PROPERTY_LIST_1,
7338                        property.getName()));
7339                }
7340            }
7341
7342            for (int i = 0; i < properties.size(); i++) {
7343                // write the property
7344
CmsProperty property = (CmsProperty)properties.get(i);
7345                m_vfsDriver.writePropertyObject(dbc, dbc.currentProject(), resource, property);
7346            }
7347        } finally {
7348            // update the driver manager cache
7349
clearResourceCache();
7350            m_propertyCache.clear();
7351
7352            // fire an event that the properties of a resource have been modified
7353
OpenCms.fireCmsEvent(new CmsEvent(
7354                I_CmsEventListener.EVENT_RESOURCE_AND_PROPERTIES_MODIFIED,
7355                Collections.singletonMap("resource", resource)));
7356        }
7357    }
7358
7359    /**
7360     * Writes a resource to the OpenCms VFS.<p>
7361     *
7362     * @param dbc the current database context
7363     * @param resource the resource to write
7364     *
7365     * @throws CmsException if something goes wrong
7366     */

7367    public void writeResource(CmsDbContext dbc, CmsResource resource) throws CmsException {
7368
7369        // access was granted - write the resource
7370
resource.setUserLastModified(dbc.currentUser().getId());
7371
7372        m_vfsDriver.writeResource(dbc, dbc.currentProject(), resource, UPDATE_RESOURCE_STATE);
7373
7374        // make sure the written resource has the state corretly set
7375
if (resource.getState() == CmsResource.STATE_UNCHANGED) {
7376            resource.setState(CmsResource.STATE_CHANGED);
7377        }
7378
7379        // update the cache
7380
clearResourceCache();
7381
7382        OpenCms.fireCmsEvent(new CmsEvent(I_CmsEventListener.EVENT_RESOURCE_MODIFIED, Collections.singletonMap(
7383            "resource",
7384            resource)));
7385    }
7386
7387    /**
7388     * Inserts an entry in the published resource table.<p>
7389     *
7390     * This is done during static export.<p>
7391     *
7392     * @param dbc the current database context
7393     * @param resourceName The name of the resource to be added to the static export
7394     * @param linkType the type of resource exported (0= non-paramter, 1=parameter)
7395     * @param linkParameter the parameters added to the resource
7396     * @param timestamp a timestamp for writing the data into the db
7397     *
7398     * @throws CmsException if something goes wrong
7399     */

7400    public void writeStaticExportPublishedResource(
7401        CmsDbContext dbc,
7402        String JavaDoc resourceName,
7403        int linkType,
7404        String JavaDoc linkParameter,
7405        long timestamp) throws CmsException {
7406
7407        m_projectDriver.writeStaticExportPublishedResource(
7408            dbc,
7409            dbc.currentProject(),
7410            resourceName,
7411            linkType,
7412            linkParameter,
7413            timestamp);
7414    }
7415
7416    /**
7417     * Writes a new user tasklog for a task.<p>
7418     *
7419     * @param dbc the current database context
7420     * @param taskid the Id of the task
7421     * @param comment description for the log
7422     *
7423     * @throws CmsException if something goes wrong
7424     */

7425    public void writeTaskLog(CmsDbContext dbc, int taskid, String JavaDoc comment) throws CmsException {
7426
7427        m_workflowDriver.writeTaskLog(dbc, taskid, dbc.currentUser().getId(), new java.sql.Timestamp JavaDoc(
7428            System.currentTimeMillis()), comment, CmsTaskService.TASKLOG_USER);
7429    }
7430
7431    /**
7432     * Writes a new task log entry for a task.<p>
7433     *
7434     * @param dbc the current database context
7435     * @param taskId the Id of the task
7436     * @param comment description for the log
7437     * @param type type of the tasklog. User tasktypes must be greater then 100
7438     *
7439     * @throws CmsException something goes wrong
7440     */

7441    public void writeTaskLog(CmsDbContext dbc, int taskId, String JavaDoc comment, int type) throws CmsException {
7442
7443        m_workflowDriver.writeTaskLog(dbc, taskId, dbc.currentUser().getId(), new java.sql.Timestamp JavaDoc(
7444            System.currentTimeMillis()), comment, type);
7445    }
7446
7447    /**
7448     * Updates the user information. <p>
7449     *
7450     * The user id has to be a valid OpenCms user id.<br>
7451     *
7452     * The user with the given id will be completely overriden
7453     * by the given data.<p>
7454     *
7455     * @param dbc the current database context
7456     * @param user the user to be updated
7457     *
7458     * @throws CmsException if operation was not succesful
7459     */

7460    public void writeUser(CmsDbContext dbc, CmsUser user) throws CmsException {
7461
7462        clearUserCache(user);
7463        m_userDriver.writeUser(dbc, user);
7464        // update the cache
7465
putUserInCache(user);
7466    }
7467
7468    /**
7469     * Updates the user information of a web user.<br>
7470     *
7471     * Only a web user can be updated this way.<p>
7472     *
7473     * The user id has to be a valid OpenCms user id.<br>
7474     *
7475     * The user with the given id will be completely overriden
7476     * by the given data.<p>
7477     *
7478     * @param dbc the current database context
7479     * @param user the user to be updated
7480     *
7481     * @throws CmsException if operation was not succesful
7482     */

7483    public void writeWebUser(CmsDbContext dbc, CmsUser user) throws CmsException {
7484
7485        clearUserCache(user);
7486        m_userDriver.writeUser(dbc, user);
7487        // update the cache
7488
putUserInCache(user);
7489    }
7490
7491    /**
7492     * Converts a resource to a folder (if possible).<p>
7493     *
7494     * @param resource the resource to convert
7495     * @return the converted resource
7496     *
7497     * @throws CmsVfsResourceNotFoundException if the resource is not a folder
7498     */

7499    protected CmsFolder convertResourceToFolder(CmsResource resource) throws CmsVfsResourceNotFoundException {
7500
7501        if (resource.isFolder()) {
7502            return new CmsFolder(resource);
7503        }
7504
7505        throw new CmsVfsResourceNotFoundException(Messages.get().container(
7506            Messages.ERR_ACCESS_FILE_AS_FOLDER_1,
7507            resource.getRootPath()));
7508    }
7509
7510    /**
7511     * Releases any allocated resources during garbage collection.<p>
7512     *
7513     * @see java.lang.Object#finalize()
7514     */

7515    protected void finalize() throws Throwable JavaDoc {
7516
7517        try {
7518            clearcache(false);
7519
7520            try {
7521                m_projectDriver.destroy();
7522            } catch (Throwable JavaDoc t) {
7523                LOG.error(Messages.get().getBundle().key(Messages.ERR_CLOSE_PROJECT_DRIVER_0), t);
7524            }
7525            try {
7526                m_userDriver.destroy();
7527            } catch (Throwable JavaDoc t) {
7528                LOG.error(Messages.get().getBundle().key(Messages.ERR_CLOSE_USER_DRIVER_0), t);
7529            }
7530            try {
7531                m_vfsDriver.destroy();
7532            } catch (Throwable JavaDoc t) {
7533                LOG.error(Messages.get().getBundle().key(Messages.ERR_CLOSE_VFS_DRIVER_0), t);
7534            }
7535            try {
7536                m_workflowDriver.destroy();
7537            } catch (Throwable JavaDoc t) {
7538                LOG.error(Messages.get().getBundle().key(Messages.ERR_CLOSE_WORKFLOW_DRIVER_0), t);
7539            }
7540            try {
7541                m_backupDriver.destroy();
7542            } catch (Throwable JavaDoc t) {
7543                LOG.error(Messages.get().getBundle().key(Messages.ERR_CLOSE_BACKUP_DRIVER_0), t);
7544            }
7545
7546            for (int i = 0; i < m_connectionPools.size(); i++) {
7547                PoolingDriver driver = (PoolingDriver)m_connectionPools.get(i);
7548                String JavaDoc[] pools = driver.getPoolNames();
7549                for (int j = 0; j < pools.length; j++) {
7550                    try {
7551                        driver.closePool(pools[j]);
7552                        if (CmsLog.INIT.isDebugEnabled()) {
7553                            CmsLog.INIT.debug(Messages.get().getBundle().key(Messages.INIT_CLOSE_CONN_POOL_1, pools[j]));
7554                        }
7555                    } catch (Throwable JavaDoc t) {
7556                        LOG.error(Messages.get().getBundle().key(Messages.LOG_CLOSE_CONN_POOL_ERROR_1, pools[j]), t);
7557                    }
7558                }
7559            }
7560
7561            m_userCache = null;
7562            m_groupCache = null;
7563            m_userGroupsCache = null;
7564            m_projectCache = null;
7565            m_propertyCache = null;
7566            m_resourceCache = null;
7567            m_resourceListCache = null;
7568            m_accessControlListCache = null;
7569
7570            m_projectDriver = null;
7571            m_userDriver = null;
7572            m_vfsDriver = null;
7573            m_workflowDriver = null;
7574            m_backupDriver = null;
7575
7576            m_htmlLinkValidator = null;
7577        } catch (Throwable JavaDoc t) {
7578            // ignore
7579
}
7580        super.finalize();
7581    }
7582
7583    /**
7584     * Checks if this is a valid group for webusers.<p>
7585     *
7586     * @param dbc the current database context
7587     * @param group the group to be checked
7588     *
7589     * @return true if the group does not belong to users, administrators or projectmanagers
7590     * @throws CmsException if operation was not succesful
7591     */

7592    protected boolean isWebgroup(CmsDbContext dbc, CmsGroup group) throws CmsException {
7593
7594        CmsUUID user = m_userDriver.readGroup(dbc, OpenCms.getDefaultUsers().getGroupUsers()).getId();
7595        CmsUUID admin = m_userDriver.readGroup(dbc, OpenCms.getDefaultUsers().getGroupAdministrators()).getId();
7596        CmsUUID manager = m_userDriver.readGroup(dbc, OpenCms.getDefaultUsers().getGroupProjectmanagers()).getId();
7597
7598        if ((group.getId().equals(user)) || (group.getId().equals(admin)) || (group.getId().equals(manager))) {
7599            return false;
7600        } else {
7601            // check if the group belongs to Users, Administrators or Projectmanager
7602
if (!group.getParentId().isNullUUID()) {
7603                // check is the parentgroup is a webgroup
7604
return isWebgroup(dbc, m_userDriver.readGroup(dbc, group.getParentId()));
7605            }
7606        }
7607
7608        return true;
7609    }
7610
7611    /**
7612     * Checks the parent of a resource during publishing.<p>
7613     *
7614     * @param dbc the current database context
7615     * @param folderList a list of folders
7616     * @param res a resource to check the parent for
7617     *
7618     * @return true if the resource should be published
7619     */

7620    private boolean checkParentResource(CmsDbContext dbc, List folderList, CmsResource res) {
7621
7622        String JavaDoc parentPath = CmsResource.getParentFolder(res.getRootPath());
7623        CmsResource parent;
7624
7625        if (parentPath == null) {
7626            // resource has no parent
7627
return true;
7628        }
7629
7630        try {
7631            parent = readResource(dbc, parentPath, CmsResourceFilter.ALL);
7632        } catch (Exception JavaDoc e) {
7633            // failure: if we cannot read the parent, we should not publish the resource
7634
return false;
7635        }
7636
7637        if (parent.getState() != CmsResource.STATE_NEW) {
7638            // parent is already published
7639
return true;
7640        }
7641
7642        for (int j = 0; j < folderList.size(); j++) {
7643            if (((CmsResource)folderList.get(j)).getStructureId().equals(parent.getStructureId())) {
7644                // parent is new, but it will get published
7645
return true;
7646            }
7647        }
7648
7649        // parent is new, but it will not get published
7650
return false;
7651    }
7652
7653    /**
7654     * Clears the access control list cache when access control entries are changed.<p>
7655     */

7656    private void clearAccessControlListCache() {
7657
7658        m_accessControlListCache.clear();
7659        m_securityManager.clearPermissionCache();
7660        clearResourceCache();
7661    }
7662
7663    /**
7664     * Clears all internal caches.<p>
7665     *
7666     * @param principalsOnly clear group and user caches only flag
7667     */

7668    private void clearcache(boolean principalsOnly) {
7669
7670        m_userCache.clear();
7671        m_groupCache.clear();
7672        m_userGroupsCache.clear();
7673        m_accessControlListCache.clear();
7674        m_securityManager.clearPermissionCache();
7675
7676        if (!principalsOnly) {
7677            m_projectCache.clear();
7678            m_resourceCache.clear();
7679            m_resourceListCache.clear();
7680            m_propertyCache.clear();
7681        }
7682    }
7683
7684    /**
7685     * Clears all the depending caches when a resource was changed.<p>
7686     */

7687    private void clearResourceCache() {
7688
7689        m_resourceCache.clear();
7690        m_resourceListCache.clear();
7691    }
7692
7693    /**
7694     * Clears the user cache for the given user.<p>
7695     * @param user the user
7696     */

7697    private void clearUserCache(CmsUser user) {
7698
7699        removeUserFromCache(user);
7700        m_resourceListCache.clear();
7701    }
7702
7703    /**
7704     * Creates a new user.<p>
7705     *
7706     * @param dbc the current database context
7707     * @param name the name for the new user
7708     * @param password the password for the new user
7709     * @param description the description for the new user
7710     * @param additionalInfos the additional infos for the user
7711     * @param type the type of the user to create
7712     *
7713     * @return the created user
7714     *
7715     * @see CmsObject#createUser(String, String, String, Map)
7716     *
7717     * @throws CmsException if something goes wrong
7718     * @throws CmsIllegalArgumentException if the name for the user is not valid
7719     */

7720    private CmsUser createUser(
7721        CmsDbContext dbc,
7722        String JavaDoc name,
7723        String JavaDoc password,
7724        String JavaDoc description,
7725        Map JavaDoc additionalInfos,
7726        int type) throws CmsException, CmsIllegalArgumentException {
7727
7728        // no space before or after the name
7729
name = name.trim();
7730        // check the username
7731
OpenCms.getValidationHandler().checkUserName(name);
7732        // check the password
7733
validatePassword(password);
7734
7735        if ((name.length() > 0)) {
7736            return m_userDriver.createUser(
7737                dbc,
7738                name,
7739                password,
7740                description,
7741                " ",
7742                " ",
7743                " ",
7744                0,
7745                I_CmsPrincipal.FLAG_ENABLED,
7746                additionalInfos,
7747                " ",
7748                type);
7749        } else {
7750            throw new CmsIllegalArgumentException(Messages.get().container(Messages.ERR_BAD_USER_1, name));
7751        }
7752    }
7753
7754    /**
7755     * Filters the given list of resources, removes all resources where the current user
7756     * does not have READ permissions, plus the filter is applied.<p>
7757     *
7758     * @param dbc the current database context
7759     * @param resourceList a list of CmsResources
7760     * @param filter the resource filter to use
7761     *
7762     * @return the filtered list of resources
7763     *
7764     * @throws CmsException in case errors testing the permissions
7765     */

7766    private List filterPermissions(CmsDbContext dbc, List resourceList, CmsResourceFilter filter) throws CmsException {
7767
7768        if (filter.requireTimerange()) {
7769            // never check time range here - this must be done later in #updateContextDates(...)
7770
filter = filter.addExcludeTimerange();
7771        }
7772        ArrayList JavaDoc result = new ArrayList JavaDoc(resourceList.size());
7773        for (int i = 0; i < resourceList.size(); i++) {
7774            // check the permission of all resources
7775
CmsResource currentResource = (CmsResource)resourceList.get(i);
7776            int perms = m_securityManager.hasPermissions(
7777                dbc,
7778                currentResource,
7779                CmsPermissionSet.ACCESS_READ,
7780                true,
7781                filter);
7782            if (perms == CmsSecurityManager.PERM_ALLOWED) {
7783                // only return resources where permission was granted
7784
result.add(currentResource);
7785            }
7786        }
7787        // return the result
7788
return result;
7789    }
7790
7791    /**
7792     * Returns a filtered list of resources for publishing.<p>
7793     * Contains all resources, which are not locked
7794     * and which have a parent folder that is already published or will be published, too.
7795     *
7796     * @param dbc the current database context
7797     * @param folderList the list of folders that will be published
7798     * @param resourceList the list of resources to filter
7799     * @return a filtered list of resources
7800     */

7801    private List filterResources(CmsDbContext dbc, List folderList, List resourceList) {
7802
7803        List result = new ArrayList JavaDoc();
7804
7805        // local folder list for adding new publishing subfolders
7806
// this solves the TestPublishIssues.testPublishScenarioD problem.
7807
List newFolderList = folderList == null ? new ArrayList JavaDoc() : new ArrayList JavaDoc(folderList);
7808
7809        for (int i = 0; i < resourceList.size(); i++) {
7810            CmsResource res = (CmsResource)resourceList.get(i);
7811            try {
7812                CmsLock lock = getLock(dbc, res);
7813                if (!lock.isNullLock()) {
7814                    // checks if there is a shared lock and if the resource is deleted
7815
// this solves the TestPublishIssues.testPublishScenarioE problem.
7816
if (lock.getType() == CmsLock.TYPE_SHARED_INHERITED
7817                        || lock.getType() == CmsLock.TYPE_SHARED_EXCLUSIVE) {
7818                        if (res.getState() != CmsResource.STATE_DELETED) {
7819                            continue;
7820                        }
7821                    } else {
7822                        // don't add locked resources
7823
continue;
7824                    }
7825                }
7826
7827                if (!"/".equals(res.getRootPath()) && !checkParentResource(dbc, newFolderList, res)) {
7828                    continue;
7829                }
7830
7831                if (res.isFolder()) {
7832                    newFolderList.add(res);
7833                }
7834
7835                result.add(res);
7836
7837            } catch (Exception JavaDoc e) {
7838                // noop
7839
}
7840        }
7841        return result;
7842    }
7843
7844    /**
7845     * Returns a filtered list of sibling resources for publishing.<p>
7846     *
7847     * Contains all other siblings of the given resources, which are not locked
7848     * and which have a parent folder that is already published or will be published, too.<p>
7849     *
7850     * @param dbc the current database context
7851     * @param currentResource the resource to lookup siblings
7852     * @param folderList the list of folders that will be published
7853     * @param resourceList the list of siblings to filter
7854     *
7855     * @return a filtered list of sibling resources for publishing
7856     */

7857    private List filterSiblings(CmsDbContext dbc, CmsResource currentResource, List folderList, List resourceList) {
7858
7859        List result = new ArrayList JavaDoc();
7860
7861        // local folder list for adding new publishing subfolders
7862
// this solves the TestPublishIssues.testPublishScenarioD problem.
7863
List newFolderList = folderList == null ? new ArrayList JavaDoc() : new ArrayList JavaDoc(folderList);
7864
7865        for (int i = 0; i < resourceList.size(); i++) {
7866            CmsResource res = (CmsResource)resourceList.get(i);
7867            try {
7868                if (res.getStructureId().equals(currentResource.getStructureId())) {
7869                    // don't add if sibling is equal to current resource
7870
// note: it's also required to check for sibling duplicates in the
7871
// publish list itself
7872
continue;
7873                }
7874
7875                CmsLock lock = getLock(dbc, res);
7876                if (!lock.isNullLock()) {
7877                    // checks if there is a shared lock and if the resource is deleted
7878
// this solves the TestPublishIssues.testPublishScenarioE problem.
7879
if (lock.getType() == CmsLock.TYPE_SHARED_INHERITED
7880                        || lock.getType() == CmsLock.TYPE_SHARED_EXCLUSIVE) {
7881                        if (res.getState() != CmsResource.STATE_DELETED) {
7882                            continue;
7883                        }
7884                    } else {
7885                        // don't add locked resources
7886
continue;
7887                    }
7888                }
7889
7890                if (!"/".equals(res.getRootPath()) && !checkParentResource(dbc, newFolderList, res)) {
7891                    // don't add resources that have no parent in the online project
7892
continue;
7893                }
7894
7895                if (res.isFolder()) {
7896                    newFolderList.add(res);
7897                }
7898
7899                result.add(res);
7900
7901            } catch (Exception JavaDoc e) {
7902                // noop
7903
}
7904        }
7905        return result;
7906    }
7907
7908    /**
7909     * Returns the access control list of a given resource.<p>
7910     *
7911     * @param dbc the current database context
7912     * @param resource the resource
7913     * @param forFolder should be true if resource is a folder
7914     * @param depth the depth to include non-inherited access entries, also
7915     * @param inheritedOnly flag indicates to collect inherited permissions only
7916     *
7917     * @return the access control list of the resource
7918     *
7919     * @throws CmsException if something goes wrong
7920     */

7921    private CmsAccessControlList getAccessControlList(
7922        CmsDbContext dbc,
7923        CmsResource resource,
7924        boolean inheritedOnly,
7925        boolean forFolder,
7926        int depth) throws CmsException {
7927
7928        String JavaDoc cacheKey = getCacheKey(new String JavaDoc[] {
7929            inheritedOnly ? "+" : "-",
7930            forFolder ? "+" : "-",
7931            Integer.toString(depth),
7932            resource.getRootPath()}, dbc.currentProject());
7933
7934        CmsAccessControlList acl = (CmsAccessControlList)m_accessControlListCache.get(cacheKey);
7935
7936        // return the cached acl if already available
7937
if (acl != null) {
7938            return acl;
7939        }
7940
7941        String JavaDoc parentPath = CmsResource.getParentFolder(resource.getRootPath());
7942        // otherwise, get the acl of the parent or a new one
7943
if (parentPath != null) {
7944            CmsResource parentResource = m_vfsDriver.readFolder(dbc, dbc.currentProject().getId(), parentPath);
7945            // recurse
7946
acl = (CmsAccessControlList)getAccessControlList(dbc, parentResource, inheritedOnly, forFolder, depth + 1).clone();
7947        } else {
7948            acl = new CmsAccessControlList();
7949        }
7950
7951        if (!(depth == 0 && inheritedOnly)) {
7952
7953            ListIterator JavaDoc ace = m_userDriver.readAccessControlEntries(
7954                dbc,
7955                dbc.currentProject(),
7956                resource.getResourceId(),
7957                depth > 1 || (depth > 0 && forFolder)).listIterator();
7958
7959            while (ace.hasNext()) {
7960                CmsAccessControlEntry acEntry = (CmsAccessControlEntry)ace.next();
7961                if (depth > 0) {
7962                    acEntry.setFlags(CmsAccessControlEntry.ACCESS_FLAGS_INHERITED);
7963                }
7964
7965                acl.add(acEntry);
7966
7967                // if the overwrite flag is set, reset the allowed permissions to the permissions of this entry
7968
// denied permissions are kept or extended
7969
if ((acEntry.getFlags() & CmsAccessControlEntry.ACCESS_FLAGS_OVERWRITE) > 0) {
7970                    acl.setAllowedPermissions(acEntry);
7971                }
7972            }
7973        }
7974
7975        m_accessControlListCache.put(cacheKey, acl);
7976        return acl;
7977    }
7978
7979    /**
7980     * Return a cache key build from the provided information.<p>
7981     *
7982     * @param prefix a prefix for the key
7983     * @param flag a boolean flag for the key (only used if prefix is not null)
7984     * @param projectId the project for which to genertate the key
7985     * @param resource the resource for which to genertate the key
7986     * @return String a cache key build from the provided information
7987     */

7988    private String JavaDoc getCacheKey(String JavaDoc prefix, boolean flag, int projectId, String JavaDoc resource) {
7989
7990        StringBuffer JavaDoc b = new StringBuffer JavaDoc(64);
7991        if (prefix != null) {
7992            b.append(prefix);
7993            b.append(flag ? '+' : '-');
7994        }
7995        if (projectId >= CmsProject.ONLINE_PROJECT_ID) {
7996            b.append(CmsProject.isOnlineProject(projectId) ? '+' : '-');
7997        }
7998        return b.append(resource).toString();
7999    }
8000
8001    /**
8002     * Return a cache key build from the provided information.<p>
8003     *
8004     * @param keys an array of keys to generate the cache key from
8005     * @param project the project for which to genertate the key
8006     *
8007     * @return String a cache key build from the provided information
8008     */

8009    private String JavaDoc getCacheKey(String JavaDoc[] keys, CmsProject project) {
8010
8011        StringBuffer JavaDoc b = new StringBuffer JavaDoc(64);
8012        int len = keys.length;
8013        if (len > 0) {
8014            for (int i = 0; i < len; i++) {
8015                b.append(keys[i]);
8016                b.append('_');
8017            }
8018        }
8019        if (project != null) {
8020            b.append(project.isOnlineProject() ? '+' : '-');
8021        }
8022        return b.toString();
8023    }
8024
8025    /**
8026     * Gets a user cache key.<p>
8027     *
8028     * @param id the user uuid
8029     * @return the user cache key
8030     */

8031    private String JavaDoc getUserCacheKey(CmsUUID id) {
8032
8033        return id.toString();
8034    }
8035
8036    /**
8037     * Gets a user cache key.<p>
8038     *
8039     * @param username the name of the user
8040     * @param type the user type
8041     * @return the user cache key
8042     */

8043    private String JavaDoc getUserCacheKey(String JavaDoc username, int type) {
8044
8045        StringBuffer JavaDoc result = new StringBuffer JavaDoc(32);
8046        result.append(username);
8047        result.append(USER_CACHE_SEP);
8048        result.append(CmsUser.isSystemUser(type));
8049        return result.toString();
8050    }
8051
8052    /**
8053     * Gets a user from cache.<p>
8054     *
8055     * @param id the user uuid
8056     * @return CmsUser from cache
8057     */

8058    private CmsUser getUserFromCache(CmsUUID id) {
8059
8060        return (CmsUser)m_userCache.get(getUserCacheKey(id));
8061    }
8062
8063    /**
8064     * Gets a user from cache.<p>
8065     *
8066     * @param username the username
8067     * @param type the user tpye
8068     * @return CmsUser from cache
8069     */

8070    private CmsUser getUserFromCache(String JavaDoc username, int type) {
8071
8072        return (CmsUser)m_userCache.get(getUserCacheKey(username, type));
8073    }
8074
8075    /**
8076     * Stores a user in the user cache.<p>
8077     *
8078     * @param user the user to be stored in the cache
8079     */

8080    private void putUserInCache(CmsUser user) {
8081
8082        m_userCache.put(getUserCacheKey(user.getName(), user.getType()), user);
8083        m_userCache.put(getUserCacheKey(user.getId()), user);
8084    }
8085
8086    /**
8087     * Removes user from Cache.<p>
8088     *
8089     * @param user the user to remove
8090     */

8091    private void removeUserFromCache(CmsUser user) {
8092
8093        m_userCache.remove(getUserCacheKey(user.getName(), user.getType()));
8094        m_userCache.remove(getUserCacheKey(user.getId()));
8095    }
8096
8097    /**
8098     * All permissions and resources attributes of the principal
8099     * are transfered to a replacement principal.<p>
8100     *
8101     * @param dbc the current database context
8102     * @param project the current project
8103     * @param principalId the id of the principal to be replaced
8104     * @param replacementId the user to be transfered
8105     * @param withACEs flag to signal if the ACEs should also be transfered or just deleted
8106     *
8107     * @throws CmsException if operation was not succesfull
8108     */

8109    private void transferPrincipalResources(
8110        CmsDbContext dbc,
8111        CmsProject project,
8112        CmsUUID principalId,
8113        CmsUUID replacementId,
8114        boolean withACEs) throws CmsException {
8115
8116        // get all resources for the given user including resources associated by ACEs or attributes
8117
List resources = getResourcesForPrincipal(dbc, project, principalId, null, true);
8118        Iterator JavaDoc it = resources.iterator();
8119        while (it.hasNext()) {
8120            CmsResource resource = (CmsResource)it.next();
8121            // check resource attributes
8122
boolean attrModified = false;
8123            CmsUUID createdUser = null;
8124            if (resource.getUserCreated().equals(principalId)) {
8125                createdUser = replacementId;
8126                attrModified = true;
8127            }
8128            CmsUUID lastModUser = null;
8129            if (resource.getUserLastModified().equals(principalId)) {
8130                lastModUser = replacementId;
8131                attrModified = true;
8132            }
8133            if (attrModified) {
8134                m_vfsDriver.transferResource(dbc, project, resource, createdUser, lastModUser);
8135                // clear the cache
8136
clearResourceCache();
8137            }
8138            // check aces
8139
boolean aceModified = false;
8140            if (withACEs) {
8141                Iterator JavaDoc itAces = m_userDriver.readAccessControlEntries(dbc, project, resource.getResourceId(), false).iterator();
8142                while (itAces.hasNext()) {
8143                    CmsAccessControlEntry ace = (CmsAccessControlEntry)itAces.next();
8144                    if (ace.getPrincipal().equals(principalId)) {
8145                        CmsAccessControlEntry newAce = new CmsAccessControlEntry(
8146                            ace.getResource(),
8147                            replacementId,
8148                            ace.getAllowedPermissions(),
8149                            ace.getDeniedPermissions(),
8150                            ace.getFlags());
8151                        // write the new ace
8152
m_userDriver.writeAccessControlEntry(dbc, project, newAce);
8153                        aceModified = true;
8154                    }
8155                }
8156            }
8157            if (aceModified) {
8158                // clear the cache
8159
clearAccessControlListCache();
8160            }
8161            if (attrModified || aceModified) {
8162                // fire the event
8163
OpenCms.fireCmsEvent(new CmsEvent(I_CmsEventListener.EVENT_RESOURCE_MODIFIED, Collections.singletonMap(
8164                    "resource",
8165                    resource)));
8166            }
8167        }
8168    }
8169
8170    /**
8171     * Updates the date information in the database context.<p>
8172     *
8173     * @param dbc the context to update
8174     * @param resource the resource to get the date information from
8175     */

8176    private void updateContextDates(CmsDbContext dbc, CmsResource resource) {
8177
8178        CmsFlexRequestContextInfo info = dbc.getFlexRequestContextInfo();
8179
8180        if (info != null) {
8181            info.updateFromResource(resource);
8182        }
8183    }
8184
8185    /**
8186     * Updates the current users context dates with each {@link CmsResource} object in the given list.<p>
8187     *
8188     * The given input list is returned unmodified.<p>
8189     *
8190     * Please see {@link #updateContextDates(CmsDbContext, CmsResource)} for an explanation of what this method does.<p>
8191     *
8192     * @param dbc the current database context
8193     * @param resourceList a list of {@link CmsResource} objects
8194     *
8195     * @return the original list of CmsResources with the full resource name set
8196     */

8197    private List updateContextDates(CmsDbContext dbc, List resourceList) {
8198
8199        CmsFlexRequestContextInfo info = dbc.getFlexRequestContextInfo();
8200        if (info != null) {
8201            for (int i = 0; i < resourceList.size(); i++) {
8202                CmsResource resource = (CmsResource)resourceList.get(i);
8203                info.updateFromResource(resource);
8204            }
8205        }
8206        return resourceList;
8207    }
8208
8209    /**
8210     * Returns a List of {@link CmsResource} objects generated when applying the given filter to the given list,
8211     * also updates the current users context dates with each {@link CmsResource} object in the given list,
8212     * also applies the selected resource filter to all resources in the list and returns the remaining resources.<p>
8213     *
8214     * Please see {@link #updateContextDates(CmsDbContext, CmsResource)} for an explanation of what this method does.<p>
8215     *
8216     * @param dbc the current database context
8217     * @param resourceList a list of {@link CmsResource} objects
8218     * @param filter the resource filter to use
8219     *
8220     * @return a List of {@link CmsResource} objects generated when applying the given filter to the given list
8221     */

8222    private List updateContextDates(CmsDbContext dbc, List resourceList, CmsResourceFilter filter) {
8223
8224        if (CmsResourceFilter.ALL == filter) {
8225            // if there is no filter required, then use the simpler method that does not apply the filter
8226
if (resourceList instanceof ArrayList JavaDoc) {
8227                // performance implementation for ArrayLists
8228
return (List)((ArrayList JavaDoc)(updateContextDates(dbc, resourceList))).clone();
8229            } else {
8230                return new ArrayList JavaDoc(updateContextDates(dbc, resourceList));
8231            }
8232        }
8233
8234        CmsFlexRequestContextInfo info = dbc.getFlexRequestContextInfo();
8235        ArrayList JavaDoc result = new ArrayList JavaDoc(resourceList.size());
8236        for (int i = 0; i < resourceList.size(); i++) {
8237            CmsResource resource = (CmsResource)resourceList.get(i);
8238            if (filter.isValid(dbc.getRequestContext(), resource)) {
8239                result.add(resource);
8240            }
8241            // must also include "invalid" resources for the update of context dates
8242
// since a resource may be invalid because of release / expiration date
8243
if (info != null) {
8244                info.updateFromResource(resource);
8245            }
8246        }
8247        return result;
8248    }
8249}
Popular Tags