org.opencms.db.jpa.CmsProjectDriver.java Source code

Java tutorial

Introduction

Here is the source code for org.opencms.db.jpa.CmsProjectDriver.java

Source

/*
 * 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.CmsDbContext;
import org.opencms.db.CmsDbEntryNotFoundException;
import org.opencms.db.CmsDbIoException;
import org.opencms.db.CmsDbSqlException;
import org.opencms.db.CmsDriverManager;
import org.opencms.db.CmsPublishList;
import org.opencms.db.CmsPublishedResource;
import org.opencms.db.CmsResourceState;
import org.opencms.db.CmsVisitEntryFilter;
import org.opencms.db.I_CmsDriver;
import org.opencms.db.I_CmsHistoryDriver;
import org.opencms.db.I_CmsProjectDriver;
import org.opencms.db.I_CmsVfsDriver;
import org.opencms.db.jpa.persistence.CmsDAOLog;
import org.opencms.db.jpa.persistence.CmsDAOOfflineResources;
import org.opencms.db.jpa.persistence.CmsDAOOfflineStructure;
import org.opencms.db.jpa.persistence.CmsDAOOnlineResources;
import org.opencms.db.jpa.persistence.CmsDAOOnlineStructure;
import org.opencms.db.jpa.persistence.CmsDAOProjectResources;
import org.opencms.db.jpa.persistence.CmsDAOProjectResources.CmsDAOProjectResourcesPK;
import org.opencms.db.jpa.persistence.CmsDAOProjects;
import org.opencms.db.jpa.persistence.CmsDAOPublishHistory;
import org.opencms.db.jpa.persistence.CmsDAOPublishJobs;
import org.opencms.db.jpa.persistence.CmsDAOResourceLocks;
import org.opencms.db.jpa.persistence.CmsDAOStaticExportLinks;
import org.opencms.db.jpa.persistence.I_CmsDAOResources;
import org.opencms.db.jpa.utils.CmsQueryIntParameter;
import org.opencms.db.jpa.utils.CmsQueryLongParameter;
import org.opencms.db.jpa.utils.CmsQueryStringParameter;
import org.opencms.db.jpa.utils.I_CmsQueryParameter;
import org.opencms.db.log.CmsLogEntry;
import org.opencms.db.log.CmsLogEntryType;
import org.opencms.db.log.CmsLogFilter;
import org.opencms.file.CmsDataAccessException;
import org.opencms.file.CmsFile;
import org.opencms.file.CmsFolder;
import org.opencms.file.CmsGroup;
import org.opencms.file.CmsProject;
import org.opencms.file.CmsProperty;
import org.opencms.file.CmsResource;
import org.opencms.file.CmsResourceFilter;
import org.opencms.file.CmsUser;
import org.opencms.file.CmsVfsResourceAlreadyExistsException;
import org.opencms.file.CmsVfsResourceNotFoundException;
import org.opencms.file.history.CmsHistoryFile;
import org.opencms.file.types.CmsResourceTypeFolder;
import org.opencms.i18n.CmsMessageContainer;
import org.opencms.lock.CmsLock;
import org.opencms.lock.CmsLockType;
import org.opencms.main.CmsEvent;
import org.opencms.main.CmsException;
import org.opencms.main.CmsLog;
import org.opencms.main.I_CmsEventListener;
import org.opencms.main.OpenCms;
import org.opencms.publish.CmsPublishJobInfoBean;
import org.opencms.relations.CmsRelationFilter;
import org.opencms.report.I_CmsReport;
import org.opencms.security.CmsOrganizationalUnit;
import org.opencms.security.I_CmsPrincipal;
import org.opencms.staticexport.CmsStaticExportManager;
import org.opencms.util.CmsDataTypeUtil;
import org.opencms.util.CmsPair;
import org.opencms.util.CmsStringUtil;
import org.opencms.util.CmsUUID;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceException;
import javax.persistence.Query;

import org.apache.commons.logging.Log;

import com.google.common.collect.Sets;

/**
 * JPA database server implementation of the project driver methods.<p>
 * 
 * @since 8.0.0 
 */
public class CmsProjectDriver implements I_CmsDriver, I_CmsProjectDriver {

    /** Attribute name for reading the project of a resource. */
    public static final String DBC_ATTR_READ_PROJECT_FOR_RESOURCE = "DBC_ATTR_READ_PROJECT_FOR_RESOURCE";

    /** Query key. */
    private static final String C_DELETE_PUBLISH_HISTORY = "C_DELETE_PUBLISH_HISTORY";

    /** Query key. */
    private static final String C_LOG_DELETE_ENTRIES = "C_LOG_DELETE_ENTRIES";

    /** Query key. */
    private static final String C_LOG_FILTER_DATE_FROM = "C_LOG_FILTER_DATE_FROM";

    /** Query key. */
    private static final String C_LOG_FILTER_DATE_TO = "C_LOG_FILTER_DATE_TO";

    /** Query key. */
    private static final String C_LOG_FILTER_EXCLUDE_TYPE = "C_LOG_FILTER_EXCLUDE_TYPE";

    /** Query key. */
    private static final String C_LOG_FILTER_INCLUDE_TYPE = "C_LOG_FILTER_INCLUDE_TYPE";

    /** Query key. */
    private static final String C_LOG_FILTER_RESOURCE_ID = "C_LOG_FILTER_RESOURCE_ID";

    /** Query key. */
    private static final String C_LOG_FILTER_USER_ID = "C_LOG_FILTER_USER_ID";

    /** Query key. */
    private static final String C_LOG_READ_ENTRIES = "C_LOG_READ_ENTRIES";

    /** Query key. */
    private static final String C_LOG_READ_PUBLISH_LIST_2 = "C_LOG_READ_PUBLISH_LIST_2";

    /** Query key. */
    private static final String C_PROJECTRESOURCES_DELETEALL_1 = "C_PROJECTRESOURCES_DELETEALL_1";

    /** Query key. */
    private static final String C_PROJECTRESOURCES_READ_2 = "C_PROJECTRESOURCES_READ_2";

    /** Query key. */
    private static final String C_PROJECTRESOURCES_READ_BY_ID_1 = "C_PROJECTRESOURCES_READ_BY_ID_1";

    /** Query key. */
    private static final String C_PROJECTS_READ_1 = "C_PROJECTS_READ_1";

    /** Query key. */
    private static final String C_PROJECTS_READ_BYGROUP_2 = "C_PROJECTS_READ_BYGROUP_2";

    /** Query key. */
    private static final String C_PROJECTS_READ_BYMANAGER_1 = "C_PROJECTS_READ_BYMANAGER_1";

    /** Query key. */
    private static final String C_PROJECTS_READ_BYNAME_2 = "C_PROJECTS_READ_BYNAME_2";

    /** Query key. */
    private static final String C_PROJECTS_READ_BYOU_1 = "C_PROJECTS_READ_BYOU_1";

    /** Query key. */
    private static final String C_PROJECTS_READ_BYRESOURCE_1 = "C_PROJECTS_READ_BYRESOURCE_1";

    /** Query key. */
    private static final String C_PROJECTS_READ_BYUSER_1 = "C_PROJECTS_READ_BYUSER_1";

    /** Query key. */
    private static final String C_PROJECTS_WRITE_6 = "C_PROJECTS_WRITE_6";

    /** Query key. */
    private static final String C_PUBLISHJOB_DELETE_PUBLISHLIST = "C_PUBLISHJOB_DELETE_PUBLISHLIST";

    /** Query key. */
    private static final String C_PUBLISHJOB_READ_JOB = "C_PUBLISHJOB_READ_JOB";

    /** Query key. */
    private static final String C_PUBLISHJOB_READ_JOBS_IN_TIMERANGE = "C_PUBLISHJOB_READ_JOBS_IN_TIMERANGE";

    /** Query key. */
    private static final String C_PUBLISHJOB_READ_PUBLISHLIST = "C_PUBLISHJOB_READ_PUBLISHLIST";

    /** Query key. */
    private static final String C_PUBLISHJOB_READ_REPORT = "C_PUBLISHJOB_READ_REPORT";

    /** Query key. */
    private static final String C_RESOURCE_LOCKS_DELETEALL = "C_RESOURCE_LOCKS_DELETEALL";

    /** Query key. */
    private static final String C_RESOURCE_LOCKS_READALL = "C_RESOURCE_LOCKS_READALL";

    /** Query key. */
    private static final String C_RESOURCES_DELETE_PUBLISH_HISTORY_ENTRY = "C_RESOURCES_DELETE_PUBLISH_HISTORY_ENTRY";

    /** Query key. */
    private static final String C_RESOURCES_UNMARK = "C_RESOURCES_UNMARK";

    /** Query key. */
    private static final String C_SELECT_PUBLISHED_RESOURCES = "C_SELECT_PUBLISHED_RESOURCES";

    /** Query key. */
    private static final String C_STATICEXPORT_DELETE_ALL_PUBLISHED_LINKS = "C_STATICEXPORT_DELETE_ALL_PUBLISHED_LINKS";

    /** Query key. */
    private static final String C_STATICEXPORT_DELETE_PUBLISHED_LINKS = "C_STATICEXPORT_DELETE_PUBLISHED_LINKS";

    /** Query key. */
    private static final String C_STATICEXPORT_READ_ALL_PUBLISHED_LINKS = "C_STATICEXPORT_READ_ALL_PUBLISHED_LINKS";

    /** Query key. */
    private static final String C_STATICEXPORT_READ_PUBLISHED_LINK_PARAMETERS = "C_STATICEXPORT_READ_PUBLISHED_LINK_PARAMETERS";

    /** Query key. */
    private static final String C_STATICEXPORT_READ_PUBLISHED_RESOURCES = "C_STATICEXPORT_READ_PUBLISHED_RESOURCES";

    /** The log object for this class. */
    private static final Log LOG = CmsLog.getLog(org.opencms.db.jpa.CmsProjectDriver.class);

    /** The driver manager. */
    protected CmsDriverManager m_driverManager;

    /** The SQL manager. */
    protected CmsSqlManager m_sqlManager;

