/* * This library is part of OpenCms - * the Open Source Content Management System * * Copyright (c) Alkacon Software GmbH (http://www.alkacon.com) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * For further information about Alkacon Software, 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.jpa; 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.db.jpa.persistence.CmsDAOContents; import org.opencms.db.jpa.persistence.CmsDAOHistoryPrincipals; import org.opencms.db.jpa.persistence.CmsDAOHistoryProjectResources; import org.opencms.db.jpa.persistence.CmsDAOHistoryProjects; import org.opencms.db.jpa.persistence.CmsDAOHistoryProperties; import org.opencms.db.jpa.persistence.CmsDAOHistoryPropertyDef; import org.opencms.db.jpa.persistence.CmsDAOHistoryResources; import org.opencms.db.jpa.persistence.CmsDAOHistoryStructure; 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.CmsPropertyDefinition.CmsPropertyType; 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.CmsDataTypeUtil; import org.opencms.util.CmsStringUtil; import org.opencms.util.CmsUUID; 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 javax.persistence.NoResultException; import javax.persistence.PersistenceException; import javax.persistence.Query; import org.apache.commons.logging.Log; /** * JPA database server implementation of the history driver methods.<p> * * @since 8.0.0 */ public class CmsHistoryDriver implements I_CmsDriver, I_CmsHistoryDriver { /** Query key. */ private static final String C_CONTENT_HISTORY_DELETE = "C_CONTENT_HISTORY_DELETE"; /** Query key. */ private static final String C_CONTENT_PUBLISH_MAXTAG = "C_CONTENT_PUBLISH_MAXTAG"; /** Query key. */ private static final String C_FILES_READ_HISTORY_BYID = "C_FILES_READ_HISTORY_BYID"; /** Query key. */ private static final String C_HISTORY_EXISTS_RESOURCE = "C_HISTORY_EXISTS_RESOURCE"; /** Query key. */ private static final String C_HISTORY_PRINCIPAL_READ = "C_HISTORY_PRINCIPAL_READ"; /** Query key. */ private static final String C_HISTORY_READ_CONTENT = "C_HISTORY_READ_CONTENT"; /** Query key. */ private static final String C_HISTORY_READ_MAXTAG_FOR_VERSION = "C_HISTORY_READ_MAXTAG_FOR_VERSION"; /** Query key. */ private static final String C_HISTORY_READ_MIN_USED_TAG = "C_HISTORY_READ_MIN_USED_TAG"; /** Query key. */ private static final String C_PROJECTRESOURCES_HISTORY_READ = "C_PROJECTRESOURCES_HISTORY_READ"; /** Query key. */ private static final String C_PROJECTS_HISTORY_MAXTAG = "C_PROJECTS_HISTORY_MAXTAG"; /** Query key. */ private static final String C_PROJECTS_HISTORY_READ = "C_PROJECTS_HISTORY_READ"; /** Query key. */ private static final String C_PROJECTS_HISTORY_READ_ALL = "C_PROJECTS_HISTORY_READ_ALL"; /** Query key. */ private static final String C_PROJECTS_HISTORY_READ_BYID = "C_PROJECTS_HISTORY_READ_BYID"; /** Query key. */ private static final String C_PROJECTS_HISTORY_READ_TAG_FOR_DATE = "C_PROJECTS_HISTORY_READ_TAG_FOR_DATE"; /** Query key. */ private static final String C_PROPERTIES_HISTORY_DELETE = "C_PROPERTIES_HISTORY_DELETE"; /** Query key. */ private static final String C_PROPERTIES_HISTORY_READ_PUBTAG = "C_PROPERTIES_HISTORY_READ_PUBTAG"; /** Query key. */ private static final String C_PROPERTIES_HISTORY_READALL_RES = "C_PROPERTIES_HISTORY_READALL_RES"; /** Query key. */ private static final String C_PROPERTIES_HISTORY_READALL_STR = "C_PROPERTIES_HISTORY_READALL_STR"; /** Query key. */ private static final String C_PROPERTIES_READALL_COUNT = "C_PROPERTIES_READALL_COUNT"; /** Query key. */ private static final String C_PROPERTYDEF_DELETE_HISTORY = "C_PROPERTYDEF_DELETE_HISTORY"; /** Query key. */ private static final String C_PROPERTYDEF_READ_HISTORY = "C_PROPERTYDEF_READ_HISTORY"; /** Query key. */ private static final String C_RESOURCES_HISTORY_DELETE = "C_RESOURCES_HISTORY_DELETE"; /** Query key. */ private static final String C_RESOURCES_HISTORY_MAXTAG = "C_RESOURCES_HISTORY_MAXTAG"; /** Query key. */ private static final String C_RESOURCES_HISTORY_READ_ALL_VERSIONS = "C_RESOURCES_HISTORY_READ_ALL_VERSIONS"; /** Query key. */ private static final String C_RESOURCES_HISTORY_READ_BTW_VERSIONS = "C_RESOURCES_HISTORY_READ_BTW_VERSIONS"; /** Query key. */ private static final String C_RESOURCES_HISTORY_READ_DELETED = "C_RESOURCES_HISTORY_READ_DELETED"; /** Query key. */ private static final String C_RESOURCES_HISTORY_READ_DELETED_NAME = "C_RESOURCES_HISTORY_READ_DELETED_NAME"; /** Query key. */ private static final String C_RESOURCES_HISTORY_READ_DELETED_NAME_RESTRICTED = "C_RESOURCES_HISTORY_READ_DELETED_NAME_RESTRICTED"; /** Query key. */ private static final String C_RESOURCES_HISTORY_READ_DELETED_RESTRICTED = "C_RESOURCES_HISTORY_READ_DELETED_RESTRICTED"; /** Query key. */ private static final String C_RESOURCES_HISTORY_READ_NEW_VERSIONS = "C_RESOURCES_HISTORY_READ_NEW_VERSIONS"; /** Query key. */ private static final String C_RESOURCES_HISTORY_READ_OLD_VERSIONS = "C_RESOURCES_HISTORY_READ_OLD_VERSIONS"; /** Query key. */ private static final String C_RESOURCES_HISTORY_READ_VERSION = "C_RESOURCES_HISTORY_READ_VERSION"; /** Query key. */ private static final String C_RESOURCES_READ_MAX_PUBLISH_TAG = "C_RESOURCES_READ_MAX_PUBLISH_TAG"; /** Query key. */ private static final String C_STRUCTURE_HISTORY_DELETE = "C_STRUCTURE_HISTORY_DELETE"; /** Query key. */ private static final String C_STRUCTURE_HISTORY_MAXVER = "C_STRUCTURE_HISTORY_MAXVER"; /** Query key. */ private static final String C_STRUCTURE_HISTORY_MAXVER_BYTIME = "C_STRUCTURE_HISTORY_MAXVER_BYTIME"; /** Query key. */ private static final String C_STRUCTURE_HISTORY_READ_DELETED = "C_STRUCTURE_HISTORY_READ_DELETED"; /** Query key. */ private static final String C_STRUCTURE_HISTORY_READ_NOTDELETED = "C_STRUCTURE_HISTORY_READ_NOTDELETED"; /** Query key. */ private static final String C_STRUCTURE_HISTORY_READ_SUBRESOURCES = "C_STRUCTURE_HISTORY_READ_SUBRESOURCES"; /** The log object for this class. */ private static final Log LOG = CmsLog.getLog(org.opencms.db.jpa.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, CmsPropertyType type) throws CmsDataAccessException { try { CmsDAOHistoryPropertyDef chpd = new CmsDAOHistoryPropertyDef(); chpd.setPropertyDefId(new CmsUUID().toString()); chpd.setPropertyDefName(name); chpd.setPropertyDefType(type.getMode()); m_sqlManager.persist(dbc, chpd); } catch (PersistenceException e) { throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE), e); } return readPropertyDefinition(dbc, name); } /** * @see org.opencms.db.I_CmsHistoryDriver#deleteEntries(org.opencms.db.CmsDbContext, org.opencms.file.history.I_CmsHistoryResource, int, long) */ public int deleteEntries(CmsDbContext dbc, I_CmsHistoryResource resource, int versionsToKeep, long time) throws CmsDataAccessException { try { int maxVersion = -1; // get the maximal version number for this resource Query q = m_sqlManager.createQuery(dbc, C_STRUCTURE_HISTORY_MAXVER); q.setParameter(1, resource.getStructureId().toString()); try { maxVersion = CmsDataTypeUtil.numberToInt((Number)q.getSingleResult()); } catch (NoResultException e) { // nothing to delete internalCleanup(dbc, resource); return 0; } if (time >= 0) { int maxVersionByTime = -1; // get the maximal version to keep for this resource based on the time parameter q = m_sqlManager.createQuery(dbc, C_STRUCTURE_HISTORY_MAXVER_BYTIME); q.setParameter(1, resource.getStructureId().toString()); q.setParameter(2, Long.valueOf(time)); try { maxVersionByTime = CmsDataTypeUtil.numberToInt((Number)q.getSingleResult()); } catch (NoResultException e) { // do nothing } if (maxVersionByTime > 0) { if (versionsToKeep < 0) { versionsToKeep = (maxVersion - maxVersionByTime); } else { versionsToKeep = Math.min(versionsToKeep, (maxVersion - maxVersionByTime)); } } } if ((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; q = m_sqlManager.createQuery(dbc, C_HISTORY_READ_MAXTAG_FOR_VERSION); q.setParameter(1, resource.getStructureId().toString()); q.setParameter(2, Integer.valueOf((1 + maxVersion) - versionsToKeep)); try { minStrPublishTagToKeep = CmsDataTypeUtil.numberToInt((Number)q.getSingleResult()); } catch (NoResultException e) { // nothing to delete internalCleanup(dbc, resource); return 0; } if (minStrPublishTagToKeep < 1) { // nothing to delete internalCleanup(dbc, resource); return 0; } minStrPublishTagToKeep++; // delete the properties q = m_sqlManager.createQuery(dbc, C_PROPERTIES_HISTORY_DELETE); q.setParameter(1, resource.getStructureId().toString()); q.setParameter(2, Integer.valueOf(minStrPublishTagToKeep)); @SuppressWarnings("unchecked") List<CmsDAOHistoryProperties> hisProps = q.getResultList(); for (CmsDAOHistoryProperties hp : hisProps) { m_sqlManager.remove(dbc, hp); } // delete the structure entries q = m_sqlManager.createQuery(dbc, C_STRUCTURE_HISTORY_DELETE); q.setParameter(1, resource.getStructureId().toString()); q.setParameter(2, Integer.valueOf(minStrPublishTagToKeep)); @SuppressWarnings("unchecked") List<CmsDAOHistoryStructure> structureEntries = q.getResultList(); int structureVersions = 0; for (CmsDAOHistoryStructure hs : structureEntries) { m_sqlManager.remove(dbc, hs); structureVersions++; } // get the minimal resource publish tag to keep, // all entries with publish tag less than this will be deleted int minResPublishTagToKeep = -1; q = m_sqlManager.createQuery(dbc, C_HISTORY_READ_MIN_USED_TAG); q.setParameter(1, resource.getResourceId().toString()); try { Object numObj = q.getSingleResult(); if (numObj == null) { minResPublishTagToKeep = Integer.MAX_VALUE; } else { minResPublishTagToKeep = CmsDataTypeUtil.numberToInt((Number)numObj); } } catch (NoResultException e) { internalCleanup(dbc, resource); return structureVersions; } // delete the resource entries q = m_sqlManager.createQuery(dbc, C_RESOURCES_HISTORY_DELETE); q.setParameter(1, resource.getResourceId().toString()); q.setParameter(2, Integer.valueOf(minResPublishTagToKeep)); int resourceVersions = 0; @SuppressWarnings("unchecked") List<CmsDAOHistoryResources> resourceEntries = q.getResultList(); for (CmsDAOHistoryResources hr : resourceEntries) { m_sqlManager.remove(dbc, hr); resourceVersions++; } // delete the content entries q = m_sqlManager.createQuery(dbc, C_CONTENT_HISTORY_DELETE); q.setParameter(1, resource.getResourceId().toString()); q.setParameter(2, Integer.valueOf(minResPublishTagToKeep)); @SuppressWarnings("unchecked") List<CmsDAOContents> contentEntries = q.getResultList(); for (CmsDAOContents c : contentEntries) { m_sqlManager.remove(dbc, c); } internalCleanup(dbc, resource); return Math.max(structureVersions, resourceVersions); } catch (PersistenceException e) { throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE), e); } } /** * @see org.opencms.db.I_CmsHistoryDriver#deletePropertyDefinition(org.opencms.db.CmsDbContext, org.opencms.file.CmsPropertyDefinition) */ public void deletePropertyDefinition(CmsDbContext dbc, CmsPropertyDefinition metadef) throws CmsDataAccessException { 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 Query q = m_sqlManager.createQuery(dbc, C_PROPERTYDEF_DELETE_HISTORY); q.setParameter(1, metadef.getId().toString()); @SuppressWarnings("unchecked") List<CmsDAOHistoryPropertyDef> res = q.getResultList(); for (CmsDAOHistoryPropertyDef hpd : res) { m_sqlManager.remove(dbc, hpd); } } catch (PersistenceException e) { throw new CmsDataAccessException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, Messages.ERR_JPA_PERSITENCE), e); } } /** * @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<I_CmsHistoryResource> getAllDeletedEntries(CmsDbContext dbc) throws CmsDataAccessException { Query q = null; List<I_CmsHistoryResource> entries = new ArrayList<I_CmsHistoryResource>(); try { // get all not-deleted historical entries that may come in question q = m_sqlManager.createQuery(dbc, C_STRUCTURE_HISTORY_READ_DELETED); @SuppressWarnings("unchecked") List<Object[]> res = q.getResultList(); for (Object[] obj : res) { CmsUUID structureId = new CmsUUID((String)obj[0]); int version = CmsDataTypeUtil.numberToInt((Integer)obj[1]); entries.add(readResource(dbc, structureId, version)); } } catch (PersistenceException e) { throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e); } return entries; } /** * @see org.opencms.db.I_CmsHistoryDriver#getAllNotDeletedEntries(CmsDbContext) */ public List<I_CmsHistoryResource> getAllNotDeletedEntries(CmsDbContext dbc) throws CmsDataAccessException { List<I_CmsHistoryResource> entries = new ArrayList<I_CmsHistoryResource>(); try { // get all not-deleted historical entries that may come in question Query q = m_sqlManager.createQuery(dbc, C_STRUCTURE_HISTORY_READ_NOTDELETED); @SuppressWarnings("unchecked") List<Object[]> res = q.getResultList(); for (Object[] o : res) { CmsUUID structureId = new CmsUUID((String)o[0]); int version = CmsDataTypeUtil.numberToInt((Number)o[1]); entries.add(readResource(dbc, structureId, version)); } } catch (PersistenceException e) { throw new CmsDbSqlException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e); } return entries; } /** * @see org.opencms.db.I_CmsHistoryDriver#getSqlManager() */ public org.opencms.db.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<String> successiveDrivers, CmsDriverManager driverManager) { CmsParameterConfiguration config = configurationManager.getConfiguration(); String poolUrl = config.get("db.history.pool"); String classname = config.get("db.history.sqlmanager"); m_sqlManager = initSqlManager(classname); 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(java.lang.String) */ public CmsSqlManager initSqlManager(String classname) { return CmsSqlManager.getInstance(classname); } /** * @see org.opencms.db.I_CmsHistoryDriver#readAllAvailableVersions(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID) */ public List<I_CmsHistoryResource> readAllAvailableVersions(CmsDbContext dbc, CmsUUID structureId) throws CmsDataAccessException { List<I_CmsHistoryResource> result = new ArrayList<I_CmsHistoryResource>(); Query q = null; try { // get all direct versions (where the structure entry has been written) // sorted from the NEWEST to the OLDEST version (publish tag descendant) List<I_CmsHistoryResource> historyResources = new ArrayList<I_CmsHistoryResource>(); q = m_sqlManager.createQuery(dbc, C_RESOURCES_HISTORY_READ_ALL_VERSIONS); q.setParameter(1, structureId.toString()); @SuppressWarnings("unchecked") List<Object[]> res = q.getResultList(); for (Object[] o : res) { historyResources.add(internalCreateResource(o)); } res = null; 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 q = m_sqlManager.createQuery(dbc, C_RESOURCES_HISTORY_READ_NEW_VERSIONS); q.setParameter(1, histRes.getResourceId().toString()); q.setParameter(2, Integer.valueOf(histRes.getPublishTag())); @SuppressWarnings("unchecked") List<CmsDAOHistoryResources> lResources = q.getResultList(); I_CmsHistoryResource lastHistRes = histRes; // these are sorted from the oldest to the newest version (publish tag ascendent) for (CmsDAOHistoryResources hr : lResources) { int resVersion = hr.getResourceVersion(); if (resVersion == lastHistRes.getResourceVersion()) { // skip not interesting versions continue; } I_CmsHistoryResource newHistRes = internalMergeResource(histRes, hr, 0); // add interesting versions, in the right order result.add(0, newHistRes); lastHistRes = newHistRes; } } // 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 q = m_sqlManager.createQuery(dbc, C_RESOURCES_HISTORY_READ_BTW_VERSIONS); q.setParameter(1, histRes.getResourceId().toString()); q.setParameter(2, Integer.valueOf(histRes2.getPublishTag())); // lower limit q.setParameter(3, Integer.valueOf(histRes.getPublishTag())); // upper limit @SuppressWarnings("unchecked") List<CmsDAOHistoryResources> lResources = q.getResultList(); int pos = result.size(); I_CmsHistoryResource lastHistRes = histRes2; for (CmsDAOHistoryResources hr : lResources) { int resVersion = hr.getResourceVersion(); if (resVersion == lastHistRes.getResourceVersion()) { // skip not interesting versions continue; } I_CmsHistoryResource newHistRes = internalMergeResource(histRes2, hr, 0); // add interesting versions, in the right order result.add(pos, newHistRes); lastHistRes = newHistRes; } lResources = null; } } 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 q = m_sqlManager.createQuery(dbc, C_RESOURCES_HISTORY_READ_OLD_VERSIONS); q.setParameter(1, String.valueOf(histRes.getResourceId())); q.setParameter(2, Integer.valueOf(histRes.getPublishTag())); @SuppressWarnings("unchecked") List<CmsDAOHistoryResources> lResources = q.getResultList(); int offset = (histRes.getStructureVersion() > 0 ? 1 : 0); I_CmsHistoryResource lastHistRes = histRes; for (CmsDAOHistoryResources hr : lResources) { I_CmsHistoryResource newHistRes = internalMergeResource(histRes, hr, 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); } } } } catch (PersistenceException e) { throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e); } 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 { byte[] content = null; try { Query q = m_sqlManager.createQuery(dbc, C_HISTORY_READ_CONTENT); q.setParameter(1, resourceId.toString()); q.setParameter(2, Integer.valueOf(publishTag)); q.setParameter(3, Integer.valueOf(publishTag)); try { content = ((CmsDAOContents)q.getSingleResult()).getFileContent(); } catch (NoResultException e) { // do nothing } } catch (PersistenceException e) { throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e); } return content; } /** * @see org.opencms.db.I_CmsHistoryDriver#readDeletedResources(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID, org.opencms.util.CmsUUID) */ public List<I_CmsHistoryResource> readDeletedResources(CmsDbContext dbc, CmsUUID structureId, CmsUUID userId) throws CmsDataAccessException { List<I_CmsHistoryResource> result = new ArrayList<I_CmsHistoryResource>(); Query q = null; I_CmsVfsDriver vfsDriver = m_driverManager.getVfsDriver(dbc); try { if (userId == null) { q = m_sqlManager.createQuery(dbc, C_RESOURCES_HISTORY_READ_DELETED); } else { q = m_sqlManager.createQuery(dbc, C_RESOURCES_HISTORY_READ_DELETED_RESTRICTED); } q.setParameter(1, structureId.toString()); if (userId != null) { q.setParameter(2, userId.toString()); } @SuppressWarnings("unchecked") List<Object[]> res = q.getResultList(); for (Object[] o : res) { I_CmsHistoryResource histRes = internalCreateResource(o); if (vfsDriver.validateStructureIdExists(dbc, dbc.currentProject().getUuid(), histRes.getStructureId())) { // only add resources that are really deleted continue; } result.add(histRes); } } catch (PersistenceException e) { throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e); } if (!result.isEmpty() || (dbc.getRequestContext() == null) || (dbc.getRequestContext().getAttribute("ATTR_RESOURCE_NAME") == null)) { return result; } try { if (userId == null) { q = m_sqlManager.createQuery(dbc, C_RESOURCES_HISTORY_READ_DELETED_NAME); } else { q = m_sqlManager.createQuery(dbc, C_RESOURCES_HISTORY_READ_DELETED_NAME_RESTRICTED); } String path = dbc.getRequestContext().getAttribute("ATTR_RESOURCE_NAME").toString(); q.setParameter(1, CmsVfsDriver.escapeDbWildcard(path + '%')); q.setParameter(2, path); if (userId != null) { q.setParameter(3, userId.toString()); } @SuppressWarnings("unchecked") List<Object[]> res = q.getResultList(); for (Object[] o : res) { I_CmsHistoryResource histRes = internalCreateResource(o); if (vfsDriver.validateStructureIdExists(dbc, dbc.currentProject().getUuid(), histRes.getStructureId())) { // only add resources that are really deleted continue; } result.add(histRes); } } catch (PersistenceException e) { throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e); } return result; } /** * Possibly there is no need for this method.<p> * * TODO: check if this method is used somewhere * TODO: remove this method * * @param dbc the db context * @param structureId the structure id * @param tagId the tag id * * @return the historical resource * * @throws CmsDataAccessException if something goes wrong */ @Deprecated public I_CmsHistoryResource readFile(CmsDbContext dbc, CmsUUID structureId, int tagId) throws CmsDataAccessException { I_CmsHistoryResource file = null; try { Query q = m_sqlManager.createQuery(dbc, C_FILES_READ_HISTORY_BYID); q.setParameter(1, structureId.toString()); q.setParameter(2, Integer.valueOf(tagId)); Object[] res = (Object[])q.getSingleResult(); file = internalCreateResource(res); } catch (NoResultException e) { throw new CmsVfsResourceNotFoundException(Messages.get().container( Messages.ERR_HISTORY_FILE_NOT_FOUND_1, structureId)); } catch (PersistenceException e) { throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e); } ((CmsFile)file).setContents(readContent(dbc, file.getResourceId(), file.getPublishTag())); return file; } /** * @see org.opencms.db.I_CmsHistoryDriver#readLastVersion(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID) */ public int readLastVersion(CmsDbContext dbc, CmsUUID structureId) throws CmsDataAccessException { int lastVersion = 0; try { Query q = m_sqlManager.createQuery(dbc, C_STRUCTURE_HISTORY_MAXVER); q.setParameter(1, structureId.toString()); try { lastVersion = CmsDataTypeUtil.numberToInt((Number)q.getSingleResult()); } catch (NoResultException e) { // do nothing } catch (NullPointerException e) { lastVersion = 0; } } catch (PersistenceException e) { throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e); } return lastVersion; } /** * @see org.opencms.db.I_CmsHistoryDriver#readMaxPublishTag(CmsDbContext, CmsUUID) */ public int readMaxPublishTag(CmsDbContext dbc, CmsUUID resourceId) throws CmsDataAccessException { int result = 0; try { Query q = m_sqlManager.createQuery(dbc, C_RESOURCES_READ_MAX_PUBLISH_TAG); q.setParameter(1, resourceId.toString()); try { result = CmsDataTypeUtil.numberToInt((Number)q.getSingleResult()); } catch (NoResultException e) { // do nothing } } catch (PersistenceException e) { throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e); } return result; } /** * @see org.opencms.db.I_CmsHistoryDriver#readNextPublishTag(org.opencms.db.CmsDbContext) */ public int readNextPublishTag(CmsDbContext dbc) { int projectPublishTag = 1; int resourcePublishTag = 1; Query q; try { // get the max publish tag from project history q = m_sqlManager.createQuery(dbc, C_PROJECTS_HISTORY_MAXTAG); try { projectPublishTag = CmsDataTypeUtil.numberToInt((Number)q.getSingleResult()) + 1; } catch (NoResultException e) { // do nothing } } catch (PersistenceException e) { LOG.error(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e); } try { // get the max publish tag from resource history q = m_sqlManager.createQuery(dbc, C_RESOURCES_HISTORY_MAXTAG); try { resourcePublishTag = CmsDataTypeUtil.numberToInt((Number)q.getSingleResult()) + 1; } catch (NoResultException e) { // do nothing } } catch (PersistenceException e) { LOG.error(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e); } // keep the biggest if (resourcePublishTag > projectPublishTag) { projectPublishTag = resourcePublishTag; } try { // get the max publish tag from contents q = m_sqlManager.createQuery(dbc, C_CONTENT_PUBLISH_MAXTAG); try { resourcePublishTag = CmsDataTypeUtil.numberToInt((Number)q.getSingleResult()) + 1; } catch (NoResultException e) { // do nothing } } catch (PersistenceException e) { // do nothing } // 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 { CmsHistoryPrincipal historyPrincipal = null; try { Query q = m_sqlManager.createQuery(dbc, C_HISTORY_PRINCIPAL_READ); q.setParameter(1, principalId.toString()); try { CmsDAOHistoryPrincipals hp = (CmsDAOHistoryPrincipals)q.getSingleResult(); String userName = hp.getPrincipalName(); String ou = CmsOrganizationalUnit.removeLeadingSeparator(hp.getPrincipalOu()); historyPrincipal = new CmsHistoryPrincipal( principalId, ou + userName, hp.getPrincipalDescription(), hp.getPrincipalEmail(), hp.getPrincipalType(), new CmsUUID(hp.getPrincipalUserDeleted()), hp.getPrincipalDateDeleted()); } catch (NoResultException e) { throw new CmsDbEntryNotFoundException(Messages.get().container( Messages.ERR_HISTORY_PRINCIPAL_NOT_FOUND_1, principalId)); } } catch (PersistenceException e) { throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e); } return historyPrincipal; } /** * @see org.opencms.db.I_CmsHistoryDriver#readProject(org.opencms.db.CmsDbContext, CmsUUID) */ public CmsHistoryProject readProject(CmsDbContext dbc, CmsUUID projectId) throws CmsDataAccessException { CmsHistoryProject project = null; try { Query q = m_sqlManager.createQuery(dbc, C_PROJECTS_HISTORY_READ_BYID); q.setParameter(1, projectId.toString()); try { CmsDAOHistoryProjects hp = (CmsDAOHistoryProjects)q.getSingleResult(); int tag = hp.getPublishTag(); List<String> projectresources = readProjectResources(dbc, tag); project = internalCreateProject(hp, projectresources); } catch (NoResultException e) { throw new CmsDbEntryNotFoundException(Messages.get().container( Messages.ERR_NO_HISTORY_PROJECT_WITH_ID_1, projectId)); } } catch (PersistenceException e) { throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e); } return project; } /** * @see org.opencms.db.I_CmsHistoryDriver#readProject(org.opencms.db.CmsDbContext, int) */ public CmsHistoryProject readProject(CmsDbContext dbc, int publishTag) throws CmsDataAccessException { CmsHistoryProject project = null; try { Query q = m_sqlManager.createQuery(dbc, C_PROJECTS_HISTORY_READ); q.setParameter(1, Integer.valueOf(publishTag)); try { CmsDAOHistoryProjects hp = (CmsDAOHistoryProjects)q.getSingleResult(); List<String> projectresources = readProjectResources(dbc, publishTag); project = internalCreateProject(hp, projectresources); } catch (NoResultException e) { throw new CmsDbEntryNotFoundException(Messages.get().container( Messages.ERR_NO_HISTORY_PROJECT_WITH_TAG_ID_1, new Integer(publishTag))); } } catch (PersistenceException e) { throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e); } return project; } /** * @see org.opencms.db.I_CmsHistoryDriver#readProjectResources(org.opencms.db.CmsDbContext, int) */ public List<String> readProjectResources(CmsDbContext dbc, int publishTag) throws CmsDataAccessException { List<String> projectResources = new ArrayList<String>(); try { Query q = m_sqlManager.createQuery(dbc, C_PROJECTRESOURCES_HISTORY_READ); q.setParameter(1, Integer.valueOf(publishTag)); @SuppressWarnings("unchecked") List<String> res = q.getResultList(); for (String s : res) { projectResources.add(s); } } catch (PersistenceException e) { throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e); } return projectResources; } /** * @see org.opencms.db.I_CmsHistoryDriver#readProjects(org.opencms.db.CmsDbContext) */ public List<CmsHistoryProject> readProjects(CmsDbContext dbc) throws CmsDataAccessException { List<CmsHistoryProject> projects = new ArrayList<CmsHistoryProject>(); try { Query q = m_sqlManager.createQuery(dbc, C_PROJECTS_HISTORY_READ_ALL); q.setMaxResults(300); @SuppressWarnings("unchecked") List<CmsDAOHistoryProjects> res = q.getResultList(); for (CmsDAOHistoryProjects hp : res) { List<String> resources = readProjectResources(dbc, hp.getPublishTag()); projects.add(internalCreateProject(hp, resources)); } } catch (PersistenceException e) { throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e); } return (projects); } /** * @see org.opencms.db.I_CmsHistoryDriver#readProperties(org.opencms.db.CmsDbContext, org.opencms.file.history.I_CmsHistoryResource) */ public List<CmsProperty> readProperties(CmsDbContext dbc, I_CmsHistoryResource resource) throws CmsDataAccessException { Map<String, CmsProperty> propertyMap = new HashMap<String, CmsProperty>(); try { // get the latest properties for this sibling int pubTag = -1; Query q = m_sqlManager.createQuery(dbc, C_PROPERTIES_HISTORY_READ_PUBTAG); q.setParameter(1, String.valueOf(resource.getStructureId())); q.setParameter(2, Integer.valueOf(resource.getPublishTag())); try { pubTag = CmsDataTypeUtil.numberToInt((Number)q.getSingleResult()); } catch (NoResultException e) { // do nothing } if (pubTag > 0) { // add the siblings props q = m_sqlManager.createQuery(dbc, C_PROPERTIES_HISTORY_READALL_STR); q.setParameter(1, resource.getStructureId().toString()); q.setParameter(2, Integer.valueOf(pubTag)); @SuppressWarnings("unchecked") List<Object[]> res = q.getResultList(); for (Object[] o : res) { String propertyKey = (String)o[0]; String propertyValue = (String)o[1]; int mappingType = CmsDataTypeUtil.numberToInt((Number)o[2]); internalAddToPropMap(propertyMap, resource, propertyKey, propertyValue, mappingType); } } if (pubTag != resource.getPublishTag()) { // check if there were newer shared properties modifications q = m_sqlManager.createQuery(dbc, C_PROPERTIES_HISTORY_READALL_RES); q.setParameter(1, resource.getStructureId().toString()); q.setParameter(2, Integer.valueOf(resource.getPublishTag())); @SuppressWarnings("unchecked") List<Object[]> res = q.getResultList(); for (Object[] o : res) { String propertyKey = (String)o[0]; String propertyValue = (String)o[1]; int mappingType = CmsDataTypeUtil.numberToInt((Number)o[2]); internalAddToPropMap(propertyMap, resource, propertyKey, propertyValue, mappingType); } } } catch (PersistenceException e) { throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e); } return new ArrayList<CmsProperty>(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; try { Query q = m_sqlManager.createQuery(dbc, C_PROPERTYDEF_READ_HISTORY); q.setParameter(1, name); try { CmsDAOHistoryPropertyDef hpd = (CmsDAOHistoryPropertyDef)q.getSingleResult(); propDef = new CmsPropertyDefinition( new CmsUUID(hpd.getPropertyDefId()), hpd.getPropertyDefName(), CmsPropertyDefinition.CmsPropertyType.valueOf(hpd.getPropertyDefType())); } catch (NoResultException e) { throw new CmsDbEntryNotFoundException(Messages.get().container( Messages.ERR_NO_PROPERTYDEF_WITH_NAME_1, name)); } } catch (PersistenceException e) { throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e); } return propDef; } /** * @see org.opencms.db.I_CmsHistoryDriver#readPublishTag(org.opencms.db.CmsDbContext, long) */ public int readPublishTag(CmsDbContext dbc, long maxdate) throws CmsDataAccessException { int maxVersion = 0; try { Query q = m_sqlManager.createQuery(dbc, C_PROJECTS_HISTORY_READ_TAG_FOR_DATE); q.setParameter(1, Long.valueOf(maxdate)); try { maxVersion = CmsDataTypeUtil.numberToInt((Number)q.getSingleResult()); } catch (NoResultException e) { // do nothing } } catch (PersistenceException e) { throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e); } 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; try { Query q = m_sqlManager.createQuery(dbc, C_RESOURCES_HISTORY_READ_VERSION); q.setParameter(1, structureId.toString()); q.setParameter(2, Integer.valueOf(version)); try { resource = internalCreateResource((Object[])q.getSingleResult()); } catch (NoResultException e) { throw new CmsVfsResourceNotFoundException(Messages.get().container( Messages.ERR_HISTORY_FILE_NOT_FOUND_1, structureId)); } } catch (PersistenceException e) { throw new CmsDbSqlException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e); } 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 { try { // check if the principal was already saved readPrincipal(dbc, principal.getId()); return; } catch (CmsDbEntryNotFoundException e) { // ok } try { CmsDAOHistoryPrincipals hp = new CmsDAOHistoryPrincipals(); hp.setPrincipalId(principal.getId().toString()); hp.setPrincipalName(principal.getSimpleName()); String desc = principal.getDescription(); desc = CmsStringUtil.isEmptyOrWhitespaceOnly(desc) ? "-" : desc; hp.setPrincipalDescription(desc); hp.setPrincipalOu(CmsOrganizationalUnit.SEPARATOR + principal.getOuFqn()); if (principal instanceof CmsUser) { String email = ((CmsUser)principal).getEmail(); email = CmsStringUtil.isEmptyOrWhitespaceOnly(email) ? "-" : email; hp.setPrincipalEmail(email); hp.setPrincipalType(I_CmsPrincipal.PRINCIPAL_USER); } else { hp.setPrincipalEmail("-"); hp.setPrincipalType(I_CmsPrincipal.PRINCIPAL_GROUP); } hp.setPrincipalUserDeleted(dbc.currentUser().getId().toString()); hp.setPrincipalDateDeleted(System.currentTimeMillis()); m_sqlManager.persist(dbc, hp); } catch (PersistenceException e) { throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e); } } /** * @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<String> projectresources = m_driverManager.getProjectDriver(dbc).readProjectResources(dbc, currentProject); // write historical project to the database try { CmsDAOHistoryProjects hp = new CmsDAOHistoryProjects(); hp.setPublishTag(publishTag); hp.setProjectId(currentProject.getUuid().toString()); hp.setProjectName(currentProject.getSimpleName()); hp.setProjectPublishDate(publishDate); hp.setProjectPublishedBy(currentUser.getId().toString()); hp.setUserId(currentProject.getOwnerId().toString()); hp.setGroupId(currentProject.getGroupId().toString()); hp.setManagerGroupId(currentProject.getManagerGroupId().toString()); hp.setProjectDescription(currentProject.getDescription()); hp.setDateCreated(currentProject.getDateCreated()); hp.setProjectType(currentProject.getType().getMode()); hp.setProjectOu(CmsOrganizationalUnit.SEPARATOR + currentProject.getOuFqn()); m_sqlManager.persist(dbc, hp); // now write the projectresources CmsDAOHistoryProjectResources hpr; for (String projectResource : projectresources) { hpr = new CmsDAOHistoryProjectResources(); hpr.setPublishTag(publishTag); hpr.setProjectId(currentProject.getUuid().toString()); hpr.setResourcePath(projectResource); m_sqlManager.persist(dbc, hpr); } } catch (PersistenceException e) { throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e); } } /** * @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<CmsProperty> properties, int publishTag) throws CmsDataAccessException { CmsDAOHistoryProperties hp; try { Iterator<CmsProperty> dummy = properties.iterator(); while (dummy.hasNext()) { CmsProperty property = dummy.next(); CmsPropertyDefinition propDef = null; try { propDef = readPropertyDefinition(dbc, property.getName()); } catch (CmsDbEntryNotFoundException e) { // create if missing propDef = createPropertyDefinition(dbc, property.getName(), CmsPropertyDefinition.TYPE_NORMAL); } 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 = property.getStructureValue(); mappingType = CmsProperty.STRUCTURE_RECORD_MAPPING; id = resource.getStructureId(); if (CmsStringUtil.isEmpty(value)) { continue; } } else { // write the resource value on the second cycle value = property.getResourceValue(); mappingType = CmsProperty.RESOURCE_RECORD_MAPPING; id = resource.getResourceId(); if (CmsStringUtil.isEmpty(value)) { break; } } hp = new CmsDAOHistoryProperties(); hp.setStructureId(resource.getStructureId().toString()); hp.setPropertyDefId(propDef.getId().toString()); hp.setPropertyMappingId(id.toString()); hp.setPropertyMappingType(mappingType); hp.setPropertyValue(m_sqlManager.validateEmpty(value)); hp.setPublishTag(publishTag); m_sqlManager.persist(dbc, hp); } } } catch (PersistenceException e) { throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e); } } /** * @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<CmsProperty> properties, int publishTag) throws CmsDataAccessException { try { int sibCount = resource.getSiblingCount(); boolean valResource = internalValidateResource(dbc, resource, publishTag); // 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<CmsUUID> changedAndDeleted = (Set<CmsUUID>)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 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<String, Integer> versions = m_driverManager.getVfsDriver(dbc).readVersions( dbc, CmsProject.ONLINE_PROJECT_ID, resource.getResourceId(), resource.getStructureId()); int structureVersion = CmsDataTypeUtil.numberToInt(versions.get("structure")); int resourceVersion = CmsDataTypeUtil.numberToInt(versions.get("resource")); if (!valResource) { // write the resource CmsDAOHistoryResources hs = new CmsDAOHistoryResources(); hs.setResourceId(resource.getResourceId().toString()); hs.setResourceType(resource.getTypeId()); hs.setResourceFlags(resource.getFlags()); hs.setDateCreated(resource.getDateCreated()); hs.setUserCreated(resource.getUserCreated().toString()); hs.setDateLastModified(resource.getDateLastModified()); hs.setUserLastModified(resource.getUserLastModified().toString()); hs.setResourceState(resource.getState().getState()); hs.setResourceSize(resource.getLength()); hs.setDateContent(resource.getDateContent()); hs.setProjectLastModified(dbc.currentProject().getUuid().toString()); hs.setSiblingCount(resource.getSiblingCount()); hs.setResourceVersion(resourceVersion); hs.setPublishTag(publishTag); m_sqlManager.persist(dbc, hs); } CmsUUID parentId = CmsUUID.getNullUUID(); CmsFolder parent = m_driverManager.getVfsDriver(dbc).readParentFolder( dbc, CmsProject.ONLINE_PROJECT_ID, resource.getStructureId()); if (parent != null) { parentId = parent.getStructureId(); } // write the structure CmsDAOHistoryStructure hstr = new CmsDAOHistoryStructure(); hstr.setStructureId(resource.getStructureId().toString()); hstr.setResourceId(resource.getResourceId().toString()); hstr.setResourcePath(resource.getRootPath()); hstr.setStructureState(resource.getState().getState()); hstr.setDateReleased(resource.getDateReleased()); hstr.setDateExpired(resource.getDateExpired()); hstr.setStructureVersion(structureVersion); hstr.setParentId(parentId.toString()); hstr.setPublishTag(publishTag); hstr.setVersion(resource.getVersion()); m_sqlManager.persist(dbc, hstr); } catch (PersistenceException e) { throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e); } writeProperties(dbc, resource, properties, publishTag); } /** * Updates the property map for the given resource with the given property data.<p> * * @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<String, CmsProperty> 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.<p> * * @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 { boolean isFolder = resource.getRootPath().endsWith("/"); List<I_CmsHistoryResource> subResources = new ArrayList<I_CmsHistoryResource>(); // if the resource is a folder if (isFolder) { // and if no versions left if (readLastVersion(dbc, resource.getStructureId()) == 0) { // get all direct subresources try { Query q = m_sqlManager.createQuery(dbc, C_STRUCTURE_HISTORY_READ_SUBRESOURCES); q.setParameter(1, resource.getStructureId().toString()); @SuppressWarnings("unchecked") List<Object[]> res = q.getResultList(); for (Object[] obj : res) { CmsUUID structureId = new CmsUUID((String)obj[0]); int version = CmsDataTypeUtil.numberToInt((Integer)obj[1]); subResources.add(readResource(dbc, structureId, version)); } } catch (PersistenceException e) { throw new CmsDbSqlException(Messages.get().container( Messages.ERR_GENERIC_SQL_1, Messages.ERR_JPA_PERSITENCE), e); } } } // delete all sub resource versions for (I_CmsHistoryResource histResource : subResources) { deleteEntries(dbc, histResource, 0, -1); } } /** * Returns the amount of properties for a propertydefinition.<p> * * @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 { int returnValue; try { // create statement Query q = m_sqlManager.createQuery(dbc, projectId, C_PROPERTIES_READALL_COUNT); q.setParameter(1, metadef.getId().toString()); try { returnValue = CmsDataTypeUtil.numberToInt((Number)q.getSingleResult()); } catch (NoResultException e) { throw new CmsDbConsistencyException(Messages.get().container( Messages.ERR_NO_PROPERTIES_FOR_PROPERTYDEF_1, metadef.getName())); } } catch (PersistenceException e) { throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e); } return returnValue; } /** * Creates a historical project from the given result set and resources.<p> * @param hp the CmsDAOHistoryProjects instance * @param resources the historical resources * * @return the historical project * * @throws PersistenceException if something goes wrong */ protected CmsHistoryProject internalCreateProject(CmsDAOHistoryProjects hp, List<String> resources) throws PersistenceException { String ou = CmsOrganizationalUnit.removeLeadingSeparator(hp.getProjectOu()); CmsUUID publishedById = new CmsUUID(hp.getProjectPublishedBy()); CmsUUID userId = new CmsUUID(hp.getUserId()); return new CmsHistoryProject( hp.getPublishTag(), new CmsUUID(hp.getProjectId()), ou + hp.getProjectName(), hp.getProjectDescription(), userId, new CmsUUID(hp.getGroupId()), new CmsUUID(hp.getManagerGroupId()), hp.getDateCreated(), CmsProject.CmsProjectType.valueOf(hp.getProjectType()), hp.getProjectPublishDate(), publishedById, resources); } /** * Creates a valid {@link I_CmsHistoryResource} instance from a JDBC ResultSet.<p> * * @param res the JDBC result set * * @return the new historical resource instance * */ protected I_CmsHistoryResource internalCreateResource(Object[] res) { CmsDAOHistoryStructure hs = (CmsDAOHistoryStructure)res[0]; CmsDAOHistoryResources hr = (CmsDAOHistoryResources)res[1]; int resourceVersion = hr.getResourceVersion(); int structureVersion = hs.getStructureVersion(); int tagId = hr.getPublishTag(); CmsUUID structureId = new CmsUUID(hs.getStructureId()); CmsUUID resourceId = new CmsUUID(hr.getResourceId()); String resourcePath = hs.getResourcePath(); int resourceType = hr.getResourceType(); int resourceFlags = hr.getResourceFlags(); CmsUUID projectLastModified = new CmsUUID(hr.getProjectLastModified()); int state = Math.max(hr.getResourceState(), hs.getStructureState()); long dateCreated = hr.getDateCreated(); long dateLastModified = hr.getDateLastModified(); long dateReleased = hs.getDateReleased(); long dateExpired = hs.getDateExpired(); int resourceSize = hr.getResourceSize(); CmsUUID userLastModified = new CmsUUID(hr.getUserLastModified()); CmsUUID userCreated = new CmsUUID(hr.getUserCreated()); CmsUUID parentId = new CmsUUID(hs.getParentId()); long dateContent = hr.getDateContent(); 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.<p> * * @param histRes the original historical entry * @param hr the CmsDAOHistoryResources instance of the resource entry * @param versionOffset the offset for the structure version * * @return a merged historical entry for the sibling * */ protected I_CmsHistoryResource internalMergeResource( I_CmsHistoryResource histRes, CmsDAOHistoryResources hr, int versionOffset) { int resourceVersion = hr.getResourceVersion(); int structureVersion = histRes.getStructureVersion() - versionOffset; int tagId = hr.getPublishTag(); CmsUUID structureId = histRes.getStructureId(); CmsUUID resourceId = new CmsUUID(hr.getResourceId()); int resourceType = hr.getResourceType(); int resourceFlags = hr.getResourceFlags(); CmsUUID projectLastModified = new CmsUUID(hr.getProjectLastModified()); int state = histRes.getState().getState(); // may be we have to compute something here? long dateCreated = hr.getDateCreated(); long dateLastModified = hr.getDateLastModified(); long dateReleased = histRes.getDateReleased(); long dateExpired = histRes.getDateExpired(); int resourceSize = hr.getResourceSize(); CmsUUID userLastModified = new CmsUUID(hr.getUserLastModified()); CmsUUID userCreated = new CmsUUID(hr.getUserCreated()); // 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 = hr.getDateContent(); 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.<p> * * @param dbc the current database context * @param resource the resource to test * @param publishTag the publish tag of the resource to test * * @return <code>true</code> if the resource already exists, <code>false</code> otherwise * * @throws CmsDataAccessException if something goes wrong */ protected boolean internalValidateResource(CmsDbContext dbc, CmsResource resource, int publishTag) throws CmsDataAccessException { boolean exists = false; try { Query q = m_sqlManager.createQuery(dbc, C_HISTORY_EXISTS_RESOURCE); q.setParameter(1, resource.getResourceId().toString()); q.setParameter(2, Integer.valueOf(publishTag)); try { q.getSingleResult(); exists = true; } catch (NoResultException e) { //do nothing } } catch (PersistenceException e) { throw new CmsDbSqlException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e); } return exists; } }