/* * This library is part of OpenCms - * the Open Source Content Management System * * Copyright (c) Alkacon Software GmbH (http://www.alkacon.com) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * For further information about Alkacon Software GmbH, please see the * company website: http://www.alkacon.com * * For further information about OpenCms, please see the * project website: http://www.opencms.org * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.opencms.db.generic; import org.opencms.configuration.CmsConfigurationManager; import org.opencms.configuration.CmsParameterConfiguration; import org.opencms.db.CmsDbContext; import org.opencms.db.CmsDbEntryNotFoundException; import org.opencms.db.CmsDbIoException; import org.opencms.db.CmsDbSqlException; import org.opencms.db.CmsDriverManager; import org.opencms.db.CmsPreparedStatementIntParameter; import org.opencms.db.CmsPreparedStatementLongParameter; import org.opencms.db.CmsPreparedStatementStringParameter; import org.opencms.db.CmsPublishList; import org.opencms.db.CmsPublishedResource; import org.opencms.db.CmsResourceState; import org.opencms.db.CmsVisitEntryFilter; import org.opencms.db.I_CmsDriver; import org.opencms.db.I_CmsHistoryDriver; import org.opencms.db.I_CmsPreparedStatementParameter; import org.opencms.db.I_CmsProjectDriver; import org.opencms.db.I_CmsVfsDriver; import org.opencms.db.log.CmsLogEntry; import org.opencms.db.log.CmsLogEntryType; import org.opencms.db.log.CmsLogFilter; import org.opencms.file.CmsDataAccessException; import org.opencms.file.CmsFile; import org.opencms.file.CmsFolder; import org.opencms.file.CmsGroup; import org.opencms.file.CmsProject; import org.opencms.file.CmsProperty; import org.opencms.file.CmsResource; import org.opencms.file.CmsResourceFilter; import org.opencms.file.CmsUser; import org.opencms.file.CmsVfsResourceAlreadyExistsException; import org.opencms.file.CmsVfsResourceNotFoundException; import org.opencms.file.history.CmsHistoryFile; import org.opencms.file.types.CmsResourceTypeFolder; import org.opencms.i18n.CmsMessageContainer; import org.opencms.lock.CmsLock; import org.opencms.lock.CmsLockType; import org.opencms.main.CmsEvent; import org.opencms.main.CmsException; import org.opencms.main.CmsLog; import org.opencms.main.I_CmsEventListener; import org.opencms.main.OpenCms; import org.opencms.publish.CmsPublishJobInfoBean; import org.opencms.relations.CmsRelationFilter; import org.opencms.report.I_CmsReport; import org.opencms.security.CmsOrganizationalUnit; import org.opencms.security.I_CmsPrincipal; import org.opencms.staticexport.CmsStaticExportManager; import org.opencms.util.CmsPair; import org.opencms.util.CmsStringUtil; import org.opencms.util.CmsUUID; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.apache.commons.logging.Log; import com.google.common.collect.Sets; /** * Generic (ANSI-SQL) implementation of the project driver methods.<p> * * @since 6.0.0 */ public class CmsProjectDriver implements I_CmsDriver, I_CmsProjectDriver { /** * This private class is a temporary storage for the method {@link CmsProjectDriver#readLocks(CmsDbContext)}.<p> */ private class CmsTempResourceLock { /** The lock type. */ private int m_lockType; /** The project id. */ private CmsUUID m_projectId; /** The resource path. */ private String m_resourcePath; /** The user id. */ private CmsUUID m_userId; /** * The constructor.<p> * * @param resourcePath resource path * @param userId user id * @param projectId project id * @param lockType lock type */ public CmsTempResourceLock(String resourcePath, CmsUUID userId, CmsUUID projectId, int lockType) { m_resourcePath = resourcePath; m_userId = userId; m_projectId = projectId; m_lockType = lockType; } /** * Returns the lockType.<p> * * @return the lockType */ public int getLockType() { return m_lockType; } /** * Returns the projectId.<p> * * @return the projectId */ public CmsUUID getProjectId() { return m_projectId; } /** * Returns the resourcePath.<p> * * @return the resourcePath */ public String getResourcePath() { return m_resourcePath; } /** * Returns the userId.<p> * * @return the userId */ public CmsUUID getUserId() { return m_userId; } } /** Attribute name for reading the project of a resource. */ public static final String DBC_ATTR_READ_PROJECT_FOR_RESOURCE = "DBC_ATTR_READ_PROJECT_FOR_RESOURCE"; /** The log object for this class. */ private static final Log LOG = CmsLog.getLog(org.opencms.db.generic.CmsProjectDriver.class); /** The driver manager. */ protected CmsDriverManager m_driverManager; /** The SQL manager. */ protected CmsSqlManager m_sqlManager; /** * @see org.opencms.db.I_CmsProjectDriver#createProject(org.opencms.db.CmsDbContext, CmsUUID, org.opencms.file.CmsUser, org.opencms.file.CmsGroup, org.opencms.file.CmsGroup, java.lang.String, java.lang.String, int, CmsProject.CmsProjectType) */ public CmsProject createProject( CmsDbContext dbc, CmsUUID id, CmsUser owner, CmsGroup group, CmsGroup managergroup, String projectFqn, String description, int flags, CmsProject.CmsProjectType type) throws CmsDataAccessException { CmsProject project = null; if ((description == null) || (description.length() < 1)) { description = " "; } Connection conn = null; PreparedStatement stmt = null; try { // get a JDBC connection from the OpenCms standard pool conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_CREATE_10"); stmt.setString(1, id.toString()); stmt.setString(2, owner.getId().toString()); stmt.setString(3, group.getId().toString()); stmt.setString(4, managergroup.getId().toString()); stmt.setString(5, CmsOrganizationalUnit.getSimpleName(projectFqn)); stmt.setString(6, description); stmt.setInt(7, flags); stmt.setInt(9, type.getMode()); stmt.setString(10, CmsOrganizationalUnit.SEPARATOR + CmsOrganizationalUnit.getParentFqn(projectFqn)); synchronized (this) { long createTime = System.currentTimeMillis(); stmt.setLong(8, createTime); stmt.executeUpdate(); try { // this is an ugly hack, but for MySQL (and maybe other DBs as well) // there is a UNIQUE INDEX constraint on the project name+createTime // so theoretically if 2 projects with the same name are created very fast, this // SQL restraint would be violated if we don't wait here Thread.sleep(50); } catch (InterruptedException e) { // continue } project = new CmsProject( id, projectFqn, description, owner.getId(), group.getId(), managergroup.getId(), flags, createTime, type); } } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, null); } return project; } /** * @see org.opencms.db.I_CmsProjectDriver#createProjectResource(org.opencms.db.CmsDbContext, CmsUUID, java.lang.String) */ public void createProjectResource(CmsDbContext dbc, CmsUUID projectId, String resourcePath) throws CmsDataAccessException { // do not create entries for online-project PreparedStatement stmt = null; Connection conn = null; boolean projectResourceExists = false; try { readProjectResource(dbc, projectId, resourcePath); projectResourceExists = true; } catch (CmsVfsResourceNotFoundException e) { // resource does not exist yet, everything is okay projectResourceExists = false; } if (projectResourceExists) { throw new CmsVfsResourceAlreadyExistsException(Messages.get().container( Messages.ERR_RESOURCE_WITH_NAME_ALREADY_EXISTS_1, dbc.removeSiteRoot(resourcePath))); } try { conn = getSqlManager().getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTRESOURCES_CREATE_2"); // write new resource to the database stmt.setString(1, projectId.toString()); stmt.setString(2, resourcePath); stmt.executeUpdate(); } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, null); } } /** * @see org.opencms.db.I_CmsProjectDriver#createPublishJob(org.opencms.db.CmsDbContext, org.opencms.publish.CmsPublishJobInfoBean) */ public void createPublishJob(CmsDbContext dbc, CmsPublishJobInfoBean publishJob) throws CmsDataAccessException { Connection conn = null; PreparedStatement stmt = null; try { CmsPublishJobInfoBean currentJob = readPublishJob(dbc, publishJob.getPublishHistoryId()); LOG.error("wanted to write: " + publishJob); LOG.error("already on db: " + currentJob); return; } catch (CmsDbEntryNotFoundException e) { // ok, this is the expected behavior } try { conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_PUBLISHJOB_CREATE"); stmt.setString(1, publishJob.getPublishHistoryId().toString()); stmt.setString(2, publishJob.getProjectId().toString()); stmt.setString(3, publishJob.getProjectName()); stmt.setString(4, publishJob.getUserId().toString()); stmt.setString(5, publishJob.getLocale().toString()); stmt.setInt(6, publishJob.getFlags()); stmt.setInt(7, publishJob.getSize()); stmt.setLong(8, publishJob.getEnqueueTime()); stmt.setLong(9, publishJob.getStartTime()); stmt.setLong(10, publishJob.getFinishTime()); byte[] publishList = internalSerializePublishList(publishJob.getPublishList()); if (publishList.length < 2000) { stmt.setBytes(11, publishList); } else { stmt.setBinaryStream(11, new ByteArrayInputStream(publishList), publishList.length); } stmt.executeUpdate(); } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } catch (IOException e) { throw new CmsDbIoException(Messages.get().container( Messages.ERR_SERIALIZING_PUBLISHLIST_1, publishJob.getPublishHistoryId().toString()), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, null); } } /** * @see org.opencms.db.I_CmsProjectDriver#deleteAllStaticExportPublishedResources(org.opencms.db.CmsDbContext, int) */ public void deleteAllStaticExportPublishedResources(CmsDbContext dbc, int linkType) throws CmsDataAccessException { Connection conn = null; PreparedStatement stmt = null; try { conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_STATICEXPORT_DELETE_ALL_PUBLISHED_LINKS"); stmt.setInt(1, linkType); stmt.executeUpdate(); } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, null); } } /** * @see org.opencms.db.I_CmsProjectDriver#deleteLog(org.opencms.db.CmsDbContext, org.opencms.db.log.CmsLogFilter) */ public void deleteLog(CmsDbContext dbc, CmsLogFilter filter) throws CmsDataAccessException { Connection conn = null; PreparedStatement stmt = null; try { conn = m_sqlManager.getConnection(dbc); // compose statement StringBuffer queryBuf = new StringBuffer(256); queryBuf.append(m_sqlManager.readQuery("C_LOG_DELETE_ENTRIES")); CmsPair<String, List<I_CmsPreparedStatementParameter>> conditionsAndParams = prepareLogConditions(filter); queryBuf.append(conditionsAndParams.getFirst()); if (LOG.isDebugEnabled()) { LOG.debug(queryBuf.toString()); } stmt = m_sqlManager.getPreparedStatementForSql(conn, queryBuf.toString()); List<I_CmsPreparedStatementParameter> params = conditionsAndParams.getSecond(); for (int i = 0; i < params.size(); i++) { I_CmsPreparedStatementParameter param = conditionsAndParams.getSecond().get(i); param.insertIntoStatement(stmt, i + 1); } // execute stmt.executeUpdate(); } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, null); } } /** * @see org.opencms.db.I_CmsProjectDriver#deleteProject(org.opencms.db.CmsDbContext, org.opencms.file.CmsProject) */ public void deleteProject(CmsDbContext dbc, CmsProject project) throws CmsDataAccessException { // delete the resources from project_resources deleteProjectResources(dbc, project); // remove the project id form all resources within their project unmarkProjectResources(dbc, project); // finally delete the project Connection conn = null; PreparedStatement stmt = null; try { conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_DELETE_1"); // create the statement stmt.setString(1, project.getUuid().toString()); stmt.executeUpdate(); } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, null); } } /** * @see org.opencms.db.I_CmsProjectDriver#deleteProjectResource(org.opencms.db.CmsDbContext, CmsUUID, java.lang.String) */ public void deleteProjectResource(CmsDbContext dbc, CmsUUID projectId, String resourceName) throws CmsDataAccessException { Connection conn = null; PreparedStatement stmt = null; try { conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTRESOURCES_DELETE_2"); // delete resource from the database stmt.setString(1, projectId.toString()); stmt.setString(2, resourceName); stmt.executeUpdate(); } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, null); } } /** * @see org.opencms.db.I_CmsProjectDriver#deleteProjectResources(org.opencms.db.CmsDbContext, org.opencms.file.CmsProject) */ public void deleteProjectResources(CmsDbContext dbc, CmsProject project) throws CmsDataAccessException { Connection conn = null; PreparedStatement stmt = null; try { conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTRESOURCES_DELETEALL_1"); stmt.setString(1, project.getUuid().toString()); stmt.executeUpdate(); } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, null); } } /** * @see org.opencms.db.I_CmsProjectDriver#deletePublishHistory(org.opencms.db.CmsDbContext, CmsUUID, int) */ public void deletePublishHistory(CmsDbContext dbc, CmsUUID projectId, int maxpublishTag) throws CmsDataAccessException { PreparedStatement stmt = null; Connection conn = null; try { conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_DELETE_PUBLISH_HISTORY"); stmt.setInt(1, maxpublishTag); stmt.executeUpdate(); } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, null); } } /** * @see org.opencms.db.I_CmsProjectDriver#deletePublishHistoryEntry(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID, org.opencms.db.CmsPublishedResource) */ public void deletePublishHistoryEntry( CmsDbContext dbc, CmsUUID publishHistoryId, CmsPublishedResource publishedResource) throws CmsDataAccessException { Connection conn = null; PreparedStatement stmt = null; try { conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_DELETE_PUBLISH_HISTORY_ENTRY"); stmt.setString(1, publishHistoryId.toString()); stmt.setInt(2, publishedResource.getPublishTag()); stmt.setString(3, publishedResource.getStructureId().toString()); stmt.setString(4, publishedResource.getRootPath()); stmt.executeUpdate(); } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, null); } } /** * @see org.opencms.db.I_CmsProjectDriver#deletePublishJob(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID) */ public void deletePublishJob(CmsDbContext dbc, CmsUUID publishHistoryId) throws CmsDataAccessException { Connection conn = null; PreparedStatement stmt = null; try { conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_PUBLISHJOB_DELETE"); stmt.setString(1, publishHistoryId.toString()); stmt.executeUpdate(); } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, null); } } /** * @see org.opencms.db.I_CmsProjectDriver#deletePublishList(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID) */ public void deletePublishList(CmsDbContext dbc, CmsUUID publishHistoryId) throws CmsDataAccessException { Connection conn = null; PreparedStatement stmt = null; try { conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_PUBLISHJOB_DELETE_PUBLISHLIST"); stmt.setString(1, publishHistoryId.toString()); stmt.executeUpdate(); } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, null); } } /** * @see org.opencms.db.I_CmsProjectDriver#deleteStaticExportPublishedResource(org.opencms.db.CmsDbContext, java.lang.String, int, java.lang.String) */ public void deleteStaticExportPublishedResource( CmsDbContext dbc, String resourceName, int linkType, String linkParameter) throws CmsDataAccessException { Connection conn = null; PreparedStatement stmt = null; try { conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_STATICEXPORT_DELETE_PUBLISHED_LINKS"); stmt.setString(1, resourceName); stmt.setInt(2, linkType); stmt.setString(3, linkParameter); stmt.executeUpdate(); } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, null); } } /** * @see org.opencms.db.I_CmsProjectDriver#destroy() */ public void destroy() throws Throwable { m_sqlManager = null; m_driverManager = null; if (CmsLog.INIT.isInfoEnabled()) { CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_SHUTDOWN_DRIVER_1, getClass().getName())); } } /** * @see org.opencms.db.I_CmsProjectDriver#fillDefaults(org.opencms.db.CmsDbContext) */ public void fillDefaults(CmsDbContext dbc) throws CmsDataAccessException { try { if (readProject(dbc, CmsProject.ONLINE_PROJECT_ID) != null) { // online-project exists - no need of filling defaults return; } } catch (CmsDataAccessException exc) { // ignore the exception - the project was not readable so fill in the defaults } if (CmsLog.INIT.isInfoEnabled()) { CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_FILL_DEFAULTS_0)); } String adminUser = OpenCms.getDefaultUsers().getUserAdmin(); CmsUser admin = m_driverManager.readUser(dbc, adminUser); String administratorsGroup = OpenCms.getDefaultUsers().getGroupAdministrators(); CmsGroup administrators = m_driverManager.readGroup(dbc, administratorsGroup); String usersGroup = OpenCms.getDefaultUsers().getGroupUsers(); CmsGroup users = m_driverManager.readGroup(dbc, usersGroup); String projectmanagersGroup = OpenCms.getDefaultUsers().getGroupProjectmanagers(); CmsGroup projectmanager = m_driverManager.readGroup(dbc, projectmanagersGroup); //////////////////////////////////////////////////////////////////////////////////////////// // online project stuff //////////////////////////////////////////////////////////////////////////////////////////// // create the online project CmsProject onlineProject = createProject( dbc, CmsProject.ONLINE_PROJECT_ID, admin, users, projectmanager, CmsProject.ONLINE_PROJECT_NAME, "The Online project", I_CmsPrincipal.FLAG_ENABLED, CmsProject.PROJECT_TYPE_NORMAL); // create the root-folder for the online project CmsFolder rootFolder = new CmsFolder( new CmsUUID(), new CmsUUID(), "/", CmsResourceTypeFolder.RESOURCE_TYPE_ID, 0, onlineProject.getUuid(), CmsResource.STATE_CHANGED, 0, admin.getId(), 0, admin.getId(), CmsResource.DATE_RELEASED_DEFAULT, CmsResource.DATE_EXPIRED_DEFAULT, 0); m_driverManager.getVfsDriver(dbc).createResource(dbc, onlineProject.getUuid(), rootFolder, null); // important: must access through driver manager to ensure proper cascading m_driverManager.getProjectDriver(dbc).createProjectResource( dbc, onlineProject.getUuid(), rootFolder.getRootPath()); // create the system-folder for the online project CmsFolder systemFolder = new CmsFolder( new CmsUUID(), new CmsUUID(), "/system", CmsResourceTypeFolder.RESOURCE_TYPE_ID, 0, onlineProject.getUuid(), CmsResource.STATE_CHANGED, 0, admin.getId(), 0, admin.getId(), CmsResource.DATE_RELEASED_DEFAULT, CmsResource.DATE_EXPIRED_DEFAULT, 0); m_driverManager.getVfsDriver(dbc).createResource(dbc, onlineProject.getUuid(), systemFolder, null); //////////////////////////////////////////////////////////////////////////////////////////// // setup project stuff //////////////////////////////////////////////////////////////////////////////////////////// // important: must access through driver manager to ensure proper cascading CmsProject setupProject = m_driverManager.getProjectDriver(dbc).createProject( dbc, CmsUUID.getConstantUUID(SETUP_PROJECT_NAME), admin, administrators, administrators, SETUP_PROJECT_NAME, "The Project for the initial import", I_CmsPrincipal.FLAG_ENABLED, CmsProject.PROJECT_TYPE_TEMPORARY); rootFolder.setState(CmsResource.STATE_CHANGED); // create the root-folder for the offline project CmsResource offlineRootFolder = m_driverManager.getVfsDriver(dbc).createResource( dbc, setupProject.getUuid(), rootFolder, null); offlineRootFolder.setState(CmsResource.STATE_UNCHANGED); m_driverManager.getVfsDriver(dbc).writeResource( dbc, setupProject.getUuid(), offlineRootFolder, CmsDriverManager.NOTHING_CHANGED); // important: must access through driver manager to ensure proper cascading m_driverManager.getProjectDriver(dbc).createProjectResource( dbc, setupProject.getUuid(), offlineRootFolder.getRootPath()); systemFolder.setState(CmsResource.STATE_CHANGED); // create the system-folder for the offline project CmsResource offlineSystemFolder = m_driverManager.getVfsDriver(dbc).createResource( dbc, setupProject.getUuid(), systemFolder, null); offlineSystemFolder.setState(CmsResource.STATE_UNCHANGED); m_driverManager.getVfsDriver(dbc).writeResource( dbc, setupProject.getUuid(), offlineSystemFolder, CmsDriverManager.NOTHING_CHANGED); } /** * @see org.opencms.db.I_CmsProjectDriver#getSqlManager() */ public CmsSqlManager getSqlManager() { return m_sqlManager; } /** * @see org.opencms.db.I_CmsProjectDriver#getUsersPubList(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID) */ public List<CmsResource> getUsersPubList(CmsDbContext dbc, CmsUUID userId) throws CmsDataAccessException { Connection conn = null; PreparedStatement stmt = null; ResultSet res = null; List<CmsResource> result = null; try { conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, dbc.currentProject().getUuid(), "C_LOG_READ_PUBLISH_LIST_2"); stmt.setString(1, userId.toString()); stmt.setString(2, userId.toString()); res = stmt.executeQuery(); result = new ArrayList<CmsResource>(); while (res.next()) { CmsResource resource = m_driverManager.getVfsDriver(dbc).createResource( res, dbc.currentProject().getUuid()); long date = res.getLong(m_sqlManager.readQuery("C_LOG_DATE")); resource.setDateLastModified(date); result.add(resource); } } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, res); } return result; } /** * @see org.opencms.db.I_CmsDriver#init(CmsDbContext, CmsConfigurationManager, List, CmsDriverManager) */ public void init( CmsDbContext dbc, CmsConfigurationManager configurationManager, List<String> successiveDrivers, CmsDriverManager driverManager) { CmsParameterConfiguration configuration = configurationManager.getConfiguration(); String poolUrl = configuration.get("db.project.pool"); String classname = configuration.get("db.project.sqlmanager"); m_sqlManager = initSqlManager(classname); m_sqlManager.init(I_CmsProjectDriver.DRIVER_TYPE_ID, poolUrl); m_driverManager = driverManager; if (CmsLog.INIT.isInfoEnabled()) { CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_ASSIGNED_POOL_1, poolUrl)); } if ((successiveDrivers != null) && !successiveDrivers.isEmpty()) { if (LOG.isWarnEnabled()) { LOG.warn(Messages.get().getBundle().key( Messages.LOG_SUCCESSIVE_DRIVERS_UNSUPPORTED_1, getClass().getName())); } } } /** * @see org.opencms.db.I_CmsProjectDriver#initSqlManager(String) */ public org.opencms.db.generic.CmsSqlManager initSqlManager(String classname) { return CmsSqlManager.getInstance(classname); } /** * @see org.opencms.db.I_CmsProjectDriver#log(org.opencms.db.CmsDbContext, java.util.List) */ public void log(CmsDbContext dbc, List<CmsLogEntry> logEntries) throws CmsDbSqlException { Connection conn = null; PreparedStatement stmt = null; try { conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_LOG_CREATE_5"); for (CmsLogEntry logEntry : logEntries) { stmt.setString(1, logEntry.getUserId().toString()); stmt.setLong(2, logEntry.getDate()); stmt.setString(3, logEntry.getStructureId() == null ? null : logEntry.getStructureId().toString()); stmt.setInt(4, logEntry.getType().getId()); stmt.setString(5, CmsStringUtil.arrayAsString(logEntry.getData(), "|")); try { stmt.executeUpdate(); } catch (SQLException e) { // ignore, most likely a duplicate entry LOG.debug( Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)).key(), e); } } } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { try { m_sqlManager.closeAll(dbc, conn, stmt, null); } catch (Throwable t) { // this could happen during shutdown LOG.debug(t.getLocalizedMessage(), t); } } } /** * @see org.opencms.db.I_CmsProjectDriver#publishDeletedFolder(org.opencms.db.CmsDbContext, org.opencms.report.I_CmsReport, int, int, org.opencms.file.CmsProject, org.opencms.file.CmsFolder, org.opencms.util.CmsUUID, int) */ public void publishDeletedFolder( CmsDbContext dbc, I_CmsReport report, int m, int n, CmsProject onlineProject, CmsFolder currentFolder, CmsUUID publishHistoryId, int publishTag) throws CmsDataAccessException { try { report.print( org.opencms.report.Messages.get().container( org.opencms.report.Messages.RPT_SUCCESSION_2, String.valueOf(m), String.valueOf(n)), I_CmsReport.FORMAT_NOTE); report.print(Messages.get().container(Messages.RPT_DELETE_FOLDER_0), I_CmsReport.FORMAT_NOTE); report.print(org.opencms.report.Messages.get().container( org.opencms.report.Messages.RPT_ARGUMENT_1, dbc.removeSiteRoot(currentFolder.getRootPath()))); report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0)); CmsResourceState folderState = fixMovedResource( dbc, onlineProject, currentFolder, publishHistoryId, publishTag); // read the folder online CmsFolder onlineFolder = m_driverManager.readFolder(dbc, currentFolder.getRootPath(), CmsResourceFilter.ALL); // if the folder in the online-project contains any files, these need to be removed. // this can occur if these files were moved in the offline-project List movedFiles = null; I_CmsVfsDriver vfsDriver = m_driverManager.getVfsDriver(dbc); movedFiles = vfsDriver.readResourceTree( dbc, onlineProject.getUuid(), currentFolder.getRootPath(), CmsDriverManager.READ_IGNORE_TYPE, null, CmsDriverManager.READ_IGNORE_TIME, CmsDriverManager.READ_IGNORE_TIME, CmsDriverManager.READ_IGNORE_TIME, CmsDriverManager.READ_IGNORE_TIME, CmsDriverManager.READ_IGNORE_TIME, CmsDriverManager.READ_IGNORE_TIME, CmsDriverManager.READMODE_ONLY_FILES); for (Iterator it = movedFiles.iterator(); it.hasNext();) { CmsResource delFile = (CmsResource)it.next(); try { CmsResource offlineResource = vfsDriver.readResource( dbc, dbc.currentProject().getUuid(), delFile.getStructureId(), true); CmsFile offlineFile = new CmsFile(offlineResource); offlineFile.setContents(vfsDriver.readContent( dbc, dbc.currentProject().getUuid(), offlineFile.getResourceId())); internalWriteHistory( dbc, offlineFile, CmsResource.STATE_DELETED, null, publishHistoryId, publishTag); vfsDriver.deletePropertyObjects( dbc, onlineProject.getUuid(), delFile, CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES); vfsDriver.removeFile(dbc, onlineProject.getUuid(), delFile); } catch (CmsDataAccessException e) { if (LOG.isWarnEnabled()) { LOG.warn(Messages.get().getBundle().key(Messages.LOG_REMOVING_RESOURCE_1, delFile.getName()), e); } } } // write history before deleting internalWriteHistory(dbc, currentFolder, folderState, null, publishHistoryId, publishTag); try { // delete the properties online and offline vfsDriver.deletePropertyObjects( dbc, onlineProject.getUuid(), onlineFolder, CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES); vfsDriver.deletePropertyObjects( dbc, dbc.currentProject().getUuid(), currentFolder, CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES); } catch (CmsDataAccessException e) { if (LOG.isErrorEnabled()) { LOG.error( Messages.get().getBundle().key(Messages.LOG_DELETING_PROPERTIES_1, currentFolder.getRootPath()), e); } throw e; } try { // remove the folder online and offline vfsDriver.removeFolder(dbc, dbc.currentProject(), currentFolder); vfsDriver.removeFolder(dbc, onlineProject, currentFolder); } catch (CmsDataAccessException e) { if (LOG.isErrorEnabled()) { LOG.error( Messages.get().getBundle().key(Messages.LOG_REMOVING_RESOURCE_1, currentFolder.getRootPath()), e); } throw e; } try { // remove the ACL online and offline m_driverManager.getUserDriver(dbc).removeAccessControlEntries( dbc, onlineProject, onlineFolder.getResourceId()); m_driverManager.getUserDriver(dbc).removeAccessControlEntries( dbc, dbc.currentProject(), currentFolder.getResourceId()); } catch (CmsDataAccessException e) { if (LOG.isErrorEnabled()) { LOG.error( Messages.get().getBundle().key(Messages.LOG_REMOVING_ACL_1, currentFolder.getRootPath()), e); } throw e; } // remove relations try { vfsDriver.deleteRelations(dbc, onlineProject.getUuid(), onlineFolder, CmsRelationFilter.TARGETS); vfsDriver.deleteRelations(dbc, dbc.currentProject().getUuid(), currentFolder, CmsRelationFilter.TARGETS); } catch (CmsDataAccessException e) { if (LOG.isErrorEnabled()) { LOG.error( Messages.get().getBundle().key(Messages.LOG_REMOVING_RELATIONS_1, currentFolder.getRootPath()), e); } throw e; } // remove project resources String deletedResourceRootPath = currentFolder.getRootPath(); Iterator itProjects = readProjectsForResource(dbc, deletedResourceRootPath).iterator(); while (itProjects.hasNext()) { CmsProject project = (CmsProject)itProjects.next(); deleteProjectResource(dbc, project.getUuid(), deletedResourceRootPath); } report.println( org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0), I_CmsReport.FORMAT_OK); if (LOG.isDebugEnabled()) { if (LOG.isDebugEnabled()) { LOG.debug(Messages.get().getBundle().key( Messages.LOG_DEL_FOLDER_3, currentFolder.getRootPath(), String.valueOf(m), String.valueOf(n))); } } } finally { // notify the app. that the published folder and it's properties have been modified offline OpenCms.fireCmsEvent(new CmsEvent( I_CmsEventListener.EVENT_RESOURCE_AND_PROPERTIES_MODIFIED, Collections.<String, Object> singletonMap(I_CmsEventListener.KEY_RESOURCE, currentFolder))); } } /** * @see org.opencms.db.I_CmsProjectDriver#publishFile(org.opencms.db.CmsDbContext, org.opencms.report.I_CmsReport, int, int, org.opencms.file.CmsProject, org.opencms.file.CmsResource, java.util.Set, org.opencms.util.CmsUUID, int) */ public void publishFile( CmsDbContext dbc, I_CmsReport report, int m, int n, CmsProject onlineProject, CmsResource offlineResource, Set<CmsUUID> publishedContentIds, CmsUUID publishHistoryId, int publishTag) throws CmsDataAccessException { /* * Never use onlineResource.getState() here! * Only use offlineResource.getState() to determine the state of an offline resource! * * In case a resource has siblings, after a sibling was published the structure * and resource states are reset to UNCHANGED -> the state of the corresponding * onlineResource is still NEW, DELETED or CHANGED. * Thus, using onlineResource.getState() will inevitably result in unpublished resources! */ try { report.print( org.opencms.report.Messages.get().container( org.opencms.report.Messages.RPT_SUCCESSION_2, String.valueOf(m), String.valueOf(n)), I_CmsReport.FORMAT_NOTE); if (offlineResource.getState().isDeleted()) { report.print(Messages.get().container(Messages.RPT_DELETE_FILE_0), I_CmsReport.FORMAT_NOTE); report.print(org.opencms.report.Messages.get().container( org.opencms.report.Messages.RPT_ARGUMENT_1, dbc.removeSiteRoot(offlineResource.getRootPath()))); report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0)); publishDeletedFile(dbc, onlineProject, offlineResource, publishHistoryId, publishTag); dbc.pop(); // delete old historical entries m_driverManager.getHistoryDriver(dbc).deleteEntries( dbc, new CmsHistoryFile(offlineResource), OpenCms.getSystemInfo().getHistoryVersionsAfterDeletion(), -1); report.println( org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0), I_CmsReport.FORMAT_OK); if (LOG.isDebugEnabled()) { LOG.debug(Messages.get().getBundle().key( Messages.LOG_DEL_FILE_3, String.valueOf(m), String.valueOf(n), offlineResource.getRootPath())); } } else if (offlineResource.getState().isChanged()) { report.print(Messages.get().container(Messages.RPT_PUBLISH_FILE_0), I_CmsReport.FORMAT_NOTE); report.print(org.opencms.report.Messages.get().container( org.opencms.report.Messages.RPT_ARGUMENT_1, dbc.removeSiteRoot(offlineResource.getRootPath()))); report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0)); publishChangedFile( dbc, onlineProject, offlineResource, publishedContentIds, publishHistoryId, publishTag); dbc.pop(); // delete old historical entries m_driverManager.getHistoryDriver(dbc).deleteEntries( dbc, new CmsHistoryFile(offlineResource), OpenCms.getSystemInfo().getHistoryVersions(), -1); report.println( org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0), I_CmsReport.FORMAT_OK); if (LOG.isDebugEnabled()) { LOG.debug(Messages.get().getBundle().key( Messages.LOG_PUBLISHING_FILE_3, offlineResource.getRootPath(), String.valueOf(m), String.valueOf(n))); } } else if (offlineResource.getState().isNew()) { report.print(Messages.get().container(Messages.RPT_PUBLISH_FILE_0), I_CmsReport.FORMAT_NOTE); report.print(org.opencms.report.Messages.get().container( org.opencms.report.Messages.RPT_ARGUMENT_1, dbc.removeSiteRoot(offlineResource.getRootPath()))); report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0)); publishNewFile(dbc, onlineProject, offlineResource, publishedContentIds, publishHistoryId, publishTag); dbc.pop(); // delete old historical entries m_driverManager.getHistoryDriver(dbc).deleteEntries( dbc, new CmsHistoryFile(offlineResource), OpenCms.getSystemInfo().getHistoryVersions(), -1); report.println( org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0), I_CmsReport.FORMAT_OK); if (LOG.isDebugEnabled()) { if (LOG.isDebugEnabled()) { LOG.debug(Messages.get().getBundle().key( Messages.LOG_PUBLISHING_FILE_3, offlineResource.getRootPath(), String.valueOf(m), String.valueOf(n))); } } } else { // state == unchanged !!?? something went really wrong report.print(Messages.get().container(Messages.RPT_PUBLISH_FILE_0), I_CmsReport.FORMAT_NOTE); report.print(org.opencms.report.Messages.get().container( org.opencms.report.Messages.RPT_ARGUMENT_1, dbc.removeSiteRoot(offlineResource.getRootPath()))); report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0)); report.println( org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_FAILED_0), I_CmsReport.FORMAT_ERROR); if (LOG.isErrorEnabled()) { // the whole resource is printed out here LOG.error(Messages.get().getBundle().key( Messages.LOG_PUBLISHING_FILE_3, String.valueOf(m), String.valueOf(n), offlineResource)); } } m_driverManager.publishUrlNameMapping(dbc, offlineResource); } catch (CmsException e) { throw new CmsDataAccessException(e.getMessageContainer(), e); } finally { // notify the app. that the published file and it's properties have been modified offline OpenCms.fireCmsEvent(new CmsEvent( I_CmsEventListener.EVENT_RESOURCE_AND_PROPERTIES_MODIFIED, Collections.<String, Object> singletonMap(I_CmsEventListener.KEY_RESOURCE, offlineResource))); } } /** * @see org.opencms.db.I_CmsProjectDriver#publishFileContent(CmsDbContext, CmsProject, CmsProject, CmsResource, Set, boolean, int) */ public CmsFile publishFileContent( CmsDbContext dbc, CmsProject offlineProject, CmsProject onlineProject, CmsResource offlineResource, Set<CmsUUID> publishedResourceIds, boolean needToUpdateContent, int publishTag) throws CmsDataAccessException { CmsFile newFile = null; try { // read the file content offline CmsUUID projectId = dbc.getProjectId(); boolean dbcHasProjectId = (projectId != null) && !projectId.isNullUUID(); CmsUUID projectIdForReading = (!dbcHasProjectId ? offlineProject.getUuid() : CmsProject.ONLINE_PROJECT_ID); dbc.setProjectId(offlineProject.getUuid()); byte[] offlineContent = m_driverManager.getVfsDriver(dbc).readContent( dbc, projectIdForReading, offlineResource.getResourceId()); CmsFile offlineFile = new CmsFile(offlineResource); offlineFile.setContents(offlineContent); dbc.setProjectId(projectId); // create the file online newFile = (CmsFile)offlineFile.clone(); newFile.setState(CmsResource.STATE_UNCHANGED); boolean createSibling = true; // check if we are facing with a create new sibling operation if (!offlineFile.getState().isNew()) { createSibling = false; } else { // check if the resource entry already exists if (!m_driverManager.getVfsDriver(dbc).validateResourceIdExists( dbc, onlineProject.getUuid(), offlineFile.getResourceId())) { // we are creating a normal resource and not a sibling createSibling = false; } } // only update the content if it was not updated before boolean alreadyPublished = publishedResourceIds.contains(offlineResource.getResourceId()); needToUpdateContent &= !alreadyPublished; if (createSibling) { if (!alreadyPublished) { // create the file online, the first time a sibling is published also the resource entry has to be actualized m_driverManager.getVfsDriver(dbc).createResource(dbc, onlineProject.getUuid(), newFile, null); } else { // create the sibling online m_driverManager.getVfsDriver(dbc).createSibling(dbc, onlineProject, offlineResource); } newFile = new CmsFile(offlineResource); newFile.setContents(offlineContent); } else { // update the online/offline structure and resource records of the file m_driverManager.getVfsDriver(dbc).publishResource(dbc, onlineProject, newFile, offlineFile); } // update version numbers m_driverManager.getVfsDriver(dbc).publishVersions(dbc, offlineResource, !alreadyPublished); // create/update the content m_driverManager.getVfsDriver(dbc).createOnlineContent( dbc, offlineFile.getResourceId(), offlineFile.getContents(), publishTag, true, needToUpdateContent); // mark the resource as written to avoid that the same content is written for each sibling instance publishedResourceIds.add(offlineResource.getResourceId()); } catch (CmsDataAccessException e) { if (LOG.isErrorEnabled()) { LOG.error( Messages.get().getBundle().key(Messages.LOG_PUBLISHING_FILE_CONTENT_1, offlineResource.toString()), e); } throw e; } return newFile; } /** * @see org.opencms.db.I_CmsProjectDriver#publishFolder(org.opencms.db.CmsDbContext, org.opencms.report.I_CmsReport, int, int, org.opencms.file.CmsProject, org.opencms.file.CmsFolder, org.opencms.util.CmsUUID, int) */ public void publishFolder( CmsDbContext dbc, I_CmsReport report, int m, int n, CmsProject onlineProject, CmsFolder offlineFolder, CmsUUID publishHistoryId, int publishTag) throws CmsDataAccessException { try { report.print( org.opencms.report.Messages.get().container( org.opencms.report.Messages.RPT_SUCCESSION_2, String.valueOf(m), String.valueOf(n)), I_CmsReport.FORMAT_NOTE); report.print(Messages.get().container(Messages.RPT_PUBLISH_FOLDER_0), I_CmsReport.FORMAT_NOTE); report.print(org.opencms.report.Messages.get().container( org.opencms.report.Messages.RPT_ARGUMENT_1, dbc.removeSiteRoot(offlineFolder.getRootPath()))); report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0)); CmsResourceState resourceState = fixMovedResource( dbc, onlineProject, offlineFolder, publishHistoryId, publishTag); CmsResource onlineFolder = null; if (offlineFolder.getState().isNew()) { try { // create the folder online CmsResource newFolder = (CmsFolder)offlineFolder.clone(); newFolder.setState(CmsResource.STATE_UNCHANGED); onlineFolder = m_driverManager.getVfsDriver(dbc).createResource( dbc, onlineProject.getUuid(), newFolder, null); m_driverManager.getVfsDriver(dbc).publishResource(dbc, onlineProject, onlineFolder, offlineFolder); // update version numbers m_driverManager.getVfsDriver(dbc).publishVersions(dbc, offlineFolder, true); } catch (CmsVfsResourceAlreadyExistsException e) { if (!offlineFolder.getRootPath().equals("/") && !offlineFolder.getRootPath().equals("/system/") && LOG.isWarnEnabled()) { LOG.warn(Messages.get().getBundle().key( Messages.LOG_WARN_FOLDER_WRONG_STATE_CN_1, offlineFolder.getRootPath())); } try { onlineFolder = m_driverManager.getVfsDriver(dbc).readFolder( dbc, onlineProject.getUuid(), offlineFolder.getRootPath()); m_driverManager.getVfsDriver(dbc).publishResource( dbc, onlineProject, onlineFolder, offlineFolder); // update version numbers m_driverManager.getVfsDriver(dbc).publishVersions(dbc, offlineFolder, true); } catch (CmsDataAccessException e1) { if (LOG.isErrorEnabled()) { LOG.error( Messages.get().getBundle().key( Messages.LOG_READING_RESOURCE_1, offlineFolder.getRootPath()), e); } throw e1; } } catch (CmsDataAccessException e) { if (LOG.isErrorEnabled()) { LOG.error( Messages.get().getBundle().key( Messages.LOG_PUBLISHING_RESOURCE_1, offlineFolder.getRootPath()), e); } throw e; } } else if (offlineFolder.getState().isChanged()) { try { // read the folder online onlineFolder = m_driverManager.getVfsDriver(dbc).readFolder( dbc, onlineProject.getUuid(), offlineFolder.getStructureId()); } catch (CmsVfsResourceNotFoundException e) { if (LOG.isWarnEnabled()) { LOG.warn(Messages.get().getBundle().key( Messages.LOG_WARN_FOLDER_WRONG_STATE_NC_1, offlineFolder.getRootPath())); } try { onlineFolder = m_driverManager.getVfsDriver(dbc).createResource( dbc, onlineProject.getUuid(), offlineFolder, null); internalResetResourceState(dbc, onlineFolder); } catch (CmsDataAccessException e1) { if (LOG.isErrorEnabled()) { LOG.error( Messages.get().getBundle().key( Messages.LOG_PUBLISHING_RESOURCE_1, offlineFolder.getRootPath()), e); } throw e1; } } try { // update the folder online m_driverManager.getVfsDriver(dbc).publishResource(dbc, onlineProject, onlineFolder, offlineFolder); // update version numbers m_driverManager.getVfsDriver(dbc).publishVersions(dbc, offlineFolder, true); } catch (CmsDataAccessException e) { if (LOG.isErrorEnabled()) { LOG.error( Messages.get().getBundle().key( Messages.LOG_PUBLISHING_RESOURCE_1, offlineFolder.getRootPath()), e); } throw e; } } if (onlineFolder != null) { try { // write the ACL online m_driverManager.getUserDriver(dbc).publishAccessControlEntries( dbc, dbc.currentProject(), onlineProject, offlineFolder.getResourceId(), onlineFolder.getResourceId()); } catch (CmsDataAccessException e) { if (LOG.isErrorEnabled()) { LOG.error( Messages.get().getBundle().key(Messages.LOG_PUBLISHING_ACL_1, offlineFolder.getRootPath()), e); } throw e; } } List offlineProperties = null; try { // write the properties online m_driverManager.getVfsDriver(dbc).deletePropertyObjects( dbc, onlineProject.getUuid(), onlineFolder, CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES); offlineProperties = m_driverManager.getVfsDriver(dbc).readPropertyObjects( dbc, dbc.currentProject(), offlineFolder); CmsProperty.setAutoCreatePropertyDefinitions(offlineProperties, true); m_driverManager.getVfsDriver(dbc).writePropertyObjects( dbc, onlineProject, onlineFolder, offlineProperties); } catch (CmsDataAccessException e) { if (LOG.isErrorEnabled()) { LOG.error( Messages.get().getBundle().key( Messages.LOG_PUBLISHING_PROPERTIES_1, offlineFolder.getRootPath()), e); } throw e; } internalWriteHistory(dbc, offlineFolder, resourceState, offlineProperties, publishHistoryId, publishTag); m_driverManager.getVfsDriver(dbc).updateRelations(dbc, onlineProject, offlineFolder); report.println( org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0), I_CmsReport.FORMAT_OK); if (LOG.isDebugEnabled()) { LOG.debug(Messages.get().getBundle().key( Messages.LOG_PUBLISHING_FOLDER_3, String.valueOf(m), String.valueOf(n), offlineFolder.getRootPath())); } } finally { // notify the app. that the published folder and it's properties have been modified offline OpenCms.fireCmsEvent(new CmsEvent( I_CmsEventListener.EVENT_RESOURCE_AND_PROPERTIES_MODIFIED, Collections.<String, Object> singletonMap(I_CmsEventListener.KEY_RESOURCE, offlineFolder))); } } /** * @see org.opencms.db.I_CmsProjectDriver#publishProject(org.opencms.db.CmsDbContext, org.opencms.report.I_CmsReport, org.opencms.file.CmsProject, org.opencms.db.CmsPublishList, int) */ public void publishProject( CmsDbContext dbc, I_CmsReport report, CmsProject onlineProject, CmsPublishList publishList, int publishTag) throws CmsException { int publishedFolderCount = 0; int deletedFolderCount = 0; int publishedFileCount = 0; Set<CmsUUID> publishedContentIds = new HashSet<CmsUUID>(); Set<CmsUUID> publishedIds = new HashSet<CmsUUID>(); try { //////////////////////////////////////////////////////////////////////////////////////// // write the historical project entry if (OpenCms.getSystemInfo().isHistoryEnabled()) { try { // write an entry in the publish project log m_driverManager.getHistoryDriver(dbc).writeProject(dbc, publishTag, System.currentTimeMillis()); dbc.pop(); } catch (Throwable t) { dbc.report( report, Messages.get().container( Messages.ERR_WRITING_HISTORY_OF_PROJECT_1, dbc.currentProject().getName()), t); } } /////////////////////////////////////////////////////////////////////////////////////// // publish new/changed folders if (LOG.isDebugEnabled()) { LOG.debug(Messages.get().getBundle().key( Messages.LOG_START_PUBLISHING_PROJECT_2, dbc.currentProject().getName(), dbc.currentUser().getName())); } publishedFolderCount = 0; int foldersSize = publishList.getFolderList().size(); if (foldersSize > 0) { report.println( Messages.get().container(Messages.RPT_PUBLISH_FOLDERS_BEGIN_0), I_CmsReport.FORMAT_HEADLINE); } Iterator<CmsResource> itFolders = publishList.getFolderList().iterator(); I_CmsProjectDriver projectDriver = m_driverManager.getProjectDriver(dbc); I_CmsHistoryDriver historyDriver = m_driverManager.getHistoryDriver(dbc); while (itFolders.hasNext()) { CmsResource currentFolder = itFolders.next(); try { if (currentFolder.getState().isNew() || currentFolder.getState().isChanged()) { // bounce the current publish task through all project drivers projectDriver.publishFolder( dbc, report, ++publishedFolderCount, foldersSize, onlineProject, new CmsFolder(currentFolder), publishList.getPublishHistoryId(), publishTag); dbc.pop(); publishedIds.add(currentFolder.getStructureId()); // log it CmsLogEntryType type = currentFolder.getState().isNew() ? CmsLogEntryType.RESOURCE_PUBLISHED_NEW : CmsLogEntryType.RESOURCE_PUBLISHED_MODIFIED; m_driverManager.log(dbc, new CmsLogEntry( dbc, currentFolder.getStructureId(), type, new String[] {currentFolder.getRootPath()}), true); // delete old historical entries historyDriver.deleteEntries( dbc, new CmsHistoryFile(currentFolder), OpenCms.getSystemInfo().getHistoryVersions(), -1); // reset the resource state to UNCHANGED and the last-modified-in-project-ID to 0 internalResetResourceState(dbc, currentFolder); m_driverManager.unlockResource(dbc, currentFolder, true, true); } else { // state == unchanged !!?? something went really wrong report.print(Messages.get().container(Messages.RPT_PUBLISH_FOLDER_0), I_CmsReport.FORMAT_NOTE); report.print(org.opencms.report.Messages.get().container( org.opencms.report.Messages.RPT_ARGUMENT_1, dbc.removeSiteRoot(currentFolder.getRootPath()))); report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0)); report.println( org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_FAILED_0), I_CmsReport.FORMAT_ERROR); if (LOG.isErrorEnabled()) { // the whole resource is printed out here LOG.error(Messages.get().getBundle().key( Messages.LOG_PUBLISHING_FILE_3, String.valueOf(++publishedFolderCount), String.valueOf(foldersSize), currentFolder)); } } dbc.pop(); } catch (Throwable t) { dbc.report( report, Messages.get().container(Messages.ERR_ERROR_PUBLISHING_FOLDER_1, currentFolder.getRootPath()), t); } } if (foldersSize > 0) { report.println( Messages.get().container(Messages.RPT_PUBLISH_FOLDERS_END_0), I_CmsReport.FORMAT_HEADLINE); } /////////////////////////////////////////////////////////////////////////////////////// // publish changed/new/deleted files publishedFileCount = 0; int filesSize = publishList.getFileList().size(); if (filesSize > 0) { report.println( Messages.get().container(Messages.RPT_PUBLISH_FILES_BEGIN_0), I_CmsReport.FORMAT_HEADLINE); } Set<CmsUUID> deletedResourceIds = new HashSet<CmsUUID>(); Set<CmsUUID> changedResourceIds = new HashSet<CmsUUID>(); for (CmsResource res : publishList.getFileList()) { if (res.getState().isDeleted()) { deletedResourceIds.add(res.getResourceId()); } else { changedResourceIds.add(res.getResourceId()); } } Set<CmsUUID> changedAndDeletedResourceIds = Sets.intersection(deletedResourceIds, changedResourceIds); dbc.setAttribute(CmsDriverManager.KEY_CHANGED_AND_DELETED, changedAndDeletedResourceIds); Iterator<CmsResource> itFiles = publishList.getFileList().iterator(); while (itFiles.hasNext()) { CmsResource currentResource = itFiles.next(); try { // bounce the current publish task through all project drivers projectDriver.publishFile( dbc, report, ++publishedFileCount, filesSize, onlineProject, currentResource, publishedContentIds, publishList.getPublishHistoryId(), publishTag); CmsResourceState state = currentResource.getState(); if (!state.isDeleted()) { // reset the resource state to UNCHANGED and the last-modified-in-project-ID to 0 internalResetResourceState(dbc, currentResource); } // unlock it m_driverManager.unlockResource(dbc, currentResource, true, true); // log it CmsLogEntryType type = state.isNew() ? CmsLogEntryType.RESOURCE_PUBLISHED_NEW : (state.isDeleted() ? CmsLogEntryType.RESOURCE_PUBLISHED_DELETED : CmsLogEntryType.RESOURCE_PUBLISHED_MODIFIED); m_driverManager.log(dbc, new CmsLogEntry( dbc, currentResource.getStructureId(), type, new String[] {currentResource.getRootPath()}), true); publishedIds.add(currentResource.getStructureId()); dbc.pop(); } catch (Throwable t) { dbc.report( report, Messages.get().container(Messages.ERR_ERROR_PUBLISHING_FILE_1, currentResource.getRootPath()), t); } } if (filesSize > 0) { report.println(Messages.get().container(Messages.RPT_PUBLISH_FILES_END_0), I_CmsReport.FORMAT_HEADLINE); } //////////////////////////////////////////////////////////////////////////////////////// // publish deleted folders List<CmsResource> deletedFolders = publishList.getDeletedFolderList(); if (deletedFolders.isEmpty()) { return; } deletedFolderCount = 0; int deletedFoldersSize = deletedFolders.size(); if (deletedFoldersSize > 0) { report.println( Messages.get().container(Messages.RPT_DELETE_FOLDERS_BEGIN_0), I_CmsReport.FORMAT_HEADLINE); } Iterator<CmsResource> itDeletedFolders = deletedFolders.iterator(); while (itDeletedFolders.hasNext()) { CmsResource currentFolder = itDeletedFolders.next(); try { // bounce the current publish task through all project drivers projectDriver.publishDeletedFolder( dbc, report, ++deletedFolderCount, deletedFoldersSize, onlineProject, new CmsFolder(currentFolder), publishList.getPublishHistoryId(), publishTag); dbc.pop(); // delete old historical entries m_driverManager.getHistoryDriver(dbc).deleteEntries( dbc, new CmsHistoryFile(currentFolder), OpenCms.getSystemInfo().getHistoryVersionsAfterDeletion(), -1); publishedIds.add(currentFolder.getStructureId()); // unlock it m_driverManager.unlockResource(dbc, currentFolder, true, true); // log it m_driverManager.log(dbc, new CmsLogEntry( dbc, currentFolder.getStructureId(), CmsLogEntryType.RESOURCE_PUBLISHED_DELETED, new String[] {currentFolder.getRootPath()}), true); dbc.pop(); } catch (Throwable t) { dbc.report( report, Messages.get().container( Messages.ERR_ERROR_PUBLISHING_DELETED_FOLDER_1, currentFolder.getRootPath()), t); } } if (deletedFoldersSize > 0) { report.println(Messages.get().container(Messages.RPT_DELETE_FOLDERS_END_0), I_CmsReport.FORMAT_HEADLINE); } } catch (OutOfMemoryError o) { // clear all caches to reclaim memory OpenCms.fireCmsEvent(new CmsEvent( I_CmsEventListener.EVENT_CLEAR_CACHES, Collections.<String, Object> emptyMap())); CmsMessageContainer message = Messages.get().container(Messages.ERR_OUT_OF_MEMORY_0); if (LOG.isErrorEnabled()) { LOG.error(message.key(), o); } throw new CmsDataAccessException(message, o); } finally { // reset vfs driver internal info after publishing m_driverManager.getVfsDriver(dbc).publishVersions(dbc, null, false); Object[] msgArgs = new Object[] { String.valueOf(publishedFileCount), String.valueOf(publishedFolderCount), String.valueOf(deletedFolderCount), report.formatRuntime()}; CmsMessageContainer message = Messages.get().container(Messages.RPT_PUBLISH_STAT_4, msgArgs); if (LOG.isInfoEnabled()) { LOG.info(message.key()); } report.println(message); } } /** * @see org.opencms.db.I_CmsProjectDriver#readLocks(org.opencms.db.CmsDbContext) */ public List<CmsLock> readLocks(CmsDbContext dbc) throws CmsDataAccessException { Connection conn = null; PreparedStatement stmt = null; List<CmsTempResourceLock> tmpLocks = new ArrayList<CmsTempResourceLock>(256); List<CmsLock> locks = new ArrayList<CmsLock>(256); try { conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCE_LOCKS_READALL"); ResultSet rs = stmt.executeQuery(); while (rs.next()) { String resourcePath = rs.getString(m_sqlManager.readQuery("C_RESOURCE_LOCKS_RESOURCE_PATH")); CmsUUID userId = new CmsUUID(rs.getString(m_sqlManager.readQuery("C_RESOURCE_LOCKS_USER_ID"))); CmsUUID projectId = new CmsUUID(rs.getString(m_sqlManager.readQuery("C_RESOURCE_LOCKS_PROJECT_ID"))); int lockType = rs.getInt(m_sqlManager.readQuery("C_RESOURCE_LOCKS_LOCK_TYPE")); CmsTempResourceLock tmpLock = new CmsTempResourceLock(resourcePath, userId, projectId, lockType); tmpLocks.add(tmpLock); } } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, null); } for (CmsTempResourceLock tmpLock : tmpLocks) { CmsProject project; try { project = readProject(dbc, tmpLock.getProjectId()); } catch (CmsDataAccessException dae) { // the project does not longer exist, ignore this lock (should usually not happen) project = null; } if (project != null) { CmsLock lock = new CmsLock( tmpLock.getResourcePath(), tmpLock.getUserId(), project, CmsLockType.valueOf(tmpLock.getLockType())); locks.add(lock); } } if (LOG.isDebugEnabled()) { LOG.debug(Messages.get().getBundle().key(Messages.LOG_DBG_READ_LOCKS_1, new Integer(locks.size()))); } return locks; } /** * @see org.opencms.db.I_CmsProjectDriver#readLog(org.opencms.db.CmsDbContext, org.opencms.db.log.CmsLogFilter) */ public List<CmsLogEntry> readLog(CmsDbContext dbc, CmsLogFilter filter) throws CmsDataAccessException { List<CmsLogEntry> entries = new ArrayList<CmsLogEntry>(); Connection conn = null; PreparedStatement stmt = null; ResultSet res = null; try { conn = m_sqlManager.getConnection(dbc); // compose statement StringBuffer queryBuf = new StringBuffer(256); queryBuf.append(m_sqlManager.readQuery("C_LOG_READ_ENTRIES")); CmsPair<String, List<I_CmsPreparedStatementParameter>> conditionsAndParameters = prepareLogConditions(filter); List<I_CmsPreparedStatementParameter> params = conditionsAndParameters.getSecond(); queryBuf.append(conditionsAndParameters.getFirst()); if (LOG.isDebugEnabled()) { LOG.debug(queryBuf.toString()); } stmt = m_sqlManager.getPreparedStatementForSql(conn, queryBuf.toString()); for (int i = 0; i < params.size(); i++) { I_CmsPreparedStatementParameter param = params.get(i); param.insertIntoStatement(stmt, i + 1); } // execute res = stmt.executeQuery(); while (res.next()) { // get results entries.add(internalReadLogEntry(res)); } } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, res); } return entries; } /** * @see org.opencms.db.I_CmsProjectDriver#readProject(org.opencms.db.CmsDbContext, CmsUUID) */ public CmsProject readProject(CmsDbContext dbc, CmsUUID id) throws CmsDataAccessException { PreparedStatement stmt = null; CmsProject project = null; ResultSet res = null; Connection conn = null; try { conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_READ_1"); stmt.setString(1, id.toString()); res = stmt.executeQuery(); if (res.next()) { project = internalCreateProject(res); while (res.next()) { // do nothing only move through all rows because of mssql odbc driver } } else { throw new CmsDbEntryNotFoundException(Messages.get().container( Messages.ERR_NO_PROJECT_WITH_ID_1, String.valueOf(id))); } } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, res); } return project; } /** * @see org.opencms.db.I_CmsProjectDriver#readProject(org.opencms.db.CmsDbContext, java.lang.String) */ public CmsProject readProject(CmsDbContext dbc, String projectFqn) throws CmsDataAccessException { PreparedStatement stmt = null; CmsProject project = null; ResultSet res = null; Connection conn = null; try { conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_READ_BYNAME_2"); stmt.setString(1, CmsOrganizationalUnit.getSimpleName(projectFqn)); stmt.setString(2, CmsOrganizationalUnit.SEPARATOR + CmsOrganizationalUnit.getParentFqn(projectFqn)); res = stmt.executeQuery(); if (res.next()) { project = internalCreateProject(res); while (res.next()) { // do nothing only move through all rows because of mssql odbc driver } } else { throw new CmsDbEntryNotFoundException(Messages.get().container( Messages.ERR_NO_PROJECT_WITH_NAME_1, projectFqn)); } } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, res); } return project; } /** * @see org.opencms.db.I_CmsProjectDriver#readProjectResource(org.opencms.db.CmsDbContext, CmsUUID, java.lang.String) */ public String readProjectResource(CmsDbContext dbc, CmsUUID projectId, String resourcePath) throws CmsDataAccessException { PreparedStatement stmt = null; Connection conn = null; ResultSet res = null; String resName = null; try { conn = getSqlManager().getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTRESOURCES_READ_2"); // select resource from the database stmt.setString(1, projectId.toString()); stmt.setString(2, resourcePath); res = stmt.executeQuery(); if (res.next()) { resName = res.getString("RESOURCE_PATH"); while (res.next()) { // do nothing only move through all rows because of mssql odbc driver } } else { throw new CmsVfsResourceNotFoundException(Messages.get().container( Messages.ERR_NO_PROJECTRESOURCE_1, resourcePath)); } } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, res); } return resName; } /** * @see org.opencms.db.I_CmsProjectDriver#readProjectResources(org.opencms.db.CmsDbContext, org.opencms.file.CmsProject) */ public List readProjectResources(CmsDbContext dbc, CmsProject project) throws CmsDataAccessException { PreparedStatement stmt = null; Connection conn = null; ResultSet res = null; List result = new ArrayList(); try { conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTRESOURCES_READ_BY_ID_1"); stmt.setString(1, project.getUuid().toString()); res = stmt.executeQuery(); while (res.next()) { result.add(res.getString("RESOURCE_PATH")); } } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, res); } return result; } /** * @see org.opencms.db.I_CmsProjectDriver#readProjects(org.opencms.db.CmsDbContext, String) */ public List readProjects(CmsDbContext dbc, String ouFqn) throws CmsDataAccessException { if ((dbc.getRequestContext() != null) && (dbc.getRequestContext().getAttribute(DBC_ATTR_READ_PROJECT_FOR_RESOURCE) != null)) { dbc.getRequestContext().removeAttribute(DBC_ATTR_READ_PROJECT_FOR_RESOURCE); // TODO: this should get its own method in the interface return readProjectsForResource(dbc, ouFqn); } List projects = new ArrayList(); ResultSet res = null; PreparedStatement stmt = null; Connection conn = null; try { // create the statement conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_READ_BYOU_1"); stmt.setString(1, CmsOrganizationalUnit.SEPARATOR + ouFqn + "%"); res = stmt.executeQuery(); while (res.next()) { projects.add(internalCreateProject(res)); } } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, res); } return (projects); } /** * @see org.opencms.db.I_CmsProjectDriver#readProjectsForGroup(org.opencms.db.CmsDbContext, org.opencms.file.CmsGroup) */ public List readProjectsForGroup(CmsDbContext dbc, CmsGroup group) throws CmsDataAccessException { List projects = new ArrayList(); ResultSet res = null; Connection conn = null; PreparedStatement stmt = null; try { // create the statement conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_READ_BYGROUP_2"); stmt.setString(1, group.getId().toString()); stmt.setString(2, group.getId().toString()); res = stmt.executeQuery(); while (res.next()) { projects.add(internalCreateProject(res)); } } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, res); } return (projects); } /** * @see org.opencms.db.I_CmsProjectDriver#readProjectsForManagerGroup(org.opencms.db.CmsDbContext, org.opencms.file.CmsGroup) */ public List readProjectsForManagerGroup(CmsDbContext dbc, CmsGroup group) throws CmsDataAccessException { List projects = new ArrayList(); ResultSet res = null; PreparedStatement stmt = null; Connection conn = null; try { // create the statement conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_READ_BYMANAGER_1"); stmt.setString(1, group.getId().toString()); res = stmt.executeQuery(); while (res.next()) { projects.add(internalCreateProject(res)); } } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, res); } return (projects); } /** * Returns the projects of a given resource.<p> * * @param dbc the database context * @param rootPath the resource root path * * @return the projects of the resource, as a list of projects * * @throws CmsDataAccessException if something goes wrong */ public List readProjectsForResource(CmsDbContext dbc, String rootPath) throws CmsDataAccessException { PreparedStatement stmt = null; List projects = new ArrayList(); ResultSet res = null; Connection conn = null; try { conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_READ_BYRESOURCE_1"); stmt.setString(1, rootPath + "%"); res = stmt.executeQuery(); if (res.next()) { projects.add(internalCreateProject(res)); while (res.next()) { // do nothing only move through all rows because of mssql odbc driver } } } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, res); } return projects; } /** * @see org.opencms.db.I_CmsProjectDriver#readProjectsForUser(org.opencms.db.CmsDbContext, org.opencms.file.CmsUser) */ public List readProjectsForUser(CmsDbContext dbc, CmsUser user) throws CmsDataAccessException { List projects = new ArrayList(); ResultSet res = null; PreparedStatement stmt = null; Connection conn = null; try { // create the statement conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_READ_BYUSER_1"); stmt.setString(1, user.getId().toString()); res = stmt.executeQuery(); while (res.next()) { projects.add(internalCreateProject(res)); } } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, res); } return (projects); } /** * @see org.opencms.db.I_CmsProjectDriver#readPublishedResources(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID) */ public List readPublishedResources(CmsDbContext dbc, CmsUUID publishHistoryId) throws CmsDataAccessException { Connection conn = null; PreparedStatement stmt = null; ResultSet res = null; List publishedResources = new ArrayList(); try { conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_SELECT_PUBLISHED_RESOURCES"); stmt.setString(1, publishHistoryId.toString()); res = stmt.executeQuery(); while (res.next()) { CmsUUID structureId = new CmsUUID(res.getString("STRUCTURE_ID")); CmsUUID resourceId = new CmsUUID(res.getString("RESOURCE_ID")); String rootPath = res.getString("RESOURCE_PATH"); int resourceState = res.getInt("RESOURCE_STATE"); int resourceType = res.getInt("RESOURCE_TYPE"); int siblingCount = res.getInt("SIBLING_COUNT"); int publishTag = res.getInt("PUBLISH_TAG"); // compose the resource state CmsResourceState state; if (resourceState == CmsPublishedResource.STATE_MOVED_SOURCE.getState()) { state = CmsPublishedResource.STATE_MOVED_SOURCE; } else if (resourceState == CmsPublishedResource.STATE_MOVED_DESTINATION.getState()) { state = CmsPublishedResource.STATE_MOVED_DESTINATION; } else { state = CmsResourceState.valueOf(resourceState); } publishedResources.add(new CmsPublishedResource( structureId, resourceId, publishTag, rootPath, resourceType, structureId.isNullUUID() ? false : CmsFolder.isFolderType(resourceType), state, siblingCount)); } } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, res); } return publishedResources; } /** * @see org.opencms.db.I_CmsProjectDriver#readPublishJob(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID) */ public CmsPublishJobInfoBean readPublishJob(CmsDbContext dbc, CmsUUID publishHistoryId) throws CmsDataAccessException { Connection conn = null; PreparedStatement stmt = null; ResultSet res = null; CmsPublishJobInfoBean result = null; try { conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_PUBLISHJOB_READ_JOB"); stmt.setString(1, publishHistoryId.toString()); res = stmt.executeQuery(); if (res.next()) { result = createPublishJobInfoBean(res); while (res.next()) { // do nothing only move through all rows because of mssql odbc driver } } else { throw new CmsDbEntryNotFoundException(Messages.get().container( Messages.ERR_READ_PUBLISH_JOB_1, publishHistoryId.toString())); } } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, res); } return result; } /** * @see org.opencms.db.I_CmsProjectDriver#readPublishJobs(org.opencms.db.CmsDbContext, long, long) */ public List readPublishJobs(CmsDbContext dbc, long startTime, long endTime) throws CmsDataAccessException { Connection conn = null; PreparedStatement stmt = null; ResultSet res = null; List result = null; try { conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_PUBLISHJOB_READ_JOBS_IN_TIMERANGE"); stmt.setLong(1, startTime); stmt.setLong(2, endTime); res = stmt.executeQuery(); result = new ArrayList(); while (res.next()) { result.add(createPublishJobInfoBean(res)); } } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, res); } return result; } /** * @see org.opencms.db.I_CmsProjectDriver#readPublishList(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID) */ public CmsPublishList readPublishList(CmsDbContext dbc, CmsUUID publishHistoryId) throws CmsDataAccessException { Connection conn = null; PreparedStatement stmt = null; ResultSet res = null; CmsPublishList publishList = null; try { conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_PUBLISHJOB_READ_PUBLISHLIST"); stmt.setString(1, publishHistoryId.toString()); res = stmt.executeQuery(); if (res.next()) { byte[] bytes = m_sqlManager.getBytes(res, "PUBLISH_LIST"); publishList = internalDeserializePublishList(bytes); while (res.next()) { // do nothing only move through all rows because of mssql odbc driver } } else { throw new CmsDataAccessException(Messages.get().container( Messages.ERR_READ_PUBLISH_JOB_1, publishHistoryId.toString())); } } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } catch (Exception e) { throw new CmsDataAccessException(Messages.get().container( Messages.ERR_PUBLISHLIST_DESERIALIZATION_FAILED_1, publishHistoryId), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, res); } return publishList; } /** * @see org.opencms.db.I_CmsProjectDriver#readPublishReportContents(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID) */ public byte[] readPublishReportContents(CmsDbContext dbc, CmsUUID publishHistoryId) throws CmsDataAccessException { PreparedStatement stmt = null; ResultSet res = null; Connection conn = null; byte[] bytes = null; try { conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_PUBLISHJOB_READ_REPORT"); stmt.setString(1, publishHistoryId.toString()); res = stmt.executeQuery(); if (res.next()) { // query to read Array of bytes for the given attribute bytes = m_sqlManager.getBytes(res, "PUBLISH_REPORT"); while (res.next()) { // do nothing only move through all rows because of mssql odbc driver } } else { throw new CmsDataAccessException(Messages.get().container( Messages.ERR_READ_PUBLISH_JOB_1, publishHistoryId.toString())); } } catch (SQLException e) { LOG.error(CmsDbSqlException.getErrorQuery(stmt), e); bytes = Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)).key().getBytes(); } finally { m_sqlManager.closeAll(dbc, conn, stmt, res); } return bytes; } /** * @see org.opencms.db.I_CmsProjectDriver#readStaticExportPublishedResourceParameters(org.opencms.db.CmsDbContext, java.lang.String) */ public String readStaticExportPublishedResourceParameters(CmsDbContext dbc, String rfsName) throws CmsDataAccessException { String returnValue = null; Connection conn = null; PreparedStatement stmt = null; ResultSet res = null; try { conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_STATICEXPORT_READ_PUBLISHED_LINK_PARAMETERS"); stmt.setString(1, rfsName); res = stmt.executeQuery(); // add all resourcenames to the list of return values if (res.next()) { returnValue = res.getString(1); while (res.next()) { // do nothing only move through all rows because of mssql odbc driver } } } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, res); } return returnValue; } /** * @see org.opencms.db.I_CmsProjectDriver#readStaticExportResources(org.opencms.db.CmsDbContext, int, long) */ public List readStaticExportResources(CmsDbContext dbc, int parameterResources, long timestamp) throws CmsDataAccessException { Connection conn = null; PreparedStatement stmt = null; ResultSet res = null; List returnValue = new ArrayList(); if (parameterResources == CmsStaticExportManager.EXPORT_LINK_WITHOUT_PARAMETER) { timestamp = 0; } try { conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_STATICEXPORT_READ_ALL_PUBLISHED_LINKS"); stmt.setInt(1, parameterResources); stmt.setLong(2, timestamp); res = stmt.executeQuery(); // add all resourcenames to the list of return values while (res.next()) { returnValue.add(res.getString(1)); } } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, res); } return returnValue; } /** * @see org.opencms.db.I_CmsProjectDriver#setDriverManager(org.opencms.db.CmsDriverManager) */ public void setDriverManager(CmsDriverManager driverManager) { m_driverManager = driverManager; } /** * @see org.opencms.db.I_CmsProjectDriver#setSqlManager(org.opencms.db.CmsSqlManager) */ public void setSqlManager(org.opencms.db.CmsSqlManager manager) { m_sqlManager = (CmsSqlManager)manager; } /** * @see org.opencms.db.I_CmsProjectDriver#unmarkProjectResources(org.opencms.db.CmsDbContext, org.opencms.file.CmsProject) */ public void unmarkProjectResources(CmsDbContext dbc, CmsProject project) throws CmsDataAccessException { // finally remove the project id form all resources Connection conn = null; PreparedStatement stmt = null; try { conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_UNMARK"); // create the statement stmt.setString(1, project.getUuid().toString()); stmt.executeUpdate(); } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, null); } } /** * @see org.opencms.db.I_CmsProjectDriver#writeLocks(org.opencms.db.CmsDbContext, java.util.List) */ public void writeLocks(CmsDbContext dbc, List<CmsLock> locks) throws CmsDataAccessException { Connection conn = null; PreparedStatement stmt = null; try { conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCE_LOCKS_DELETEALL"); int deleted = stmt.executeUpdate(); if (LOG.isDebugEnabled()) { LOG.debug(Messages.get().getBundle().key(Messages.LOG_DBG_CLEAR_LOCKS_1, new Integer(deleted))); } stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCE_LOCK_WRITE"); if (LOG.isDebugEnabled()) { LOG.debug("SQL :" + m_sqlManager.readQuery("C_RESOURCE_LOCK_WRITE")); } Iterator i = locks.iterator(); int count = 0; while (i.hasNext()) { CmsLock lock = (CmsLock)i.next(); // only persist locks that should be written to the DB CmsLock sysLock = lock.getSystemLock(); if (sysLock.isPersistent()) { // persist system lock stmt.setString(1, sysLock.getResourceName()); stmt.setString(2, sysLock.getUserId().toString()); stmt.setString(3, sysLock.getProjectId().toString()); stmt.setInt(4, sysLock.getType().hashCode()); stmt.executeUpdate(); count++; } CmsLock editLock = lock.getEditionLock(); if (editLock.isPersistent()) { // persist edition lock stmt.setString(1, editLock.getResourceName()); stmt.setString(2, editLock.getUserId().toString()); stmt.setString(3, editLock.getProjectId().toString()); stmt.setInt(4, editLock.getType().hashCode()); stmt.executeUpdate(); count++; } } if (LOG.isDebugEnabled()) { LOG.debug(Messages.get().getBundle().key(Messages.LOG_DBG_WRITE_LOCKS_1, new Integer(count))); } } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, null); } } /** * @see org.opencms.db.I_CmsProjectDriver#writeProject(org.opencms.db.CmsDbContext, org.opencms.file.CmsProject) */ public void writeProject(CmsDbContext dbc, CmsProject project) throws CmsDataAccessException { if (CmsStringUtil.isEmptyOrWhitespaceOnly(project.getDescription())) { project.setDescription(" "); } Connection conn = null; PreparedStatement stmt = null; try { // get a JDBC connection from the OpenCms standard pools conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_WRITE_6"); stmt.setString(1, project.getDescription()); stmt.setString(2, project.getGroupId().toString()); stmt.setString(3, project.getManagerGroupId().toString()); stmt.setInt(4, project.getFlags()); stmt.setInt(5, project.getType().getMode()); stmt.setString(6, project.getUuid().toString()); stmt.executeUpdate(); } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, null); } } /** * @see org.opencms.db.I_CmsProjectDriver#writePublishHistory(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID, org.opencms.db.CmsPublishedResource) */ public void writePublishHistory(CmsDbContext dbc, CmsUUID publishId, CmsPublishedResource resource) throws CmsDataAccessException { Connection conn = null; PreparedStatement stmt = null; try { conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_WRITE_PUBLISH_HISTORY"); stmt.setInt(1, resource.getPublishTag()); stmt.setString(2, resource.getStructureId().toString()); stmt.setString(3, resource.getResourceId().toString()); stmt.setString(4, resource.getRootPath()); stmt.setInt(5, resource.getMovedState().getState()); stmt.setInt(6, resource.getType()); stmt.setString(7, publishId.toString()); stmt.setInt(8, resource.getSiblingCount()); stmt.executeUpdate(); } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, null); } } /** * @see org.opencms.db.I_CmsProjectDriver#writePublishJob(org.opencms.db.CmsDbContext, org.opencms.publish.CmsPublishJobInfoBean) */ public void writePublishJob(CmsDbContext dbc, CmsPublishJobInfoBean publishJob) throws CmsDataAccessException { Connection conn = null; PreparedStatement stmt = null; try { conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_PUBLISHJOB_WRITE"); stmt.setString(1, publishJob.getProjectId().toString()); stmt.setString(2, publishJob.getProjectName()); stmt.setString(3, publishJob.getUserId().toString()); stmt.setString(4, publishJob.getLocale().toString()); stmt.setInt(5, publishJob.getFlags()); stmt.setInt(6, publishJob.getSize()); stmt.setLong(7, publishJob.getEnqueueTime()); stmt.setLong(8, publishJob.getStartTime()); stmt.setLong(9, publishJob.getFinishTime()); stmt.setString(10, publishJob.getPublishHistoryId().toString()); stmt.executeUpdate(); } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, null); } } /** * @see org.opencms.db.I_CmsProjectDriver#writePublishReport(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID, byte[]) */ public void writePublishReport(CmsDbContext dbc, CmsUUID publishId, byte[] content) throws CmsDataAccessException { Connection conn = null; PreparedStatement stmt = null; try { conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_PUBLISHJOB_WRITE_REPORT"); if (content.length < 2000) { stmt.setBytes(1, content); } else { stmt.setBinaryStream(1, new ByteArrayInputStream(content), content.length); } stmt.setString(2, publishId.toString()); stmt.executeUpdate(); } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, null); } } /** * @see org.opencms.db.I_CmsProjectDriver#writeStaticExportPublishedResource(org.opencms.db.CmsDbContext, java.lang.String, int, java.lang.String, long) */ public void writeStaticExportPublishedResource( CmsDbContext dbc, String resourceName, int linkType, String linkParameter, long timestamp) throws CmsDataAccessException { Connection conn = null; PreparedStatement stmt = null; ResultSet res = null; int returnValue = 0; // first check if a record with this resource name does already exist try { conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_STATICEXPORT_READ_PUBLISHED_RESOURCES"); stmt.setString(1, resourceName); res = stmt.executeQuery(); if (res.next()) { returnValue = res.getInt(1); while (res.next()) { // do nothing only move through all rows because of mssql odbc driver } } } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, res); } // there was no entry found, so add it to the database if (returnValue == 0) { try { conn = m_sqlManager.getConnection(dbc); stmt = m_sqlManager.getPreparedStatement(conn, "C_STATICEXPORT_WRITE_PUBLISHED_LINKS"); stmt.setString(1, new CmsUUID().toString()); stmt.setString(2, resourceName); stmt.setInt(3, linkType); stmt.setString(4, linkParameter); stmt.setLong(5, timestamp); stmt.executeUpdate(); } catch (SQLException e) { throw new CmsDbSqlException(Messages.get().container(Messages.ERR_GENERIC_SQL_1, stmt), e); } finally { m_sqlManager.closeAll(dbc, conn, stmt, null); } } } /** * Creates a <code>CmsPublishJobInfoBean</code> from a result set.<p> * * @param res the result set * @return an initialized <code>CmsPublishJobInfoBean</code> * @throws SQLException if something goes wrong */ protected CmsPublishJobInfoBean createPublishJobInfoBean(ResultSet res) throws SQLException { return new CmsPublishJobInfoBean( new CmsUUID(res.getString("HISTORY_ID")), new CmsUUID(res.getString("PROJECT_ID")), res.getString("PROJECT_NAME"), new CmsUUID(res.getString("USER_ID")), res.getString("PUBLISH_LOCALE"), res.getInt("PUBLISH_FLAGS"), res.getInt("RESOURCE_COUNT"), res.getLong("ENQUEUE_TIME"), res.getLong("START_TIME"), res.getLong("FINISH_TIME")); } /** * Checks if the given resource (by id) is available in the online project, * if there exists a resource with a different path (a moved file), then the * online entry is moved to the right (new) location before publishing.<p> * * @param dbc the db context * @param onlineProject the online project * @param offlineResource the offline resource to check * @param publishHistoryId the publish history id * @param publishTag the publish tag * * @return <code>true</code> if the resource has actually been moved * * @throws CmsDataAccessException if something goes wrong */ protected CmsResourceState fixMovedResource( CmsDbContext dbc, CmsProject onlineProject, CmsResource offlineResource, CmsUUID publishHistoryId, int publishTag) throws CmsDataAccessException { CmsResource onlineResource; // check if the resource has been moved since last publishing try { onlineResource = m_driverManager.getVfsDriver(dbc).readResource( dbc, onlineProject.getUuid(), offlineResource.getStructureId(), true); if (onlineResource.getRootPath().equals(offlineResource.getRootPath())) { // resource changed, not moved return offlineResource.getState(); } } catch (CmsVfsResourceNotFoundException e) { // ok, resource new, not moved return offlineResource.getState(); } // move the online resource to the new position m_driverManager.getVfsDriver(dbc).moveResource( dbc, onlineProject.getUuid(), onlineResource, offlineResource.getRootPath()); try { // write the resource to the publish history m_driverManager.getProjectDriver(dbc).writePublishHistory( dbc, publishHistoryId, new CmsPublishedResource(onlineResource, publishTag, CmsPublishedResource.STATE_MOVED_SOURCE)); } catch (CmsDataAccessException e) { if (LOG.isErrorEnabled()) { LOG.error( Messages.get().getBundle().key( Messages.LOG_WRITING_PUBLISHING_HISTORY_1, onlineResource.getRootPath()), e); } throw e; } return offlineResource.getState().isDeleted() ? CmsResource.STATE_DELETED : CmsPublishedResource.STATE_MOVED_DESTINATION; } /** * Returns a SQL parameter string for the given data.<p> * * @param data the data * * @return the SQL parameter */ protected String getParameterString(Collection<?> data) { StringBuffer conditions = new StringBuffer(); conditions.append(BEGIN_CONDITION); Iterator<?> it = data.iterator(); while (it.hasNext()) { it.next(); conditions.append("?"); if (it.hasNext()) { conditions.append(", "); } } conditions.append(END_CONDITION); return conditions.toString(); } /** * Creates a new project from the current row of the given result set.<p> * * @param res the result set * * @return the new project * * @throws SQLException is something goes wrong */ protected CmsProject internalCreateProject(ResultSet res) throws SQLException { String ou = CmsOrganizationalUnit.removeLeadingSeparator(res.getString(m_sqlManager.readQuery("C_PROJECTS_PROJECT_OU_0"))); return new CmsProject( new CmsUUID(res.getString(m_sqlManager.readQuery("C_PROJECTS_PROJECT_ID_0"))), ou + res.getString(m_sqlManager.readQuery("C_PROJECTS_PROJECT_NAME_0")), res.getString(m_sqlManager.readQuery("C_PROJECTS_PROJECT_DESCRIPTION_0")), new CmsUUID(res.getString(m_sqlManager.readQuery("C_PROJECTS_USER_ID_0"))), new CmsUUID(res.getString(m_sqlManager.readQuery("C_PROJECTS_GROUP_ID_0"))), new CmsUUID(res.getString(m_sqlManager.readQuery("C_PROJECTS_MANAGERGROUP_ID_0"))), res.getInt(m_sqlManager.readQuery("C_PROJECTS_PROJECT_FLAGS_0")), res.getLong(m_sqlManager.readQuery("C_PROJECTS_DATE_CREATED_0")), CmsProject.CmsProjectType.valueOf(res.getInt(m_sqlManager.readQuery("C_PROJECTS_PROJECT_TYPE_0")))); } /** * Builds a publish list from serialized data.<p> * * @param bytes the byte array containing the serailized data for the publish list * @return the initialized publish list * * @throws IOException if deserialization fails * @throws ClassNotFoundException if deserialization fails */ protected CmsPublishList internalDeserializePublishList(byte[] bytes) throws IOException, ClassNotFoundException { ByteArrayInputStream bin = new ByteArrayInputStream(bytes); ObjectInputStream oin = new ObjectInputStream(bin); return (CmsPublishList)oin.readObject(); } /** * Creates a new {@link CmsLogEntry} object from the given result set entry.<p> * * @param res the result set * * @return the new {@link CmsLogEntry} object * * @throws SQLException if something goes wrong */ protected CmsLogEntry internalReadLogEntry(ResultSet res) throws SQLException { CmsUUID userId = new CmsUUID(res.getString(m_sqlManager.readQuery("C_LOG_USER_ID"))); long date = res.getLong(m_sqlManager.readQuery("C_LOG_DATE")); CmsUUID structureId = new CmsUUID(res.getString(m_sqlManager.readQuery("C_LOG_STRUCTURE_ID"))); CmsLogEntryType type = CmsLogEntryType.valueOf(res.getInt(m_sqlManager.readQuery("C_LOG_TYPE"))); String[] data = CmsStringUtil.splitAsArray(res.getString(m_sqlManager.readQuery("C_LOG_DATA")), '|'); return new CmsLogEntry(userId, date, structureId, type, data); } /** * Resets the state to UNCHANGED for a specified resource.<p> * * @param dbc the current database context * @param resource the Cms resource * * @throws CmsDataAccessException if something goes wrong */ protected void internalResetResourceState(CmsDbContext dbc, CmsResource resource) throws CmsDataAccessException { try { // reset the resource state resource.setState(CmsResource.STATE_UNCHANGED); m_driverManager.getVfsDriver(dbc).writeResourceState( dbc, dbc.currentProject(), resource, CmsDriverManager.UPDATE_ALL, true); } catch (CmsDataAccessException e) { if (LOG.isErrorEnabled()) { LOG.error( Messages.get().getBundle().key( Messages.LOG_ERROR_RESETTING_RESOURCE_STATE_1, resource.getRootPath()), e); } throw e; } } /** * Serialize publish list to write it as byte array to the database.<p> * * @param publishList the publish list * @return byte array containing the publish list data * @throws IOException if something goes wrong */ protected byte[] internalSerializePublishList(CmsPublishList publishList) throws IOException { // serialize the publish list ByteArrayOutputStream bout = new ByteArrayOutputStream(); ObjectOutputStream oout = new ObjectOutputStream(bout); oout.writeObject(publishList); oout.close(); return bout.toByteArray(); } /** * Writes the needed history entries.<p> * * @param dbc the current database context * @param resource the offline resource * @param state the state to store in the publish history entry * @param properties the offline properties * @param publishHistoryId the current publish process id * @param publishTag the current publish process tag * * @throws CmsDataAccessException if something goes wrong */ protected void internalWriteHistory( CmsDbContext dbc, CmsResource resource, CmsResourceState state, List properties, CmsUUID publishHistoryId, int publishTag) throws CmsDataAccessException { try { if (OpenCms.getSystemInfo().isHistoryEnabled()) { // write the resource to the historical archive if (properties == null) { properties = m_driverManager.getVfsDriver(dbc).readPropertyObjects( dbc, dbc.currentProject(), resource); } m_driverManager.getHistoryDriver(dbc).writeResource(dbc, resource, properties, publishTag); } // write the resource to the publish history m_driverManager.getProjectDriver(dbc).writePublishHistory( dbc, publishHistoryId, new CmsPublishedResource(resource, publishTag, state)); } catch (CmsDataAccessException e) { if (LOG.isErrorEnabled()) { LOG.error( Messages.get().getBundle().key(Messages.LOG_WRITING_PUBLISHING_HISTORY_1, resource.getRootPath()), e); } throw e; } } /** * Build the whole WHERE SQL statement part for the given log entry filter.<p> * * @param filter the filter * * @return a pair containing both the SQL and the parameters for it */ protected CmsPair<String, List<I_CmsPreparedStatementParameter>> prepareLogConditions(CmsLogFilter filter) { List<I_CmsPreparedStatementParameter> params = new ArrayList<I_CmsPreparedStatementParameter>(); StringBuffer conditions = new StringBuffer(); // user id filter if (filter.getUserId() != null) { if (conditions.length() == 0) { conditions.append(BEGIN_CONDITION); } else { conditions.append(BEGIN_INCLUDE_CONDITION); } conditions.append(m_sqlManager.readQuery("C_LOG_FILTER_USER_ID")); params.add(new CmsPreparedStatementStringParameter(filter.getUserId().toString())); conditions.append(END_CONDITION); } // resource id filter if (filter.getStructureId() != null) { if (conditions.length() == 0) { conditions.append(BEGIN_CONDITION); } else { conditions.append(BEGIN_INCLUDE_CONDITION); } conditions.append(m_sqlManager.readQuery("C_LOG_FILTER_RESOURCE_ID")); params.add(new CmsPreparedStatementStringParameter(filter.getStructureId().toString())); conditions.append(END_CONDITION); } // date from filter if (filter.getDateFrom() != CmsResource.DATE_RELEASED_DEFAULT) { if (conditions.length() == 0) { conditions.append(BEGIN_CONDITION); } else { conditions.append(BEGIN_INCLUDE_CONDITION); } conditions.append(m_sqlManager.readQuery("C_LOG_FILTER_DATE_FROM")); params.add(new CmsPreparedStatementLongParameter(filter.getDateFrom())); conditions.append(END_CONDITION); } // date to filter if (filter.getDateTo() != CmsResource.DATE_RELEASED_DEFAULT) { if (conditions.length() == 0) { conditions.append(BEGIN_CONDITION); } else { conditions.append(BEGIN_INCLUDE_CONDITION); } conditions.append(m_sqlManager.readQuery("C_LOG_FILTER_DATE_TO")); params.add(new CmsPreparedStatementLongParameter(filter.getDateTo())); conditions.append(END_CONDITION); } // include type filter Set<CmsLogEntryType> includeTypes = filter.getIncludeTypes(); if (!includeTypes.isEmpty()) { if (conditions.length() == 0) { conditions.append(BEGIN_CONDITION); } else { conditions.append(BEGIN_INCLUDE_CONDITION); } conditions.append(m_sqlManager.readQuery("C_LOG_FILTER_INCLUDE_TYPE")); conditions.append(BEGIN_CONDITION); Iterator<CmsLogEntryType> it = includeTypes.iterator(); while (it.hasNext()) { CmsLogEntryType type = it.next(); conditions.append("?"); params.add(new CmsPreparedStatementIntParameter(type.getId())); if (it.hasNext()) { conditions.append(", "); } } conditions.append(END_CONDITION); conditions.append(END_CONDITION); } // exclude type filter Set<CmsLogEntryType> excludeTypes = filter.getExcludeTypes(); if (!excludeTypes.isEmpty()) { if (conditions.length() == 0) { conditions.append(BEGIN_CONDITION); } else { conditions.append(BEGIN_INCLUDE_CONDITION); } conditions.append(m_sqlManager.readQuery("C_LOG_FILTER_EXCLUDE_TYPE")); conditions.append(BEGIN_CONDITION); Iterator<CmsLogEntryType> it = excludeTypes.iterator(); while (it.hasNext()) { CmsLogEntryType type = it.next(); conditions.append("?"); params.add(new CmsPreparedStatementIntParameter(type.getId())); if (it.hasNext()) { conditions.append(", "); } } conditions.append(END_CONDITION); conditions.append(END_CONDITION); } return CmsPair.create(conditions.toString(), params); } /** * Publishes a changed file.<p> * * @param dbc the current database context * @param onlineProject the online project * @param offlineResource the resource to publish * @param publishedResourceIds contains the UUIDs of already published content records * @param publishHistoryId the publish history id * @param publishTag the publish tag * * @throws CmsDataAccessException is something goes wrong */ protected void publishChangedFile( CmsDbContext dbc, CmsProject onlineProject, CmsResource offlineResource, Set publishedResourceIds, CmsUUID publishHistoryId, int publishTag) throws CmsDataAccessException { CmsResource onlineResource = null; boolean needToUpdateContent = true; boolean existsOnline = m_driverManager.getVfsDriver(dbc).validateStructureIdExists( dbc, CmsProject.ONLINE_PROJECT_ID, offlineResource.getStructureId()); CmsResourceState resourceState = existsOnline ? fixMovedResource( dbc, onlineProject, offlineResource, publishHistoryId, publishTag) : offlineResource.getState(); try { // reset the labeled link flag before writing the online file int flags = offlineResource.getFlags(); flags &= ~CmsResource.FLAG_LABELED; offlineResource.setFlags(flags); if (existsOnline) { // read the file header online onlineResource = m_driverManager.getVfsDriver(dbc).readResource( dbc, onlineProject.getUuid(), offlineResource.getStructureId(), false); needToUpdateContent = (onlineResource.getDateContent() < offlineResource.getDateContent()); // delete the properties online m_driverManager.getVfsDriver(dbc).deletePropertyObjects( dbc, onlineProject.getUuid(), onlineResource, CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES); // if the offline file has a resource ID different from the online file // (probably because a deleted file was replaced by a new file with the // same name), the properties mapped to the "old" resource ID have to be // deleted also offline. if this is the case, the online and offline structure // ID's do match, but the resource ID's are different. structure IDs are reused // to prevent orphan structure records in the online project. if (!onlineResource.getResourceId().equals(offlineResource.getResourceId())) { List offlineProperties = m_driverManager.getVfsDriver(dbc).readPropertyObjects( dbc, dbc.currentProject(), onlineResource); if (offlineProperties.size() > 0) { for (int i = 0; i < offlineProperties.size(); i++) { CmsProperty property = (CmsProperty)offlineProperties.get(i); property.setStructureValue(null); property.setResourceValue(CmsProperty.DELETE_VALUE); } m_driverManager.getVfsDriver(dbc).writePropertyObjects( dbc, dbc.currentProject(), onlineResource, offlineProperties); } } } } catch (CmsDataAccessException e) { if (LOG.isErrorEnabled()) { LOG.error( Messages.get().getBundle().key(Messages.LOG_DELETING_PROPERTIES_1, offlineResource.toString()), e); } throw e; } CmsFile newFile; try { // publish the file content newFile = m_driverManager.getProjectDriver(dbc).publishFileContent( dbc, dbc.currentProject(), onlineProject, offlineResource, publishedResourceIds, needToUpdateContent, publishTag); } catch (CmsDataAccessException e) { if (LOG.isErrorEnabled()) { LOG.error( Messages.get().getBundle().key(Messages.LOG_PUBLISHING_RESOURCE_1, offlineResource.getRootPath()), e); } throw e; } List offlineProperties; try { // write the properties online offlineProperties = m_driverManager.getVfsDriver(dbc).readPropertyObjects( dbc, dbc.currentProject(), offlineResource); CmsProperty.setAutoCreatePropertyDefinitions(offlineProperties, true); m_driverManager.getVfsDriver(dbc).writePropertyObjects(dbc, onlineProject, newFile, offlineProperties); } catch (CmsDataAccessException e) { if (LOG.isErrorEnabled()) { LOG.error( Messages.get().getBundle().key(Messages.LOG_PUBLISHING_PROPERTIES_1, newFile.getRootPath()), e); } throw e; } try { // write the ACL online m_driverManager.getUserDriver(dbc).publishAccessControlEntries( dbc, dbc.currentProject(), onlineProject, newFile.getResourceId(), offlineResource.getResourceId()); } catch (CmsDataAccessException e) { if (LOG.isErrorEnabled()) { LOG.error(Messages.get().getBundle().key(Messages.LOG_PUBLISHING_ACL_1, newFile.getRootPath()), e); } throw e; } CmsFile offlineFile = new CmsFile(offlineResource); offlineFile.setContents(newFile.getContents()); internalWriteHistory(dbc, offlineFile, resourceState, offlineProperties, publishHistoryId, publishTag); m_driverManager.getVfsDriver(dbc).updateRelations(dbc, onlineProject, offlineResource); } /** * Publishes a deleted file.<p> * * @param dbc the current database context * @param onlineProject the online project * @param offlineResource the resource to publish * @param publishHistoryId the publish history id * @param publishTag the publish tag * * @throws CmsDataAccessException is something goes wrong */ protected void publishDeletedFile( CmsDbContext dbc, CmsProject onlineProject, CmsResource offlineResource, CmsUUID publishHistoryId, int publishTag) throws CmsDataAccessException { CmsResourceState resourceState = fixMovedResource( dbc, onlineProject, offlineResource, publishHistoryId, publishTag); boolean existsOnline = m_driverManager.getVfsDriver(dbc).validateStructureIdExists( dbc, CmsProject.ONLINE_PROJECT_ID, offlineResource.getStructureId()); CmsResource onlineResource = null; if (existsOnline) { try { // read the file header online onlineResource = m_driverManager.getVfsDriver(dbc).readResource( dbc, onlineProject.getUuid(), offlineResource.getStructureId(), true); } catch (CmsDataAccessException e) { if (LOG.isErrorEnabled()) { LOG.error( Messages.get().getBundle().key(Messages.LOG_READING_RESOURCE_1, offlineResource.getRootPath()), e); } throw e; } } if (offlineResource.isLabeled() && !m_driverManager.labelResource(dbc, offlineResource, null, 2)) { // update the resource flags to "unlabeled" of the siblings of the offline resource int flags = offlineResource.getFlags(); flags &= ~CmsResource.FLAG_LABELED; offlineResource.setFlags(flags); } // write history before deleting CmsFile offlineFile = new CmsFile(offlineResource); offlineFile.setContents(m_driverManager.getVfsDriver(dbc).readContent( dbc, dbc.currentProject().getUuid(), offlineFile.getResourceId())); internalWriteHistory(dbc, offlineFile, resourceState, null, publishHistoryId, publishTag); int propertyDeleteOption = -1; try { // delete the properties online and offline if (offlineResource.getSiblingCount() > 1) { // there are other siblings- delete only structure property values and keep the resource property values propertyDeleteOption = CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_VALUES; } else { // there are no other siblings- delete both the structure and resource property values propertyDeleteOption = CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES; } if (existsOnline) { m_driverManager.getVfsDriver(dbc).deletePropertyObjects( dbc, onlineProject.getUuid(), onlineResource, propertyDeleteOption); } m_driverManager.getVfsDriver(dbc).deletePropertyObjects( dbc, dbc.currentProject().getUuid(), offlineResource, propertyDeleteOption); // if the offline file has a resource ID different from the online file // (probably because a (deleted) file was replaced by a new file with the // same name), the properties with the "old" resource ID have to be // deleted also offline if (existsOnline && (onlineResource != null) && !onlineResource.getResourceId().equals(offlineResource.getResourceId())) { m_driverManager.getVfsDriver(dbc).deletePropertyObjects( dbc, dbc.currentProject().getUuid(), onlineResource, CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES); } } catch (CmsDataAccessException e) { if (LOG.isErrorEnabled()) { LOG.error( Messages.get().getBundle().key(Messages.LOG_DELETING_PROPERTIES_1, offlineResource.getRootPath()), e); } throw e; } try { // remove the file online and offline m_driverManager.getVfsDriver(dbc).removeFile(dbc, dbc.currentProject().getUuid(), offlineResource); if (existsOnline && (onlineResource != null)) { m_driverManager.getVfsDriver(dbc).removeFile(dbc, onlineProject.getUuid(), onlineResource); } } catch (CmsDataAccessException e) { if (LOG.isErrorEnabled()) { LOG.error( Messages.get().getBundle().key(Messages.LOG_REMOVING_RESOURCE_1, offlineResource.getRootPath()), e); } throw e; } // delete the ACL online and offline try { if (existsOnline && (onlineResource != null) && (onlineResource.getSiblingCount() == 1)) { // only if no siblings left m_driverManager.getUserDriver(dbc).removeAccessControlEntries( dbc, onlineProject, onlineResource.getResourceId()); } if (offlineResource.getSiblingCount() == 1) { // only if no siblings left m_driverManager.getUserDriver(dbc).removeAccessControlEntries( dbc, dbc.currentProject(), offlineResource.getResourceId()); } } catch (CmsDataAccessException e) { if (LOG.isErrorEnabled()) { LOG.error(Messages.get().getBundle().key(Messages.LOG_REMOVING_ACL_1, offlineResource.toString()), e); } throw e; } try { // delete relations online and offline m_driverManager.getVfsDriver(dbc).deleteRelations( dbc, onlineProject.getUuid(), offlineResource, CmsRelationFilter.TARGETS); m_driverManager.getVfsDriver(dbc).deleteRelations( dbc, dbc.currentProject().getUuid(), offlineResource, CmsRelationFilter.TARGETS); } catch (CmsDataAccessException e) { if (LOG.isErrorEnabled()) { LOG.error( Messages.get().getBundle().key(Messages.LOG_REMOVING_RELATIONS_1, offlineResource.toString()), e); } throw e; } if (OpenCms.getSubscriptionManager().isEnabled()) { try { // delete visited information for resource from log CmsVisitEntryFilter filter = CmsVisitEntryFilter.ALL.filterResource(offlineResource.getStructureId()); m_driverManager.getSubscriptionDriver().deleteVisits( dbc, OpenCms.getSubscriptionManager().getPoolName(), filter); } catch (CmsDataAccessException e) { if (LOG.isErrorEnabled()) { LOG.error( Messages.get().getBundle().key(Messages.LOG_REMOVING_VISITEDLOG_1, offlineResource.toString()), e); } throw e; } try { // mark the subscribed resource as deleted /* changed to subscription driver */ // m_driverManager.getUserDriver(dbc).setSubscribedResourceAsDeleted( // dbc, // OpenCms.getSubscriptionManager().getPoolName(), // offlineResource); m_driverManager.getSubscriptionDriver().setSubscribedResourceAsDeleted( dbc, OpenCms.getSubscriptionManager().getPoolName(), offlineResource); } catch (CmsDataAccessException e) { if (LOG.isErrorEnabled()) { LOG.error( Messages.get().getBundle().key( Messages.LOG_REMOVING_SUBSCRIPTIONS_1, offlineResource.toString()), e); } throw e; } } } /** * Publishes a new file.<p> * * @param dbc the current database context * @param onlineProject the online project * @param offlineResource the resource to publish * @param publishedContentIds contains the UUIDs of already published content records * @param publishHistoryId the publish history id * @param publishTag the publish tag * * @throws CmsDataAccessException is something goes wrong */ protected void publishNewFile( CmsDbContext dbc, CmsProject onlineProject, CmsResource offlineResource, Set publishedContentIds, CmsUUID publishHistoryId, int publishTag) throws CmsDataAccessException { CmsResourceState resourceState = fixMovedResource( dbc, onlineProject, offlineResource, publishHistoryId, publishTag); CmsFile newFile; try { // reset the labeled link flag before writing the online file int flags = offlineResource.getFlags(); flags &= ~CmsResource.FLAG_LABELED; offlineResource.setFlags(flags); // publish the file content newFile = m_driverManager.getProjectDriver(dbc).publishFileContent( dbc, dbc.currentProject(), onlineProject, offlineResource, publishedContentIds, true, publishTag); } catch (CmsVfsResourceAlreadyExistsException e) { try { // remove the existing file and ensure that it's content is written // in any case by removing it's resource ID from the set of published resource IDs m_driverManager.getVfsDriver(dbc).removeFile(dbc, onlineProject.getUuid(), offlineResource); publishedContentIds.remove(offlineResource.getResourceId()); newFile = m_driverManager.getProjectDriver(dbc).publishFileContent( dbc, dbc.currentProject(), onlineProject, offlineResource, publishedContentIds, true, publishTag); } catch (CmsDataAccessException e1) { if (LOG.isErrorEnabled()) { LOG.error( Messages.get().getBundle().key( Messages.LOG_PUBLISHING_RESOURCE_1, offlineResource.getRootPath()), e); } throw e1; } } catch (CmsDataAccessException e) { if (LOG.isErrorEnabled()) { LOG.error( Messages.get().getBundle().key(Messages.LOG_PUBLISHING_RESOURCE_1, offlineResource.getRootPath()), e); } throw e; } List offlineProperties; try { // write the properties online offlineProperties = m_driverManager.getVfsDriver(dbc).readPropertyObjects( dbc, dbc.currentProject(), offlineResource); CmsProperty.setAutoCreatePropertyDefinitions(offlineProperties, true); m_driverManager.getVfsDriver(dbc).writePropertyObjects(dbc, onlineProject, newFile, offlineProperties); } catch (CmsDataAccessException e) { if (LOG.isErrorEnabled()) { LOG.error( Messages.get().getBundle().key(Messages.LOG_PUBLISHING_PROPERTIES_1, newFile.getRootPath()), e); } throw e; } try { // write the ACL online m_driverManager.getUserDriver(dbc).publishAccessControlEntries( dbc, dbc.currentProject(), onlineProject, offlineResource.getResourceId(), newFile.getResourceId()); } catch (CmsDataAccessException e) { if (LOG.isErrorEnabled()) { LOG.error(Messages.get().getBundle().key(Messages.LOG_PUBLISHING_ACL_1, newFile.getRootPath()), e); } throw e; } CmsFile offlineFile = new CmsFile(offlineResource); offlineFile.setContents(newFile.getContents()); internalWriteHistory(dbc, offlineFile, resourceState, offlineProperties, publishHistoryId, publishTag); m_driverManager.getVfsDriver(dbc).updateRelations(dbc, onlineProject, offlineResource); } }