    /**
     * @see org.opencms.db.I_CmsProjectDriver#createProject(org.opencms.db.CmsDbContext, CmsUUID, org.opencms.file.CmsUser, org.opencms.file.CmsGroup, org.opencms.file.CmsGroup, java.lang.String, java.lang.String, int, CmsProject.CmsProjectType)
     */
    public CmsProject createProject(CmsDbContext dbc, CmsUUID id, CmsUser owner, CmsGroup group,
            CmsGroup managergroup, String projectFqn, String description, int flags, CmsProject.CmsProjectType type)
            throws CmsDataAccessException {

        CmsProject project = null;

        if ((description == null) || (description.length() < 1)) {
            description = " ";
        }

        try {
            CmsDAOProjects p = new CmsDAOProjects();

            p.setProjectId(id.toString());
            p.setUserId(owner.getId().toString());
            p.setGroupId(group.getId().toString());
            p.setManagerGroupId(managergroup.getId().toString());
            p.setProjectName(CmsOrganizationalUnit.getSimpleName(projectFqn));
            p.setProjectDescription(description);
            p.setProjectFlags(flags);
            p.setProjectType(type.getMode());
            p.setProjectOu(CmsOrganizationalUnit.SEPARATOR + CmsOrganizationalUnit.getParentFqn(projectFqn));

            synchronized (this) {
                long createTime = System.currentTimeMillis();
                p.setDateCreated(createTime);
                m_sqlManager.persist(dbc, p);
                try {
                    // this is an ugly hack, but for MySQL (and maybe other DBs as well)
                    // there is a UNIQUE INDEX constraint on the project name+createTime
                    // so theoretically if 2 projects with the same name are created very fast, this
                    // SQL restraint would be violated if we don't wait here
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    // continue
                }
                project = new CmsProject(id, projectFqn, description, owner.getId(), group.getId(),
                        managergroup.getId(), flags, createTime, type);
            }
        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        }

        return project;
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#createProjectResource(org.opencms.db.CmsDbContext, CmsUUID, java.lang.String)
     */
    public void createProjectResource(CmsDbContext dbc, CmsUUID projectId, String resourcePath)
            throws CmsDataAccessException {

        // do not create entries for online-project
        boolean projectResourceExists = false;
        try {
            readProjectResource(dbc, projectId, resourcePath);
            projectResourceExists = true;
        } catch (CmsVfsResourceNotFoundException e) {
            // resource does not exist yet, everything is okay 
            projectResourceExists = false;
        }

        if (projectResourceExists) {
            throw new CmsVfsResourceAlreadyExistsException(Messages.get()
                    .container(Messages.ERR_RESOURCE_WITH_NAME_ALREADY_EXISTS_1, dbc.removeSiteRoot(resourcePath)));
        }

        try {
            CmsDAOProjectResources pr = new CmsDAOProjectResources();

            pr.setProjectId(projectId.toString());
            pr.setResourcePath(resourcePath);

            m_sqlManager.persist(dbc, pr);
        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        }
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#createPublishJob(org.opencms.db.CmsDbContext, org.opencms.publish.CmsPublishJobInfoBean)
     */
    public void createPublishJob(CmsDbContext dbc, CmsPublishJobInfoBean publishJob) throws CmsDataAccessException {

        try {
            CmsPublishJobInfoBean currentJob = readPublishJob(dbc, publishJob.getPublishHistoryId());
            LOG.error("wanted to write: " + publishJob);
            LOG.error("already on db: " + currentJob);
            return;
        } catch (CmsDbEntryNotFoundException e) {
            // ok, this is the expected behavior
        }
        try {
            CmsDAOPublishJobs pj = new CmsDAOPublishJobs();

            pj.setHistoryId(publishJob.getPublishHistoryId().toString());
            pj.setProjectId(publishJob.getProjectId().toString());
            pj.setProjectName(publishJob.getProjectName());
            pj.setUserId(publishJob.getUserId().toString());
            pj.setPublishLocale(publishJob.getLocale().toString());
            pj.setPublishFlags(publishJob.getFlags());
            pj.setResourceCount(publishJob.getSize());
            pj.setEnqueueTime(publishJob.getEnqueueTime());
            pj.setStartTime(publishJob.getStartTime());
            pj.setFinishTime(publishJob.getFinishTime());
            byte[] publishList = internalSerializePublishList(publishJob.getPublishList());
            pj.setPublishList(publishList);

            m_sqlManager.persist(dbc, pj);
        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        } catch (IOException e) {
            throw new CmsDbIoException(Messages.get().container(Messages.ERR_SERIALIZING_PUBLISHLIST_1,
                    publishJob.getPublishHistoryId().toString()), e);
        }
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#deleteAllStaticExportPublishedResources(org.opencms.db.CmsDbContext, int)
     */
    public void deleteAllStaticExportPublishedResources(CmsDbContext dbc, int linkType)
            throws CmsDataAccessException {

        try {
            Query q = m_sqlManager.createQuery(dbc, C_STATICEXPORT_DELETE_ALL_PUBLISHED_LINKS);
            q.setParameter(1, Integer.valueOf(linkType));
            @SuppressWarnings("unchecked")
            List<CmsDAOStaticExportLinks> res = q.getResultList();
            for (CmsDAOStaticExportLinks sel : res) {
                m_sqlManager.remove(dbc, sel);
            }
        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        }
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#deleteLog(org.opencms.db.CmsDbContext, org.opencms.db.log.CmsLogFilter)
     */
    public void deleteLog(CmsDbContext dbc, CmsLogFilter filter) throws CmsDataAccessException {

        try {
            StringBuffer queryBuf = new StringBuffer(256);
            queryBuf.append(m_sqlManager.readQuery(C_LOG_DELETE_ENTRIES));

            CmsPair<String, List<I_CmsQueryParameter>> conditionsAndParams = prepareLogConditions(filter);
            queryBuf.append(conditionsAndParams.getFirst());
            if (LOG.isDebugEnabled()) {
                LOG.debug(queryBuf.toString());
            }
            Query q = m_sqlManager.createQueryFromJPQL(dbc, queryBuf.toString());
            List<I_CmsQueryParameter> params = conditionsAndParams.getSecond();
            for (int i = 0; i < params.size(); i++) {
                I_CmsQueryParameter param = conditionsAndParams.getSecond().get(i);
                param.insertIntoQuery(q, i + 1);
            }

            // execute
            q.executeUpdate();
        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        }
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#deleteProject(org.opencms.db.CmsDbContext, org.opencms.file.CmsProject)
     */
    public void deleteProject(CmsDbContext dbc, CmsProject project) throws CmsDataAccessException {

        // delete the resources from project_resources
        deleteProjectResources(dbc, project);

        // remove the project id form all resources within their project
        unmarkProjectResources(dbc, project);

        // finally delete the project     
        try {
            CmsDAOProjects p = m_sqlManager.find(dbc, CmsDAOProjects.class, project.getUuid().toString());
            if (p != null) {
                m_sqlManager.remove(dbc, p);
            }
        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        }
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#deleteProjectResource(org.opencms.db.CmsDbContext, CmsUUID, java.lang.String)
     */
    public void deleteProjectResource(CmsDbContext dbc, CmsUUID projectId, String resourceName)
            throws CmsDataAccessException {

        try {
            CmsDAOProjectResourcesPK pk = new CmsDAOProjectResourcesPK();
            pk.setProjectId(projectId.toString());
            pk.setResourcePath(resourceName);
            CmsDAOProjectResources pr = m_sqlManager.find(dbc, CmsDAOProjectResources.class, pk);
            if (pr != null) {
                m_sqlManager.remove(dbc, pr);
            }
        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        }
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#deleteProjectResources(org.opencms.db.CmsDbContext, org.opencms.file.CmsProject)
     */
    public void deleteProjectResources(CmsDbContext dbc, CmsProject project) throws CmsDataAccessException {

        try {
            Query q = m_sqlManager.createQuery(dbc, C_PROJECTRESOURCES_DELETEALL_1);
            q.setParameter(1, project.getUuid().toString());
            @SuppressWarnings("unchecked")
            List<CmsDAOProjectResources> res = q.getResultList();
            for (CmsDAOProjectResources pr : res) {
                m_sqlManager.remove(dbc, pr);
            }
        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        }
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#deletePublishHistory(org.opencms.db.CmsDbContext, CmsUUID, int)
     */
    public void deletePublishHistory(CmsDbContext dbc, CmsUUID projectId, int maxpublishTag)
            throws CmsDataAccessException {

        try {
            Query q = m_sqlManager.createQuery(dbc, projectId, C_DELETE_PUBLISH_HISTORY);
            q.setParameter(1, Integer.valueOf(maxpublishTag));
            @SuppressWarnings("unchecked")
            List<CmsDAOPublishHistory> res = q.getResultList();
            for (CmsDAOPublishHistory ph : res) {
                m_sqlManager.remove(dbc, ph);
            }
        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        }
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#deletePublishHistoryEntry(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID, org.opencms.db.CmsPublishedResource)
     */
    public void deletePublishHistoryEntry(CmsDbContext dbc, CmsUUID publishHistoryId,
            CmsPublishedResource publishedResource) throws CmsDataAccessException {

        try {
            Query q = m_sqlManager.createQuery(dbc, C_RESOURCES_DELETE_PUBLISH_HISTORY_ENTRY);
            q.setParameter(1, publishHistoryId.toString());
            q.setParameter(2, Integer.valueOf(publishedResource.getPublishTag()));
            q.setParameter(3, publishedResource.getStructureId().toString());
            q.setParameter(4, publishedResource.getRootPath());
            @SuppressWarnings("unchecked")
            List<CmsDAOPublishHistory> res = q.getResultList();
            for (CmsDAOPublishHistory ph : res) {
                m_sqlManager.remove(dbc, ph);
            }
        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        }
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#deletePublishJob(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID)
     */
    public void deletePublishJob(CmsDbContext dbc, CmsUUID publishHistoryId) throws CmsDataAccessException {

        try {
            CmsDAOPublishJobs pj = m_sqlManager.find(dbc, CmsDAOPublishJobs.class, publishHistoryId.toString());
            if (pj != null) {
                m_sqlManager.remove(dbc, pj);
            }
        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        }
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#deletePublishList(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID)
     */
    public void deletePublishList(CmsDbContext dbc, CmsUUID publishHistoryId) throws CmsDataAccessException {

        try {
            Query q = m_sqlManager.createQuery(dbc, C_PUBLISHJOB_DELETE_PUBLISHLIST);
            q.setParameter(1, publishHistoryId.toString());
            @SuppressWarnings("unchecked")
            List<CmsDAOPublishJobs> res = q.getResultList();

            for (CmsDAOPublishJobs pj : res) {
                pj.setPublishList(null);
            }

        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        }
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#deleteStaticExportPublishedResource(org.opencms.db.CmsDbContext, java.lang.String, int, java.lang.String)
     */
    public void deleteStaticExportPublishedResource(CmsDbContext dbc, String resourceName, int linkType,
            String linkParameter) throws CmsDataAccessException {

        try {
            Query q = m_sqlManager.createQuery(dbc, C_STATICEXPORT_DELETE_PUBLISHED_LINKS);
            q.setParameter(1, resourceName);
            q.setParameter(2, Integer.valueOf(linkType));
            q.setParameter(3, linkParameter);
            @SuppressWarnings("unchecked")
            List<CmsDAOStaticExportLinks> res = q.getResultList();
            for (CmsDAOStaticExportLinks sel : res) {
                m_sqlManager.remove(dbc, sel);
            }
        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        }
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#destroy()
     */
    public void destroy() throws Throwable {

        m_sqlManager = null;
        m_driverManager = null;

        if (CmsLog.INIT.isInfoEnabled()) {
            CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_SHUTDOWN_DRIVER_1, getClass().getName()));
        }
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#fillDefaults(org.opencms.db.CmsDbContext)
     */
    public void fillDefaults(CmsDbContext dbc) throws CmsDataAccessException {

        try {
            if (readProject(dbc, CmsProject.ONLINE_PROJECT_ID) != null) {
                // online-project exists - no need of filling defaults
                return;
            }
        } catch (CmsDataAccessException exc) {
            // ignore the exception - the project was not readable so fill in the defaults
        }

        if (CmsLog.INIT.isInfoEnabled()) {
            CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_FILL_DEFAULTS_0));
        }

        String adminUser = OpenCms.getDefaultUsers().getUserAdmin();
        CmsUser admin = m_driverManager.readUser(dbc, adminUser);

        String administratorsGroup = OpenCms.getDefaultUsers().getGroupAdministrators();
        CmsGroup administrators = m_driverManager.readGroup(dbc, administratorsGroup);

        String usersGroup = OpenCms.getDefaultUsers().getGroupUsers();
        CmsGroup users = m_driverManager.readGroup(dbc, usersGroup);

        String projectmanagersGroup = OpenCms.getDefaultUsers().getGroupProjectmanagers();
        CmsGroup projectmanager = m_driverManager.readGroup(dbc, projectmanagersGroup);

        ////////////////////////////////////////////////////////////////////////////////////////////
        // online project stuff
        ////////////////////////////////////////////////////////////////////////////////////////////        

        // create the online project
        CmsProject onlineProject = createProject(dbc, CmsProject.ONLINE_PROJECT_ID, admin, users, projectmanager,
                CmsProject.ONLINE_PROJECT_NAME, "The Online project", I_CmsPrincipal.FLAG_ENABLED,
                CmsProject.PROJECT_TYPE_NORMAL);

        // create the root-folder for the online project
        CmsFolder rootFolder = new CmsFolder(new CmsUUID(), new CmsUUID(), "/",
                CmsResourceTypeFolder.RESOURCE_TYPE_ID, 0, onlineProject.getUuid(), CmsResource.STATE_CHANGED, 0,
                admin.getId(), 0, admin.getId(), CmsResource.DATE_RELEASED_DEFAULT,
                CmsResource.DATE_EXPIRED_DEFAULT, 0);

        m_driverManager.getVfsDriver(dbc).createResource(dbc, onlineProject.getUuid(), rootFolder, null);

        // important: must access through driver manager to ensure proper cascading
        m_driverManager.getProjectDriver(dbc).createProjectResource(dbc, onlineProject.getUuid(),
                rootFolder.getRootPath());

        // create the system-folder for the online project
        CmsFolder systemFolder = new CmsFolder(new CmsUUID(), new CmsUUID(), "/system",
                CmsResourceTypeFolder.RESOURCE_TYPE_ID, 0, onlineProject.getUuid(), CmsResource.STATE_CHANGED, 0,
                admin.getId(), 0, admin.getId(), CmsResource.DATE_RELEASED_DEFAULT,
                CmsResource.DATE_EXPIRED_DEFAULT, 0);

        m_driverManager.getVfsDriver(dbc).createResource(dbc, onlineProject.getUuid(), systemFolder, null);

        ////////////////////////////////////////////////////////////////////////////////////////////
        // setup project stuff
        ////////////////////////////////////////////////////////////////////////////////////////////

        // important: must access through driver manager to ensure proper cascading        
        CmsProject setupProject = m_driverManager.getProjectDriver(dbc).createProject(dbc,
                CmsUUID.getConstantUUID(SETUP_PROJECT_NAME), admin, administrators, administrators,
                SETUP_PROJECT_NAME, "The Project for the initial import", I_CmsPrincipal.FLAG_ENABLED,
                CmsProject.PROJECT_TYPE_TEMPORARY);

        rootFolder.setState(CmsResource.STATE_CHANGED);
        // create the root-folder for the offline project       
        CmsResource offlineRootFolder = m_driverManager.getVfsDriver(dbc).createResource(dbc,
                setupProject.getUuid(), rootFolder, null);

        offlineRootFolder.setState(CmsResource.STATE_UNCHANGED);

        m_driverManager.getVfsDriver(dbc).writeResource(dbc, setupProject.getUuid(), offlineRootFolder,
                CmsDriverManager.NOTHING_CHANGED);

        // important: must access through driver manager to ensure proper cascading        
        m_driverManager.getProjectDriver(dbc).createProjectResource(dbc, setupProject.getUuid(),
                offlineRootFolder.getRootPath());

        systemFolder.setState(CmsResource.STATE_CHANGED);
        // create the system-folder for the offline project       
        CmsResource offlineSystemFolder = m_driverManager.getVfsDriver(dbc).createResource(dbc,
                setupProject.getUuid(), systemFolder, null);

        offlineSystemFolder.setState(CmsResource.STATE_UNCHANGED);

        m_driverManager.getVfsDriver(dbc).writeResource(dbc, setupProject.getUuid(), offlineSystemFolder,
                CmsDriverManager.NOTHING_CHANGED);
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#getSqlManager()
     */
    public CmsSqlManager getSqlManager() {

        return m_sqlManager;
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#getUsersPubList(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID)
     */
    public List<CmsResource> getUsersPubList(CmsDbContext dbc, CmsUUID userId) throws CmsDataAccessException {

        List<CmsResource> result = null;
        try {
            Query q = m_sqlManager.createNativeQuery(dbc, dbc.currentProject().getUuid(),
                    C_LOG_READ_PUBLISH_LIST_2);
            q.setParameter(1, userId.toString());
            q.setParameter(2, userId.toString());
            @SuppressWarnings("unchecked")
            List<Object[]> res = q.getResultList();

            result = new ArrayList<CmsResource>();

            Class<?> structureClass;
            Class<?> resourcesClass;
            Object[] obj = new Object[3];

            if (CmsProject.ONLINE_PROJECT_ID.equals(dbc.currentProject().getUuid())) {
                structureClass = CmsDAOOnlineStructure.class;
                resourcesClass = CmsDAOOnlineResources.class;
            } else {
                structureClass = CmsDAOOfflineStructure.class;
                resourcesClass = CmsDAOOfflineResources.class;
            }

            for (Object[] objArray : res) {
                // there are building obj array which should normally 
                // returned by JPQL query
                obj[0] = m_sqlManager.find(dbc, resourcesClass, objArray[0]);
                obj[1] = m_sqlManager.find(dbc, structureClass, objArray[1]);
                obj[2] = ((I_CmsDAOResources) obj[0]).getProjectLastModified();

                CmsResource resource = ((CmsVfsDriver) m_driverManager.getVfsDriver(dbc)).createResource(obj,
                        dbc.currentProject().getUuid());
                long date = ((Number) objArray[2]).longValue();
                resource.setDateLastModified(date);
                result.add(resource);
            }
        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        } catch (Exception e) {
            LOG.error(e.getLocalizedMessage(), e);
        }

        return result;
    }

    /**
     * @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.project.pool");
        String classname = config.get("db.project.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_CmsProjectDriver#initSqlManager(String)
     */
    public CmsSqlManager initSqlManager(String classname) {

        return CmsSqlManager.getInstance(classname);
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#log(org.opencms.db.CmsDbContext, java.util.List)
     */
    public void log(CmsDbContext dbc, List<CmsLogEntry> logEntries) throws CmsDbSqlException {

        try {

            EntityManager em = m_sqlManager.getEntityManager(dbc);
            em.getTransaction().commit();
            CmsDAOLog daoLog;
            for (CmsLogEntry logEntry : logEntries) {
                em.getTransaction().begin();
                daoLog = new CmsDAOLog();
                daoLog.setUserId(logEntry.getUserId().toString());
                daoLog.setLogDate(logEntry.getDate());
                daoLog.setStructureId(
                        logEntry.getStructureId() == null ? null : logEntry.getStructureId().toString());
                daoLog.setLogType(logEntry.getType().getId());
                daoLog.setLogData(CmsStringUtil.arrayAsString(logEntry.getData(), "|"));
                em.persist(daoLog);
                // here commits on each record, 
                // because there may be a duplicate records
                // and just ignore them
                try {
                    if ((em.getTransaction() != null) && em.getTransaction().isActive()) {
                        em.getTransaction().commit();
                    }
                } catch (RuntimeException e) {
                    if ((em.getTransaction() != null) && em.getTransaction().isActive()) {
                        em.getTransaction().rollback();
                    }
                } finally {
                    em.clear();
                }
            }
            em.getTransaction().begin();
        } catch (PersistenceException e) {
            throw new CmsDbSqlException(Messages.get().container(Messages.ERR_GENERIC_SQL_1, ""), e);
        }
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#publishDeletedFolder(org.opencms.db.CmsDbContext, org.opencms.report.I_CmsReport, int, int, org.opencms.file.CmsProject, org.opencms.file.CmsFolder, org.opencms.util.CmsUUID, int)
     */
    public void publishDeletedFolder(CmsDbContext dbc, I_CmsReport report, int m, int n, CmsProject onlineProject,
            CmsFolder currentFolder, CmsUUID publishHistoryId, int publishTag) throws CmsDataAccessException {

        try {
            report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_SUCCESSION_2,
                    String.valueOf(m), String.valueOf(n)), I_CmsReport.FORMAT_NOTE);
            report.print(Messages.get().container(Messages.RPT_DELETE_FOLDER_0), I_CmsReport.FORMAT_NOTE);
            report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_ARGUMENT_1,
                    dbc.removeSiteRoot(currentFolder.getRootPath())));
            report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0));

            CmsResourceState folderState = fixMovedResource(dbc, onlineProject, currentFolder, publishHistoryId,
                    publishTag);

            // read the folder online
            CmsFolder onlineFolder = m_driverManager.readFolder(dbc, currentFolder.getRootPath(),
                    CmsResourceFilter.ALL);

            // if the folder in the online-project contains any files, these need to be removed.
            // this can occur if these files were moved in the offline-project   
            List<CmsResource> movedFiles = null;
            I_CmsVfsDriver vfsDriver = m_driverManager.getVfsDriver(dbc);
            movedFiles = vfsDriver.readResourceTree(dbc, onlineProject.getUuid(), currentFolder.getRootPath(),
                    CmsDriverManager.READ_IGNORE_TYPE, null, CmsDriverManager.READ_IGNORE_TIME,
                    CmsDriverManager.READ_IGNORE_TIME, CmsDriverManager.READ_IGNORE_TIME,
                    CmsDriverManager.READ_IGNORE_TIME, CmsDriverManager.READ_IGNORE_TIME,
                    CmsDriverManager.READ_IGNORE_TIME, CmsDriverManager.READMODE_ONLY_FILES);

            for (Iterator<CmsResource> it = movedFiles.iterator(); it.hasNext();) {
                CmsResource delFile = it.next();
                try {
                    CmsResource offlineResource = vfsDriver.readResource(dbc, dbc.currentProject().getUuid(),
                            delFile.getStructureId(), true);
                    CmsFile offlineFile = new CmsFile(offlineResource);
                    offlineFile.setContents(vfsDriver.readContent(dbc, dbc.currentProject().getUuid(),
                            offlineFile.getResourceId()));
                    internalWriteHistory(dbc, offlineFile, CmsResource.STATE_DELETED, null, publishHistoryId,
                            publishTag);
                    vfsDriver.deletePropertyObjects(dbc, onlineProject.getUuid(), delFile,
                            CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES);
                    vfsDriver.removeFile(dbc, onlineProject.getUuid(), delFile);
                    m_sqlManager.getEntityManager(dbc).getTransaction().commit();
                    m_sqlManager.getEntityManager(dbc).getTransaction().begin();
                } catch (CmsDataAccessException e) {
                    if (LOG.isWarnEnabled()) {
                        LOG.warn(
                                Messages.get().getBundle().key(Messages.LOG_REMOVING_RESOURCE_1, delFile.getName()),
                                e);
                    }
                }
            }

            // write history before deleting
            internalWriteHistory(dbc, currentFolder, folderState, null, publishHistoryId, publishTag);

            try {
                // delete the properties online and offline
                vfsDriver.deletePropertyObjects(dbc, onlineProject.getUuid(), onlineFolder,
                        CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES);
                vfsDriver.deletePropertyObjects(dbc, dbc.currentProject().getUuid(), currentFolder,
                        CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES);
            } catch (CmsDataAccessException e) {
                if (LOG.isErrorEnabled()) {
                    LOG.error(Messages.get().getBundle().key(Messages.LOG_DELETING_PROPERTIES_1,
                            currentFolder.getRootPath()), e);
                }
                throw e;
            }

            try {
                // remove the folder online and offline
                vfsDriver.removeFolder(dbc, dbc.currentProject(), currentFolder);
                vfsDriver.removeFolder(dbc, onlineProject, currentFolder);
            } catch (CmsDataAccessException e) {
                if (LOG.isErrorEnabled()) {
                    LOG.error(Messages.get().getBundle().key(Messages.LOG_REMOVING_RESOURCE_1,
                            currentFolder.getRootPath()), e);
                }
                throw e;
            }

            try {
                // remove the ACL online and offline
                m_driverManager.getUserDriver(dbc).removeAccessControlEntries(dbc, onlineProject,
                        onlineFolder.getResourceId());
                m_driverManager.getUserDriver(dbc).removeAccessControlEntries(dbc, dbc.currentProject(),
                        currentFolder.getResourceId());
            } catch (CmsDataAccessException e) {
                if (LOG.isErrorEnabled()) {
                    LOG.error(Messages.get().getBundle().key(Messages.LOG_REMOVING_ACL_1,
                            currentFolder.getRootPath()), e);
                }
                throw e;
            }

            // remove relations
            try {
                vfsDriver.deleteRelations(dbc, onlineProject.getUuid(), onlineFolder, CmsRelationFilter.TARGETS);
                vfsDriver.deleteRelations(dbc, dbc.currentProject().getUuid(), currentFolder,
                        CmsRelationFilter.TARGETS);
            } catch (CmsDataAccessException e) {
                if (LOG.isErrorEnabled()) {
                    LOG.error(Messages.get().getBundle().key(Messages.LOG_REMOVING_RELATIONS_1,
                            currentFolder.getRootPath()), e);
                }
                throw e;
            }

            // remove project resources
            String deletedResourceRootPath = currentFolder.getRootPath();
            Iterator<CmsProject> itProjects = readProjectsForResource(dbc, deletedResourceRootPath).iterator();
            while (itProjects.hasNext()) {
                CmsProject project = itProjects.next();
                deleteProjectResource(dbc, project.getUuid(), deletedResourceRootPath);
            }

            report.println(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0),
                    I_CmsReport.FORMAT_OK);

            if (LOG.isDebugEnabled()) {
                if (LOG.isDebugEnabled()) {
                    LOG.debug(Messages.get().getBundle().key(Messages.LOG_DEL_FOLDER_3, currentFolder.getRootPath(),
                            String.valueOf(m), String.valueOf(n)));
                }
            }
        } finally {
            // notify the app. that the published folder and it's properties have been modified offline
            OpenCms.fireCmsEvent(new CmsEvent(I_CmsEventListener.EVENT_RESOURCE_AND_PROPERTIES_MODIFIED,
                    Collections.<String, Object>singletonMap(I_CmsEventListener.KEY_RESOURCE, currentFolder)));
        }
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#publishFile(org.opencms.db.CmsDbContext, org.opencms.report.I_CmsReport, int, int, org.opencms.file.CmsProject, org.opencms.file.CmsResource, java.util.Set, org.opencms.util.CmsUUID, int)
     */
    public void publishFile(CmsDbContext dbc, I_CmsReport report, int m, int n, CmsProject onlineProject,
            CmsResource offlineResource, Set<CmsUUID> publishedContentIds, CmsUUID publishHistoryId, int publishTag)
            throws CmsDataAccessException {

        /*
         * Never use onlineResource.getState() here!
         * Only use offlineResource.getState() to determine the state of an offline resource!
         * 
         * In case a resource has siblings, after a sibling was published the structure
         * and resource states are reset to UNCHANGED -> the state of the corresponding
         * onlineResource is still NEW, DELETED or CHANGED. 
         * Thus, using onlineResource.getState() will inevitably result in unpublished resources!
         */

        try {
            report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_SUCCESSION_2,
                    String.valueOf(m), String.valueOf(n)), I_CmsReport.FORMAT_NOTE);

            if (offlineResource.getState().isDeleted()) {
                report.print(Messages.get().container(Messages.RPT_DELETE_FILE_0), I_CmsReport.FORMAT_NOTE);
                report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_ARGUMENT_1,
                        dbc.removeSiteRoot(offlineResource.getRootPath())));
                report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0));

                publishDeletedFile(dbc, onlineProject, offlineResource, publishHistoryId, publishTag);

                dbc.pop();
                // delete old historical entries
                m_driverManager.getHistoryDriver(dbc).deleteEntries(dbc, new CmsHistoryFile(offlineResource),
                        OpenCms.getSystemInfo().getHistoryVersionsAfterDeletion(), -1);

                report.println(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0),
                        I_CmsReport.FORMAT_OK);

                if (LOG.isDebugEnabled()) {
                    LOG.debug(Messages.get().getBundle().key(Messages.LOG_DEL_FILE_3, String.valueOf(m),
                            String.valueOf(n), offlineResource.getRootPath()));
                }

            } else if (offlineResource.getState().isChanged()) {
                report.print(Messages.get().container(Messages.RPT_PUBLISH_FILE_0), I_CmsReport.FORMAT_NOTE);
                report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_ARGUMENT_1,
                        dbc.removeSiteRoot(offlineResource.getRootPath())));
                report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0));

