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