0001: /*
0002: * File : $Source: /usr/local/cvs/opencms/src/org/opencms/db/generic/CmsHistoryDriver.java,v $
0003: * Date : $Date: 2008-02-27 12:05:52 $
0004: * Version: $Revision: 1.9 $
0005: *
0006: * This library is part of OpenCms -
0007: * the Open Source Content Management System
0008: *
0009: * Copyright (c) 2002 - 2008 Alkacon Software GmbH (http://www.alkacon.com)
0010: *
0011: * This library is free software; you can redistribute it and/or
0012: * modify it under the terms of the GNU Lesser General Public
0013: * License as published by the Free Software Foundation; either
0014: * version 2.1 of the License, or (at your option) any later version.
0015: *
0016: * This library is distributed in the hope that it will be useful,
0017: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0018: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0019: * Lesser General Public License for more details.
0020: *
0021: * For further information about Alkacon Software GmbH, please see the
0022: * company website: http://www.alkacon.com
0023: *
0024: * For further information about OpenCms, please see the
0025: * project website: http://www.opencms.org
0026: *
0027: * You should have received a copy of the GNU Lesser General Public
0028: * License along with this library; if not, write to the Free Software
0029: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0030: */
0031:
0032: package org.opencms.db.generic;
0033:
0034: import org.opencms.configuration.CmsConfigurationManager;
0035: import org.opencms.db.CmsDbConsistencyException;
0036: import org.opencms.db.CmsDbContext;
0037: import org.opencms.db.CmsDbEntryNotFoundException;
0038: import org.opencms.db.CmsDbSqlException;
0039: import org.opencms.db.CmsDriverManager;
0040: import org.opencms.db.CmsResourceState;
0041: import org.opencms.db.I_CmsDriver;
0042: import org.opencms.db.I_CmsHistoryDriver;
0043: import org.opencms.file.CmsDataAccessException;
0044: import org.opencms.file.CmsFile;
0045: import org.opencms.file.CmsFolder;
0046: import org.opencms.file.CmsProject;
0047: import org.opencms.file.CmsProperty;
0048: import org.opencms.file.CmsPropertyDefinition;
0049: import org.opencms.file.CmsResource;
0050: import org.opencms.file.CmsUser;
0051: import org.opencms.file.CmsVfsResourceNotFoundException;
0052: import org.opencms.file.history.CmsHistoryFile;
0053: import org.opencms.file.history.CmsHistoryFolder;
0054: import org.opencms.file.history.CmsHistoryPrincipal;
0055: import org.opencms.file.history.CmsHistoryProject;
0056: import org.opencms.file.history.I_CmsHistoryResource;
0057: import org.opencms.main.CmsLog;
0058: import org.opencms.security.CmsOrganizationalUnit;
0059: import org.opencms.security.I_CmsPrincipal;
0060: import org.opencms.util.CmsStringUtil;
0061: import org.opencms.util.CmsUUID;
0062:
0063: import java.sql.Connection;
0064: import java.sql.PreparedStatement;
0065: import java.sql.ResultSet;
0066: import java.sql.SQLException;
0067: import java.util.ArrayList;
0068: import java.util.HashMap;
0069: import java.util.HashSet;
0070: import java.util.Iterator;
0071: import java.util.List;
0072: import java.util.Map;
0073: import java.util.Set;
0074:
0075: import org.apache.commons.logging.Log;
0076:
0077: /**
0078: * Generic (ANSI-SQL) database server implementation of the history driver methods.<p>
0079: *
0080: * @author Thomas Weckert
0081: * @author Michael Emmerich
0082: * @author Carsten Weinholz
0083: * @author Michael Moossen
0084: *
0085: * @version $Revision: 1.9 $
0086: *
0087: * @since 6.9.1
0088: */
0089: public class CmsHistoryDriver implements I_CmsDriver,
0090: I_CmsHistoryDriver {
0091:
0092: /** The log object for this class. */
0093: private static final Log LOG = CmsLog
0094: .getLog(org.opencms.db.generic.CmsHistoryDriver.class);
0095:
0096: /** The driver manager instance. */
0097: protected CmsDriverManager m_driverManager;
0098:
0099: /** The SQL manager instance. */
0100: protected org.opencms.db.generic.CmsSqlManager m_sqlManager;
0101:
0102: /**
0103: * @see org.opencms.db.I_CmsHistoryDriver#createPropertyDefinition(org.opencms.db.CmsDbContext, java.lang.String, org.opencms.file.CmsPropertyDefinition.CmsPropertyType)
0104: */
0105: public CmsPropertyDefinition createPropertyDefinition(
0106: CmsDbContext dbc, String name,
0107: CmsPropertyDefinition.CmsPropertyType type)
0108: throws CmsDataAccessException {
0109:
0110: Connection conn = null;
0111: PreparedStatement stmt = null;
0112:
0113: try {
0114: conn = m_sqlManager.getConnection(dbc);
0115: stmt = m_sqlManager.getPreparedStatement(conn,
0116: "C_PROPERTYDEF_CREATE_HISTORY");
0117: stmt.setString(1, new CmsUUID().toString());
0118: stmt.setString(2, name);
0119: stmt.setInt(3, type.getMode());
0120: stmt.executeUpdate();
0121: } catch (SQLException e) {
0122: throw new CmsDbSqlException(Messages.get().container(
0123: Messages.ERR_GENERIC_SQL_1,
0124: CmsDbSqlException.getErrorQuery(stmt)), e);
0125:
0126: } finally {
0127: m_sqlManager.closeAll(dbc, conn, stmt, null);
0128: }
0129:
0130: return readPropertyDefinition(dbc, name);
0131: }
0132:
0133: /**
0134: * @see org.opencms.db.I_CmsHistoryDriver#deleteEntries(CmsDbContext, I_CmsHistoryResource, int, long)
0135: */
0136: public int deleteEntries(CmsDbContext dbc,
0137: I_CmsHistoryResource resource, int versionsToKeep, long time)
0138: throws CmsDataAccessException {
0139:
0140: Connection conn = null;
0141: PreparedStatement stmt = null;
0142: ResultSet res = null;
0143:
0144: try {
0145: conn = m_sqlManager.getConnection(dbc);
0146:
0147: int maxVersion = -1;
0148: // get the maximal version number for this resource
0149: stmt = m_sqlManager.getPreparedStatement(conn,
0150: "C_STRUCTURE_HISTORY_MAXVER");
0151: stmt.setString(1, resource.getStructureId().toString());
0152: res = stmt.executeQuery();
0153: if (res.next()) {
0154: maxVersion = res.getInt(1);
0155: while (res.next()) {
0156: // do nothing only move through all rows because of mssql odbc driver
0157: }
0158: } else {
0159: // nothing to delete
0160: internalCleanup(dbc, resource);
0161: return 0;
0162: }
0163: m_sqlManager.closeAll(dbc, null, stmt, res);
0164:
0165: if (time >= 0) {
0166: int maxVersionByTime = -1;
0167: // get the maximal version to keep for this resource based on the time parameter
0168: stmt = m_sqlManager.getPreparedStatement(conn,
0169: "C_STRUCTURE_HISTORY_MAXVER_BYTIME");
0170: stmt.setString(1, resource.getStructureId().toString());
0171: stmt.setLong(2, time);
0172: res = stmt.executeQuery();
0173: if (res.next()) {
0174: maxVersionByTime = res.getInt(1);
0175: while (res.next()) {
0176: // do nothing only move through all rows because of mssql odbc driver
0177: }
0178: }
0179: m_sqlManager.closeAll(dbc, null, stmt, res);
0180: if (maxVersionByTime > 0) {
0181: if (versionsToKeep < 0) {
0182: versionsToKeep = (maxVersion - maxVersionByTime);
0183: } else {
0184: versionsToKeep = Math.min(versionsToKeep,
0185: (maxVersion - maxVersionByTime));
0186: }
0187: }
0188: }
0189:
0190: if (maxVersion - versionsToKeep <= 0) {
0191: // nothing to delete
0192: internalCleanup(dbc, resource);
0193: return 0;
0194: }
0195:
0196: // get the minimal structure publish tag to keep for this sibling
0197: int minStrPublishTagToKeep = -1;
0198: stmt = m_sqlManager.getPreparedStatement(conn,
0199: "C_HISTORY_READ_MAXTAG_FOR_VERSION");
0200: stmt.setString(1, resource.getStructureId().toString());
0201: stmt.setInt(2, 1 + maxVersion - versionsToKeep);
0202: res = stmt.executeQuery();
0203: if (res.next()) {
0204: minStrPublishTagToKeep = res.getInt(1);
0205: while (res.next()) {
0206: // do nothing only move through all rows because of mssql odbc driver
0207: }
0208: } else {
0209: // nothing to delete
0210: internalCleanup(dbc, resource);
0211: return 0;
0212: }
0213: m_sqlManager.closeAll(dbc, null, stmt, res);
0214: if (minStrPublishTagToKeep < 1) {
0215: // nothing to delete
0216: internalCleanup(dbc, resource);
0217: return 0;
0218: }
0219: minStrPublishTagToKeep++;
0220:
0221: // delete the properties
0222: stmt = m_sqlManager.getPreparedStatement(conn,
0223: "C_PROPERTIES_HISTORY_DELETE");
0224: stmt.setString(1, resource.getStructureId().toString());
0225: stmt.setInt(2, minStrPublishTagToKeep);
0226: stmt.executeUpdate();
0227: m_sqlManager.closeAll(dbc, null, stmt, null);
0228:
0229: // delete the structure entries
0230: stmt = m_sqlManager.getPreparedStatement(conn,
0231: "C_STRUCTURE_HISTORY_DELETE");
0232: stmt.setString(1, resource.getStructureId().toString());
0233: stmt.setInt(2, minStrPublishTagToKeep);
0234: int structureVersions = stmt.executeUpdate();
0235: m_sqlManager.closeAll(dbc, null, stmt, null);
0236:
0237: // get the minimal resource publish tag to keep,
0238: // all entries with publish tag less than this will be deleted
0239: int minResPublishTagToKeep = -1;
0240: stmt = m_sqlManager.getPreparedStatement(conn,
0241: "C_HISTORY_READ_MIN_USED_TAG");
0242: stmt.setString(1, resource.getResourceId().toString());
0243: res = stmt.executeQuery();
0244: if (res.next()) {
0245: minResPublishTagToKeep = res.getInt(1);
0246: while (res.next()) {
0247: // do nothing only move through all rows because of mssql odbc driver
0248: }
0249: } else {
0250: // nothing to delete
0251: internalCleanup(dbc, resource);
0252: return structureVersions;
0253: }
0254: m_sqlManager.closeAll(dbc, null, stmt, res);
0255:
0256: // delete the resource entries
0257: stmt = m_sqlManager.getPreparedStatement(conn,
0258: "C_RESOURCES_HISTORY_DELETE");
0259: stmt.setString(1, resource.getResourceId().toString());
0260: stmt.setInt(2, minResPublishTagToKeep);
0261: int resourceVersions = stmt.executeUpdate();
0262: m_sqlManager.closeAll(dbc, null, stmt, null);
0263:
0264: // delete the content entries
0265: stmt = m_sqlManager.getPreparedStatement(conn,
0266: "C_CONTENT_HISTORY_DELETE");
0267: stmt.setString(1, resource.getResourceId().toString());
0268: stmt.setInt(2, minResPublishTagToKeep);
0269: stmt.executeUpdate();
0270:
0271: internalCleanup(dbc, resource);
0272: return Math.max(structureVersions, resourceVersions);
0273: } catch (SQLException e) {
0274: throw new CmsDbSqlException(Messages.get().container(
0275: Messages.ERR_GENERIC_SQL_1,
0276: CmsDbSqlException.getErrorQuery(stmt)), e);
0277: } finally {
0278: m_sqlManager.closeAll(dbc, conn, stmt, res);
0279: }
0280: }
0281:
0282: /**
0283: * @see org.opencms.db.I_CmsHistoryDriver#deletePropertyDefinition(org.opencms.db.CmsDbContext, org.opencms.file.CmsPropertyDefinition)
0284: */
0285: public void deletePropertyDefinition(CmsDbContext dbc,
0286: CmsPropertyDefinition metadef)
0287: throws CmsDataAccessException {
0288:
0289: Connection conn = null;
0290: PreparedStatement stmt = null;
0291:
0292: try {
0293: if ((internalCountProperties(dbc, metadef,
0294: CmsProject.ONLINE_PROJECT_ID) != 0)
0295: || (internalCountProperties(dbc, metadef, CmsUUID
0296: .getOpenCmsUUID()) != 0)) { // HACK: to get an offline project
0297:
0298: throw new CmsDbConsistencyException(
0299: Messages
0300: .get()
0301: .container(
0302: Messages.ERR_ERROR_DELETING_PROPERTYDEF_1,
0303: metadef.getName()));
0304: }
0305:
0306: // delete the historical property definition
0307: conn = m_sqlManager.getConnection(dbc);
0308: stmt = m_sqlManager.getPreparedStatement(conn,
0309: "C_PROPERTYDEF_DELETE_HISTORY");
0310: stmt.setString(1, metadef.getId().toString());
0311: stmt.executeUpdate();
0312: } catch (SQLException e) {
0313: throw new CmsDbSqlException(Messages.get().container(
0314: Messages.ERR_GENERIC_SQL_1,
0315: CmsDbSqlException.getErrorQuery(stmt)), e);
0316: } finally {
0317: m_sqlManager.closeAll(dbc, conn, stmt, null);
0318: }
0319: }
0320:
0321: /**
0322: * @see org.opencms.db.I_CmsHistoryDriver#destroy()
0323: */
0324: public void destroy() throws Throwable {
0325:
0326: m_sqlManager = null;
0327: m_driverManager = null;
0328:
0329: if (CmsLog.INIT.isInfoEnabled()) {
0330: CmsLog.INIT.info(Messages.get().getBundle().key(
0331: Messages.INIT_SHUTDOWN_DRIVER_1,
0332: getClass().getName()));
0333: }
0334: }
0335:
0336: /**
0337: * @see org.opencms.db.I_CmsHistoryDriver#getAllDeletedEntries(CmsDbContext, CmsUUID)
0338: */
0339: public List getAllDeletedEntries(CmsDbContext dbc, CmsUUID parentId)
0340: throws CmsDataAccessException {
0341:
0342: Connection conn = null;
0343: PreparedStatement stmt = null;
0344: ResultSet res = null;
0345:
0346: List entries = new ArrayList();
0347: try {
0348: conn = m_sqlManager.getConnection(dbc);
0349:
0350: // get all not-deleted historical entries that may come in question
0351: stmt = m_sqlManager.getPreparedStatement(conn,
0352: "C_STRUCTURE_HISTORY_READ_DELETED");
0353: res = stmt.executeQuery();
0354: while (res.next()) {
0355: CmsUUID structureId = new CmsUUID(res.getString(1));
0356: int version = res.getInt(2);
0357: entries.add(readResource(dbc, structureId, version));
0358: }
0359: } catch (SQLException e) {
0360: throw new CmsDbSqlException(Messages.get().container(
0361: Messages.ERR_GENERIC_SQL_1,
0362: CmsDbSqlException.getErrorQuery(stmt)), e);
0363: } finally {
0364: m_sqlManager.closeAll(dbc, conn, stmt, res);
0365: }
0366: return internalFilterParentId(parentId, entries);
0367: }
0368:
0369: /**
0370: * @see org.opencms.db.I_CmsHistoryDriver#getAllNotDeletedEntries(CmsDbContext, CmsUUID)
0371: */
0372: public List getAllNotDeletedEntries(CmsDbContext dbc,
0373: CmsUUID parentId) throws CmsDataAccessException {
0374:
0375: Connection conn = null;
0376: PreparedStatement stmt = null;
0377: ResultSet res = null;
0378:
0379: List entries = new ArrayList();
0380: try {
0381: conn = m_sqlManager.getConnection(dbc);
0382:
0383: // get all not-deleted historical entries that may come in question
0384: stmt = m_sqlManager.getPreparedStatement(conn,
0385: "C_STRUCTURE_HISTORY_READ_NOTDELETED");
0386: res = stmt.executeQuery();
0387: while (res.next()) {
0388: CmsUUID structureId = new CmsUUID(res.getString(1));
0389: int version = res.getInt(2);
0390: entries.add(readResource(dbc, structureId, version));
0391: }
0392: } catch (SQLException e) {
0393: throw new CmsDbSqlException(Messages.get().container(
0394: Messages.ERR_GENERIC_SQL_1,
0395: CmsDbSqlException.getErrorQuery(stmt)), e);
0396: } finally {
0397: m_sqlManager.closeAll(dbc, conn, stmt, res);
0398: }
0399: return internalFilterParentId(parentId, entries);
0400:
0401: }
0402:
0403: /**
0404: * @see org.opencms.db.I_CmsHistoryDriver#getSqlManager()
0405: */
0406: public CmsSqlManager getSqlManager() {
0407:
0408: return m_sqlManager;
0409: }
0410:
0411: /**
0412: * @see org.opencms.db.I_CmsDriver#init(org.opencms.db.CmsDbContext, org.opencms.configuration.CmsConfigurationManager, java.util.List, org.opencms.db.CmsDriverManager)
0413: */
0414: public void init(CmsDbContext dbc,
0415: CmsConfigurationManager configurationManager,
0416: List successiveDrivers, CmsDriverManager driverManager) {
0417:
0418: Map configuration = configurationManager.getConfiguration();
0419:
0420: String poolUrl;
0421: if (configuration.get("db.history.pool") != null) {
0422: poolUrl = configuration.get("db.history.pool").toString();
0423: } else {
0424: // TODO: deprecated, remove as soon as possible
0425: poolUrl = configuration.get("db.backup.pool").toString();
0426: }
0427:
0428: String classname;
0429: if (configuration.get("db.history.sqlmanager") != null) {
0430: classname = configuration.get("db.history.sqlmanager")
0431: .toString();
0432: } else {
0433: // TODO: deprecated, remove as soon as possible
0434: classname = configuration.get("db.backup.sqlmanager")
0435: .toString();
0436: }
0437:
0438: m_sqlManager = initSqlManager(classname);
0439: m_sqlManager.init(I_CmsHistoryDriver.DRIVER_TYPE_ID, poolUrl);
0440:
0441: m_driverManager = driverManager;
0442:
0443: if (CmsLog.INIT.isInfoEnabled()) {
0444: CmsLog.INIT.info(Messages.get().getBundle().key(
0445: Messages.INIT_ASSIGNED_POOL_1, poolUrl));
0446: }
0447:
0448: if ((successiveDrivers != null) && !successiveDrivers.isEmpty()) {
0449: if (LOG.isWarnEnabled()) {
0450: LOG.warn(Messages.get().getBundle().key(
0451: Messages.LOG_SUCCESSIVE_DRIVERS_UNSUPPORTED_1,
0452: getClass().getName()));
0453: }
0454: }
0455: }
0456:
0457: /**
0458: * @see org.opencms.db.I_CmsHistoryDriver#initSqlManager(String)
0459: */
0460: public org.opencms.db.generic.CmsSqlManager initSqlManager(
0461: String classname) {
0462:
0463: return CmsSqlManager.getInstance(classname);
0464: }
0465:
0466: /**
0467: * @see org.opencms.db.I_CmsHistoryDriver#readAllAvailableVersions(CmsDbContext, CmsUUID)
0468: */
0469: public List readAllAvailableVersions(CmsDbContext dbc,
0470: CmsUUID structureId) throws CmsDataAccessException {
0471:
0472: ResultSet res = null;
0473: List result = new ArrayList();
0474: PreparedStatement stmt = null;
0475: Connection conn = null;
0476:
0477: try {
0478: conn = m_sqlManager.getConnection(dbc);
0479:
0480: // get all direct versions (where the structure entry has been written)
0481: // sorted from the NEWEST to the OLDEST version (publish tag descendant)
0482: List historyResources = new ArrayList();
0483: stmt = m_sqlManager.getPreparedStatement(conn,
0484: "C_RESOURCES_HISTORY_READ_ALL_VERSIONS");
0485: stmt.setString(1, structureId.toString());
0486: res = stmt.executeQuery();
0487: while (res.next()) {
0488: historyResources.add(internalCreateResource(res));
0489: }
0490: m_sqlManager.closeAll(dbc, null, stmt, res);
0491:
0492: if (!historyResources.isEmpty()) {
0493: // look for newer versions
0494: // this is the NEWEST version, with the HIGHEST publish tag
0495: I_CmsHistoryResource histRes = (I_CmsHistoryResource) historyResources
0496: .get(0);
0497:
0498: // look for later resource entries
0499: stmt = m_sqlManager.getPreparedStatement(conn,
0500: "C_RESOURCES_HISTORY_READ_NEW_VERSIONS");
0501: stmt.setString(1, histRes.getResourceId().toString());
0502: stmt.setInt(2, histRes.getPublishTag());
0503: res = stmt.executeQuery();
0504:
0505: I_CmsHistoryResource lastHistRes = histRes;
0506: // these are sorted from the oldest to the newest version (publish tag ascendent)
0507: while (res.next()) {
0508: int resVersion = res.getInt(m_sqlManager
0509: .readQuery("C_RESOURCES_VERSION"));
0510: if (resVersion == lastHistRes.getResourceVersion()) {
0511: // skip not interesting versions
0512: continue;
0513: }
0514: I_CmsHistoryResource newHistRes = internalMergeResource(
0515: histRes, res, 0);
0516: // add interesting versions, in the right order
0517: result.add(0, newHistRes);
0518: lastHistRes = newHistRes;
0519: }
0520: m_sqlManager.closeAll(dbc, null, stmt, res);
0521: }
0522: // iterate from the NEWEST to the OLDEST versions (publish tag descendant)
0523: for (int i = 0; i < historyResources.size(); i++) {
0524: I_CmsHistoryResource histRes = (I_CmsHistoryResource) historyResources
0525: .get(i);
0526: result.add(histRes);
0527: if (i < historyResources.size() - 1) {
0528: // this is one older direct version than histRes (histRes.getPublishTag() > histRes2.getPublishTag())
0529: I_CmsHistoryResource histRes2 = (I_CmsHistoryResource) historyResources
0530: .get(i + 1);
0531:
0532: // look for resource changes in between of the direct versions in ascendent order
0533: stmt = m_sqlManager.getPreparedStatement(conn,
0534: "C_RESOURCES_HISTORY_READ_BTW_VERSIONS");
0535: stmt.setString(1, histRes.getResourceId()
0536: .toString());
0537: stmt.setInt(2, histRes2.getPublishTag()); // lower limit
0538: stmt.setInt(3, histRes.getPublishTag()); // upper limit
0539: res = stmt.executeQuery();
0540:
0541: int pos = result.size();
0542: I_CmsHistoryResource lastHistRes = histRes2;
0543: while (res.next()) {
0544: int resVersion = res.getInt(m_sqlManager
0545: .readQuery("C_RESOURCES_VERSION"));
0546: if (resVersion == lastHistRes
0547: .getResourceVersion()) {
0548: // skip not interesting versions
0549: continue;
0550: }
0551: I_CmsHistoryResource newHistRes = internalMergeResource(
0552: histRes2, res, 0);
0553: // add interesting versions, in the right order
0554: result.add(pos, newHistRes);
0555: lastHistRes = newHistRes;
0556: }
0557: m_sqlManager.closeAll(dbc, null, stmt, res);
0558: }
0559: }
0560: if (!result.isEmpty()) {
0561: // get the oldest version
0562: I_CmsHistoryResource histRes = (I_CmsHistoryResource) result
0563: .get(result.size() - 1);
0564:
0565: if (histRes.getVersion() > 1) {
0566: // look for older resource versions, in descendant order
0567: stmt = m_sqlManager.getPreparedStatement(conn,
0568: "C_RESOURCES_HISTORY_READ_OLD_VERSIONS");
0569: stmt.setString(1, histRes.getResourceId()
0570: .toString());
0571: stmt.setInt(2, histRes.getPublishTag());
0572: res = stmt.executeQuery();
0573:
0574: int offset = (histRes.getStructureVersion() > 0 ? 1
0575: : 0);
0576:
0577: I_CmsHistoryResource lastHistRes = histRes;
0578: while (res.next()) {
0579: I_CmsHistoryResource newHistRes = internalMergeResource(
0580: histRes, res, offset);
0581: if (newHistRes.getResourceVersion() != lastHistRes
0582: .getResourceVersion()) {
0583: // only add interesting versions
0584: if (offset == 1) {
0585: result.add(lastHistRes);
0586: } else {
0587: result.add(newHistRes);
0588: }
0589: }
0590: lastHistRes = newHistRes;
0591: }
0592: // add the last one if there is one
0593: if ((offset == 1) && (lastHistRes != histRes)) {
0594: result.add(lastHistRes);
0595: }
0596: m_sqlManager.closeAll(dbc, null, stmt, res);
0597: }
0598: } else {
0599: // new resources have no history entries (despite they could be computed for siblings)
0600: /*
0601: // look for older resource versions, and merge with online or offline entry
0602: CmsResource resource;
0603: try {
0604: // first try online
0605: resource = m_driverManager.getVfsDriver().readResource(dbc, CmsProject.ONLINE_PROJECT_ID, structureId, true);
0606: } catch (CmsVfsResourceNotFoundException e) {
0607: // then try offline
0608: resource = m_driverManager.getVfsDriver().readResource(dbc, dbc.getProjectId(), structureId, true);
0609: }
0610:
0611: if (resource.getVersion() > 1) {
0612: stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_HISTORY_READ_OLD_VERSIONS_ALL");
0613: stmt.setString(1, resource.getResourceId().toString());
0614: res = stmt.executeQuery();
0615:
0616: I_CmsHistoryResource histRes = new CmsHistoryFile(resource);
0617: I_CmsHistoryResource lastHistRes = histRes;
0618: while (res.next()) {
0619: int pubTag = res.getInt(1);
0620: I_CmsHistoryResource newHistRes = internalReadMergedResource(dbc, histRes, pubTag); // this needs improvement
0621: if (newHistRes.getVersion() == lastHistRes.getVersion()) {
0622: lastHistRes = newHistRes;
0623: continue;
0624: }
0625: lastHistRes = newHistRes;
0626: result.add(lastHistRes);
0627: }
0628: m_sqlManager.closeAll(dbc, null, stmt, res);
0629: }
0630: */
0631: }
0632: } catch (SQLException e) {
0633: throw new CmsDbSqlException(Messages.get().container(
0634: Messages.ERR_GENERIC_SQL_1,
0635: CmsDbSqlException.getErrorQuery(stmt)), e);
0636: } finally {
0637: m_sqlManager.closeAll(dbc, conn, stmt, res);
0638: }
0639:
0640: return result;
0641: }
0642:
0643: /**
0644: * @see org.opencms.db.I_CmsHistoryDriver#readContent(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID, int)
0645: */
0646: public byte[] readContent(CmsDbContext dbc, CmsUUID resourceId,
0647: int publishTag) throws CmsDataAccessException {
0648:
0649: Connection conn = null;
0650: PreparedStatement stmt = null;
0651: ResultSet res = null;
0652: byte[] content = null;
0653:
0654: try {
0655: conn = m_sqlManager.getConnection(dbc);
0656: stmt = m_sqlManager.getPreparedStatement(conn,
0657: "C_HISTORY_READ_CONTENT");
0658: stmt.setString(1, resourceId.toString());
0659: stmt.setInt(2, publishTag);
0660: stmt.setInt(3, publishTag);
0661: res = stmt.executeQuery();
0662:
0663: if (res.next()) {
0664: content = m_sqlManager.getBytes(res, m_sqlManager
0665: .readQuery("C_RESOURCES_FILE_CONTENT"));
0666: while (res.next()) {
0667: // do nothing only move through all rows because of mssql odbc driver
0668: }
0669: }
0670: } catch (SQLException e) {
0671: throw new CmsDbSqlException(Messages.get().container(
0672: Messages.ERR_GENERIC_SQL_1,
0673: CmsDbSqlException.getErrorQuery(stmt)), e);
0674: } finally {
0675: m_sqlManager.closeAll(dbc, conn, stmt, res);
0676: }
0677: return content;
0678: }
0679:
0680: /**
0681: * @see org.opencms.db.I_CmsHistoryDriver#readDeletedResources(CmsDbContext, CmsUUID, CmsUUID)
0682: */
0683: public List readDeletedResources(CmsDbContext dbc,
0684: CmsUUID structureId, CmsUUID userId)
0685: throws CmsDataAccessException {
0686:
0687: Connection conn = null;
0688: PreparedStatement stmt = null;
0689: ResultSet res = null;
0690: List result = new ArrayList();
0691:
0692: try {
0693: conn = m_sqlManager.getConnection(dbc);
0694: if (userId == null) {
0695: stmt = m_sqlManager.getPreparedStatement(conn,
0696: "C_RESOURCES_HISTORY_READ_DELETED");
0697: } else {
0698: stmt = m_sqlManager.getPreparedStatement(conn,
0699: "C_RESOURCES_HISTORY_READ_DELETED_RESTRICTED");
0700: }
0701: stmt.setString(1, structureId.toString());
0702: if (userId != null) {
0703: stmt.setString(2, userId.toString());
0704: }
0705: res = stmt.executeQuery();
0706: while (res.next()) {
0707: I_CmsHistoryResource histRes = internalCreateResource(res);
0708: if (m_driverManager.getVfsDriver()
0709: .validateStructureIdExists(dbc,
0710: dbc.currentProject().getUuid(),
0711: histRes.getStructureId())) {
0712: // only add resources that are really deleted
0713: continue;
0714: }
0715: result.add(histRes);
0716: }
0717: } catch (SQLException e) {
0718: throw new CmsDbSqlException(Messages.get().container(
0719: Messages.ERR_GENERIC_SQL_1,
0720: CmsDbSqlException.getErrorQuery(stmt)), e);
0721: } finally {
0722: m_sqlManager.closeAll(dbc, conn, stmt, res);
0723: }
0724: return result;
0725: }
0726:
0727: /**
0728: * @see org.opencms.db.I_CmsHistoryDriver#readFile(CmsDbContext, CmsUUID, int)
0729: * @deprecated
0730: */
0731: public I_CmsHistoryResource readFile(CmsDbContext dbc,
0732: CmsUUID structureId, int tagId)
0733: throws CmsDataAccessException {
0734:
0735: I_CmsHistoryResource file = null;
0736: PreparedStatement stmt = null;
0737: ResultSet res = null;
0738: Connection conn = null;
0739:
0740: try {
0741: conn = m_sqlManager.getConnection(dbc);
0742: stmt = m_sqlManager.getPreparedStatement(conn,
0743: "C_FILES_READ_HISTORY_BYID");
0744: stmt.setString(1, structureId.toString());
0745: stmt.setInt(2, tagId);
0746: res = stmt.executeQuery();
0747: if (res.next()) {
0748: file = internalCreateResource(res);
0749: while (res.next()) {
0750: // do nothing only move through all rows because of mssql odbc driver
0751: }
0752: } else {
0753: throw new CmsVfsResourceNotFoundException(Messages
0754: .get().container(
0755: Messages.ERR_HISTORY_FILE_NOT_FOUND_1,
0756: structureId));
0757: }
0758: } catch (SQLException e) {
0759: throw new CmsDbSqlException(Messages.get().container(
0760: Messages.ERR_GENERIC_SQL_1,
0761: CmsDbSqlException.getErrorQuery(stmt)), e);
0762: } finally {
0763: m_sqlManager.closeAll(dbc, conn, stmt, res);
0764: }
0765:
0766: ((CmsFile) file).setContents(readContent(dbc, file
0767: .getResourceId(), file.getPublishTag()));
0768: return file;
0769: }
0770:
0771: /**
0772: * @see org.opencms.db.I_CmsHistoryDriver#readLastVersion(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID)
0773: */
0774: public int readLastVersion(CmsDbContext dbc, CmsUUID structureId)
0775: throws CmsDataAccessException {
0776:
0777: PreparedStatement stmt = null;
0778: Connection conn = null;
0779: ResultSet res = null;
0780: int lastVersion = 0;
0781:
0782: try {
0783: conn = m_sqlManager.getConnection(dbc);
0784: stmt = m_sqlManager.getPreparedStatement(conn,
0785: "C_STRUCTURE_HISTORY_MAXVER");
0786: stmt.setString(1, structureId.toString());
0787: res = stmt.executeQuery();
0788:
0789: if (res.next()) {
0790: lastVersion = res.getInt(1);
0791: while (res.next()) {
0792: // do nothing only move through all rows because of mssql odbc driver
0793: }
0794: } else {
0795: lastVersion = 0;
0796: }
0797: } catch (SQLException e) {
0798: throw new CmsDbSqlException(Messages.get().container(
0799: Messages.ERR_GENERIC_SQL_1,
0800: CmsDbSqlException.getErrorQuery(stmt)), e);
0801: } finally {
0802: m_sqlManager.closeAll(dbc, conn, stmt, res);
0803: }
0804:
0805: return lastVersion;
0806: }
0807:
0808: /**
0809: * @see org.opencms.db.I_CmsHistoryDriver#readMaxPublishTag(CmsDbContext, CmsUUID)
0810: */
0811: public int readMaxPublishTag(CmsDbContext dbc, CmsUUID resourceId)
0812: throws CmsDataAccessException {
0813:
0814: PreparedStatement stmt = null;
0815: Connection conn = null;
0816: ResultSet res = null;
0817: int result = 0;
0818:
0819: try {
0820: conn = m_sqlManager.getConnection(dbc);
0821: stmt = m_sqlManager.getPreparedStatement(conn,
0822: "C_RESOURCES_READ_MAX_PUBLISH_TAG");
0823: stmt.setString(1, resourceId.toString());
0824: res = stmt.executeQuery();
0825:
0826: if (res.next()) {
0827: result = res.getInt(1);
0828: while (res.next()) {
0829: // do nothing only move through all rows because of mssql odbc driver
0830: }
0831: }
0832: } catch (SQLException e) {
0833: throw new CmsDbSqlException(Messages.get().container(
0834: Messages.ERR_GENERIC_SQL_1,
0835: CmsDbSqlException.getErrorQuery(stmt)), e);
0836: } finally {
0837: m_sqlManager.closeAll(dbc, conn, stmt, res);
0838: }
0839:
0840: return result;
0841: }
0842:
0843: /**
0844: * @see org.opencms.db.I_CmsHistoryDriver#readNextPublishTag(org.opencms.db.CmsDbContext)
0845: */
0846: public int readNextPublishTag(CmsDbContext dbc) {
0847:
0848: PreparedStatement stmt = null;
0849: Connection conn = null;
0850: ResultSet res = null;
0851: int projectPublishTag = 1;
0852: int resourcePublishTag = 1;
0853:
0854: try {
0855: // get the max publish tag from project history
0856: conn = m_sqlManager.getConnection(dbc);
0857: stmt = m_sqlManager.getPreparedStatement(conn,
0858: "C_PROJECTS_HISTORY_MAXTAG");
0859: res = stmt.executeQuery();
0860:
0861: if (res.next()) {
0862: projectPublishTag = res.getInt(1) + 1;
0863: while (res.next()) {
0864: // do nothing only move through all rows because of mssql odbc driver
0865: }
0866: }
0867:
0868: } catch (SQLException exc) {
0869: LOG.error(Messages.get().container(
0870: Messages.ERR_GENERIC_SQL_1,
0871: CmsDbSqlException.getErrorQuery(stmt)), exc);
0872: } finally {
0873: m_sqlManager.closeAll(dbc, null, stmt, res);
0874: }
0875:
0876: try {
0877: // get the max publish tag from resource history
0878: stmt = m_sqlManager.getPreparedStatement(conn,
0879: "C_RESOURCES_HISTORY_MAXTAG");
0880: res = stmt.executeQuery();
0881:
0882: if (res.next()) {
0883: resourcePublishTag = res.getInt(1) + 1;
0884: while (res.next()) {
0885: // do nothing only move through all rows because of mssql odbc driver
0886: }
0887: }
0888: } catch (SQLException exc) {
0889: LOG.error(Messages.get().container(
0890: Messages.ERR_GENERIC_SQL_1,
0891: CmsDbSqlException.getErrorQuery(stmt)), exc);
0892: } finally {
0893: m_sqlManager.closeAll(dbc, conn, stmt, res);
0894: }
0895:
0896: // return the biggest
0897: if (resourcePublishTag > projectPublishTag) {
0898: projectPublishTag = resourcePublishTag;
0899: }
0900:
0901: return projectPublishTag;
0902: }
0903:
0904: /**
0905: * @see org.opencms.db.I_CmsHistoryDriver#readPrincipal(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID)
0906: */
0907: public CmsHistoryPrincipal readPrincipal(CmsDbContext dbc,
0908: CmsUUID principalId) throws CmsDataAccessException {
0909:
0910: Connection conn = null;
0911: PreparedStatement stmt = null;
0912: ResultSet res = null;
0913: CmsHistoryPrincipal historyPrincipal = null;
0914:
0915: try {
0916: conn = m_sqlManager.getConnection(dbc);
0917: stmt = m_sqlManager.getPreparedStatement(conn,
0918: "C_HISTORY_PRINCIPAL_READ");
0919: stmt.setString(1, principalId.toString());
0920: res = stmt.executeQuery();
0921: if (res.next()) {
0922: String userName = res.getString(m_sqlManager
0923: .readQuery("C_PRINCIPALS_HISTORY_NAME"));
0924: String ou = CmsOrganizationalUnit
0925: .removeLeadingSeparator(res
0926: .getString(m_sqlManager
0927: .readQuery("C_PRINCIPALS_HISTORY_OU")));
0928: historyPrincipal = new CmsHistoryPrincipal(
0929: principalId,
0930: ou + userName,
0931: res
0932: .getString(m_sqlManager
0933: .readQuery("C_PRINCIPALS_HISTORY_DESCRIPTION")),
0934: res
0935: .getString(m_sqlManager
0936: .readQuery("C_PRINCIPALS_HISTORY_EMAIL")),
0937: res
0938: .getString(m_sqlManager
0939: .readQuery("C_PRINCIPALS_HISTORY_TYPE")),
0940: new CmsUUID(
0941: res
0942: .getString(m_sqlManager
0943: .readQuery("C_PRINCIPALS_HISTORY_USERDELETED"))),
0944: res
0945: .getLong(m_sqlManager
0946: .readQuery("C_PRINCIPALS_HISTORY_DATEDELETED")));
0947: while (res.next()) {
0948: // do nothing only move through all rows because of mssql odbc driver
0949: }
0950: } else {
0951: throw new CmsDbEntryNotFoundException(
0952: Messages
0953: .get()
0954: .container(
0955: Messages.ERR_HISTORY_PRINCIPAL_NOT_FOUND_1,
0956: principalId));
0957: }
0958: } catch (SQLException e) {
0959: throw new CmsDbSqlException(Messages.get().container(
0960: Messages.ERR_GENERIC_SQL_1,
0961: CmsDbSqlException.getErrorQuery(stmt)), e);
0962: } finally {
0963: m_sqlManager.closeAll(dbc, conn, stmt, res);
0964: }
0965: return historyPrincipal;
0966: }
0967:
0968: /**
0969: * @see org.opencms.db.I_CmsHistoryDriver#readProject(org.opencms.db.CmsDbContext, int)
0970: */
0971: public CmsHistoryProject readProject(CmsDbContext dbc,
0972: int publishTag) throws CmsDataAccessException {
0973:
0974: PreparedStatement stmt = null;
0975: CmsHistoryProject project = null;
0976: ResultSet res = null;
0977: Connection conn = null;
0978: try {
0979: conn = m_sqlManager.getConnection(dbc);
0980: stmt = m_sqlManager.getPreparedStatement(conn,
0981: "C_PROJECTS_HISTORY_READ");
0982:
0983: stmt.setInt(1, publishTag);
0984: res = stmt.executeQuery();
0985:
0986: if (res.next()) {
0987: List projectresources = readProjectResources(dbc,
0988: publishTag);
0989: project = internalCreateProject(res, projectresources);
0990: while (res.next()) {
0991: // do nothing only move through all rows because of mssql odbc driver
0992: }
0993: } else {
0994: throw new CmsDbEntryNotFoundException(
0995: Messages
0996: .get()
0997: .container(
0998: Messages.ERR_NO_HISTORY_PROJECT_WITH_TAG_ID_1,
0999: new Integer(publishTag)));
1000: }
1001: } catch (SQLException e) {
1002: throw new CmsDbSqlException(Messages.get().container(
1003: Messages.ERR_GENERIC_SQL_1,
1004: CmsDbSqlException.getErrorQuery(stmt)), e);
1005: } finally {
1006: m_sqlManager.closeAll(dbc, conn, stmt, res);
1007: }
1008: return project;
1009: }
1010:
1011: /**
1012: * @see org.opencms.db.I_CmsHistoryDriver#readProjectResources(org.opencms.db.CmsDbContext, int)
1013: */
1014: public List readProjectResources(CmsDbContext dbc, int publishTag)
1015: throws CmsDataAccessException {
1016:
1017: PreparedStatement stmt = null;
1018: Connection conn = null;
1019: ResultSet res = null;
1020: List projectResources = new ArrayList();
1021:
1022: try {
1023: conn = m_sqlManager.getConnection(dbc);
1024: stmt = m_sqlManager.getPreparedStatement(conn,
1025: "C_PROJECTRESOURCES_HISTORY_READ");
1026: stmt.setInt(1, publishTag);
1027: res = stmt.executeQuery();
1028: while (res.next()) {
1029: projectResources.add(res.getString("RESOURCE_PATH"));
1030: }
1031: } catch (SQLException e) {
1032: throw new CmsDbSqlException(Messages.get().container(
1033: Messages.ERR_GENERIC_SQL_1,
1034: CmsDbSqlException.getErrorQuery(stmt)), e);
1035: } finally {
1036: m_sqlManager.closeAll(dbc, conn, stmt, res);
1037: }
1038:
1039: return projectResources;
1040: }
1041:
1042: /**
1043: * @see org.opencms.db.I_CmsHistoryDriver#readProjects(org.opencms.db.CmsDbContext)
1044: */
1045: public List readProjects(CmsDbContext dbc)
1046: throws CmsDataAccessException {
1047:
1048: List projects = new ArrayList();
1049: ResultSet res = null;
1050: PreparedStatement stmt = null;
1051: Connection conn = null;
1052:
1053: try {
1054: // create the statement
1055: conn = m_sqlManager.getConnection(dbc);
1056: stmt = m_sqlManager.getPreparedStatement(conn,
1057: "C_PROJECTS_HISTORY_READ_ALL");
1058: res = stmt.executeQuery();
1059:
1060: // this is not really efficient
1061: // but it is overriden in all db specific implementations, including mysql
1062: int i = 0;
1063: int max = 300;
1064:
1065: while (res.next() && (i < max)) {
1066: List resources = readProjectResources(dbc, res
1067: .getInt("PUBLISH_TAG"));
1068: projects.add(internalCreateProject(res, resources));
1069: i++;
1070: }
1071: } catch (SQLException e) {
1072: throw new CmsDbSqlException(Messages.get().container(
1073: Messages.ERR_GENERIC_SQL_1,
1074: CmsDbSqlException.getErrorQuery(stmt)), e);
1075: } finally {
1076: m_sqlManager.closeAll(dbc, conn, stmt, res);
1077: }
1078: return (projects);
1079: }
1080:
1081: /**
1082: * @see org.opencms.db.I_CmsHistoryDriver#readProperties(org.opencms.db.CmsDbContext, org.opencms.file.history.I_CmsHistoryResource)
1083: */
1084: public List readProperties(CmsDbContext dbc,
1085: I_CmsHistoryResource resource)
1086: throws CmsDataAccessException {
1087:
1088: ResultSet res = null;
1089: PreparedStatement stmt = null;
1090: Connection conn = null;
1091:
1092: Map propertyMap = new HashMap();
1093:
1094: try {
1095: conn = m_sqlManager.getConnection(dbc);
1096:
1097: // get the latest properties for this sibling
1098: int pubTag = -1;
1099: stmt = m_sqlManager.getPreparedStatement(conn,
1100: "C_PROPERTIES_HISTORY_READ_PUBTAG");
1101: stmt.setString(1, resource.getStructureId().toString());
1102: stmt.setInt(2, resource.getPublishTag());
1103: res = stmt.executeQuery();
1104: if (res.next()) {
1105: pubTag = res.getInt(1);
1106: while (res.next()) {
1107: // do nothing only move through all rows because of mssql odbc driver
1108: }
1109: }
1110: m_sqlManager.closeAll(dbc, null, stmt, res);
1111:
1112: if (pubTag > 0) {
1113: // add the siblings props
1114: stmt = m_sqlManager.getPreparedStatement(conn,
1115: "C_PROPERTIES_HISTORY_READALL_STR");
1116: stmt.setString(1, resource.getStructureId().toString());
1117: stmt.setInt(2, pubTag);
1118: res = stmt.executeQuery();
1119:
1120: while (res.next()) {
1121: String propertyKey = res.getString(1);
1122: String propertyValue = res.getString(2);
1123: int mappingType = res.getInt(3);
1124:
1125: internalAddToPropMap(propertyMap, resource,
1126: propertyKey, propertyValue, mappingType);
1127: }
1128: m_sqlManager.closeAll(dbc, null, stmt, res);
1129: }
1130:
1131: if (pubTag != resource.getPublishTag()) {
1132: // check if there were newer shared properties modifications
1133: stmt = m_sqlManager.getPreparedStatement(conn,
1134: "C_PROPERTIES_HISTORY_READALL_RES");
1135: stmt.setString(1, resource.getStructureId().toString());
1136: stmt.setInt(2, resource.getPublishTag());
1137: res = stmt.executeQuery();
1138:
1139: while (res.next()) {
1140: String propertyKey = res.getString(1);
1141: String propertyValue = res.getString(2);
1142: int mappingType = res.getInt(3);
1143:
1144: internalAddToPropMap(propertyMap, resource,
1145: propertyKey, propertyValue, mappingType);
1146: }
1147: m_sqlManager.closeAll(dbc, null, stmt, res);
1148: }
1149: } catch (SQLException e) {
1150: throw new CmsDbSqlException(Messages.get().container(
1151: Messages.ERR_GENERIC_SQL_1,
1152: CmsDbSqlException.getErrorQuery(stmt)), e);
1153: } finally {
1154: m_sqlManager.closeAll(dbc, conn, stmt, res);
1155: }
1156:
1157: return new ArrayList(propertyMap.values());
1158: }
1159:
1160: /**
1161: * @see org.opencms.db.I_CmsHistoryDriver#readPropertyDefinition(org.opencms.db.CmsDbContext, java.lang.String)
1162: */
1163: public CmsPropertyDefinition readPropertyDefinition(
1164: CmsDbContext dbc, String name)
1165: throws CmsDataAccessException {
1166:
1167: CmsPropertyDefinition propDef = null;
1168: ResultSet res = null;
1169: PreparedStatement stmt = null;
1170: Connection conn = null;
1171:
1172: try {
1173: conn = m_sqlManager.getConnection(dbc);
1174: stmt = m_sqlManager.getPreparedStatement(conn,
1175: "C_PROPERTYDEF_READ_HISTORY");
1176: stmt.setString(1, name);
1177: res = stmt.executeQuery();
1178:
1179: if (res.next()) {
1180: propDef = new CmsPropertyDefinition(
1181: new CmsUUID(res.getString(m_sqlManager
1182: .readQuery("C_PROPERTYDEF_ID"))),
1183: res.getString(m_sqlManager
1184: .readQuery("C_PROPERTYDEF_NAME")),
1185: CmsPropertyDefinition.CmsPropertyType
1186: .valueOf(res
1187: .getInt(m_sqlManager
1188: .readQuery("C_PROPERTYDEF_TYPE"))));
1189: while (res.next()) {
1190: // do nothing only move through all rows because of mssql odbc driver
1191: }
1192: } else {
1193: throw new CmsDbEntryNotFoundException(
1194: Messages
1195: .get()
1196: .container(
1197: Messages.ERR_NO_PROPERTYDEF_WITH_NAME_1,
1198: name));
1199: }
1200: } catch (SQLException e) {
1201: throw new CmsDbSqlException(Messages.get().container(
1202: Messages.ERR_GENERIC_SQL_1,
1203: CmsDbSqlException.getErrorQuery(stmt)), e);
1204: } finally {
1205: m_sqlManager.closeAll(dbc, conn, stmt, res);
1206: }
1207:
1208: return propDef;
1209: }
1210:
1211: /**
1212: * @see org.opencms.db.I_CmsHistoryDriver#readPublishTag(org.opencms.db.CmsDbContext, long)
1213: */
1214: public int readPublishTag(CmsDbContext dbc, long maxdate)
1215: throws CmsDataAccessException {
1216:
1217: ResultSet res = null;
1218: PreparedStatement stmt = null;
1219: Connection conn = null;
1220: int maxVersion = 0;
1221:
1222: try {
1223: conn = m_sqlManager.getConnection(dbc);
1224: stmt = m_sqlManager.getPreparedStatement(conn,
1225: "C_PROJECTS_HISTORY_READ_TAG_FOR_DATE");
1226: stmt.setLong(1, maxdate);
1227: res = stmt.executeQuery();
1228: if (res.next()) {
1229: maxVersion = res.getInt(1);
1230: while (res.next()) {
1231: // do nothing only move through all rows because of mssql odbc driver
1232: }
1233: }
1234: } catch (SQLException e) {
1235: throw new CmsDbSqlException(Messages.get().container(
1236: Messages.ERR_GENERIC_SQL_1,
1237: CmsDbSqlException.getErrorQuery(stmt)), e);
1238: } finally {
1239: m_sqlManager.closeAll(dbc, conn, stmt, res);
1240: }
1241: return maxVersion;
1242: }
1243:
1244: /**
1245: * @see org.opencms.db.I_CmsHistoryDriver#readResource(CmsDbContext, CmsUUID, int)
1246: */
1247: public I_CmsHistoryResource readResource(CmsDbContext dbc,
1248: CmsUUID structureId, int version)
1249: throws CmsDataAccessException {
1250:
1251: I_CmsHistoryResource resource = null;
1252: PreparedStatement stmt = null;
1253: ResultSet res = null;
1254: Connection conn = null;
1255:
1256: try {
1257: conn = m_sqlManager.getConnection(dbc);
1258: stmt = m_sqlManager.getPreparedStatement(conn,
1259: "C_RESOURCES_HISTORY_READ_VERSION");
1260: stmt.setString(1, structureId.toString());
1261: stmt.setInt(2, version);
1262: res = stmt.executeQuery();
1263: if (res.next()) {
1264: resource = internalCreateResource(res);
1265: while (res.next()) {
1266: // do nothing only move through all rows because of mssql odbc driver
1267: }
1268: } else {
1269: throw new CmsVfsResourceNotFoundException(Messages
1270: .get().container(
1271: Messages.ERR_HISTORY_FILE_NOT_FOUND_1,
1272: structureId));
1273: }
1274: } catch (SQLException e) {
1275: throw new CmsDbSqlException(Messages.get().container(
1276: Messages.ERR_GENERIC_SQL_1,
1277: CmsDbSqlException.getErrorQuery(stmt)), e);
1278: } finally {
1279: m_sqlManager.closeAll(dbc, conn, stmt, res);
1280: }
1281: return resource;
1282: }
1283:
1284: /**
1285: * @see org.opencms.db.I_CmsHistoryDriver#writePrincipal(CmsDbContext, org.opencms.security.I_CmsPrincipal)
1286: */
1287: public void writePrincipal(CmsDbContext dbc,
1288: I_CmsPrincipal principal) throws CmsDataAccessException {
1289:
1290: Connection conn = null;
1291: PreparedStatement stmt = null;
1292:
1293: try {
1294: // check if the principal was already saved
1295: readPrincipal(dbc, principal.getId());
1296: return;
1297: } catch (CmsDbEntryNotFoundException e) {
1298: // ok
1299: }
1300: try {
1301: conn = m_sqlManager.getConnection(dbc);
1302: stmt = m_sqlManager.getPreparedStatement(conn,
1303: "C_HISTORY_PRINCIPAL_CREATE");
1304: stmt.setString(1, principal.getId().toString());
1305: stmt.setString(2, principal.getSimpleName());
1306: String desc = principal.getDescription();
1307: desc = CmsStringUtil.isEmptyOrWhitespaceOnly(desc) ? "-"
1308: : desc;
1309: stmt.setString(3, desc);
1310: stmt.setString(4, CmsOrganizationalUnit.SEPARATOR
1311: + principal.getOuFqn());
1312: if (principal instanceof CmsUser) {
1313: String email = ((CmsUser) principal).getEmail();
1314: email = CmsStringUtil.isEmptyOrWhitespaceOnly(email) ? "-"
1315: : email;
1316: stmt.setString(5, email);
1317: stmt.setString(6, I_CmsPrincipal.PRINCIPAL_USER);
1318: } else {
1319: stmt.setString(5, "-");
1320: stmt.setString(6, I_CmsPrincipal.PRINCIPAL_GROUP);
1321: }
1322: stmt.setString(7, dbc.currentUser().getId().toString());
1323: stmt.setLong(8, System.currentTimeMillis());
1324:
1325: stmt.executeUpdate();
1326: } catch (SQLException e) {
1327: throw new CmsDbSqlException(Messages.get().container(
1328: Messages.ERR_GENERIC_SQL_1,
1329: CmsDbSqlException.getErrorQuery(stmt)), e);
1330: } finally {
1331: m_sqlManager.closeAll(dbc, conn, stmt, null);
1332: }
1333: }
1334:
1335: /**
1336: * @see org.opencms.db.I_CmsHistoryDriver#writeProject(org.opencms.db.CmsDbContext, int, long)
1337: */
1338: public void writeProject(CmsDbContext dbc, int publishTag,
1339: long publishDate) throws CmsDataAccessException {
1340:
1341: CmsProject currentProject = dbc.currentProject();
1342: CmsUser currentUser = dbc.currentUser();
1343:
1344: List projectresources = m_driverManager.getProjectDriver()
1345: .readProjectResources(dbc, currentProject);
1346:
1347: // write historical project to the database
1348: Connection conn = null;
1349: PreparedStatement stmt = null;
1350: try {
1351: conn = m_sqlManager.getConnection(dbc);
1352:
1353: stmt = m_sqlManager.getPreparedStatement(conn,
1354: "C_PROJECTS_HISTORY_CREATE");
1355: // first write the project
1356: stmt.setInt(1, publishTag);
1357: stmt.setString(2, currentProject.getUuid().toString());
1358: stmt.setString(3, currentProject.getSimpleName());
1359: stmt.setLong(4, publishDate);
1360: stmt.setString(5, currentUser.getId().toString());
1361: stmt.setString(6, currentProject.getOwnerId().toString());
1362: stmt.setString(7, currentProject.getGroupId().toString());
1363: stmt.setString(8, currentProject.getManagerGroupId()
1364: .toString());
1365: stmt.setString(9, currentProject.getDescription());
1366: stmt.setLong(10, currentProject.getDateCreated());
1367: stmt.setInt(11, currentProject.getType().getMode());
1368: stmt.setString(12, CmsOrganizationalUnit.SEPARATOR
1369: + currentProject.getOuFqn());
1370: stmt.executeUpdate();
1371:
1372: m_sqlManager.closeAll(dbc, null, stmt, null);
1373:
1374: // now write the projectresources
1375: stmt = m_sqlManager.getPreparedStatement(conn,
1376: "C_PROJECTRESOURCES_HISTORY_CREATE");
1377: Iterator i = projectresources.iterator();
1378: while (i.hasNext()) {
1379: stmt.setInt(1, publishTag);
1380: stmt.setString(2, currentProject.getUuid().toString());
1381: stmt.setString(3, (String) i.next());
1382: stmt.executeUpdate();
1383: stmt.clearParameters();
1384: }
1385: } catch (SQLException e) {
1386: throw new CmsDbSqlException(Messages.get().container(
1387: Messages.ERR_GENERIC_SQL_1,
1388: CmsDbSqlException.getErrorQuery(stmt)), e);
1389: } finally {
1390: m_sqlManager.closeAll(dbc, conn, stmt, null);
1391: }
1392: }
1393:
1394: /**
1395: * @see org.opencms.db.I_CmsHistoryDriver#writeProperties(org.opencms.db.CmsDbContext, org.opencms.file.CmsResource, java.util.List, int)
1396: */
1397: public void writeProperties(CmsDbContext dbc, CmsResource resource,
1398: List properties, int publishTag)
1399: throws CmsDataAccessException {
1400:
1401: Connection conn = null;
1402: PreparedStatement stmt = null;
1403:
1404: try {
1405: conn = m_sqlManager.getConnection(dbc);
1406: Iterator dummy = properties.iterator();
1407: while (dummy.hasNext()) {
1408: CmsProperty property = (CmsProperty) dummy.next();
1409: CmsPropertyDefinition propDef = readPropertyDefinition(
1410: dbc, property.getName());
1411: if (propDef == null) {
1412: // create if missing
1413: propDef = createPropertyDefinition(dbc, property
1414: .getName(),
1415: CmsPropertyDefinition.TYPE_NORMAL);
1416: }
1417:
1418: for (int i = 0; i < 2; i++) {
1419: int mappingType;
1420: String value;
1421: CmsUUID id;
1422: if (i == 0) {
1423: // write the structure value on the first cycle
1424: value = property.getStructureValue();
1425: mappingType = CmsProperty.STRUCTURE_RECORD_MAPPING;
1426: id = resource.getStructureId();
1427: if (CmsStringUtil.isEmpty(value)) {
1428: continue;
1429: }
1430: } else {
1431: // write the resource value on the second cycle
1432: value = property.getResourceValue();
1433: mappingType = CmsProperty.RESOURCE_RECORD_MAPPING;
1434: id = resource.getResourceId();
1435: if (CmsStringUtil.isEmpty(value)) {
1436: break;
1437: }
1438: }
1439:
1440: stmt = m_sqlManager.getPreparedStatement(conn,
1441: "C_PROPERTIES_HISTORY_CREATE");
1442:
1443: stmt.setString(1, resource.getStructureId()
1444: .toString());
1445: stmt.setString(2, propDef.getId().toString());
1446: stmt.setString(3, id.toString());
1447: stmt.setInt(4, mappingType);
1448: stmt
1449: .setString(5, m_sqlManager
1450: .validateEmpty(value));
1451: stmt.setInt(6, publishTag);
1452:
1453: stmt.executeUpdate();
1454: m_sqlManager.closeAll(dbc, null, stmt, null);
1455: }
1456: }
1457: } catch (SQLException e) {
1458: throw new CmsDbSqlException(Messages.get().container(
1459: Messages.ERR_GENERIC_SQL_1,
1460: CmsDbSqlException.getErrorQuery(stmt)), e);
1461: } finally {
1462: m_sqlManager.closeAll(dbc, conn, stmt, null);
1463: }
1464: }
1465:
1466: /**
1467: * @see org.opencms.db.I_CmsHistoryDriver#writeResource(org.opencms.db.CmsDbContext, org.opencms.file.CmsResource, java.util.List, int)
1468: */
1469: public void writeResource(CmsDbContext dbc, CmsResource resource,
1470: List properties, int publishTag)
1471: throws CmsDataAccessException {
1472:
1473: Connection conn = null;
1474: PreparedStatement stmt = null;
1475:
1476: try {
1477: conn = m_sqlManager.getConnection(dbc);
1478:
1479: int sibCount = resource.getSiblingCount();
1480:
1481: boolean valResource = internalValidateResource(dbc,
1482: resource, publishTag);
1483:
1484: // if deleted
1485: if (resource.getState().isDeleted()) {
1486: // if it is a file
1487: if (resource instanceof CmsFile) {
1488: if (!valResource) {
1489: if (sibCount < 2) {
1490: // copy from offline content to content tables
1491: // so that the history contains the last state of the file
1492: m_driverManager.getVfsDriver()
1493: .createOnlineContent(
1494: dbc,
1495: resource.getResourceId(),
1496: ((CmsFile) resource)
1497: .getContents(),
1498: publishTag, false, true);
1499: } else {
1500: // put the content definitively in the history if no sibling is left
1501: m_driverManager.getVfsDriver()
1502: .createOnlineContent(
1503: dbc,
1504: resource.getResourceId(),
1505: ((CmsFile) resource)
1506: .getContents(),
1507: publishTag, true, false);
1508: }
1509: }
1510: }
1511:
1512: // update version numbers
1513: m_driverManager.getVfsDriver().publishVersions(dbc,
1514: resource, !valResource);
1515: }
1516:
1517: // read the version numbers
1518: Map versions = m_driverManager.getVfsDriver()
1519: .readVersions(dbc, CmsProject.ONLINE_PROJECT_ID,
1520: resource.getResourceId(),
1521: resource.getStructureId());
1522: int structureVersion = ((Integer) versions.get("structure"))
1523: .intValue();
1524: int resourceVersion = ((Integer) versions.get("resource"))
1525: .intValue();
1526:
1527: if (!valResource) {
1528: // write the resource
1529: stmt = m_sqlManager.getPreparedStatement(conn,
1530: "C_RESOURCES_HISTORY_WRITE");
1531: stmt.setString(1, resource.getResourceId().toString());
1532: stmt.setInt(2, resource.getTypeId());
1533: stmt.setInt(3, resource.getFlags());
1534: stmt.setLong(4, resource.getDateCreated());
1535: stmt.setString(5, resource.getUserCreated().toString());
1536: stmt.setLong(6, resource.getDateLastModified());
1537: stmt.setString(7, resource.getUserLastModified()
1538: .toString());
1539: stmt.setInt(8, resource.getState().getState());
1540: stmt.setInt(9, resource.getLength());
1541: stmt.setLong(10, resource.getDateContent());
1542: stmt.setString(11, dbc.currentProject().getUuid()
1543: .toString());
1544: stmt.setInt(12, resource.getSiblingCount());
1545: stmt.setInt(13, resourceVersion);
1546: stmt.setInt(14, publishTag);
1547: stmt.executeUpdate();
1548:
1549: m_sqlManager.closeAll(dbc, null, stmt, null);
1550: }
1551: CmsUUID parentId = CmsUUID.getNullUUID();
1552: CmsFolder parent = m_driverManager.getVfsDriver()
1553: .readParentFolder(dbc,
1554: CmsProject.ONLINE_PROJECT_ID,
1555: resource.getStructureId());
1556: if (parent != null) {
1557: parentId = parent.getStructureId();
1558: }
1559: // write the structure
1560: stmt = m_sqlManager.getPreparedStatement(conn,
1561: "C_STRUCTURE_HISTORY_WRITE");
1562: stmt.setString(1, resource.getStructureId().toString());
1563: stmt.setString(2, resource.getResourceId().toString());
1564: stmt.setString(3, resource.getRootPath());
1565: stmt.setInt(4, resource.getState().getState());
1566: stmt.setLong(5, resource.getDateReleased());
1567: stmt.setLong(6, resource.getDateExpired());
1568: stmt.setInt(7, structureVersion);
1569: stmt.setString(8, parentId.toString());
1570: stmt.setInt(9, publishTag);
1571: stmt.setInt(10, resource.getVersion());
1572: stmt.executeUpdate();
1573: } catch (SQLException e) {
1574: throw new CmsDbSqlException(Messages.get().container(
1575: Messages.ERR_GENERIC_SQL_1,
1576: CmsDbSqlException.getErrorQuery(stmt)), e);
1577: } finally {
1578: m_sqlManager.closeAll(dbc, conn, stmt, null);
1579: }
1580:
1581: writeProperties(dbc, resource, properties, publishTag);
1582: }
1583:
1584: /**
1585: * Updates the property map for the given resource with the given property data.<p>
1586: *
1587: * @param propertyMap the map to update
1588: * @param resource the resource the properties belong to
1589: * @param propertyKey the property key
1590: * @param propertyValue the property value
1591: * @param mappingType the mapping type
1592: *
1593: * @throws CmsDbConsistencyException if the mapping type is wrong
1594: */
1595: protected void internalAddToPropMap(Map propertyMap,
1596: I_CmsHistoryResource resource, String propertyKey,
1597: String propertyValue, int mappingType)
1598: throws CmsDbConsistencyException {
1599:
1600: CmsProperty property = (CmsProperty) propertyMap
1601: .get(propertyKey);
1602: if (property != null) {
1603: // there exists already a property for this key in the result
1604: switch (mappingType) {
1605: case CmsProperty.STRUCTURE_RECORD_MAPPING:
1606: // this property value is mapped to a structure record
1607: property.setStructureValue(propertyValue);
1608: break;
1609: case CmsProperty.RESOURCE_RECORD_MAPPING:
1610: // this property value is mapped to a resource record
1611: property.setResourceValue(propertyValue);
1612: break;
1613: default:
1614: throw new CmsDbConsistencyException(
1615: Messages
1616: .get()
1617: .container(
1618: Messages.ERR_UNKNOWN_PROPERTY_VALUE_MAPPING_3,
1619: resource.getRootPath(),
1620: new Integer(mappingType),
1621: propertyKey));
1622: }
1623: } else {
1624: // there doesn't exist a property for this key yet
1625: property = new CmsProperty();
1626: property.setName(propertyKey);
1627:
1628: switch (mappingType) {
1629: case CmsProperty.STRUCTURE_RECORD_MAPPING:
1630: // this property value is mapped to a structure record
1631: property.setStructureValue(propertyValue);
1632: property.setResourceValue(null);
1633: break;
1634: case CmsProperty.RESOURCE_RECORD_MAPPING:
1635: // this property value is mapped to a resource record
1636: property.setStructureValue(null);
1637: property.setResourceValue(propertyValue);
1638: break;
1639: default:
1640: throw new CmsDbConsistencyException(
1641: Messages
1642: .get()
1643: .container(
1644: Messages.ERR_UNKNOWN_PROPERTY_VALUE_MAPPING_3,
1645: resource.getRootPath(),
1646: new Integer(mappingType),
1647: propertyKey));
1648: }
1649: propertyMap.put(propertyKey, property);
1650: }
1651: }
1652:
1653: /**
1654: * Deletes all historical entries of subresources of a folder without any historical netry left.<p>
1655: *
1656: * @param dbc the current database context
1657: * @param resource the resource to check
1658: *
1659: * @throws CmsDataAccessException if something goes wrong
1660: */
1661: protected void internalCleanup(CmsDbContext dbc,
1662: I_CmsHistoryResource resource)
1663: throws CmsDataAccessException {
1664:
1665: boolean isFolder = resource.getRootPath().endsWith("/");
1666: List subResources = new ArrayList();
1667:
1668: // if the resource is a folder
1669: if (isFolder) {
1670: // and if no versions left
1671: if (readLastVersion(dbc, resource.getStructureId()) == 0) {
1672: // get all direct subresources
1673: Connection conn = null;
1674: PreparedStatement stmt = null;
1675: ResultSet res = null;
1676:
1677: try {
1678: conn = m_sqlManager.getConnection(dbc);
1679:
1680: stmt = m_sqlManager.getPreparedStatement(conn,
1681: "C_STRUCTURE_HISTORY_READ_SUBRESOURCES");
1682: stmt.setString(1, resource.getStructureId()
1683: .toString());
1684: res = stmt.executeQuery();
1685: while (res.next()) {
1686: CmsUUID structureId = new CmsUUID(res
1687: .getString(1));
1688: int version = res.getInt(2);
1689: subResources.add(readResource(dbc, structureId,
1690: version));
1691: }
1692: } catch (SQLException e) {
1693: throw new CmsDbSqlException(Messages.get()
1694: .container(
1695: Messages.ERR_GENERIC_SQL_1,
1696: CmsDbSqlException
1697: .getErrorQuery(stmt)), e);
1698: } finally {
1699: m_sqlManager.closeAll(dbc, conn, stmt, res);
1700: }
1701: }
1702: }
1703:
1704: // delete all subresource versions
1705: Iterator it = subResources.iterator();
1706: while (it.hasNext()) {
1707: I_CmsHistoryResource histResource = (I_CmsHistoryResource) it
1708: .next();
1709: deleteEntries(dbc, histResource, 0, -1);
1710: }
1711: }
1712:
1713: /**
1714: * Returns the amount of properties for a propertydefinition.<p>
1715: *
1716: * @param dbc the current database context
1717: * @param metadef the propertydefinition to test
1718: * @param projectId the ID of the current project
1719: *
1720: * @return the amount of properties for a propertydefinition
1721: * @throws CmsDataAccessException if something goes wrong
1722: */
1723: protected int internalCountProperties(CmsDbContext dbc,
1724: CmsPropertyDefinition metadef, CmsUUID projectId)
1725: throws CmsDataAccessException {
1726:
1727: ResultSet res = null;
1728: PreparedStatement stmt = null;
1729: Connection conn = null;
1730:
1731: int returnValue;
1732: try {
1733: // create statement
1734: conn = m_sqlManager.getConnection(dbc);
1735: stmt = m_sqlManager.getPreparedStatement(conn, projectId,
1736: "C_PROPERTIES_READALL_COUNT");
1737: stmt.setString(1, metadef.getId().toString());
1738: res = stmt.executeQuery();
1739:
1740: if (res.next()) {
1741: returnValue = res.getInt(1);
1742: while (res.next()) {
1743: // do nothing only move through all rows because of mssql odbc driver
1744: }
1745: } else {
1746: throw new CmsDbConsistencyException(
1747: Messages
1748: .get()
1749: .container(
1750: Messages.ERR_NO_PROPERTIES_FOR_PROPERTYDEF_1,
1751: metadef.getName()));
1752: }
1753: } catch (SQLException e) {
1754: throw new CmsDbSqlException(Messages.get().container(
1755: Messages.ERR_GENERIC_SQL_1,
1756: CmsDbSqlException.getErrorQuery(stmt)), e);
1757: } finally {
1758: m_sqlManager.closeAll(dbc, conn, stmt, res);
1759: }
1760: return returnValue;
1761: }
1762:
1763: /**
1764: * Creates a historical project from the given result set and resources.<p>
1765: * @param res the resource set
1766: * @param resources the historical resources
1767: *
1768: * @return the historical project
1769: *
1770: * @throws SQLException if something goes wrong
1771: */
1772: protected CmsHistoryProject internalCreateProject(ResultSet res,
1773: List resources) throws SQLException {
1774:
1775: String ou = CmsOrganizationalUnit.removeLeadingSeparator(res
1776: .getString(m_sqlManager
1777: .readQuery("C_PROJECTS_PROJECT_OU_0")));
1778: CmsUUID publishedById = new CmsUUID(res.getString(m_sqlManager
1779: .readQuery("C_PROJECT_PUBLISHED_BY_0")));
1780: CmsUUID userId = new CmsUUID(res.getString(m_sqlManager
1781: .readQuery("C_PROJECTS_USER_ID_0")));
1782: return new CmsHistoryProject(
1783: res.getInt(m_sqlManager
1784: .readQuery("C_PROJECTS_PUBLISH_TAG_0")),
1785: new CmsUUID(res.getString(m_sqlManager
1786: .readQuery("C_PROJECTS_PROJECT_ID_0"))),
1787: ou
1788: + res
1789: .getString(m_sqlManager
1790: .readQuery("C_PROJECTS_PROJECT_NAME_0")),
1791: res.getString(m_sqlManager
1792: .readQuery("C_PROJECTS_PROJECT_DESCRIPTION_0")),
1793: userId,
1794: new CmsUUID(res.getString(m_sqlManager
1795: .readQuery("C_PROJECTS_GROUP_ID_0"))),
1796: new CmsUUID(res.getString(m_sqlManager
1797: .readQuery("C_PROJECTS_MANAGERGROUP_ID_0"))),
1798: res.getLong(m_sqlManager
1799: .readQuery("C_PROJECTS_DATE_CREATED_0")),
1800: CmsProject.CmsProjectType
1801: .valueOf(res
1802: .getInt(m_sqlManager
1803: .readQuery("C_PROJECTS_PROJECT_TYPE_0"))),
1804: res.getLong(m_sqlManager
1805: .readQuery("C_PROJECT_PUBLISHDATE_0")),
1806: publishedById, resources);
1807: }
1808:
1809: /**
1810: * Creates a valid {@link I_CmsHistoryResource} instance from a JDBC ResultSet.<p>
1811: *
1812: * @param res the JDBC result set
1813: *
1814: * @return the new historical resource instance
1815: *
1816: * @throws SQLException if a requested attribute was not found in the result set
1817: */
1818: protected I_CmsHistoryResource internalCreateResource(ResultSet res)
1819: throws SQLException {
1820:
1821: int resourceVersion = res.getInt(m_sqlManager
1822: .readQuery("C_RESOURCES_VERSION"));
1823: int structureVersion = res.getInt(m_sqlManager
1824: .readQuery("C_RESOURCES_STRUCTURE_VERSION"));
1825: int tagId = res.getInt(m_sqlManager
1826: .readQuery("C_RESOURCES_PUBLISH_TAG"));
1827: CmsUUID structureId = new CmsUUID(res.getString(m_sqlManager
1828: .readQuery("C_RESOURCES_STRUCTURE_ID")));
1829: CmsUUID resourceId = new CmsUUID(res.getString(m_sqlManager
1830: .readQuery("C_RESOURCES_RESOURCE_ID")));
1831: String resourcePath = res.getString(m_sqlManager
1832: .readQuery("C_RESOURCES_RESOURCE_PATH"));
1833: int resourceType = res.getInt(m_sqlManager
1834: .readQuery("C_RESOURCES_RESOURCE_TYPE"));
1835: int resourceFlags = res.getInt(m_sqlManager
1836: .readQuery("C_RESOURCES_RESOURCE_FLAGS"));
1837: CmsUUID projectLastModified = new CmsUUID(res
1838: .getString(m_sqlManager
1839: .readQuery("C_RESOURCES_PROJECT_LASTMODIFIED")));
1840: int state = Math.max(res.getInt(m_sqlManager
1841: .readQuery("C_RESOURCES_STATE")), res
1842: .getInt(m_sqlManager
1843: .readQuery("C_RESOURCES_STRUCTURE_STATE")));
1844: long dateCreated = res.getLong(m_sqlManager
1845: .readQuery("C_RESOURCES_DATE_CREATED"));
1846: long dateLastModified = res.getLong(m_sqlManager
1847: .readQuery("C_RESOURCES_DATE_LASTMODIFIED"));
1848: long dateReleased = res.getLong(m_sqlManager
1849: .readQuery("C_RESOURCES_DATE_RELEASED"));
1850: long dateExpired = res.getLong(m_sqlManager
1851: .readQuery("C_RESOURCES_DATE_EXPIRED"));
1852: int resourceSize = res.getInt(m_sqlManager
1853: .readQuery("C_RESOURCES_SIZE"));
1854: CmsUUID userLastModified = new CmsUUID(res
1855: .getString(m_sqlManager
1856: .readQuery("C_RESOURCES_USER_LASTMODIFIED")));
1857: CmsUUID userCreated = new CmsUUID(res.getString(m_sqlManager
1858: .readQuery("C_RESOURCES_USER_CREATED")));
1859: CmsUUID parentId = new CmsUUID(res.getString(m_sqlManager
1860: .readQuery("C_RESOURCES_HISTORY_PARENTID")));
1861: long dateContent = res.getLong(m_sqlManager
1862: .readQuery("C_RESOURCES_DATE_CONTENT"));
1863:
1864: boolean isFolder = resourcePath.endsWith("/");
1865: if (isFolder) {
1866: return new CmsHistoryFolder(tagId, structureId, resourceId,
1867: resourcePath, resourceType, resourceFlags,
1868: projectLastModified, CmsResourceState
1869: .valueOf(state), dateCreated, userCreated,
1870: dateLastModified, userLastModified, dateReleased,
1871: dateExpired, resourceVersion + structureVersion,
1872: parentId, resourceVersion, structureVersion);
1873: } else {
1874: return new CmsHistoryFile(tagId, structureId, resourceId,
1875: resourcePath, resourceType, resourceFlags,
1876: projectLastModified, CmsResourceState
1877: .valueOf(state), dateCreated, userCreated,
1878: dateLastModified, userLastModified, dateReleased,
1879: dateExpired, resourceSize, dateContent,
1880: resourceVersion + structureVersion, parentId, null,
1881: resourceVersion, structureVersion);
1882: }
1883: }
1884:
1885: /**
1886: * Filters all resources in the subtree of the folder identified by the given id.<p>
1887: *
1888: * @param parentId the id of the folder to filter
1889: * @param resources the resources to filter
1890: *
1891: * @return the filtered list of resource
1892: */
1893: protected List internalFilterParentId(CmsUUID parentId,
1894: List resources) {
1895:
1896: List result = new ArrayList();
1897:
1898: // filter the parent id
1899: Set ids = new HashSet();
1900: ids.add(parentId);
1901:
1902: boolean modified = true;
1903: while (modified) {
1904: modified = false;
1905: Iterator it = resources.iterator();
1906: while (it.hasNext()) {
1907: I_CmsHistoryResource resource = (I_CmsHistoryResource) it
1908: .next();
1909: if (ids.contains(resource.getParentId())) {
1910: ids.add(resource.getStructureId());
1911: result.add(resource);
1912: modified = true;
1913: it.remove();
1914: }
1915: }
1916: }
1917: return result;
1918: }
1919:
1920: /**
1921: * Merges an historical entry for a sibling, based on the structure data from the given historical resource
1922: * and result set for the resource entry.<p>
1923: *
1924: * @param histRes the original historical entry
1925: * @param res the result set of the resource entry
1926: * @param versionOffset the offset for the structure version
1927: *
1928: * @return a merged historical entry for the sibling
1929: *
1930: * @throws SQLException if something goes wrong
1931: */
1932: protected I_CmsHistoryResource internalMergeResource(
1933: I_CmsHistoryResource histRes, ResultSet res,
1934: int versionOffset) throws SQLException {
1935:
1936: int resourceVersion = res.getInt(m_sqlManager
1937: .readQuery("C_RESOURCES_VERSION"));
1938: int structureVersion = histRes.getStructureVersion()
1939: - versionOffset;
1940: int tagId = res.getInt(m_sqlManager
1941: .readQuery("C_RESOURCES_PUBLISH_TAG"));
1942: CmsUUID structureId = histRes.getStructureId();
1943: CmsUUID resourceId = new CmsUUID(res.getString(m_sqlManager
1944: .readQuery("C_RESOURCES_RESOURCE_ID")));
1945: int resourceType = res.getInt(m_sqlManager
1946: .readQuery("C_RESOURCES_RESOURCE_TYPE"));
1947: int resourceFlags = res.getInt(m_sqlManager
1948: .readQuery("C_RESOURCES_RESOURCE_FLAGS"));
1949: CmsUUID projectLastModified = new CmsUUID(res
1950: .getString(m_sqlManager
1951: .readQuery("C_RESOURCES_PROJECT_LASTMODIFIED")));
1952: int state = histRes.getState().getState(); // may be we have to compute something here?
1953: long dateCreated = res.getLong(m_sqlManager
1954: .readQuery("C_RESOURCES_DATE_CREATED"));
1955: long dateLastModified = res.getLong(m_sqlManager
1956: .readQuery("C_RESOURCES_DATE_LASTMODIFIED"));
1957: long dateReleased = histRes.getDateReleased();
1958: long dateExpired = histRes.getDateExpired();
1959: int resourceSize = res.getInt(m_sqlManager
1960: .readQuery("C_RESOURCES_SIZE"));
1961: CmsUUID userLastModified = new CmsUUID(res
1962: .getString(m_sqlManager
1963: .readQuery("C_RESOURCES_USER_LASTMODIFIED")));
1964: CmsUUID userCreated = new CmsUUID(res.getString(m_sqlManager
1965: .readQuery("C_RESOURCES_USER_CREATED")));
1966: // here we could use the path/parent id for the sibling where the modification really occurred
1967: String resourcePath = histRes.getRootPath();
1968: CmsUUID parentId = histRes.getParentId();
1969: long dateContent = res.getLong(m_sqlManager
1970: .readQuery("C_RESOURCES_DATE_CONTENT"));
1971:
1972: if (histRes.isFolder()) {
1973: return new CmsHistoryFolder(tagId, structureId, resourceId,
1974: resourcePath, resourceType, resourceFlags,
1975: projectLastModified, CmsResourceState
1976: .valueOf(state), dateCreated, userCreated,
1977: dateLastModified, userLastModified, dateReleased,
1978: dateExpired, resourceVersion + structureVersion,
1979: parentId, resourceVersion, structureVersion);
1980: } else {
1981: return new CmsHistoryFile(tagId, structureId, resourceId,
1982: resourcePath, resourceType, resourceFlags,
1983: projectLastModified, CmsResourceState
1984: .valueOf(state), dateCreated, userCreated,
1985: dateLastModified, userLastModified, dateReleased,
1986: dateExpired, resourceSize, dateContent,
1987: resourceVersion + structureVersion, parentId, null,
1988: resourceVersion, structureVersion);
1989: }
1990: }
1991:
1992: /**
1993: * Tests if a history resource does exist.<p>
1994: *
1995: * @param dbc the current database context
1996: * @param resource the resource to test
1997: * @param publishTag the publish tag of the resource to test
1998: *
1999: * @return <code>true</code> if the resource already exists, <code>false</code> otherwise
2000: *
2001: * @throws CmsDataAccessException if something goes wrong
2002: */
2003: protected boolean internalValidateResource(CmsDbContext dbc,
2004: CmsResource resource, int publishTag)
2005: throws CmsDataAccessException {
2006:
2007: Connection conn = null;
2008: PreparedStatement stmt = null;
2009: ResultSet res = null;
2010: boolean exists = false;
2011:
2012: try {
2013: conn = m_sqlManager.getConnection(dbc);
2014: stmt = m_sqlManager.getPreparedStatement(conn,
2015: "C_HISTORY_EXISTS_RESOURCE");
2016: stmt.setString(1, resource.getResourceId().toString());
2017: stmt.setInt(2, publishTag);
2018: res = stmt.executeQuery();
2019:
2020: exists = res.next();
2021: } catch (SQLException e) {
2022: throw new CmsDbSqlException(Messages.get().container(
2023: Messages.ERR_GENERIC_SQL_1,
2024: CmsDbSqlException.getErrorQuery(stmt)), e);
2025: } finally {
2026: m_sqlManager.closeAll(dbc, conn, stmt, res);
2027: }
2028: return exists;
2029: }
2030: }
|