org.opencms.db.generic.CmsHistoryDriver Maven / Gradle / Ivy
Show all versions of opencms-test Show documentation
/*
* This library is part of OpenCms -
* the Open Source Content Management System
*
* Copyright (c) Alkacon Software GmbH & Co. KG (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 & Co. KG, 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.CmsDbConsistencyException;
import org.opencms.db.CmsDbContext;
import org.opencms.db.CmsDbEntryNotFoundException;
import org.opencms.db.CmsDbSqlException;
import org.opencms.db.CmsDriverManager;
import org.opencms.db.CmsResourceState;
import org.opencms.db.I_CmsDriver;
import org.opencms.db.I_CmsHistoryDriver;
import org.opencms.db.I_CmsVfsDriver;
import org.opencms.file.CmsDataAccessException;
import org.opencms.file.CmsFile;
import org.opencms.file.CmsFolder;
import org.opencms.file.CmsProject;
import org.opencms.file.CmsProperty;
import org.opencms.file.CmsPropertyDefinition;
import org.opencms.file.CmsResource;
import org.opencms.file.CmsUser;
import org.opencms.file.CmsVfsResourceNotFoundException;
import org.opencms.file.history.CmsHistoryFile;
import org.opencms.file.history.CmsHistoryFolder;
import org.opencms.file.history.CmsHistoryPrincipal;
import org.opencms.file.history.CmsHistoryProject;
import org.opencms.file.history.I_CmsHistoryResource;
import org.opencms.main.CmsLog;
import org.opencms.security.CmsOrganizationalUnit;
import org.opencms.security.I_CmsPrincipal;
import org.opencms.util.CmsStringUtil;
import org.opencms.util.CmsUUID;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log;
/**
* Generic (ANSI-SQL) database server implementation of the history driver methods.
*
* @since 6.9.1
*/
public class CmsHistoryDriver implements I_CmsDriver, I_CmsHistoryDriver {
/** The log object for this class. */
private static final Log LOG = CmsLog.getLog(org.opencms.db.generic.CmsHistoryDriver.class);
/** The driver manager instance. */
protected CmsDriverManager m_driverManager;
/** The SQL manager instance. */
protected CmsSqlManager m_sqlManager;
/**
* @see org.opencms.db.I_CmsHistoryDriver#createPropertyDefinition(org.opencms.db.CmsDbContext, java.lang.String, org.opencms.file.CmsPropertyDefinition.CmsPropertyType)
*/
public CmsPropertyDefinition createPropertyDefinition(
CmsDbContext dbc,
String name,
CmsPropertyDefinition.CmsPropertyType type) throws CmsDataAccessException {
Connection conn = null;
PreparedStatement stmt = null;
try {
conn = m_sqlManager.getConnection(dbc);
stmt = m_sqlManager.getPreparedStatement(conn, "C_PROPERTYDEF_CREATE_HISTORY");
stmt.setString(1, new CmsUUID().toString());
stmt.setString(2, name);
stmt.setInt(3, type.getMode());
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);
}
return readPropertyDefinition(dbc, name);
}
/**
* @see org.opencms.db.I_CmsHistoryDriver#deleteEntries(CmsDbContext, I_CmsHistoryResource, int, long)
*/
public int deleteEntries(CmsDbContext dbc, I_CmsHistoryResource resource, int versionsToKeep, long time)
throws CmsDataAccessException {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet res = null;
try {
conn = m_sqlManager.getConnection(dbc);
int maxVersion = -1;
// get the maximal version number for this resource
stmt = m_sqlManager.getPreparedStatement(conn, "C_STRUCTURE_HISTORY_MAXVER");
stmt.setString(1, resource.getStructureId().toString());
res = stmt.executeQuery();
boolean noHistoryStructure = false;
if (res.next()) {
maxVersion = res.getInt(1);
noHistoryStructure |= res.wasNull();
while (res.next()) {
// do nothing only move through all rows because of mssql odbc driver
}
} else {
// make sure the connection is closed
m_sqlManager.closeAll(dbc, conn, stmt, res);
// nothing to delete
internalCleanup(dbc, resource);
return 0;
}
m_sqlManager.closeAll(dbc, conn, stmt, res);
if (time >= 0) {
int maxVersionByTime = -1;
conn = m_sqlManager.getConnection(dbc);
// get the maximal version to keep for this resource based on the time parameter
stmt = m_sqlManager.getPreparedStatement(conn, "C_STRUCTURE_HISTORY_MAXVER_BYTIME");
stmt.setString(1, resource.getStructureId().toString());
stmt.setLong(2, time);
res = stmt.executeQuery();
if (res.next()) {
maxVersionByTime = res.getInt(1);
while (res.next()) {
// do nothing only move through all rows because of mssql odbc driver
}
}
m_sqlManager.closeAll(dbc, conn, stmt, res);
if (maxVersionByTime > 0) {
if (versionsToKeep < 0) {
versionsToKeep = (maxVersion - maxVersionByTime);
} else {
versionsToKeep = Math.min(versionsToKeep, (maxVersion - maxVersionByTime));
}
}
}
int structureVersions = 0;
// get the minimal structure publish tag to keep for this sibling
conn = m_sqlManager.getConnection(dbc);
if (!noHistoryStructure) {
if ((versionsToKeep == -1) || ((maxVersion - versionsToKeep) <= 0)) {
// nothing to delete
internalCleanup(dbc, resource);
return 0;
}
// get the minimal structure publish tag to keep for this sibling
int minStrPublishTagToKeep = -1;
stmt = m_sqlManager.getPreparedStatement(conn, "C_HISTORY_READ_MAXTAG_FOR_VERSION");
stmt.setString(1, resource.getStructureId().toString());
stmt.setInt(2, (1 + maxVersion) - versionsToKeep);
res = stmt.executeQuery();
if (res.next()) {
minStrPublishTagToKeep = res.getInt(1);
while (res.next()) {
// do nothing only move through all rows because of mssql odbc driver
}
} else {
// make sure the statement and the result is closed
m_sqlManager.closeAll(dbc, conn, stmt, res);
// nothing to delete
internalCleanup(dbc, resource);
return 0;
}
m_sqlManager.closeAll(dbc, conn, stmt, res);
if (minStrPublishTagToKeep < 1) {
// nothing to delete
internalCleanup(dbc, resource);
return 0;
}
minStrPublishTagToKeep++;
// delete the properties
conn = m_sqlManager.getConnection(dbc);
stmt = m_sqlManager.getPreparedStatement(conn, "C_PROPERTIES_HISTORY_DELETE");
stmt.setString(1, resource.getStructureId().toString());
stmt.setInt(2, minStrPublishTagToKeep);
stmt.executeUpdate();
m_sqlManager.closeAll(dbc, null, stmt, null);
// delete the structure entries
stmt = m_sqlManager.getPreparedStatement(conn, "C_STRUCTURE_HISTORY_DELETE");
stmt.setString(1, resource.getStructureId().toString());
stmt.setInt(2, minStrPublishTagToKeep);
structureVersions = stmt.executeUpdate();
m_sqlManager.closeAll(dbc, null, stmt, null);
}
// get the minimal resource publish tag to keep,
// all entries with publish tag less than this will be deleted
int minResPublishTagToKeep = -1;
stmt = m_sqlManager.getPreparedStatement(conn, "C_HISTORY_READ_MIN_USED_TAG");
stmt.setString(1, resource.getResourceId().toString());
res = stmt.executeQuery();
if (res.next()) {
minResPublishTagToKeep = res.getInt(1);
if (res.wasNull()) {
// the database will return a row with a single NULL column if there are no rows at all for the given
// resource id. This means that we want to clean up all resource history and content history entries
// for this resource id, and we achieve this by comparing their publish tag with the maximum integer.
minResPublishTagToKeep = Integer.MAX_VALUE;
}
while (res.next()) {
// do nothing only move through all rows because of mssql odbc driver
}
}
m_sqlManager.closeAll(dbc, conn, stmt, res);
// delete the resource entries
conn = m_sqlManager.getConnection(dbc);
stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_HISTORY_DELETE");
stmt.setString(1, resource.getResourceId().toString());
stmt.setInt(2, minResPublishTagToKeep);
int resourceVersions = stmt.executeUpdate();
m_sqlManager.closeAll(dbc, null, stmt, null);
// delete the content entries
stmt = m_sqlManager.getPreparedStatement(conn, "C_CONTENT_HISTORY_DELETE");
stmt.setString(1, resource.getResourceId().toString());
stmt.setInt(2, minResPublishTagToKeep);
stmt.executeUpdate();
// make sure the statement and the result is closed
m_sqlManager.closeAll(dbc, conn, stmt, res);
internalCleanup(dbc, resource);
return Math.max(structureVersions, resourceVersions);
} 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);
}
}
/**
* @see org.opencms.db.I_CmsHistoryDriver#deletePropertyDefinition(org.opencms.db.CmsDbContext, org.opencms.file.CmsPropertyDefinition)
*/
public void deletePropertyDefinition(CmsDbContext dbc, CmsPropertyDefinition metadef)
throws CmsDataAccessException {
Connection conn = null;
PreparedStatement stmt = null;
try {
if ((internalCountProperties(dbc, metadef, CmsProject.ONLINE_PROJECT_ID) != 0)
|| (internalCountProperties(dbc, metadef, CmsUUID.getOpenCmsUUID()) != 0)) { // HACK: to get an offline project
throw new CmsDbConsistencyException(
Messages.get().container(Messages.ERR_ERROR_DELETING_PROPERTYDEF_1, metadef.getName()));
}
// delete the historical property definition
conn = m_sqlManager.getConnection(dbc);
stmt = m_sqlManager.getPreparedStatement(conn, "C_PROPERTYDEF_DELETE_HISTORY");
stmt.setString(1, metadef.getId().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_CmsHistoryDriver#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_CmsHistoryDriver#getAllDeletedEntries(org.opencms.db.CmsDbContext)
*/
public List getAllDeletedEntries(CmsDbContext dbc) throws CmsDataAccessException {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet res = null;
Map tmpEntrieis = new HashMap();
List entries = new ArrayList();
try {
conn = m_sqlManager.getConnection(dbc);
// get all not-deleted historical entries that may come in question
stmt = m_sqlManager.getPreparedStatement(conn, "C_STRUCTURE_HISTORY_READ_DELETED");
res = stmt.executeQuery();
while (res.next()) {
CmsUUID structureId = new CmsUUID(res.getString(1));
int version = res.getInt(2);
tmpEntrieis.put(structureId, Integer.valueOf(version));
}
} 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);
}
for (Map.Entry entry : tmpEntrieis.entrySet()) {
entries.add(readResource(dbc, entry.getKey(), entry.getValue().intValue()));
}
return entries;
}
/**
* @see org.opencms.db.I_CmsHistoryDriver#getAllNotDeletedEntries(org.opencms.db.CmsDbContext)
*/
public List getAllNotDeletedEntries(CmsDbContext dbc) throws CmsDataAccessException {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet res = null;
Map tmpEntrieis = new HashMap();
List entries = new ArrayList();
try {
conn = m_sqlManager.getConnection(dbc);
// get all not-deleted historical entries that may come in question
stmt = m_sqlManager.getPreparedStatement(conn, "C_STRUCTURE_HISTORY_READ_NOTDELETED");
res = stmt.executeQuery();
while (res.next()) {
CmsUUID structureId = new CmsUUID(res.getString(1));
int version = res.getInt(2);
tmpEntrieis.put(structureId, Integer.valueOf(version));
}
} 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);
}
for (Map.Entry entry : tmpEntrieis.entrySet()) {
entries.add(readResource(dbc, entry.getKey(), entry.getValue().intValue()));
}
return entries;
}
/**
* @see org.opencms.db.I_CmsHistoryDriver#getSqlManager()
*/
public CmsSqlManager getSqlManager() {
return m_sqlManager;
}
/**
* @see org.opencms.db.I_CmsDriver#init(org.opencms.db.CmsDbContext, org.opencms.configuration.CmsConfigurationManager, java.util.List, org.opencms.db.CmsDriverManager)
*/
public void init(
CmsDbContext dbc,
CmsConfigurationManager configurationManager,
List successiveDrivers,
CmsDriverManager driverManager) {
CmsParameterConfiguration configuration = configurationManager.getConfiguration();
String poolUrl;
if (configuration.get("db.history.pool") != null) {
poolUrl = configuration.get("db.history.pool").toString();
} else {
// TODO: deprecated, remove as soon as possible
poolUrl = configuration.get("db.backup.pool").toString();
}
String classname;
if (configuration.get("db.history.sqlmanager") != null) {
classname = configuration.get("db.history.sqlmanager").toString();
} else {
// TODO: deprecated, remove as soon as possible
classname = configuration.get("db.backup.sqlmanager").toString();
}
m_sqlManager = initSqlManager(classname);
m_sqlManager.init(I_CmsHistoryDriver.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_CmsHistoryDriver#initSqlManager(String)
*/
public org.opencms.db.generic.CmsSqlManager initSqlManager(String classname) {
return CmsSqlManager.getInstance(classname);
}
/**
* @see org.opencms.db.I_CmsHistoryDriver#readAllAvailableVersions(CmsDbContext, CmsUUID)
*/
public List readAllAvailableVersions(CmsDbContext dbc, CmsUUID structureId)
throws CmsDataAccessException {
ResultSet res = null;
List result = new ArrayList();
PreparedStatement stmt = null;
Connection conn = null;
try {
conn = m_sqlManager.getConnection(dbc);
// get all direct versions (where the structure entry has been written)
// sorted from the NEWEST to the OLDEST version (publish tag descendant)
List historyResources = new ArrayList();
stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_HISTORY_READ_ALL_VERSIONS");
stmt.setString(1, structureId.toString());
res = stmt.executeQuery();
while (res.next()) {
historyResources.add(internalCreateResource(res));
}
m_sqlManager.closeAll(dbc, null, stmt, res);
if (!historyResources.isEmpty()) {
// look for newer versions
// this is the NEWEST version, with the HIGHEST publish tag
I_CmsHistoryResource histRes = historyResources.get(0);
// look for later resource entries
stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_HISTORY_READ_NEW_VERSIONS");
stmt.setString(1, histRes.getResourceId().toString());
stmt.setInt(2, histRes.getPublishTag());
res = stmt.executeQuery();
I_CmsHistoryResource lastHistRes = histRes;
// these are sorted from the oldest to the newest version (publish tag ascendent)
while (res.next()) {
int resVersion = res.getInt(m_sqlManager.readQuery("C_RESOURCES_VERSION"));
if (resVersion == lastHistRes.getResourceVersion()) {
// skip not interesting versions
continue;
}
I_CmsHistoryResource newHistRes = internalMergeResource(histRes, res, 0);
// add interesting versions, in the right order
result.add(0, newHistRes);
lastHistRes = newHistRes;
}
m_sqlManager.closeAll(dbc, null, stmt, res);
}
// iterate from the NEWEST to the OLDEST versions (publish tag descendant)
for (int i = 0; i < historyResources.size(); i++) {
I_CmsHistoryResource histRes = historyResources.get(i);
result.add(histRes);
if (i < (historyResources.size() - 1)) {
// this is one older direct version than histRes (histRes.getPublishTag() > histRes2.getPublishTag())
I_CmsHistoryResource histRes2 = historyResources.get(i + 1);
// look for resource changes in between of the direct versions in ascendent order
stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_HISTORY_READ_BTW_VERSIONS");
stmt.setString(1, histRes.getResourceId().toString());
stmt.setInt(2, histRes2.getPublishTag()); // lower limit
stmt.setInt(3, histRes.getPublishTag()); // upper limit
res = stmt.executeQuery();
int pos = result.size();
I_CmsHistoryResource lastHistRes = histRes2;
while (res.next()) {
int resVersion = res.getInt(m_sqlManager.readQuery("C_RESOURCES_VERSION"));
if (resVersion == lastHistRes.getResourceVersion()) {
// skip not interesting versions
continue;
}
I_CmsHistoryResource newHistRes = internalMergeResource(histRes2, res, 0);
// add interesting versions, in the right order
result.add(pos, newHistRes);
lastHistRes = newHistRes;
}
m_sqlManager.closeAll(dbc, null, stmt, res);
}
}
if (!result.isEmpty()) {
// get the oldest version
I_CmsHistoryResource histRes = result.get(result.size() - 1);
if (histRes.getVersion() > 1) {
// look for older resource versions, in descendant order
stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_HISTORY_READ_OLD_VERSIONS");
stmt.setString(1, histRes.getResourceId().toString());
stmt.setInt(2, histRes.getPublishTag());
res = stmt.executeQuery();
int offset = (histRes.getStructureVersion() > 0 ? 1 : 0);
I_CmsHistoryResource lastHistRes = histRes;
while (res.next()) {
I_CmsHistoryResource newHistRes = internalMergeResource(histRes, res, offset);
if (newHistRes.getResourceVersion() != lastHistRes.getResourceVersion()) {
// only add interesting versions
if (offset == 1) {
if (histRes != lastHistRes) {
result.add(lastHistRes);
}
} else {
result.add(newHistRes);
}
}
lastHistRes = newHistRes;
}
// add the last one if there is one
if ((offset == 1) && (lastHistRes != histRes)) {
result.add(lastHistRes);
}
m_sqlManager.closeAll(dbc, null, stmt, 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_CmsHistoryDriver#readContent(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID, int)
*/
public byte[] readContent(CmsDbContext dbc, CmsUUID resourceId, int publishTag) throws CmsDataAccessException {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet res = null;
byte[] content = null;
try {
conn = m_sqlManager.getConnection(dbc);
stmt = m_sqlManager.getPreparedStatement(conn, "C_HISTORY_READ_CONTENT");
stmt.setString(1, resourceId.toString());
stmt.setInt(2, publishTag);
stmt.setInt(3, publishTag);
res = stmt.executeQuery();
if (res.next()) {
content = m_sqlManager.getBytes(res, m_sqlManager.readQuery("C_RESOURCES_FILE_CONTENT"));
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 content;
}
/**
* @see org.opencms.db.I_CmsHistoryDriver#readDeletedResources(CmsDbContext, CmsUUID, CmsUUID)
*/
public List readDeletedResources(CmsDbContext dbc, CmsUUID structureId, CmsUUID userId)
throws CmsDataAccessException {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet res = null;
List result = new ArrayList();
List tmpHistRes = new ArrayList();
try {
conn = m_sqlManager.getConnection(dbc);
if (userId == null) {
stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_HISTORY_READ_DELETED");
} else {
stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_HISTORY_READ_DELETED_RESTRICTED");
}
stmt.setString(1, structureId.toString());
if (userId != null) {
stmt.setString(2, userId.toString());
}
res = stmt.executeQuery();
while (res.next()) {
// store the result into a temporary list
tmpHistRes.add(internalCreateResource(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);
}
I_CmsVfsDriver vfsDriver = m_driverManager.getVfsDriver(dbc);
for (I_CmsHistoryResource histRes : tmpHistRes) {
if (vfsDriver.validateStructureIdExists(dbc, dbc.currentProject().getUuid(), histRes.getStructureId())) {
// only add resources that are really deleted
continue;
}
result.add(histRes);
}
if (!result.isEmpty()
|| (dbc.getRequestContext() == null)
|| (dbc.getRequestContext().getAttribute("ATTR_RESOURCE_NAME") == null)) {
return result;
}
try {
conn = m_sqlManager.getConnection(dbc);
if (userId == null) {
stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_HISTORY_READ_DELETED_NAME");
} else {
stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_HISTORY_READ_DELETED_NAME_RESTRICTED");
}
String path = dbc.getRequestContext().getAttribute("ATTR_RESOURCE_NAME").toString();
stmt.setString(1, path + '%');
stmt.setString(2, path);
if (userId != null) {
stmt.setString(3, userId.toString());
}
res = stmt.executeQuery();
// clear the temporary list
tmpHistRes.clear();
while (res.next()) {
// store the result into a temporary list
tmpHistRes.add(internalCreateResource(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);
}
for (I_CmsHistoryResource histRes : tmpHistRes) {
if (vfsDriver.validateStructureIdExists(dbc, dbc.currentProject().getUuid(), histRes.getStructureId())) {
// only add resources that are really deleted
continue;
}
result.add(histRes);
}
return result;
}
/**
* @see org.opencms.db.I_CmsHistoryDriver#readLastVersion(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID)
*/
public int readLastVersion(CmsDbContext dbc, CmsUUID structureId) throws CmsDataAccessException {
PreparedStatement stmt = null;
Connection conn = null;
ResultSet res = null;
int lastVersion = 0;
try {
conn = m_sqlManager.getConnection(dbc);
stmt = m_sqlManager.getPreparedStatement(conn, "C_STRUCTURE_HISTORY_MAXVER");
stmt.setString(1, structureId.toString());
res = stmt.executeQuery();
if (res.next()) {
lastVersion = res.getInt(1);
while (res.next()) {
// do nothing only move through all rows because of mssql odbc driver
}
} else {
lastVersion = 0;
}
} 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 lastVersion;
}
/**
* @see org.opencms.db.I_CmsHistoryDriver#readMaxPublishTag(CmsDbContext, CmsUUID)
*/
public int readMaxPublishTag(CmsDbContext dbc, CmsUUID resourceId) throws CmsDataAccessException {
PreparedStatement stmt = null;
Connection conn = null;
ResultSet res = null;
int result = 0;
try {
conn = m_sqlManager.getConnection(dbc);
stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_READ_MAX_PUBLISH_TAG");
stmt.setString(1, resourceId.toString());
res = stmt.executeQuery();
if (res.next()) {
result = 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);
}
return result;
}
/**
* @see org.opencms.db.I_CmsHistoryDriver#readNextPublishTag(org.opencms.db.CmsDbContext)
*/
public int readNextPublishTag(CmsDbContext dbc) {
PreparedStatement stmt = null;
Connection conn = null;
ResultSet res = null;
int projectPublishTag = 1;
int resourcePublishTag = 1;
try {
// get the max publish tag from project history
conn = m_sqlManager.getConnection(dbc);
stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_HISTORY_MAXTAG");
res = stmt.executeQuery();
if (res.next()) {
projectPublishTag = res.getInt(1) + 1;
while (res.next()) {
// do nothing only move through all rows because of mssql odbc driver
}
}
} catch (SQLException exc) {
LOG.error(Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), exc);
} finally {
m_sqlManager.closeAll(dbc, null, stmt, res);
}
try {
// get the max publish tag from resource history
stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_HISTORY_MAXTAG");
res = stmt.executeQuery();
if (res.next()) {
resourcePublishTag = res.getInt(1) + 1;
while (res.next()) {
// do nothing only move through all rows because of mssql odbc driver
}
}
} catch (SQLException exc) {
LOG.error(Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), exc);
} finally {
m_sqlManager.closeAll(dbc, null, stmt, res);
}
// keep the biggest
if (resourcePublishTag > projectPublishTag) {
projectPublishTag = resourcePublishTag;
}
try {
// get the max publish tag from contents
stmt = m_sqlManager.getPreparedStatement(conn, "C_CONTENT_PUBLISH_MAXTAG");
res = stmt.executeQuery();
if (res.next()) {
resourcePublishTag = res.getInt(1) + 1;
while (res.next()) {
// do nothing only move through all rows because of mssql odbc driver
}
}
} catch (SQLException exc) {
LOG.error(Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), exc);
} finally {
m_sqlManager.closeAll(dbc, conn, stmt, res);
}
// return the biggest
if (resourcePublishTag > projectPublishTag) {
projectPublishTag = resourcePublishTag;
}
return projectPublishTag;
}
/**
* @see org.opencms.db.I_CmsHistoryDriver#readPrincipal(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID)
*/
public CmsHistoryPrincipal readPrincipal(CmsDbContext dbc, CmsUUID principalId) throws CmsDataAccessException {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet res = null;
CmsHistoryPrincipal historyPrincipal = null;
try {
conn = m_sqlManager.getConnection(dbc);
stmt = m_sqlManager.getPreparedStatement(conn, "C_HISTORY_PRINCIPAL_READ");
stmt.setString(1, principalId.toString());
res = stmt.executeQuery();
if (res.next()) {
String userName = res.getString(m_sqlManager.readQuery("C_PRINCIPALS_HISTORY_NAME"));
String ou = CmsOrganizationalUnit.removeLeadingSeparator(
res.getString(m_sqlManager.readQuery("C_PRINCIPALS_HISTORY_OU")));
historyPrincipal = new CmsHistoryPrincipal(
principalId,
ou + userName,
res.getString(m_sqlManager.readQuery("C_PRINCIPALS_HISTORY_DESCRIPTION")),
res.getString(m_sqlManager.readQuery("C_PRINCIPALS_HISTORY_EMAIL")),
res.getString(m_sqlManager.readQuery("C_PRINCIPALS_HISTORY_TYPE")),
new CmsUUID(res.getString(m_sqlManager.readQuery("C_PRINCIPALS_HISTORY_USERDELETED"))),
res.getLong(m_sqlManager.readQuery("C_PRINCIPALS_HISTORY_DATEDELETED")));
while (res.next()) {
// do nothing only move through all rows because of mssql odbc driver
}
} else {
throw new CmsDbEntryNotFoundException(
Messages.get().container(Messages.ERR_HISTORY_PRINCIPAL_NOT_FOUND_1, principalId));
}
} 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 historyPrincipal;
}
/**
* @see org.opencms.db.I_CmsHistoryDriver#readProject(org.opencms.db.CmsDbContext, CmsUUID)
*/
public CmsHistoryProject readProject(CmsDbContext dbc, CmsUUID projectId) throws CmsDataAccessException {
PreparedStatement stmt = null;
CmsHistoryProject project = null;
ResultSet res = null;
Connection conn = null;
int tmpTag;
try {
conn = m_sqlManager.getConnection(dbc);
stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_HISTORY_READ_BYID");
stmt.setString(1, projectId.toString());
res = stmt.executeQuery();
if (res.next()) {
tmpTag = res.getInt(m_sqlManager.readQuery("C_PROJECTS_PUBLISH_TAG_0"));
project = internalCreateProject(res, null);
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_HISTORY_PROJECT_WITH_ID_1, projectId));
}
} 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);
}
List projectresources = readProjectResources(dbc, tmpTag);
project.setProjectResources(projectresources);
return project;
}
/**
* @see org.opencms.db.I_CmsHistoryDriver#readProject(org.opencms.db.CmsDbContext, int)
*/
public CmsHistoryProject readProject(CmsDbContext dbc, int publishTag) throws CmsDataAccessException {
PreparedStatement stmt = null;
CmsHistoryProject project = null;
ResultSet res = null;
Connection conn = null;
try {
conn = m_sqlManager.getConnection(dbc);
stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_HISTORY_READ");
stmt.setInt(1, publishTag);
res = stmt.executeQuery();
if (res.next()) {
project = internalCreateProject(res, null);
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_HISTORY_PROJECT_WITH_TAG_ID_1, new Integer(publishTag)));
}
} 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);
}
List projectresources = readProjectResources(dbc, publishTag);
project.setProjectResources(projectresources);
return project;
}
/**
* @see org.opencms.db.I_CmsHistoryDriver#readProjectResources(org.opencms.db.CmsDbContext, int)
*/
public List readProjectResources(CmsDbContext dbc, int publishTag) throws CmsDataAccessException {
PreparedStatement stmt = null;
Connection conn = null;
ResultSet res = null;
List projectResources = new ArrayList();
try {
conn = m_sqlManager.getConnection(dbc);
stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTRESOURCES_HISTORY_READ");
stmt.setInt(1, publishTag);
res = stmt.executeQuery();
while (res.next()) {
projectResources.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 projectResources;
}
/**
* @see org.opencms.db.I_CmsHistoryDriver#readProjects(org.opencms.db.CmsDbContext)
*/
public List readProjects(CmsDbContext dbc) throws CmsDataAccessException {
List projects = new ArrayList();
ResultSet res = null;
PreparedStatement stmt = null;
Connection conn = null;
Map tmpProjects = new HashMap();
try {
// create the statement
conn = m_sqlManager.getConnection(dbc);
stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_HISTORY_READ_ALL");
res = stmt.executeQuery();
// this is not really efficient
// but it is overriden in all db specific implementations, including mysql
int i = 0;
int max = 300;
while (res.next() && (i < max)) {
tmpProjects.put(Integer.valueOf(res.getInt("PUBLISH_TAG")), internalCreateProject(res, null));
i++;
}
} 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);
}
for (Map.Entry entry : tmpProjects.entrySet()) {
List resources = readProjectResources(dbc, entry.getKey().intValue());
entry.getValue().setProjectResources(resources);
projects.add(entry.getValue());
}
return projects;
}
/**
* @see org.opencms.db.I_CmsHistoryDriver#readProperties(org.opencms.db.CmsDbContext, org.opencms.file.history.I_CmsHistoryResource)
*/
public List readProperties(CmsDbContext dbc, I_CmsHistoryResource resource)
throws CmsDataAccessException {
ResultSet res = null;
PreparedStatement stmt = null;
Connection conn = null;
Map propertyMap = new HashMap();
try {
conn = m_sqlManager.getConnection(dbc);
// get the latest properties for this sibling
int pubTag = -1;
stmt = m_sqlManager.getPreparedStatement(conn, "C_PROPERTIES_HISTORY_READ_PUBTAG");
stmt.setString(1, resource.getStructureId().toString());
stmt.setInt(2, resource.getPublishTag());
res = stmt.executeQuery();
if (res.next()) {
pubTag = res.getInt(1);
while (res.next()) {
// do nothing only move through all rows because of mssql odbc driver
}
}
m_sqlManager.closeAll(dbc, null, stmt, res);
if (pubTag > 0) {
// add the siblings props
stmt = m_sqlManager.getPreparedStatement(conn, "C_PROPERTIES_HISTORY_READALL_STR");
stmt.setString(1, resource.getStructureId().toString());
stmt.setInt(2, pubTag);
res = stmt.executeQuery();
while (res.next()) {
String propertyKey = res.getString(1);
String propertyValue = res.getString(2);
int mappingType = res.getInt(3);
internalAddToPropMap(propertyMap, resource, propertyKey, propertyValue, mappingType);
}
m_sqlManager.closeAll(dbc, null, stmt, res);
}
if (pubTag != resource.getPublishTag()) {
// check if there were newer shared properties modifications
stmt = m_sqlManager.getPreparedStatement(conn, "C_PROPERTIES_HISTORY_READALL_RES");
stmt.setString(1, resource.getStructureId().toString());
stmt.setInt(2, resource.getPublishTag());
res = stmt.executeQuery();
while (res.next()) {
String propertyKey = res.getString(1);
String propertyValue = res.getString(2);
int mappingType = res.getInt(3);
internalAddToPropMap(propertyMap, resource, propertyKey, propertyValue, mappingType);
}
m_sqlManager.closeAll(dbc, null, stmt, 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 new ArrayList(propertyMap.values());
}
/**
* @see org.opencms.db.I_CmsHistoryDriver#readPropertyDefinition(org.opencms.db.CmsDbContext, java.lang.String)
*/
public CmsPropertyDefinition readPropertyDefinition(CmsDbContext dbc, String name) throws CmsDataAccessException {
CmsPropertyDefinition propDef = null;
ResultSet res = null;
PreparedStatement stmt = null;
Connection conn = null;
try {
conn = m_sqlManager.getConnection(dbc);
stmt = m_sqlManager.getPreparedStatement(conn, "C_PROPERTYDEF_READ_HISTORY");
stmt.setString(1, name);
res = stmt.executeQuery();
if (res.next()) {
propDef = new CmsPropertyDefinition(
new CmsUUID(res.getString(m_sqlManager.readQuery("C_PROPERTYDEF_ID"))),
res.getString(m_sqlManager.readQuery("C_PROPERTYDEF_NAME")),
CmsPropertyDefinition.CmsPropertyType.valueOf(
res.getInt(m_sqlManager.readQuery("C_PROPERTYDEF_TYPE"))));
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_PROPERTYDEF_WITH_NAME_1, name));
}
} 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 propDef;
}
/**
* @see org.opencms.db.I_CmsHistoryDriver#readPublishTag(org.opencms.db.CmsDbContext, long)
*/
public int readPublishTag(CmsDbContext dbc, long maxdate) throws CmsDataAccessException {
ResultSet res = null;
PreparedStatement stmt = null;
Connection conn = null;
int maxVersion = 0;
try {
conn = m_sqlManager.getConnection(dbc);
stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_HISTORY_READ_TAG_FOR_DATE");
stmt.setLong(1, maxdate);
res = stmt.executeQuery();
if (res.next()) {
maxVersion = 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);
}
return maxVersion;
}
/**
* @see org.opencms.db.I_CmsHistoryDriver#readResource(CmsDbContext, CmsUUID, int)
*/
public I_CmsHistoryResource readResource(CmsDbContext dbc, CmsUUID structureId, int version)
throws CmsDataAccessException {
I_CmsHistoryResource resource = null;
PreparedStatement stmt = null;
ResultSet res = null;
Connection conn = null;
try {
conn = m_sqlManager.getConnection(dbc);
stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_HISTORY_READ_VERSION");
stmt.setString(1, structureId.toString());
stmt.setInt(2, version);
res = stmt.executeQuery();
if (res.next()) {
resource = internalCreateResource(res);
while (res.next()) {
// do nothing only move through all rows because of mssql odbc driver
}
} else {
throw new CmsVfsResourceNotFoundException(
Messages.get().container(Messages.ERR_HISTORY_FILE_NOT_FOUND_1, structureId));
}
} 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 resource;
}
/**
* @see org.opencms.db.I_CmsHistoryDriver#setDriverManager(org.opencms.db.CmsDriverManager)
*/
public void setDriverManager(CmsDriverManager driverManager) {
m_driverManager = driverManager;
}
/**
* @see org.opencms.db.I_CmsHistoryDriver#setSqlManager(org.opencms.db.CmsSqlManager)
*/
public void setSqlManager(org.opencms.db.CmsSqlManager sqlManager) {
m_sqlManager = (CmsSqlManager)sqlManager;
}
/**
* @see org.opencms.db.I_CmsHistoryDriver#writePrincipal(CmsDbContext, org.opencms.security.I_CmsPrincipal)
*/
public void writePrincipal(CmsDbContext dbc, I_CmsPrincipal principal) throws CmsDataAccessException {
Connection conn = null;
PreparedStatement stmt = null;
try {
// check if the principal was already saved
readPrincipal(dbc, principal.getId());
return;
} catch (CmsDbEntryNotFoundException e) {
// ok
}
try {
conn = m_sqlManager.getConnection(dbc);
stmt = m_sqlManager.getPreparedStatement(conn, "C_HISTORY_PRINCIPAL_CREATE");
stmt.setString(1, principal.getId().toString());
stmt.setString(2, principal.getSimpleName());
String desc = principal.getDescription();
desc = CmsStringUtil.isEmptyOrWhitespaceOnly(desc) ? "-" : desc;
stmt.setString(3, desc);
stmt.setString(4, CmsOrganizationalUnit.SEPARATOR + principal.getOuFqn());
if (principal instanceof CmsUser) {
String email = ((CmsUser)principal).getEmail();
email = CmsStringUtil.isEmptyOrWhitespaceOnly(email) ? "-" : email;
stmt.setString(5, email);
stmt.setString(6, I_CmsPrincipal.PRINCIPAL_USER);
} else {
stmt.setString(5, "-");
stmt.setString(6, I_CmsPrincipal.PRINCIPAL_GROUP);
}
stmt.setString(7, dbc.currentUser().getId().toString());
stmt.setLong(8, System.currentTimeMillis());
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_CmsHistoryDriver#writeProject(org.opencms.db.CmsDbContext, int, long)
*/
public void writeProject(CmsDbContext dbc, int publishTag, long publishDate) throws CmsDataAccessException {
CmsProject currentProject = dbc.currentProject();
CmsUser currentUser = dbc.currentUser();
List projectresources = m_driverManager.getProjectDriver(dbc).readProjectResources(dbc, currentProject);
// write historical project to the database
Connection conn = null;
PreparedStatement stmt = null;
try {
conn = m_sqlManager.getConnection(dbc);
stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_HISTORY_CREATE");
// first write the project
stmt.setInt(1, publishTag);
stmt.setString(2, currentProject.getUuid().toString());
stmt.setString(3, currentProject.getSimpleName());
stmt.setLong(4, publishDate);
stmt.setString(5, currentUser.getId().toString());
stmt.setString(6, currentProject.getOwnerId().toString());
stmt.setString(7, currentProject.getGroupId().toString());
stmt.setString(8, currentProject.getManagerGroupId().toString());
stmt.setString(9, currentProject.getDescription());
stmt.setLong(10, currentProject.getDateCreated());
stmt.setInt(11, currentProject.getType().getMode());
stmt.setString(12, CmsOrganizationalUnit.SEPARATOR + currentProject.getOuFqn());
stmt.executeUpdate();
m_sqlManager.closeAll(dbc, null, stmt, null);
// now write the projectresources
stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTRESOURCES_HISTORY_CREATE");
Iterator i = projectresources.iterator();
while (i.hasNext()) {
stmt.setInt(1, publishTag);
stmt.setString(2, currentProject.getUuid().toString());
stmt.setString(3, i.next());
stmt.executeUpdate();
stmt.clearParameters();
}
} 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_CmsHistoryDriver#writeProperties(org.opencms.db.CmsDbContext, org.opencms.file.CmsResource, java.util.List, int)
*/
public void writeProperties(CmsDbContext dbc, CmsResource resource, List properties, int publishTag)
throws CmsDataAccessException {
Connection conn = null;
PreparedStatement stmt = null;
Map propDefs = new HashMap();
try {
for (CmsProperty property : properties) {
CmsPropertyDefinition propDef = null;
try {
propDef = readPropertyDefinition(dbc, property.getName());
} catch (CmsDbEntryNotFoundException e) {
// create if missing
propDef = createPropertyDefinition(dbc, property.getName(), CmsPropertyDefinition.TYPE_NORMAL);
}
propDefs.put(property, propDef);
}
} catch (CmsDataAccessException e) {
throw new CmsDbSqlException(
Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
e);
} finally {
m_sqlManager.closeAll(dbc, conn, stmt, null);
}
try {
conn = m_sqlManager.getConnection(dbc);
for (Map.Entry entry : propDefs.entrySet()) {
for (int i = 0; i < 2; i++) {
int mappingType;
String value;
CmsUUID id;
if (i == 0) {
// write the structure value on the first cycle
value = entry.getKey().getStructureValue();
mappingType = CmsProperty.STRUCTURE_RECORD_MAPPING;
id = resource.getStructureId();
if (CmsStringUtil.isEmpty(value)) {
continue;
}
} else {
// write the resource value on the second cycle
value = entry.getKey().getResourceValue();
mappingType = CmsProperty.RESOURCE_RECORD_MAPPING;
id = resource.getResourceId();
if (CmsStringUtil.isEmpty(value)) {
break;
}
}
stmt = m_sqlManager.getPreparedStatement(conn, "C_PROPERTIES_HISTORY_CREATE");
stmt.setString(1, resource.getStructureId().toString());
stmt.setString(2, entry.getValue().getId().toString());
stmt.setString(3, id.toString());
stmt.setInt(4, mappingType);
stmt.setString(5, m_sqlManager.validateEmpty(value));
stmt.setInt(6, publishTag);
stmt.executeUpdate();
m_sqlManager.closeAll(dbc, null, stmt, null);
}
}
} 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_CmsHistoryDriver#writeResource(org.opencms.db.CmsDbContext, org.opencms.file.CmsResource, java.util.List, int)
*/
public void writeResource(CmsDbContext dbc, CmsResource resource, List properties, int publishTag)
throws CmsDataAccessException {
Connection conn = null;
PreparedStatement stmt = null;
try {
boolean valResource = internalValidateResource(dbc, resource, publishTag);
int sibCount = resource.getSiblingCount();
// if deleted
if (resource.getState().isDeleted()) {
// if it is a file
if (resource instanceof CmsFile) {
if (!valResource) {
if (sibCount < 2) {
// copy from offline content to content tables
// so that the history contains the last state of the file
m_driverManager.getVfsDriver(dbc).createOnlineContent(
dbc,
resource.getResourceId(),
((CmsFile)resource).getContents(),
publishTag,
false,
true);
} else {
@SuppressWarnings("unchecked")
Set changedAndDeleted = (Set)dbc.getAttribute(
CmsDriverManager.KEY_CHANGED_AND_DELETED);
if ((changedAndDeleted == null) || !changedAndDeleted.contains(resource.getResourceId())) {
// put the content definitively in the history if no sibling is left
// (unless another sibling with status "changed" or "new" is published)
m_driverManager.getVfsDriver(dbc).createOnlineContent(
dbc,
resource.getResourceId(),
((CmsFile)resource).getContents(),
publishTag,
true,
false);
}
}
}
}
// update version numbers
m_driverManager.getVfsDriver(dbc).publishVersions(dbc, resource, !valResource);
}
// read the version numbers
Map versions = m_driverManager.getVfsDriver(dbc).readVersions(
dbc,
CmsProject.ONLINE_PROJECT_ID,
resource.getResourceId(),
resource.getStructureId());
int structureVersion = (versions.get("structure")).intValue();
int resourceVersion = (versions.get("resource")).intValue();
CmsUUID parentId = CmsUUID.getNullUUID();
CmsFolder parent = m_driverManager.getVfsDriver(dbc).readParentFolder(
dbc,
CmsProject.ONLINE_PROJECT_ID,
resource.getStructureId());
if (parent != null) {
parentId = parent.getStructureId();
}
conn = m_sqlManager.getConnection(dbc);
if (!valResource) {
// write the resource
stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_HISTORY_WRITE");
stmt.setString(1, resource.getResourceId().toString());
stmt.setInt(2, resource.getTypeId());
stmt.setInt(3, resource.getFlags());
stmt.setLong(4, resource.getDateCreated());
stmt.setString(5, resource.getUserCreated().toString());
stmt.setLong(6, resource.getDateLastModified());
stmt.setString(7, resource.getUserLastModified().toString());
stmt.setInt(8, resource.getState().getState());
stmt.setInt(9, resource.getLength());
stmt.setLong(10, resource.getDateContent());
stmt.setString(11, dbc.currentProject().getUuid().toString());
stmt.setInt(12, resource.getSiblingCount());
stmt.setInt(13, resourceVersion);
stmt.setInt(14, publishTag);
stmt.executeUpdate();
m_sqlManager.closeAll(dbc, null, stmt, null);
}
// write the structure
stmt = m_sqlManager.getPreparedStatement(conn, "C_STRUCTURE_HISTORY_WRITE");
stmt.setString(1, resource.getStructureId().toString());
stmt.setString(2, resource.getResourceId().toString());
stmt.setString(3, resource.getRootPath());
stmt.setInt(4, resource.getState().getState());
stmt.setLong(5, resource.getDateReleased());
stmt.setLong(6, resource.getDateExpired());
stmt.setInt(7, structureVersion);
stmt.setString(8, parentId.toString());
stmt.setInt(9, publishTag);
stmt.setInt(10, resource.getVersion());
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);
}
writeProperties(dbc, resource, properties, publishTag);
}
/**
* Updates the property map for the given resource with the given property data.
*
* @param propertyMap the map to update
* @param resource the resource the properties belong to
* @param propertyKey the property key
* @param propertyValue the property value
* @param mappingType the mapping type
*
* @throws CmsDbConsistencyException if the mapping type is wrong
*/
protected void internalAddToPropMap(
Map propertyMap,
I_CmsHistoryResource resource,
String propertyKey,
String propertyValue,
int mappingType) throws CmsDbConsistencyException {
CmsProperty property = propertyMap.get(propertyKey);
if (property != null) {
// there exists already a property for this key in the result
switch (mappingType) {
case CmsProperty.STRUCTURE_RECORD_MAPPING:
// this property value is mapped to a structure record
property.setStructureValue(propertyValue);
break;
case CmsProperty.RESOURCE_RECORD_MAPPING:
// this property value is mapped to a resource record
property.setResourceValue(propertyValue);
break;
default:
throw new CmsDbConsistencyException(
Messages.get().container(
Messages.ERR_UNKNOWN_PROPERTY_VALUE_MAPPING_3,
resource.getRootPath(),
new Integer(mappingType),
propertyKey));
}
} else {
// there doesn't exist a property for this key yet
property = new CmsProperty();
property.setName(propertyKey);
switch (mappingType) {
case CmsProperty.STRUCTURE_RECORD_MAPPING:
// this property value is mapped to a structure record
property.setStructureValue(propertyValue);
property.setResourceValue(null);
break;
case CmsProperty.RESOURCE_RECORD_MAPPING:
// this property value is mapped to a resource record
property.setStructureValue(null);
property.setResourceValue(propertyValue);
break;
default:
throw new CmsDbConsistencyException(
Messages.get().container(
Messages.ERR_UNKNOWN_PROPERTY_VALUE_MAPPING_3,
resource.getRootPath(),
new Integer(mappingType),
propertyKey));
}
propertyMap.put(propertyKey, property);
}
}
/**
* Deletes all historical entries of subresources of a folder without any historical netry left.
*
* @param dbc the current database context
* @param resource the resource to check
*
* @throws CmsDataAccessException if something goes wrong
*/
protected void internalCleanup(CmsDbContext dbc, I_CmsHistoryResource resource) throws CmsDataAccessException {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet res = null;
Map tmpSubResources = new HashMap();
// if is folder and if no versions left
boolean isFolderAndNoVersionLeft = resource.getRootPath().endsWith("/")
&& (readLastVersion(dbc, resource.getStructureId()) == 0);
// if the resource is a folder
if (isFolderAndNoVersionLeft) {
try {
conn = m_sqlManager.getConnection(dbc);
// get all direct subresources
stmt = m_sqlManager.getPreparedStatement(conn, "C_STRUCTURE_HISTORY_READ_SUBRESOURCES");
stmt.setString(1, resource.getStructureId().toString());
res = stmt.executeQuery();
while (res.next()) {
CmsUUID structureId = new CmsUUID(res.getString(1));
int version = res.getInt(2);
tmpSubResources.put(structureId, Integer.valueOf(version));
}
} 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);
}
}
// delete all subresource versions
for (Map.Entry entry : tmpSubResources.entrySet()) {
I_CmsHistoryResource histResource = readResource(dbc, entry.getKey(), entry.getValue().intValue());
deleteEntries(dbc, histResource, 0, -1);
}
}
/**
* Returns the amount of properties for a propertydefinition.
*
* @param dbc the current database context
* @param metadef the propertydefinition to test
* @param projectId the ID of the current project
*
* @return the amount of properties for a propertydefinition
* @throws CmsDataAccessException if something goes wrong
*/
protected int internalCountProperties(CmsDbContext dbc, CmsPropertyDefinition metadef, CmsUUID projectId)
throws CmsDataAccessException {
ResultSet res = null;
PreparedStatement stmt = null;
Connection conn = null;
int returnValue;
try {
// create statement
conn = m_sqlManager.getConnection(dbc);
stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_PROPERTIES_READALL_COUNT");
stmt.setString(1, metadef.getId().toString());
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
}
} else {
throw new CmsDbConsistencyException(
Messages.get().container(Messages.ERR_NO_PROPERTIES_FOR_PROPERTYDEF_1, metadef.getName()));
}
} 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;
}
/**
* Creates a historical project from the given result set and resources.
* @param res the resource set
* @param resources the historical resources
*
* @return the historical project
*
* @throws SQLException if something goes wrong
*/
protected CmsHistoryProject internalCreateProject(ResultSet res, List resources) throws SQLException {
String ou = CmsOrganizationalUnit.removeLeadingSeparator(
res.getString(m_sqlManager.readQuery("C_PROJECTS_PROJECT_OU_0")));
CmsUUID publishedById = new CmsUUID(res.getString(m_sqlManager.readQuery("C_PROJECT_PUBLISHED_BY_0")));
CmsUUID userId = new CmsUUID(res.getString(m_sqlManager.readQuery("C_PROJECTS_USER_ID_0")));
return new CmsHistoryProject(
res.getInt(m_sqlManager.readQuery("C_PROJECTS_PUBLISH_TAG_0")),
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")),
userId,
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.getLong(m_sqlManager.readQuery("C_PROJECTS_DATE_CREATED_0")),
CmsProject.CmsProjectType.valueOf(res.getInt(m_sqlManager.readQuery("C_PROJECTS_PROJECT_TYPE_0"))),
res.getLong(m_sqlManager.readQuery("C_PROJECT_PUBLISHDATE_0")),
publishedById,
resources);
}
/**
* Creates a valid {@link I_CmsHistoryResource} instance from a JDBC ResultSet.
*
* @param res the JDBC result set
*
* @return the new historical resource instance
*
* @throws SQLException if a requested attribute was not found in the result set
*/
protected I_CmsHistoryResource internalCreateResource(ResultSet res) throws SQLException {
int resourceVersion = res.getInt(m_sqlManager.readQuery("C_RESOURCES_VERSION"));
int structureVersion = res.getInt(m_sqlManager.readQuery("C_RESOURCES_STRUCTURE_VERSION"));
int tagId = res.getInt(m_sqlManager.readQuery("C_RESOURCES_PUBLISH_TAG"));
CmsUUID structureId = new CmsUUID(res.getString(m_sqlManager.readQuery("C_RESOURCES_STRUCTURE_ID")));
CmsUUID resourceId = new CmsUUID(res.getString(m_sqlManager.readQuery("C_RESOURCES_RESOURCE_ID")));
String resourcePath = res.getString(m_sqlManager.readQuery("C_RESOURCES_RESOURCE_PATH"));
int resourceType = res.getInt(m_sqlManager.readQuery("C_RESOURCES_RESOURCE_TYPE"));
int resourceFlags = res.getInt(m_sqlManager.readQuery("C_RESOURCES_RESOURCE_FLAGS"));
CmsUUID projectLastModified = new CmsUUID(
res.getString(m_sqlManager.readQuery("C_RESOURCES_PROJECT_LASTMODIFIED")));
int state = Math.max(
res.getInt(m_sqlManager.readQuery("C_RESOURCES_STATE")),
res.getInt(m_sqlManager.readQuery("C_RESOURCES_STRUCTURE_STATE")));
long dateCreated = res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_CREATED"));
long dateLastModified = res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_LASTMODIFIED"));
long dateReleased = res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_RELEASED"));
long dateExpired = res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_EXPIRED"));
int resourceSize = res.getInt(m_sqlManager.readQuery("C_RESOURCES_SIZE"));
CmsUUID userLastModified = new CmsUUID(res.getString(m_sqlManager.readQuery("C_RESOURCES_USER_LASTMODIFIED")));
CmsUUID userCreated = new CmsUUID(res.getString(m_sqlManager.readQuery("C_RESOURCES_USER_CREATED")));
CmsUUID parentId = new CmsUUID(res.getString(m_sqlManager.readQuery("C_RESOURCES_HISTORY_PARENTID")));
long dateContent = res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_CONTENT"));
boolean isFolder = resourcePath.endsWith("/");
if (isFolder) {
return new CmsHistoryFolder(
tagId,
structureId,
resourceId,
resourcePath,
resourceType,
resourceFlags,
projectLastModified,
CmsResourceState.valueOf(state),
dateCreated,
userCreated,
dateLastModified,
userLastModified,
dateReleased,
dateExpired,
resourceVersion + structureVersion,
parentId,
resourceVersion,
structureVersion);
} else {
return new CmsHistoryFile(
tagId,
structureId,
resourceId,
resourcePath,
resourceType,
resourceFlags,
projectLastModified,
CmsResourceState.valueOf(state),
dateCreated,
userCreated,
dateLastModified,
userLastModified,
dateReleased,
dateExpired,
resourceSize,
dateContent,
resourceVersion + structureVersion,
parentId,
null,
resourceVersion,
structureVersion);
}
}
/**
* Merges an historical entry for a sibling, based on the structure data from the given historical resource
* and result set for the resource entry.
*
* @param histRes the original historical entry
* @param res the result set of the resource entry
* @param versionOffset the offset for the structure version
*
* @return a merged historical entry for the sibling
*
* @throws SQLException if something goes wrong
*/
protected I_CmsHistoryResource internalMergeResource(I_CmsHistoryResource histRes, ResultSet res, int versionOffset)
throws SQLException {
int resourceVersion = res.getInt(m_sqlManager.readQuery("C_RESOURCES_VERSION"));
int structureVersion = histRes.getStructureVersion() - versionOffset;
int tagId = res.getInt(m_sqlManager.readQuery("C_RESOURCES_PUBLISH_TAG"));
CmsUUID structureId = histRes.getStructureId();
CmsUUID resourceId = new CmsUUID(res.getString(m_sqlManager.readQuery("C_RESOURCES_RESOURCE_ID")));
int resourceType = res.getInt(m_sqlManager.readQuery("C_RESOURCES_RESOURCE_TYPE"));
int resourceFlags = res.getInt(m_sqlManager.readQuery("C_RESOURCES_RESOURCE_FLAGS"));
CmsUUID projectLastModified = new CmsUUID(
res.getString(m_sqlManager.readQuery("C_RESOURCES_PROJECT_LASTMODIFIED")));
int state = histRes.getState().getState(); // may be we have to compute something here?
long dateCreated = res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_CREATED"));
long dateLastModified = res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_LASTMODIFIED"));
long dateReleased = histRes.getDateReleased();
long dateExpired = histRes.getDateExpired();
int resourceSize = res.getInt(m_sqlManager.readQuery("C_RESOURCES_SIZE"));
CmsUUID userLastModified = new CmsUUID(res.getString(m_sqlManager.readQuery("C_RESOURCES_USER_LASTMODIFIED")));
CmsUUID userCreated = new CmsUUID(res.getString(m_sqlManager.readQuery("C_RESOURCES_USER_CREATED")));
// here we could use the path/parent id for the sibling where the modification really occurred
String resourcePath = histRes.getRootPath();
CmsUUID parentId = histRes.getParentId();
long dateContent = res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_CONTENT"));
if (histRes.isFolder()) {
return new CmsHistoryFolder(
tagId,
structureId,
resourceId,
resourcePath,
resourceType,
resourceFlags,
projectLastModified,
CmsResourceState.valueOf(state),
dateCreated,
userCreated,
dateLastModified,
userLastModified,
dateReleased,
dateExpired,
resourceVersion + structureVersion,
parentId,
resourceVersion,
structureVersion);
} else {
return new CmsHistoryFile(
tagId,
structureId,
resourceId,
resourcePath,
resourceType,
resourceFlags,
projectLastModified,
CmsResourceState.valueOf(state),
dateCreated,
userCreated,
dateLastModified,
userLastModified,
dateReleased,
dateExpired,
resourceSize,
dateContent,
resourceVersion + structureVersion,
parentId,
null,
resourceVersion,
structureVersion);
}
}
/**
* Tests if a history resource does exist.
*
* @param dbc the current database context
* @param resource the resource to test
* @param publishTag the publish tag of the resource to test
*
* @return true
if the resource already exists, false
otherwise
*
* @throws CmsDataAccessException if something goes wrong
*/
protected boolean internalValidateResource(CmsDbContext dbc, CmsResource resource, int publishTag)
throws CmsDataAccessException {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet res = null;
boolean exists = false;
try {
conn = m_sqlManager.getConnection(dbc);
stmt = m_sqlManager.getPreparedStatement(conn, "C_HISTORY_EXISTS_RESOURCE");
stmt.setString(1, resource.getResourceId().toString());
stmt.setInt(2, publishTag);
res = stmt.executeQuery();
exists = res.next();
} 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 exists;
}
}