                publishChangedFile(dbc, onlineProject, offlineResource, publishedContentIds, publishHistoryId,
                        publishTag);

                dbc.pop();
                // delete old historical entries
                m_driverManager.getHistoryDriver(dbc).deleteEntries(dbc, new CmsHistoryFile(offlineResource),
                        OpenCms.getSystemInfo().getHistoryVersions(), -1);

                report.println(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0),
                        I_CmsReport.FORMAT_OK);

                if (LOG.isDebugEnabled()) {
                    LOG.debug(Messages.get().getBundle().key(Messages.LOG_PUBLISHING_FILE_3,
                            offlineResource.getRootPath(), String.valueOf(m), String.valueOf(n)));
                }
            } else if (offlineResource.getState().isNew()) {
                report.print(Messages.get().container(Messages.RPT_PUBLISH_FILE_0), I_CmsReport.FORMAT_NOTE);
                report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_ARGUMENT_1,
                        dbc.removeSiteRoot(offlineResource.getRootPath())));
                report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0));

                publishNewFile(dbc, onlineProject, offlineResource, publishedContentIds, publishHistoryId,
                        publishTag);

                dbc.pop();
                // delete old historical entries
                m_driverManager.getHistoryDriver(dbc).deleteEntries(dbc, new CmsHistoryFile(offlineResource),
                        OpenCms.getSystemInfo().getHistoryVersions(), -1);

                report.println(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0),
                        I_CmsReport.FORMAT_OK);

                if (LOG.isDebugEnabled()) {
                    if (LOG.isDebugEnabled()) {
                        LOG.debug(Messages.get().getBundle().key(Messages.LOG_PUBLISHING_FILE_3,
                                offlineResource.getRootPath(), String.valueOf(m), String.valueOf(n)));
                    }
                }
            } else {
                // state == unchanged !!?? something went really wrong
                report.print(Messages.get().container(Messages.RPT_PUBLISH_FILE_0), I_CmsReport.FORMAT_NOTE);
                report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_ARGUMENT_1,
                        dbc.removeSiteRoot(offlineResource.getRootPath())));
                report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0));
                report.println(
                        org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_FAILED_0),
                        I_CmsReport.FORMAT_ERROR);

                if (LOG.isErrorEnabled()) {
                    // the whole resource is printed out here
                    LOG.error(Messages.get().getBundle().key(Messages.LOG_PUBLISHING_FILE_3, String.valueOf(m),
                            String.valueOf(n), offlineResource));
                }
            }
        } catch (CmsException e) {
            throw new CmsDataAccessException(e.getMessageContainer(), e);
        } finally {
            // notify the app. that the published file and it's properties have been modified offline
            OpenCms.fireCmsEvent(new CmsEvent(I_CmsEventListener.EVENT_RESOURCE_AND_PROPERTIES_MODIFIED,
                    Collections.<String, Object>singletonMap(I_CmsEventListener.KEY_RESOURCE, offlineResource)));
        }
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#publishFileContent(CmsDbContext, CmsProject, CmsProject, CmsResource, Set, boolean, int)
     */
    public CmsFile publishFileContent(CmsDbContext dbc, CmsProject offlineProject, CmsProject onlineProject,
            CmsResource offlineResource, Set<CmsUUID> publishedResourceIds, boolean needToUpdateContent,
            int publishTag) throws CmsDataAccessException {

        CmsFile newFile = null;
        try {
            // read the file content offline
            CmsUUID projectId = dbc.getProjectId();
            boolean dbcHasProjectId = (projectId != null) && !projectId.isNullUUID();
            CmsUUID projectIdForReading = (!dbcHasProjectId ? offlineProject.getUuid()
                    : CmsProject.ONLINE_PROJECT_ID);
            dbc.setProjectId(offlineProject.getUuid());
            byte[] offlineContent = m_driverManager.getVfsDriver(dbc).readContent(dbc, projectIdForReading,
                    offlineResource.getResourceId());
            CmsFile offlineFile = new CmsFile(offlineResource);
            offlineFile.setContents(offlineContent);
            dbc.setProjectId(projectId);

            // create the file online              
            newFile = (CmsFile) offlineFile.clone();
            newFile.setState(CmsResource.STATE_UNCHANGED);

            boolean createSibling = true;
            // check if we are facing with a create new sibling operation
            if (!offlineFile.getState().isNew()) {
                createSibling = false;
            } else {
                // check if the resource entry already exists
                if (!m_driverManager.getVfsDriver(dbc).validateResourceIdExists(dbc, onlineProject.getUuid(),
                        offlineFile.getResourceId())) {
                    // we are creating a normal resource and not a sibling
                    createSibling = false;
                }
            }

            // only update the content if it was not updated before
            boolean alreadyPublished = publishedResourceIds.contains(offlineResource.getResourceId());
            needToUpdateContent &= !alreadyPublished;

            if (createSibling) {
                if (!alreadyPublished) {
                    // create the file online, the first time a sibling is published also the resource entry has to be actualized
                    m_driverManager.getVfsDriver(dbc).createResource(dbc, onlineProject.getUuid(), newFile, null);
                } else {
                    // create the sibling online
                    m_driverManager.getVfsDriver(dbc).createSibling(dbc, onlineProject, offlineResource);
                }
                newFile = new CmsFile(offlineResource);
                newFile.setContents(offlineContent);
            } else {
                // update the online/offline structure and resource records of the file
                m_driverManager.getVfsDriver(dbc).publishResource(dbc, onlineProject, newFile, offlineFile);
            }
            // update version numbers
            m_driverManager.getVfsDriver(dbc).publishVersions(dbc, offlineResource, !alreadyPublished);

            // create/update the content
            m_driverManager.getVfsDriver(dbc).createOnlineContent(dbc, offlineFile.getResourceId(),
                    offlineFile.getContents(), publishTag, true, needToUpdateContent);

            // mark the resource as written to avoid that the same content is written for each sibling instance
            publishedResourceIds.add(offlineResource.getResourceId());
        } catch (CmsDataAccessException e) {
            if (LOG.isErrorEnabled()) {
                LOG.error(Messages.get().getBundle().key(Messages.LOG_PUBLISHING_FILE_CONTENT_1,
                        offlineResource.toString()), e);
            }
            throw e;
        }
        return newFile;
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#publishFolder(org.opencms.db.CmsDbContext, org.opencms.report.I_CmsReport, int, int, org.opencms.file.CmsProject, org.opencms.file.CmsFolder, org.opencms.util.CmsUUID, int)
     */
    public void publishFolder(CmsDbContext dbc, I_CmsReport report, int m, int n, CmsProject onlineProject,
            CmsFolder offlineFolder, CmsUUID publishHistoryId, int publishTag) throws CmsDataAccessException {

        try {
            report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_SUCCESSION_2,
                    String.valueOf(m), String.valueOf(n)), I_CmsReport.FORMAT_NOTE);
            report.print(Messages.get().container(Messages.RPT_PUBLISH_FOLDER_0), I_CmsReport.FORMAT_NOTE);
            report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_ARGUMENT_1,
                    dbc.removeSiteRoot(offlineFolder.getRootPath())));
            report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0));

            CmsResourceState resourceState = fixMovedResource(dbc, onlineProject, offlineFolder, publishHistoryId,
                    publishTag);

            CmsResource onlineFolder = null;
            if (offlineFolder.getState().isNew()) {
                try {
                    // create the folder online
                    CmsResource newFolder = (CmsFolder) offlineFolder.clone();
                    newFolder.setState(CmsResource.STATE_UNCHANGED);

                    onlineFolder = m_driverManager.getVfsDriver(dbc).createResource(dbc, onlineProject.getUuid(),
                            newFolder, null);
                    m_driverManager.getVfsDriver(dbc).publishResource(dbc, onlineProject, onlineFolder,
                            offlineFolder);
                    // update version numbers
                    m_driverManager.getVfsDriver().publishVersions(dbc, offlineFolder, true);
                } catch (CmsVfsResourceAlreadyExistsException e) {
                    if (!offlineFolder.getRootPath().equals("/") && !offlineFolder.getRootPath().equals("/system/")
                            && LOG.isWarnEnabled()) {
                        LOG.warn(Messages.get().getBundle().key(Messages.LOG_WARN_FOLDER_WRONG_STATE_CN_1,
                                offlineFolder.getRootPath()));
                    }
                    try {
                        onlineFolder = m_driverManager.getVfsDriver(dbc).readFolder(dbc, onlineProject.getUuid(),
                                offlineFolder.getRootPath());
                        m_driverManager.getVfsDriver(dbc).publishResource(dbc, onlineProject, onlineFolder,
                                offlineFolder);
                        // update version numbers
                        m_driverManager.getVfsDriver(dbc).publishVersions(dbc, offlineFolder, true);
                    } catch (CmsDataAccessException e1) {
                        if (LOG.isErrorEnabled()) {
                            LOG.error(Messages.get().getBundle().key(Messages.LOG_READING_RESOURCE_1,
                                    offlineFolder.getRootPath()), e);
                        }
                        throw e1;
                    }
                } catch (CmsDataAccessException e) {
                    if (LOG.isErrorEnabled()) {
                        LOG.error(Messages.get().getBundle().key(Messages.LOG_PUBLISHING_RESOURCE_1,
                                offlineFolder.getRootPath()), e);
                    }
                    throw e;
                }
            } else if (offlineFolder.getState().isChanged()) {
                try {
                    // read the folder online
                    onlineFolder = m_driverManager.getVfsDriver(dbc).readFolder(dbc, onlineProject.getUuid(),
                            offlineFolder.getStructureId());
                } catch (CmsVfsResourceNotFoundException e) {
                    if (LOG.isWarnEnabled()) {
                        LOG.warn(Messages.get().getBundle().key(Messages.LOG_WARN_FOLDER_WRONG_STATE_NC_1,
                                offlineFolder.getRootPath()));
                    }
                    try {
                        onlineFolder = m_driverManager.getVfsDriver(dbc).createResource(dbc,
                                onlineProject.getUuid(), offlineFolder, null);
                        internalResetResourceState(dbc, onlineFolder);
                    } catch (CmsDataAccessException e1) {
                        if (LOG.isErrorEnabled()) {
                            LOG.error(Messages.get().getBundle().key(Messages.LOG_PUBLISHING_RESOURCE_1,
                                    offlineFolder.getRootPath()), e);
                        }
                        throw e1;
                    }
                }

                try {
                    // update the folder online
                    m_driverManager.getVfsDriver(dbc).publishResource(dbc, onlineProject, onlineFolder,
                            offlineFolder);
                    // update version numbers
                    m_driverManager.getVfsDriver(dbc).publishVersions(dbc, offlineFolder, true);
                } catch (CmsDataAccessException e) {
                    if (LOG.isErrorEnabled()) {
                        LOG.error(Messages.get().getBundle().key(Messages.LOG_PUBLISHING_RESOURCE_1,
                                offlineFolder.getRootPath()), e);
                    }
                    throw e;
                }
            }

            if (onlineFolder != null) {
                try {
                    // write the ACL online
                    m_driverManager.getUserDriver(dbc).publishAccessControlEntries(dbc, dbc.currentProject(),
                            onlineProject, offlineFolder.getResourceId(), onlineFolder.getResourceId());
                } catch (CmsDataAccessException e) {
                    if (LOG.isErrorEnabled()) {
                        LOG.error(Messages.get().getBundle().key(Messages.LOG_PUBLISHING_ACL_1,
                                offlineFolder.getRootPath()), e);
                    }
                    throw e;
                }
            }

            List<CmsProperty> offlineProperties = null;
            try {
                // write the properties online
                m_driverManager.getVfsDriver(dbc).deletePropertyObjects(dbc, onlineProject.getUuid(), onlineFolder,
                        CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES);
                offlineProperties = m_driverManager.getVfsDriver(dbc).readPropertyObjects(dbc, dbc.currentProject(),
                        offlineFolder);
                CmsProperty.setAutoCreatePropertyDefinitions(offlineProperties, true);
                m_driverManager.getVfsDriver(dbc).writePropertyObjects(dbc, onlineProject, onlineFolder,
                        offlineProperties);
            } catch (CmsDataAccessException e) {
                if (LOG.isErrorEnabled()) {
                    LOG.error(Messages.get().getBundle().key(Messages.LOG_PUBLISHING_PROPERTIES_1,
                            offlineFolder.getRootPath()), e);
                }
                throw e;
            }

            internalWriteHistory(dbc, offlineFolder, resourceState, offlineProperties, publishHistoryId,
                    publishTag);

            m_driverManager.getVfsDriver(dbc).updateRelations(dbc, onlineProject, offlineFolder);

            report.println(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0),
                    I_CmsReport.FORMAT_OK);

            if (LOG.isDebugEnabled()) {
                LOG.debug(Messages.get().getBundle().key(Messages.LOG_PUBLISHING_FOLDER_3, String.valueOf(m),
                        String.valueOf(n), offlineFolder.getRootPath()));
            }
        } finally {
            // notify the app. that the published folder and it's properties have been modified offline
            OpenCms.fireCmsEvent(new CmsEvent(I_CmsEventListener.EVENT_RESOURCE_AND_PROPERTIES_MODIFIED,
                    Collections.<String, Object>singletonMap(I_CmsEventListener.KEY_RESOURCE, offlineFolder)));
        }
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#publishProject(org.opencms.db.CmsDbContext, org.opencms.report.I_CmsReport, org.opencms.file.CmsProject, org.opencms.db.CmsPublishList, int)
     */
    public void publishProject(CmsDbContext dbc, I_CmsReport report, CmsProject onlineProject,
            CmsPublishList publishList, int publishTag) throws CmsException {

        int publishedFolderCount = 0;
        int deletedFolderCount = 0;
        int publishedFileCount = 0;
        Set<CmsUUID> publishedContentIds = new HashSet<CmsUUID>();
        Set<CmsUUID> publishedIds = new HashSet<CmsUUID>();

        try {

            ////////////////////////////////////////////////////////////////////////////////////////
            // write the historical project entry

            if (OpenCms.getSystemInfo().isHistoryEnabled()) {
                try {
                    // write an entry in the publish project log
                    m_driverManager.getHistoryDriver(dbc).writeProject(dbc, publishTag, System.currentTimeMillis());
                    dbc.pop();
                } catch (Throwable t) {
                    dbc.report(report, Messages.get().container(Messages.ERR_WRITING_HISTORY_OF_PROJECT_1,
                            dbc.currentProject().getName()), t);
                }
            }

            ///////////////////////////////////////////////////////////////////////////////////////
            // publish new/changed folders

            if (LOG.isDebugEnabled()) {
                LOG.debug(Messages.get().getBundle().key(Messages.LOG_START_PUBLISHING_PROJECT_2,
                        dbc.currentProject().getName(), dbc.currentUser().getName()));
            }

            publishedFolderCount = 0;
            int foldersSize = publishList.getFolderList().size();
            if (foldersSize > 0) {
                report.println(Messages.get().container(Messages.RPT_PUBLISH_FOLDERS_BEGIN_0),
                        I_CmsReport.FORMAT_HEADLINE);
            }

            Iterator<CmsResource> itFolders = publishList.getFolderList().iterator();
            I_CmsProjectDriver projectDriver = m_driverManager.getProjectDriver(dbc);
            I_CmsHistoryDriver historyDriver = m_driverManager.getHistoryDriver(dbc);
            while (itFolders.hasNext()) {
                CmsResource currentFolder = itFolders.next();
                try {
                    if (currentFolder.getState().isNew() || currentFolder.getState().isChanged()) {
                        // bounce the current publish task through all project drivers
                        projectDriver.publishFolder(dbc, report, ++publishedFolderCount, foldersSize, onlineProject,
                                new CmsFolder(currentFolder), publishList.getPublishHistoryId(), publishTag);

                        dbc.pop();

                        publishedIds.add(currentFolder.getStructureId());
                        // log it
                        CmsLogEntryType type = currentFolder.getState().isNew()
                                ? CmsLogEntryType.RESOURCE_PUBLISHED_NEW
                                : CmsLogEntryType.RESOURCE_PUBLISHED_MODIFIED;
                        m_driverManager.log(dbc, new CmsLogEntry(dbc, currentFolder.getStructureId(), type,
                                new String[] { currentFolder.getRootPath() }), true);

                        // delete old historical entries
                        historyDriver.deleteEntries(dbc, new CmsHistoryFile(currentFolder),
                                OpenCms.getSystemInfo().getHistoryVersions(), -1);

                        // reset the resource state to UNCHANGED and the last-modified-in-project-ID to 0
                        internalResetResourceState(dbc, currentFolder);

                        m_driverManager.unlockResource(dbc, currentFolder, true, true);
                    } else {
                        // state == unchanged !!?? something went really wrong
                        report.print(Messages.get().container(Messages.RPT_PUBLISH_FOLDER_0),
                                I_CmsReport.FORMAT_NOTE);
                        report.print(org.opencms.report.Messages.get().container(
                                org.opencms.report.Messages.RPT_ARGUMENT_1,
                                dbc.removeSiteRoot(currentFolder.getRootPath())));
                        report.print(org.opencms.report.Messages.get()
                                .container(org.opencms.report.Messages.RPT_DOTS_0));
                        report.println(org.opencms.report.Messages.get()
                                .container(org.opencms.report.Messages.RPT_FAILED_0), I_CmsReport.FORMAT_ERROR);

                        if (LOG.isErrorEnabled()) {
                            // the whole resource is printed out here
                            LOG.error(Messages.get().getBundle().key(Messages.LOG_PUBLISHING_FILE_3,
                                    String.valueOf(++publishedFolderCount), String.valueOf(foldersSize),
                                    currentFolder));
                        }
                    }

                    dbc.pop();
                } catch (Throwable t) {
                    dbc.report(report, Messages.get().container(Messages.ERR_ERROR_PUBLISHING_FOLDER_1,
                            currentFolder.getRootPath()), t);
                }
            }

            if (foldersSize > 0) {
                report.println(Messages.get().container(Messages.RPT_PUBLISH_FOLDERS_END_0),
                        I_CmsReport.FORMAT_HEADLINE);
            }

            ///////////////////////////////////////////////////////////////////////////////////////
            // publish changed/new/deleted files

            publishedFileCount = 0;
            int filesSize = publishList.getFileList().size();

            if (filesSize > 0) {
                report.println(Messages.get().container(Messages.RPT_PUBLISH_FILES_BEGIN_0),
                        I_CmsReport.FORMAT_HEADLINE);
            }

            Set<CmsUUID> deletedResourceIds = new HashSet<CmsUUID>();
            Set<CmsUUID> changedResourceIds = new HashSet<CmsUUID>();
            for (CmsResource res : publishList.getFileList()) {
                if (res.getState().isDeleted()) {
                    deletedResourceIds.add(res.getResourceId());
                } else {
                    changedResourceIds.add(res.getResourceId());
                }
            }
            Set<CmsUUID> changedAndDeletedResourceIds = Sets.intersection(deletedResourceIds, changedResourceIds);
            dbc.setAttribute(CmsDriverManager.KEY_CHANGED_AND_DELETED, changedAndDeletedResourceIds);

            Iterator<CmsResource> itFiles = publishList.getFileList().iterator();
            while (itFiles.hasNext()) {
                CmsResource currentResource = itFiles.next();
                try {
                    // bounce the current publish task through all project drivers
                    projectDriver.publishFile(dbc, report, ++publishedFileCount, filesSize, onlineProject,
                            currentResource, publishedContentIds, publishList.getPublishHistoryId(), publishTag);

                    CmsResourceState state = currentResource.getState();
                    if (!state.isDeleted()) {
                        // reset the resource state to UNCHANGED and the last-modified-in-project-ID to 0
                        internalResetResourceState(dbc, currentResource);
                    }

                    // unlock it
                    m_driverManager.unlockResource(dbc, currentResource, true, true);
                    // log it
                    CmsLogEntryType type = state.isNew() ? CmsLogEntryType.RESOURCE_PUBLISHED_NEW
                            : (state.isDeleted() ? CmsLogEntryType.RESOURCE_PUBLISHED_DELETED
                                    : CmsLogEntryType.RESOURCE_PUBLISHED_MODIFIED);
                    m_driverManager.log(dbc, new CmsLogEntry(dbc, currentResource.getStructureId(), type,
                            new String[] { currentResource.getRootPath() }), true);

                    publishedIds.add(currentResource.getStructureId());
                    dbc.pop();
                } catch (Throwable t) {
                    dbc.report(report, Messages.get().container(Messages.ERR_ERROR_PUBLISHING_FILE_1,
                            currentResource.getRootPath()), t);
                }
            }

            if (filesSize > 0) {
                report.println(Messages.get().container(Messages.RPT_PUBLISH_FILES_END_0),
                        I_CmsReport.FORMAT_HEADLINE);
            }

            ////////////////////////////////////////////////////////////////////////////////////////

            // publish deleted folders
            List<CmsResource> deletedFolders = publishList.getDeletedFolderList();
            if (deletedFolders.isEmpty()) {
                return;
            }

            deletedFolderCount = 0;
            int deletedFoldersSize = deletedFolders.size();
            if (deletedFoldersSize > 0) {
                report.println(Messages.get().container(Messages.RPT_DELETE_FOLDERS_BEGIN_0),
                        I_CmsReport.FORMAT_HEADLINE);
            }

            Iterator<CmsResource> itDeletedFolders = deletedFolders.iterator();
            while (itDeletedFolders.hasNext()) {
                CmsResource currentFolder = itDeletedFolders.next();

                try {
                    // bounce the current publish task through all project drivers
                    projectDriver.publishDeletedFolder(dbc, report, ++deletedFolderCount, deletedFoldersSize,
                            onlineProject, new CmsFolder(currentFolder), publishList.getPublishHistoryId(),
                            publishTag);

                    dbc.pop();
                    // delete old historical entries
                    m_driverManager.getHistoryDriver(dbc).deleteEntries(dbc, new CmsHistoryFile(currentFolder),
                            OpenCms.getSystemInfo().getHistoryVersionsAfterDeletion(), -1);

                    publishedIds.add(currentFolder.getStructureId());
                    // unlock it
                    m_driverManager.unlockResource(dbc, currentFolder, true, true);
                    // log it
                    m_driverManager.log(dbc,
                            new CmsLogEntry(dbc, currentFolder.getStructureId(),
                                    CmsLogEntryType.RESOURCE_PUBLISHED_DELETED,
                                    new String[] { currentFolder.getRootPath() }),
                            true);

                    dbc.pop();
                } catch (Throwable t) {
                    dbc.report(report, Messages.get().container(Messages.ERR_ERROR_PUBLISHING_DELETED_FOLDER_1,
                            currentFolder.getRootPath()), t);
                }
            }

            if (deletedFoldersSize > 0) {
                report.println(Messages.get().container(Messages.RPT_DELETE_FOLDERS_END_0),
                        I_CmsReport.FORMAT_HEADLINE);
            }
        } catch (OutOfMemoryError o) {
            // clear all caches to reclaim memory
            OpenCms.fireCmsEvent(
                    new CmsEvent(I_CmsEventListener.EVENT_CLEAR_CACHES, Collections.<String, Object>emptyMap()));

            CmsMessageContainer message = Messages.get().container(Messages.ERR_OUT_OF_MEMORY_0);
            if (LOG.isErrorEnabled()) {
                LOG.error(message.key(), o);
            }
            throw new CmsDataAccessException(message, o);
        } finally {
            // reset vfs driver internal info after publishing
            m_driverManager.getVfsDriver(dbc).publishVersions(dbc, null, false);
            Object[] msgArgs = new Object[] { String.valueOf(publishedFileCount),
                    String.valueOf(publishedFolderCount), String.valueOf(deletedFolderCount),
                    report.formatRuntime() };

            CmsMessageContainer message = Messages.get().container(Messages.RPT_PUBLISH_STAT_4, msgArgs);
            if (LOG.isInfoEnabled()) {
                LOG.info(message.key());
            }
            report.println(message);
        }
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#readLocks(org.opencms.db.CmsDbContext)
     */
    public List<CmsLock> readLocks(CmsDbContext dbc) throws CmsDataAccessException {

        List<CmsLock> locks = new ArrayList<CmsLock>(256);
        try {
            Query q = m_sqlManager.createQuery(dbc, C_RESOURCE_LOCKS_READALL);
            @SuppressWarnings("unchecked")
            List<CmsDAOResourceLocks> res = q.getResultList();
            for (CmsDAOResourceLocks rl : res) {
                String resourcePath = rl.getResourcePath();
                CmsUUID userId = new CmsUUID(rl.getUserId());
                CmsUUID projectId = new CmsUUID(rl.getProjectId());
                int lockType = rl.getLockType();
                CmsProject project;
                try {
                    project = readProject(dbc, projectId);
                } catch (CmsDataAccessException dae) {
                    // the project does not longer exist, ignore this lock (should usually not happen)
                    project = null;
                }
                if (project != null) {
                    CmsLock lock = new CmsLock(resourcePath, userId, project, CmsLockType.valueOf(lockType));
                    locks.add(lock);
                }
            }
            if (LOG.isDebugEnabled()) {
                LOG.debug(Messages.get().getBundle().key(Messages.LOG_DBG_READ_LOCKS_1, new Integer(locks.size())));
            }
        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        }

        return locks;
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#readLog(org.opencms.db.CmsDbContext, org.opencms.db.log.CmsLogFilter)
     */
    public List<CmsLogEntry> readLog(CmsDbContext dbc, CmsLogFilter filter) throws CmsDataAccessException {

        List<CmsLogEntry> entries = new ArrayList<CmsLogEntry>();

        try {
            // compose statement 
            StringBuffer queryBuf = new StringBuffer(256);
            queryBuf.append(m_sqlManager.readQuery(C_LOG_READ_ENTRIES));
            CmsPair<String, List<I_CmsQueryParameter>> conditionsAndParameters = prepareLogConditions(filter);
            List<I_CmsQueryParameter> params = conditionsAndParameters.getSecond();
            queryBuf.append(conditionsAndParameters.getFirst());

            if (LOG.isDebugEnabled()) {
                LOG.debug(queryBuf.toString());
            }
            Query q = m_sqlManager.createQueryFromJPQL(dbc, queryBuf.toString());
            for (int i = 0; i < params.size(); i++) {
                I_CmsQueryParameter param = params.get(i);
                param.insertIntoQuery(q, i + 1);
            }

            // execute
            @SuppressWarnings("unchecked")
            List<CmsDAOLog> res = q.getResultList();
            for (CmsDAOLog log : res) {
                // get results
                entries.add(internalReadLogEntry(log));
            }
        } catch (PersistenceException e) {
            throw new CmsDbSqlException(Messages.get().container(Messages.ERR_GENERIC_SQL_1, C_LOG_READ_ENTRIES),
                    e);
        }
        return entries;
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#readProject(org.opencms.db.CmsDbContext, CmsUUID)
     */
    public CmsProject readProject(CmsDbContext dbc, CmsUUID id) throws CmsDataAccessException {

        CmsProject project = null;
        try {
            Query q = m_sqlManager.createQuery(dbc, C_PROJECTS_READ_1);
            q.setParameter(1, id.toString());
            try {
                CmsDAOProjects p = (CmsDAOProjects) q.getSingleResult();
                project = internalCreateProject(p);
            } catch (NoResultException e) {
                throw new CmsDbEntryNotFoundException(
                        Messages.get().container(Messages.ERR_NO_PROJECT_WITH_ID_1, String.valueOf(id)));
            }
        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        }
        return project;
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#readProject(org.opencms.db.CmsDbContext, java.lang.String)
     */
    public CmsProject readProject(CmsDbContext dbc, String projectFqn) throws CmsDataAccessException {

        CmsProject project = null;

        try {
            Query q = m_sqlManager.createQuery(dbc, C_PROJECTS_READ_BYNAME_2);

            q.setParameter(1, CmsOrganizationalUnit.getSimpleName(projectFqn));
            q.setParameter(2, CmsOrganizationalUnit.SEPARATOR + CmsOrganizationalUnit.getParentFqn(projectFqn));

            try {
                CmsDAOProjects p = (CmsDAOProjects) q.getSingleResult();
                project = internalCreateProject(p);
            } catch (NoResultException e) {
                throw new CmsDbEntryNotFoundException(
                        Messages.get().container(Messages.ERR_NO_PROJECT_WITH_NAME_1, projectFqn));
            }
        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        }

        return project;
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#readProjectResource(org.opencms.db.CmsDbContext, CmsUUID, java.lang.String)
     */
    public String readProjectResource(CmsDbContext dbc, CmsUUID projectId, String resourcePath)
            throws CmsDataAccessException {

        String resName = null;

        try {
            Query q = m_sqlManager.createQuery(dbc, C_PROJECTRESOURCES_READ_2);

            // select resource from the database
            q.setParameter(1, projectId.toString());
            q.setParameter(2, resourcePath);

            try {
                resName = (String) q.getSingleResult();
            } catch (NoResultException e) {
                throw new CmsVfsResourceNotFoundException(
                        Messages.get().container(Messages.ERR_NO_PROJECTRESOURCE_1, resourcePath));
            }
        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        }

        return resName;
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#readProjectResources(org.opencms.db.CmsDbContext, org.opencms.file.CmsProject)
     */
    public List<String> readProjectResources(CmsDbContext dbc, CmsProject project) throws CmsDataAccessException {

        List<String> result = new ArrayList<String>();

        try {
            Query q = m_sqlManager.createQuery(dbc, C_PROJECTRESOURCES_READ_BY_ID_1);
            q.setParameter(1, project.getUuid().toString());
            @SuppressWarnings("unchecked")
            List<String> res = q.getResultList();

            for (String r : res) {
                result.add(r);
            }
        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        }

        return result;
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#readProjects(org.opencms.db.CmsDbContext, String)
     */
    public List<CmsProject> readProjects(CmsDbContext dbc, String ouFqn) throws CmsDataAccessException {

        if ((dbc.getRequestContext() != null)
                && (dbc.getRequestContext().getAttribute(DBC_ATTR_READ_PROJECT_FOR_RESOURCE) != null)) {
            dbc.getRequestContext().removeAttribute(DBC_ATTR_READ_PROJECT_FOR_RESOURCE);
            // TODO: this should get its own method in the interface
            return readProjectsForResource(dbc, ouFqn);
        }

        List<CmsProject> projects = new ArrayList<CmsProject>();

        try {
            // create the statement
            Query q = m_sqlManager.createQuery(dbc, C_PROJECTS_READ_BYOU_1);

            q.setParameter(1, CmsOrganizationalUnit.SEPARATOR + ouFqn + "%");
            @SuppressWarnings("unchecked")
            List<CmsDAOProjects> res = q.getResultList();

            for (CmsDAOProjects p : res) {
                projects.add(internalCreateProject(p));
            }
        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        }

        return (projects);
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#readProjectsForGroup(org.opencms.db.CmsDbContext, org.opencms.file.CmsGroup)
     */
    public List<CmsProject> readProjectsForGroup(CmsDbContext dbc, CmsGroup group) throws CmsDataAccessException {

        List<CmsProject> projects = new ArrayList<CmsProject>();

        try {
            // create the statement
            Query q = m_sqlManager.createQuery(dbc, C_PROJECTS_READ_BYGROUP_2);

            q.setParameter(1, group.getId().toString());
            q.setParameter(2, group.getId().toString());
            @SuppressWarnings("unchecked")
            List<CmsDAOProjects> res = q.getResultList();

            for (CmsDAOProjects p : res) {
                projects.add(internalCreateProject(p));
            }
        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        }

        return (projects);
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#readProjectsForManagerGroup(org.opencms.db.CmsDbContext, org.opencms.file.CmsGroup)
     */
    public List<CmsProject> readProjectsForManagerGroup(CmsDbContext dbc, CmsGroup group)
            throws CmsDataAccessException {

        List<CmsProject> projects = new ArrayList<CmsProject>();

        try {
            // create the statement
            Query q = m_sqlManager.createQuery(dbc, C_PROJECTS_READ_BYMANAGER_1);

            q.setParameter(1, group.getId().toString());
            @SuppressWarnings("unchecked")
            List<CmsDAOProjects> res = q.getResultList();

            for (CmsDAOProjects p : res) {
                projects.add(internalCreateProject(p));
            }
        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        }

        return (projects);
    }

    /**
     * Returns the projects of a given resource.<p>
     * 
     * @param dbc the database context
     * @param rootPath the resource root path
     * 
     * @return the projects of the resource, as a list of projects
     * 
     * @throws CmsDataAccessException if something goes wrong
     */
    public List<CmsProject> readProjectsForResource(CmsDbContext dbc, String rootPath)
            throws CmsDataAccessException {

        List<CmsProject> projects = new ArrayList<CmsProject>();

        try {
            Query q = m_sqlManager.createQuery(dbc, C_PROJECTS_READ_BYRESOURCE_1);
            q.setParameter(1, CmsVfsDriver.escapeDbWildcard(rootPath + "%"));
            @SuppressWarnings("unchecked")
            List<CmsDAOProjects> res = q.getResultList();

            if (res.size() > 0) {
                projects.add(internalCreateProject(res.get(0)));
            }

        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        }

        return projects;
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#readProjectsForUser(org.opencms.db.CmsDbContext, org.opencms.file.CmsUser)
     */
    public List<CmsProject> readProjectsForUser(CmsDbContext dbc, CmsUser user) throws CmsDataAccessException {

        List<CmsProject> projects = new ArrayList<CmsProject>();

        try {
            // create the statement
            Query q = m_sqlManager.createQuery(dbc, C_PROJECTS_READ_BYUSER_1);

            q.setParameter(1, user.getId().toString());
            @SuppressWarnings("unchecked")
            List<CmsDAOProjects> res = q.getResultList();

            for (CmsDAOProjects p : res) {
                projects.add(internalCreateProject(p));
            }

        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        }

        return (projects);
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#readPublishedResources(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID)
     */
    public List<CmsPublishedResource> readPublishedResources(CmsDbContext dbc, CmsUUID publishHistoryId)
            throws CmsDataAccessException {

        List<CmsPublishedResource> publishedResources = new ArrayList<CmsPublishedResource>();

        try {
            Query q = m_sqlManager.createQuery(dbc, C_SELECT_PUBLISHED_RESOURCES);
            q.setParameter(1, publishHistoryId.toString());
            @SuppressWarnings("unchecked")
            List<CmsDAOPublishHistory> res = q.getResultList();

            for (CmsDAOPublishHistory ph : res) {
                CmsUUID structureId = new CmsUUID(ph.getStructureId());
                CmsUUID resourceId = new CmsUUID(ph.getResourceId());
                String rootPath = ph.getResourcePath();
                int resourceState = ph.getResourceState();
                int resourceType = ph.getResourceType();
                int siblingCount = ph.getSiblingCount();
                int publishTag = ph.getPublishTag();

                // compose the resource state
                CmsResourceState state;
                if (resourceState == CmsPublishedResource.STATE_MOVED_SOURCE.getState()) {
                    state = CmsPublishedResource.STATE_MOVED_SOURCE;
                } else if (resourceState == CmsPublishedResource.STATE_MOVED_DESTINATION.getState()) {
                    state = CmsPublishedResource.STATE_MOVED_DESTINATION;
                } else {
                    state = CmsResourceState.valueOf(resourceState);
                }

                publishedResources.add(new CmsPublishedResource(structureId, resourceId, publishTag, rootPath,
                        resourceType, structureId.isNullUUID() ? false : CmsFolder.isFolderType(resourceType),
                        state, siblingCount));
            }
        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        }

        return publishedResources;
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#readPublishJob(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID)
     */
    public CmsPublishJobInfoBean readPublishJob(CmsDbContext dbc, CmsUUID publishHistoryId)
            throws CmsDataAccessException {

        CmsPublishJobInfoBean result = null;
        try {
            Query q = m_sqlManager.createQuery(dbc, C_PUBLISHJOB_READ_JOB);
            q.setParameter(1, publishHistoryId.toString());
            try {
                CmsDAOPublishJobs pj = (CmsDAOPublishJobs) q.getSingleResult();
                result = createPublishJobInfoBean(pj);
            } catch (NoResultException e) {
                throw new CmsDbEntryNotFoundException(
                        Messages.get().container(Messages.ERR_READ_PUBLISH_JOB_1, publishHistoryId.toString()));
            }

        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        }
        return result;
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#readPublishJobs(org.opencms.db.CmsDbContext, long, long)
     */
    public List<CmsPublishJobInfoBean> readPublishJobs(CmsDbContext dbc, long startTime, long endTime)
            throws CmsDataAccessException {

        List<CmsPublishJobInfoBean> result = null;
        try {
            Query q = m_sqlManager.createQuery(dbc, C_PUBLISHJOB_READ_JOBS_IN_TIMERANGE);
            q.setParameter(1, Long.valueOf(startTime));
            q.setParameter(2, Long.valueOf(endTime));
            @SuppressWarnings("unchecked")
            List<CmsDAOPublishJobs> res = q.getResultList();

            result = new ArrayList<CmsPublishJobInfoBean>();
            for (CmsDAOPublishJobs pj : res) {
                result.add(createPublishJobInfoBean(pj));
            }
        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        }

        return result;
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#readPublishList(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID)
     */
    public CmsPublishList readPublishList(CmsDbContext dbc, CmsUUID publishHistoryId)
            throws CmsDataAccessException {

        CmsPublishList publishList = null;

        try {
            Query q = m_sqlManager.createQuery(dbc, C_PUBLISHJOB_READ_PUBLISHLIST);
            q.setParameter(1, publishHistoryId.toString());
            try {
                CmsDAOPublishJobs pj = (CmsDAOPublishJobs) q.getSingleResult();
                publishList = internalDeserializePublishList(pj.getPublishList());
            } catch (NoResultException e) {
                throw new CmsDataAccessException(
                        Messages.get().container(Messages.ERR_READ_PUBLISH_JOB_1, publishHistoryId.toString()));
            }

        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        } catch (Exception e) {
            throw new CmsDataAccessException(
                    Messages.get().container(Messages.ERR_PUBLISHLIST_DESERIALIZATION_FAILED_1, publishHistoryId),
                    e);
        }

        return publishList;
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#readPublishReportContents(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID)
     */
    public byte[] readPublishReportContents(CmsDbContext dbc, CmsUUID publishHistoryId)
            throws CmsDataAccessException {

        byte[] bytes = null;

        try {
            Query q = m_sqlManager.createQuery(dbc, C_PUBLISHJOB_READ_REPORT);
            q.setParameter(1, publishHistoryId.toString());
            try {
                CmsDAOPublishJobs pj = (CmsDAOPublishJobs) q.getSingleResult();
                bytes = pj.getPublishReport();
            } catch (NoResultException e) {
                throw new CmsDataAccessException(
                        Messages.get().container(Messages.ERR_READ_PUBLISH_JOB_1, publishHistoryId.toString()));
            }

        } catch (PersistenceException e) {
            LOG.error(C_PUBLISHJOB_READ_REPORT, e);
            bytes = Messages.get().container(Messages.ERR_GENERIC_SQL_1, C_PUBLISHJOB_READ_REPORT).key().getBytes();
        }

        return bytes;
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#readStaticExportPublishedResourceParameters(org.opencms.db.CmsDbContext, java.lang.String)
     */
    public String readStaticExportPublishedResourceParameters(CmsDbContext dbc, String rfsName)
            throws CmsDataAccessException {

        String returnValue = null;

        try {
            Query q = m_sqlManager.createQuery(dbc, C_STATICEXPORT_READ_PUBLISHED_LINK_PARAMETERS);
            q.setParameter(1, rfsName);
            try {
                returnValue = (String) q.getSingleResult();
            } catch (NoResultException e) {
                // do nothing
            }

        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        }

        return returnValue;
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#readStaticExportResources(org.opencms.db.CmsDbContext, int, long)
     */
    public List<String> readStaticExportResources(CmsDbContext dbc, int parameterResources, long timestamp)
            throws CmsDataAccessException {

        List<String> returnValue = new ArrayList<String>();

        if (parameterResources == CmsStaticExportManager.EXPORT_LINK_WITHOUT_PARAMETER) {
            timestamp = 0;
        }
        try {
            Query q = m_sqlManager.createQuery(dbc, C_STATICEXPORT_READ_ALL_PUBLISHED_LINKS);
            q.setParameter(1, Integer.valueOf(parameterResources));
            q.setParameter(2, Long.valueOf(timestamp));
            @SuppressWarnings("unchecked")
            List<String> res = q.getResultList();
            // add all resource names to the list of return values
            for (String path : res) {
                returnValue.add(path);
            }
        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        }

        return returnValue;
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#setDriverManager(org.opencms.db.CmsDriverManager)
     */
    public void setDriverManager(CmsDriverManager driverManager) {

        m_driverManager = driverManager;
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#setSqlManager(org.opencms.db.CmsSqlManager)
     */
    public void setSqlManager(org.opencms.db.CmsSqlManager manager) {

        m_sqlManager = (CmsSqlManager) manager;
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#unmarkProjectResources(org.opencms.db.CmsDbContext, org.opencms.file.CmsProject)
     */
    public void unmarkProjectResources(CmsDbContext dbc, CmsProject project) throws CmsDataAccessException {

        // finally remove the project id form all resources 
        try {
            Query q = m_sqlManager.createQuery(dbc, C_RESOURCES_UNMARK);
            // create the statement
            q.setParameter(1, project.getUuid().toString());
            @SuppressWarnings("unchecked")
            List<CmsDAOOfflineResources> res = q.getResultList();

            for (CmsDAOOfflineResources r : res) {
                r.setProjectLastModified("00000000-0000-0000-0000-000000000000");
            }
        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        }
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#writeLocks(org.opencms.db.CmsDbContext, java.util.List)
     */
    public void writeLocks(CmsDbContext dbc, List<CmsLock> locks) throws CmsDataAccessException {

        CmsDAOResourceLocks rl;

        try {
            Query q = m_sqlManager.createQuery(dbc, C_RESOURCE_LOCKS_DELETEALL);
            @SuppressWarnings("unchecked")
            List<CmsDAOResourceLocks> res = q.getResultList();
            int deleted = 0;
            for (CmsDAOResourceLocks r : res) {
                m_sqlManager.remove(dbc, r);
                deleted++;
            }
            if (LOG.isDebugEnabled()) {
                LOG.debug(Messages.get().getBundle().key(Messages.LOG_DBG_CLEAR_LOCKS_1, new Integer(deleted)));
            }
            if (LOG.isDebugEnabled()) {
                LOG.debug("SQL :" + "Inserting rows in the CMS_RESOURCE_LOCKS table.");
            }
            Iterator<CmsLock> i = locks.iterator();
            int count = 0;
            while (i.hasNext()) {
                CmsLock lock = i.next();
                // only persist locks that should be written to the DB
                CmsLock sysLock = lock.getSystemLock();
                if (sysLock.isPersistent()) {
                    // persist system lock

                    rl = new CmsDAOResourceLocks();

                    rl.setResourcePath(sysLock.getResourceName());
                    rl.setUserId(sysLock.getUserId().toString());
                    rl.setProjectId(sysLock.getProjectId().toString());
                    rl.setLockType(sysLock.getType().hashCode());

                    m_sqlManager.persist(dbc, rl);
                    count++;
                }
                CmsLock editLock = lock.getEditionLock();
                if (editLock.isPersistent()) {
                    // persist edition lock
                    rl = new CmsDAOResourceLocks();

                    rl.setResourcePath(editLock.getResourceName());
                    rl.setUserId(editLock.getUserId().toString());
                    rl.setProjectId(editLock.getProjectId().toString());
                    rl.setLockType(editLock.getType().hashCode());

                    m_sqlManager.persist(dbc, rl);
                    count++;
                }
            }
            if (LOG.isDebugEnabled()) {
                LOG.debug(Messages.get().getBundle().key(Messages.LOG_DBG_WRITE_LOCKS_1, new Integer(count)));
            }
        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        }
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#writeProject(org.opencms.db.CmsDbContext, org.opencms.file.CmsProject)
     */
    public void writeProject(CmsDbContext dbc, CmsProject project) throws CmsDataAccessException {

        if (CmsStringUtil.isEmptyOrWhitespaceOnly(project.getDescription())) {
            project.setDescription(" ");
        }

        try {
            Query q = m_sqlManager.createQuery(dbc, C_PROJECTS_WRITE_6);
            q.setParameter(1, project.getUuid().toString());
            @SuppressWarnings("unchecked")
            List<CmsDAOProjects> res = q.getResultList();

            for (CmsDAOProjects pr : res) {
                pr.setProjectDescription(project.getDescription());
                pr.setGroupId(project.getGroupId().toString());
                pr.setManagerGroupId(project.getManagerGroupId().toString());
                pr.setProjectFlags(project.getFlags());
                pr.setProjectType(project.getType().getMode());
            }
        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        }
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#writePublishHistory(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID, org.opencms.db.CmsPublishedResource)
     */
    public void writePublishHistory(CmsDbContext dbc, CmsUUID publishId, CmsPublishedResource resource)
            throws CmsDataAccessException {

        try {
            CmsDAOPublishHistory ph = new CmsDAOPublishHistory();
            ph.setPublishTag(resource.getPublishTag());
            ph.setStructureId(resource.getStructureId().toString());
            ph.setResourceId(resource.getResourceId().toString());
            ph.setResourcePath(resource.getRootPath());
            ph.setResourceState(resource.getMovedState().getState());
            ph.setResourceType(resource.getType());
            ph.setHistoryId(publishId.toString());
            ph.setSiblingCount(resource.getSiblingCount());

            m_sqlManager.persist(dbc, ph);
        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        }
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#writePublishJob(org.opencms.db.CmsDbContext, org.opencms.publish.CmsPublishJobInfoBean)
     */
    public void writePublishJob(CmsDbContext dbc, CmsPublishJobInfoBean publishJob) throws CmsDataAccessException {

        try {
            CmsDAOPublishJobs pj = m_sqlManager.find(dbc, CmsDAOPublishJobs.class,
                    publishJob.getPublishHistoryId().toString());
            if (pj != null) {
                pj.setProjectId(publishJob.getProjectId().toString());
                pj.setProjectName(publishJob.getProjectName());
                pj.setUserId(publishJob.getUserId().toString());
                pj.setPublishLocale(publishJob.getLocale().toString());
                pj.setPublishFlags(publishJob.getFlags());
                pj.setResourceCount(publishJob.getSize());
                pj.setEnqueueTime(publishJob.getEnqueueTime());
                pj.setStartTime(publishJob.getStartTime());
                pj.setFinishTime(publishJob.getFinishTime());
            }

        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        }
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#writePublishReport(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID, byte[])
     */
    public void writePublishReport(CmsDbContext dbc, CmsUUID publishId, byte[] content)
            throws CmsDataAccessException {

        try {
            CmsDAOPublishJobs pj = m_sqlManager.find(dbc, CmsDAOPublishJobs.class, publishId.toString());
            if (pj != null) {
                pj.setPublishReport(content);
            }

        } catch (PersistenceException e) {
            throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
        }
    }

    /**
     * @see org.opencms.db.I_CmsProjectDriver#writeStaticExportPublishedResource(org.opencms.db.CmsDbContext, java.lang.String, int, java.lang.String, long)
     */
    public void writeStaticExportPublishedResource(CmsDbContext dbc, String resourceName, int linkType,
            String linkParameter, long timestamp) throws CmsDataAccessException {

        int returnValue = 0;
        // first check if a record with this resource name does already exist
        try {
            Query q = m_sqlManager.createQuery(dbc, C_STATICEXPORT_READ_PUBLISHED_RESOURCES);
            q.setParameter(1, resourceName);
            try {
                returnValue = 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);
        }

        // there was no entry found, so add it to the database
        if (returnValue == 0) {
            try {
                CmsDAOStaticExportLinks sel = new CmsDAOStaticExportLinks();

                sel.setLinkId(new CmsUUID().toString());
                sel.setLinkRfsPath(resourceName);
                sel.setLinkType(linkType);
                sel.setLinkParameter(linkParameter);
                sel.setLinkTimestamp(timestamp);

                m_sqlManager.persist(dbc, sel);
            } catch (PersistenceException e) {
                throw new CmsDataAccessException(Messages.get().container(Messages.ERR_JPA_PERSITENCE, e), e);
            }
        }
    }

    /**
     * Creates a <code>CmsPublishJobInfoBean</code> from a result set.<p>
     * 
     * @param pj the result set 
     * 
     * @return an initialized <code>CmsPublishJobInfoBean</code>
     */
    protected CmsPublishJobInfoBean createPublishJobInfoBean(CmsDAOPublishJobs pj) {

        return new CmsPublishJobInfoBean(new CmsUUID(pj.getHistoryId()), new CmsUUID(pj.getProjectId()),
                pj.getProjectName(), new CmsUUID(pj.getUserId()), pj.getPublishLocale(), pj.getPublishFlags(),
                pj.getResourceCount(), pj.getEnqueueTime(), pj.getStartTime(), pj.getFinishTime());
    }

    /**
     * Checks if the given resource (by id) is available in the online project,
     * if there exists a resource with a different path (a moved file), then the 
     * online entry is moved to the right (new) location before publishing.<p>
     * 
     * @param dbc the db context
     * @param onlineProject the online project
     * @param offlineResource the offline resource to check
     * @param publishHistoryId the publish history id
     * @param publishTag the publish tag
     * 
     * @return <code>true</code> if the resource has actually been moved
     * 
     * @throws CmsDataAccessException if something goes wrong
     */
    protected CmsResourceState fixMovedResource(CmsDbContext dbc, CmsProject onlineProject,
            CmsResource offlineResource, CmsUUID publishHistoryId, int publishTag) throws CmsDataAccessException {

        CmsResource onlineResource;
        // check if the resource has been moved since last publishing
        try {
            onlineResource = m_driverManager.getVfsDriver(dbc).readResource(dbc, onlineProject.getUuid(),
                    offlineResource.getStructureId(), true);
            if (onlineResource.getRootPath().equals(offlineResource.getRootPath())) {
                // resource changed, not moved 
                return offlineResource.getState();
            }
        } catch (CmsVfsResourceNotFoundException e) {
            // ok, resource new, not moved
            return offlineResource.getState();
        }

        // move the online resource to the new position
        m_driverManager.getVfsDriver(dbc).moveResource(dbc, onlineProject.getUuid(), onlineResource,
                offlineResource.getRootPath());

        try {
            // write the resource to the publish history
            m_driverManager.getProjectDriver(dbc).writePublishHistory(dbc, publishHistoryId,
                    new CmsPublishedResource(onlineResource, publishTag, CmsPublishedResource.STATE_MOVED_SOURCE));
        } catch (CmsDataAccessException e) {
            if (LOG.isErrorEnabled()) {
                LOG.error(Messages.get().getBundle().key(Messages.LOG_WRITING_PUBLISHING_HISTORY_1,
                        onlineResource.getRootPath()), e);
            }
            throw e;
        }
        return offlineResource.getState().isDeleted() ? CmsResource.STATE_DELETED
                : CmsPublishedResource.STATE_MOVED_DESTINATION;
    }

    /**
     * Returns a SQL parameter string for the given data.<p>
     * 
     * @param data the data
     * 
     * @return the SQL parameter
     */
    protected String getParameterString(Collection<?> data) {

        StringBuffer conditions = new StringBuffer();
        conditions.append(BEGIN_CONDITION);
        Iterator<?> it = data.iterator();
        while (it.hasNext()) {
            it.next();
            conditions.append("?");
            if (it.hasNext()) {
                conditions.append(", ");
            }
        }
        conditions.append(END_CONDITION);
        return conditions.toString();
    }

    /**
     * Creates a new project from the current row of the given result set.<p>
     * 
     * @param p the result set
     * 
     * @return the new project
     */
    protected CmsProject internalCreateProject(CmsDAOProjects p) {

        String ou = CmsOrganizationalUnit.removeLeadingSeparator(p.getProjectOu());
        return new CmsProject(new CmsUUID(p.getProjectId()), ou + p.getProjectName(), p.getProjectDescription(),
                new CmsUUID(p.getUserId()), new CmsUUID(p.getGroupId()), new CmsUUID(p.getManagerGroupId()),
                p.getProjectFlags(), p.getDateCreated(), CmsProject.CmsProjectType.valueOf(p.getProjectType()));
    }

    /**
     * Builds a publish list from serialized data.<p>
     * 
     * @param bytes the byte array containing the serailized data for the publish list
     * @return the initialized publish list
     * 
     * @throws IOException if deserialization fails
     * @throws ClassNotFoundException if deserialization fails
     */
    protected CmsPublishList internalDeserializePublishList(byte[] bytes)
            throws IOException, ClassNotFoundException {

        ByteArrayInputStream bin = new ByteArrayInputStream(bytes);
        ObjectInputStream oin = new ObjectInputStream(bin);
        return (CmsPublishList) oin.readObject();
    }

    /**
     * Creates a new {@link CmsLogEntry} object from the given result set entry.<p>
     * 
     * @param daoLog the result set 
     *  
     * @return the new {@link CmsLogEntry} object
     */
    protected CmsLogEntry internalReadLogEntry(CmsDAOLog daoLog) {

        CmsUUID userId = new CmsUUID(daoLog.getUserId());
        long date = daoLog.getLogDate();
        CmsUUID structureId = new CmsUUID(daoLog.getStructureId());
        CmsLogEntryType type = CmsLogEntryType.valueOf(daoLog.getLogType());
        String[] data = CmsStringUtil.splitAsArray(daoLog.getLogData(), '|');
        return new CmsLogEntry(userId, date, structureId, type, data);
    }

    /**
     * Resets the state to UNCHANGED for a specified resource.<p>
     * 
     * @param dbc the current database context
     * @param resource the Cms resource
     * 
     * @throws CmsDataAccessException if something goes wrong
     */
    protected void internalResetResourceState(CmsDbContext dbc, CmsResource resource)
            throws CmsDataAccessException {

        try {
            // reset the resource state
            resource.setState(CmsResource.STATE_UNCHANGED);
            m_driverManager.getVfsDriver(dbc).writeResourceState(dbc, dbc.currentProject(), resource,
                    CmsDriverManager.UPDATE_ALL, true);
        } catch (CmsDataAccessException e) {
            if (LOG.isErrorEnabled()) {
                LOG.error(Messages.get().getBundle().key(Messages.LOG_ERROR_RESETTING_RESOURCE_STATE_1,
                        resource.getRootPath()), e);
            }
            throw e;
        }
    }

    /**
     * Serialize publish list to write it as byte array to the database.<p>
     * 
     * @param publishList the publish list
     * @return byte array containing the publish list data
     * @throws IOException if something goes wrong
     */
    protected byte[] internalSerializePublishList(CmsPublishList publishList) throws IOException {

        // serialize the publish list
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        ObjectOutputStream oout = new ObjectOutputStream(bout);
        oout.writeObject(publishList);
        oout.close();
        return bout.toByteArray();
    }

    /**
     * Writes the needed history entries.<p>
     * 
     * @param dbc the current database context
     * @param resource the offline resource
     * @param state the state to store in the publish history entry
     * @param properties the offline properties
     * @param publishHistoryId the current publish process id
     * @param publishTag the current publish process tag
     * 
     * @throws CmsDataAccessException if something goes wrong
     */
    protected void internalWriteHistory(CmsDbContext dbc, CmsResource resource, CmsResourceState state,
            List<CmsProperty> properties, CmsUUID publishHistoryId, int publishTag) throws CmsDataAccessException {

        try {
            if (OpenCms.getSystemInfo().isHistoryEnabled()) {
                // write the resource to the historical archive
                if (properties == null) {
                    properties = m_driverManager.getVfsDriver(dbc).readPropertyObjects(dbc, dbc.currentProject(),
                            resource);
                }
                m_driverManager.getHistoryDriver(dbc).writeResource(dbc, resource, properties, publishTag);
            }
            // write the resource to the publish history
            m_driverManager.getProjectDriver().writePublishHistory(dbc, publishHistoryId,
                    new CmsPublishedResource(resource, publishTag, state));
        } catch (CmsDataAccessException e) {
            if (LOG.isErrorEnabled()) {
                LOG.error(Messages.get().getBundle().key(Messages.LOG_WRITING_PUBLISHING_HISTORY_1,
                        resource.getRootPath()), e);
            }
            throw e;
        }
    }

    /**
     * Build the whole WHERE SQL statement part for the given log entry filter.<p>
     * 
     * @param filter the filter
     * 
     * @return a pair containing both the SQL and the parameters for it
     */
    protected CmsPair<String, List<I_CmsQueryParameter>> prepareLogConditions(CmsLogFilter filter) {

        List<I_CmsQueryParameter> params = new ArrayList<I_CmsQueryParameter>();
        StringBuffer conditions = new StringBuffer();

        // user id filter
        if (filter.getUserId() != null) {
            if (conditions.length() == 0) {
                conditions.append(BEGIN_CONDITION);
            } else {
                conditions.append(BEGIN_INCLUDE_CONDITION);
            }
            conditions.append(m_sqlManager.readQuery(C_LOG_FILTER_USER_ID));
            params.add(new CmsQueryStringParameter(filter.getUserId().toString()));
            conditions.append(END_CONDITION);
        }

        // resource id filter
        if (filter.getStructureId() != null) {
            if (conditions.length() == 0) {
                conditions.append(BEGIN_CONDITION);
            } else {
                conditions.append(BEGIN_INCLUDE_CONDITION);
            }
            conditions.append(m_sqlManager.readQuery(C_LOG_FILTER_RESOURCE_ID));
            params.add(new CmsQueryStringParameter(filter.getStructureId().toString()));
            conditions.append(END_CONDITION);
        }

        // date from filter
        if (filter.getDateFrom() != CmsResource.DATE_RELEASED_DEFAULT) {
            if (conditions.length() == 0) {
                conditions.append(BEGIN_CONDITION);
            } else {
                conditions.append(BEGIN_INCLUDE_CONDITION);
            }
            conditions.append(m_sqlManager.readQuery(C_LOG_FILTER_DATE_FROM));
            params.add(new CmsQueryLongParameter(filter.getDateFrom()));
            conditions.append(END_CONDITION);
        }

        // date to filter
        if (filter.getDateTo() != CmsResource.DATE_RELEASED_DEFAULT) {
            if (conditions.length() == 0) {
                conditions.append(BEGIN_CONDITION);
            } else {
                conditions.append(BEGIN_INCLUDE_CONDITION);
            }
            conditions.append(m_sqlManager.readQuery(C_LOG_FILTER_DATE_TO));
            params.add(new CmsQueryLongParameter(filter.getDateTo()));
            conditions.append(END_CONDITION);
        }

        // include type filter
        Set<CmsLogEntryType> includeTypes = filter.getIncludeTypes();
        if (!includeTypes.isEmpty()) {
            if (conditions.length() == 0) {
                conditions.append(BEGIN_CONDITION);
            } else {
                conditions.append(BEGIN_INCLUDE_CONDITION);
            }
            conditions.append(m_sqlManager.readQuery(C_LOG_FILTER_INCLUDE_TYPE));
            conditions.append(BEGIN_CONDITION);
            Iterator<CmsLogEntryType> it = includeTypes.iterator();
            while (it.hasNext()) {
                CmsLogEntryType type = it.next();
                conditions.append("?");
                params.add(new CmsQueryIntParameter(type.getId()));
                if (it.hasNext()) {
                    conditions.append(", ");
                }
            }
            conditions.append(END_CONDITION);
            conditions.append(END_CONDITION);
        }

        // exclude type filter
        Set<CmsLogEntryType> excludeTypes = filter.getExcludeTypes();
        if (!excludeTypes.isEmpty()) {
            if (conditions.length() == 0) {
                conditions.append(BEGIN_CONDITION);
            } else {
                conditions.append(BEGIN_INCLUDE_CONDITION);
            }
            conditions.append(m_sqlManager.readQuery(C_LOG_FILTER_EXCLUDE_TYPE));
            conditions.append(BEGIN_CONDITION);
            Iterator<CmsLogEntryType> it = excludeTypes.iterator();
            while (it.hasNext()) {
                CmsLogEntryType type = it.next();
                conditions.append("?");
                params.add(new CmsQueryIntParameter(type.getId()));
                if (it.hasNext()) {
                    conditions.append(", ");
                }
            }
            conditions.append(END_CONDITION);
            conditions.append(END_CONDITION);
        }
        return CmsPair.create(conditions.toString(), params);
    }

    /**
     * Publishes a changed file.<p>
     * 
     * @param dbc the current database context
     * @param onlineProject the online project
     * @param offlineResource the resource to publish
     * @param publishedResourceIds contains the UUIDs of already published content records
     * @param publishHistoryId the publish history id
     * @param publishTag the publish tag
     * 
     * @throws CmsDataAccessException is something goes wrong
     */
    protected void publishChangedFile(CmsDbContext dbc, CmsProject onlineProject, CmsResource offlineResource,
            Set<CmsUUID> publishedResourceIds, CmsUUID publishHistoryId, int publishTag)
            throws CmsDataAccessException {

        CmsResource onlineResource = null;
        boolean needToUpdateContent = true;
        boolean existsOnline = m_driverManager.getVfsDriver(dbc).validateStructureIdExists(dbc,
                CmsProject.ONLINE_PROJECT_ID, offlineResource.getStructureId());
        CmsResourceState resourceState = existsOnline
                ? fixMovedResource(dbc, onlineProject, offlineResource, publishHistoryId, publishTag)
                : offlineResource.getState();
        try {
            // reset the labeled link flag before writing the online file
            int flags = offlineResource.getFlags();
            flags &= ~CmsResource.FLAG_LABELED;
            offlineResource.setFlags(flags);

            if (existsOnline) {
                // read the file header online                   
                onlineResource = m_driverManager.getVfsDriver(dbc).readResource(dbc, onlineProject.getUuid(),
                        offlineResource.getStructureId(), false);
                needToUpdateContent = (onlineResource.getDateContent() < offlineResource.getDateContent());
                // delete the properties online
                m_driverManager.getVfsDriver(dbc).deletePropertyObjects(dbc, onlineProject.getUuid(),
                        onlineResource, CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES);

                // if the offline file has a resource ID different from the online file
                // (probably because a deleted file was replaced by a new file with the
                // same name), the properties mapped to the "old" resource ID have to be
                // deleted also offline. if this is the case, the online and offline structure
                // ID's do match, but the resource ID's are different. structure IDs are reused
                // to prevent orphan structure records in the online project.
                if (!onlineResource.getResourceId().equals(offlineResource.getResourceId())) {
                    List<CmsProperty> offlineProperties = m_driverManager.getVfsDriver(dbc).readPropertyObjects(dbc,
                            dbc.currentProject(), onlineResource);
                    if (offlineProperties.size() > 0) {
                        for (int i = 0; i < offlineProperties.size(); i++) {
                            CmsProperty property = offlineProperties.get(i);
                            property.setStructureValue(null);
                            property.setResourceValue(CmsProperty.DELETE_VALUE);
                        }
                        m_driverManager.getVfsDriver(dbc).writePropertyObjects(dbc, dbc.currentProject(),
                                onlineResource, offlineProperties);
                    }
                }
            }
        } catch (CmsDataAccessException e) {
            if (LOG.isErrorEnabled()) {
                LOG.error(Messages.get().getBundle().key(Messages.LOG_DELETING_PROPERTIES_1,
                        offlineResource.toString()), e);
            }
            throw e;
        }

        CmsFile newFile;
        try {
            // publish the file content
            newFile = m_driverManager.getProjectDriver(dbc).publishFileContent(dbc, dbc.currentProject(),
                    onlineProject, offlineResource, publishedResourceIds, needToUpdateContent, publishTag);

        } catch (CmsDataAccessException e) {
            if (LOG.isErrorEnabled()) {
                LOG.error(Messages.get().getBundle().key(Messages.LOG_PUBLISHING_RESOURCE_1,
                        offlineResource.getRootPath()), e);
            }
            throw e;
        }

        List<CmsProperty> offlineProperties;
        try {
            // write the properties online
            offlineProperties = m_driverManager.getVfsDriver(dbc).readPropertyObjects(dbc, dbc.currentProject(),
                    offlineResource);
            CmsProperty.setAutoCreatePropertyDefinitions(offlineProperties, true);
            m_driverManager.getVfsDriver(dbc).writePropertyObjects(dbc, onlineProject, newFile, offlineProperties);
        } catch (CmsDataAccessException e) {
            if (LOG.isErrorEnabled()) {
                LOG.error(
                        Messages.get().getBundle().key(Messages.LOG_PUBLISHING_PROPERTIES_1, newFile.getRootPath()),
                        e);
            }
            throw e;
        }

        try {
            // write the ACL online
            m_driverManager.getUserDriver(dbc).publishAccessControlEntries(dbc, dbc.currentProject(), onlineProject,
                    newFile.getResourceId(), offlineResource.getResourceId());
        } catch (CmsDataAccessException e) {
            if (LOG.isErrorEnabled()) {
                LOG.error(Messages.get().getBundle().key(Messages.LOG_PUBLISHING_ACL_1, newFile.getRootPath()), e);
            }
            throw e;
        }

        CmsFile offlineFile = new CmsFile(offlineResource);
        offlineFile.setContents(newFile.getContents());
        internalWriteHistory(dbc, offlineFile, resourceState, offlineProperties, publishHistoryId, publishTag);

        m_driverManager.getVfsDriver(dbc).updateRelations(dbc, onlineProject, offlineResource);
    }

    /**
     * Publishes a deleted file.<p>
     * 
     * @param dbc the current database context
     * @param onlineProject the online project
     * @param offlineResource the resource to publish
     * @param publishHistoryId the publish history id
     * @param publishTag the publish tag
     * 
     * @throws CmsDataAccessException is something goes wrong
     */
    protected void publishDeletedFile(CmsDbContext dbc, CmsProject onlineProject, CmsResource offlineResource,
            CmsUUID publishHistoryId, int publishTag) throws CmsDataAccessException {

        CmsResourceState resourceState = fixMovedResource(dbc, onlineProject, offlineResource, publishHistoryId,
                publishTag);

        boolean existsOnline = m_driverManager.getVfsDriver(dbc).validateStructureIdExists(dbc,
                CmsProject.ONLINE_PROJECT_ID, offlineResource.getStructureId());
        CmsResource onlineResource = null;
        if (existsOnline) {
            try {
                // read the file header online
                onlineResource = m_driverManager.getVfsDriver(dbc).readResource(dbc, onlineProject.getUuid(),
                        offlineResource.getStructureId(), true);
            } catch (CmsDataAccessException e) {
                if (LOG.isErrorEnabled()) {
                    LOG.error(Messages.get().getBundle().key(Messages.LOG_READING_RESOURCE_1,
                            offlineResource.getRootPath()), e);
                }
                throw e;
            }
        }
        if (offlineResource.isLabeled() && !m_driverManager.labelResource(dbc, offlineResource, null, 2)) {
            // update the resource flags to "unlabeled" of the siblings of the offline resource
            int flags = offlineResource.getFlags();
            flags &= ~CmsResource.FLAG_LABELED;
            offlineResource.setFlags(flags);
        }

        // write history before deleting
        CmsFile offlineFile = new CmsFile(offlineResource);
        offlineFile.setContents(m_driverManager.getVfsDriver(dbc).readContent(dbc, dbc.currentProject().getUuid(),
                offlineFile.getResourceId()));
        internalWriteHistory(dbc, offlineFile, resourceState, null, publishHistoryId, publishTag);

        int propertyDeleteOption = -1;
        try {
            // delete the properties online and offline
            if (offlineResource.getSiblingCount() > 1) {
                // there are other siblings- delete only structure property values and keep the resource property values
                propertyDeleteOption = CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_VALUES;
            } else {
                // there are no other siblings- delete both the structure and resource property values
                propertyDeleteOption = CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES;
            }

            if (existsOnline) {
                m_driverManager.getVfsDriver(dbc).deletePropertyObjects(dbc, onlineProject.getUuid(),
                        onlineResource, propertyDeleteOption);
            }
            m_driverManager.getVfsDriver(dbc).deletePropertyObjects(dbc, dbc.currentProject().getUuid(),
                    offlineResource, propertyDeleteOption);

            // if the offline file has a resource ID different from the online file
            // (probably because a (deleted) file was replaced by a new file with the
            // same name), the properties with the "old" resource ID have to be
            // deleted also offline
            if (existsOnline && (onlineResource != null)
                    && !onlineResource.getResourceId().equals(offlineResource.getResourceId())) {
                m_driverManager.getVfsDriver(dbc).deletePropertyObjects(dbc, dbc.currentProject().getUuid(),
                        onlineResource, CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES);
            }
        } catch (CmsDataAccessException e) {
            if (LOG.isErrorEnabled()) {
                LOG.error(Messages.get().getBundle().key(Messages.LOG_DELETING_PROPERTIES_1,
                        offlineResource.getRootPath()), e);
            }
            throw e;
        }

        try {
            // remove the file online and offline
            m_driverManager.getVfsDriver(dbc).removeFile(dbc, dbc.currentProject().getUuid(), offlineResource);
            if (existsOnline && (onlineResource != null)) {
                m_driverManager.getVfsDriver(dbc).removeFile(dbc, onlineProject.getUuid(), onlineResource);
            }
        } catch (CmsDataAccessException e) {
            if (LOG.isErrorEnabled()) {
                LOG.error(Messages.get().getBundle().key(Messages.LOG_REMOVING_RESOURCE_1,
                        offlineResource.getRootPath()), e);
            }
            throw e;
        }

        // delete the ACL online and offline
        try {
            if (existsOnline && (onlineResource != null) && (onlineResource.getSiblingCount() == 1)) {
                // only if no siblings left
                m_driverManager.getUserDriver(dbc).removeAccessControlEntries(dbc, onlineProject,
                        onlineResource.getResourceId());
            }
            if (offlineResource.getSiblingCount() == 1) {
                // only if no siblings left
                m_driverManager.getUserDriver(dbc).removeAccessControlEntries(dbc, dbc.currentProject(),
                        offlineResource.getResourceId());
            }
        } catch (CmsDataAccessException e) {
            if (LOG.isErrorEnabled()) {
                LOG.error(Messages.get().getBundle().key(Messages.LOG_REMOVING_ACL_1, offlineResource.toString()),
                        e);
            }
            throw e;
        }

        try {
            // delete relations online and offline
            m_driverManager.getVfsDriver(dbc).deleteRelations(dbc, onlineProject.getUuid(), offlineResource,
                    CmsRelationFilter.TARGETS);
            m_driverManager.getVfsDriver(dbc).deleteRelations(dbc, dbc.currentProject().getUuid(), offlineResource,
                    CmsRelationFilter.TARGETS);
        } catch (CmsDataAccessException e) {
            if (LOG.isErrorEnabled()) {
                LOG.error(Messages.get().getBundle().key(Messages.LOG_REMOVING_RELATIONS_1,
                        offlineResource.toString()), e);
            }
            throw e;
        }

        if (OpenCms.getSubscriptionManager().isEnabled()) {
            try {
                // delete visited information for resource from log
                CmsVisitEntryFilter filter = CmsVisitEntryFilter.ALL
                        .filterResource(offlineResource.getStructureId());
                m_driverManager.getSubscriptionDriver().deleteVisits(dbc,
                        OpenCms.getSubscriptionManager().getPoolName(), filter);
            } catch (CmsDataAccessException e) {
                if (LOG.isErrorEnabled()) {
                    LOG.error(Messages.get().getBundle().key(Messages.LOG_REMOVING_VISITEDLOG_1,
                            offlineResource.toString()), e);
                }
                throw e;
            }

            try {
                // mark the subscribed resource as deleted
                /* changed to subscription driver */
                //                m_driverManager.getUserDriver(dbc).setSubscribedResourceAsDeleted(
                //                    dbc,
                //                    OpenCms.getSubscriptionManager().getPoolName(),
                //                    offlineResource);
                m_driverManager.getSubscriptionDriver().setSubscribedResourceAsDeleted(dbc,
                        OpenCms.getSubscriptionManager().getPoolName(), offlineResource);
            } catch (CmsDataAccessException e) {
                if (LOG.isErrorEnabled()) {
                    LOG.error(Messages.get().getBundle().key(Messages.LOG_REMOVING_SUBSCRIPTIONS_1,
                            offlineResource.toString()), e);
                }
                throw e;
            }
        }
    }

    /**
     * Publishes a new file.<p>
     * 
     * @param dbc the current database context
     * @param onlineProject the online project
     * @param offlineResource the resource to publish
     * @param publishedContentIds contains the UUIDs of already published content records
     * @param publishHistoryId the publish history id
     * @param publishTag the publish tag
     * 
     * @throws CmsDataAccessException is something goes wrong
     */
    protected void publishNewFile(CmsDbContext dbc, CmsProject onlineProject, CmsResource offlineResource,
            Set<CmsUUID> publishedContentIds, CmsUUID publishHistoryId, int publishTag)
            throws CmsDataAccessException {

        CmsResourceState resourceState = fixMovedResource(dbc, onlineProject, offlineResource, publishHistoryId,
                publishTag);

        CmsFile newFile;
        try {
            // reset the labeled link flag before writing the online file
            int flags = offlineResource.getFlags();
            flags &= ~CmsResource.FLAG_LABELED;
            offlineResource.setFlags(flags);

            // publish the file content
            newFile = m_driverManager.getProjectDriver(dbc).publishFileContent(dbc, dbc.currentProject(),
                    onlineProject, offlineResource, publishedContentIds, true, publishTag);

        } catch (CmsVfsResourceAlreadyExistsException e) {
            try {
                // remove the existing file and ensure that it's content is written 
                // in any case by removing it's resource ID from the set of published resource IDs
                m_driverManager.getVfsDriver(dbc).removeFile(dbc, onlineProject.getUuid(), offlineResource);
                publishedContentIds.remove(offlineResource.getResourceId());
                newFile = m_driverManager.getProjectDriver(dbc).publishFileContent(dbc, dbc.currentProject(),
                        onlineProject, offlineResource, publishedContentIds, true, publishTag);
            } catch (CmsDataAccessException e1) {
                if (LOG.isErrorEnabled()) {
                    LOG.error(Messages.get().getBundle().key(Messages.LOG_PUBLISHING_RESOURCE_1,
                            offlineResource.getRootPath()), e);
                }
                throw e1;
            }
        } catch (CmsDataAccessException e) {
            if (LOG.isErrorEnabled()) {
                LOG.error(Messages.get().getBundle().key(Messages.LOG_PUBLISHING_RESOURCE_1,
                        offlineResource.getRootPath()), e);
            }
            throw e;
        }

        List<CmsProperty> offlineProperties;
        try {
            // write the properties online
            offlineProperties = m_driverManager.getVfsDriver(dbc).readPropertyObjects(dbc, dbc.currentProject(),
                    offlineResource);
            CmsProperty.setAutoCreatePropertyDefinitions(offlineProperties, true);
            m_driverManager.getVfsDriver(dbc).writePropertyObjects(dbc, onlineProject, newFile, offlineProperties);
        } catch (CmsDataAccessException e) {
            if (LOG.isErrorEnabled()) {
                LOG.error(
                        Messages.get().getBundle().key(Messages.LOG_PUBLISHING_PROPERTIES_1, newFile.getRootPath()),
                        e);
            }

            throw e;
        }

        try {
            // write the ACL online
            m_driverManager.getUserDriver(dbc).publishAccessControlEntries(dbc, dbc.currentProject(), onlineProject,
                    offlineResource.getResourceId(), newFile.getResourceId());
        } catch (CmsDataAccessException e) {
            if (LOG.isErrorEnabled()) {
                LOG.error(Messages.get().getBundle().key(Messages.LOG_PUBLISHING_ACL_1, newFile.getRootPath()), e);
            }
            throw e;
        }

        CmsFile offlineFile = new CmsFile(offlineResource);
        offlineFile.setContents(newFile.getContents());
        internalWriteHistory(dbc, offlineFile, resourceState, offlineProperties, publishHistoryId, publishTag);

        m_driverManager.getVfsDriver(dbc).updateRelations(dbc, onlineProject, offlineResource);
    }
}