001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (https://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software GmbH & Co. KG, please see the
018 * company website: https://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: https://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.db.generic;
029
030import org.opencms.configuration.CmsConfigurationManager;
031import org.opencms.configuration.CmsParameterConfiguration;
032import org.opencms.db.CmsAliasFilter;
033import org.opencms.db.CmsDbContext;
034import org.opencms.db.CmsDbEntryNotFoundException;
035import org.opencms.db.CmsDbIoException;
036import org.opencms.db.CmsDbSqlException;
037import org.opencms.db.CmsDriverManager;
038import org.opencms.db.CmsModificationContext;
039import org.opencms.db.CmsPreparedStatementIntParameter;
040import org.opencms.db.CmsPreparedStatementLongParameter;
041import org.opencms.db.CmsPreparedStatementStringParameter;
042import org.opencms.db.CmsPublishList;
043import org.opencms.db.CmsPublishedResource;
044import org.opencms.db.CmsResourceState;
045import org.opencms.db.CmsVisitEntryFilter;
046import org.opencms.db.I_CmsDriver;
047import org.opencms.db.I_CmsHistoryDriver;
048import org.opencms.db.I_CmsPreparedStatementParameter;
049import org.opencms.db.I_CmsProjectDriver;
050import org.opencms.db.I_CmsVfsDriver;
051import org.opencms.db.log.CmsLogEntry;
052import org.opencms.db.log.CmsLogEntryType;
053import org.opencms.db.log.CmsLogFilter;
054import org.opencms.db.userpublishlist.CmsUserPublishListEntry;
055import org.opencms.file.CmsDataAccessException;
056import org.opencms.file.CmsFile;
057import org.opencms.file.CmsFolder;
058import org.opencms.file.CmsGroup;
059import org.opencms.file.CmsProject;
060import org.opencms.file.CmsProperty;
061import org.opencms.file.CmsPropertyDefinition;
062import org.opencms.file.CmsResource;
063import org.opencms.file.CmsResourceFilter;
064import org.opencms.file.CmsUser;
065import org.opencms.file.CmsVfsResourceAlreadyExistsException;
066import org.opencms.file.CmsVfsResourceNotFoundException;
067import org.opencms.file.history.CmsHistoryFile;
068import org.opencms.file.types.CmsResourceTypeFolder;
069import org.opencms.i18n.CmsMessageContainer;
070import org.opencms.lock.CmsLock;
071import org.opencms.lock.CmsLockType;
072import org.opencms.main.CmsEvent;
073import org.opencms.main.CmsException;
074import org.opencms.main.CmsLog;
075import org.opencms.main.I_CmsEventListener;
076import org.opencms.main.OpenCms;
077import org.opencms.publish.CmsPublishJobInfoBean;
078import org.opencms.relations.CmsRelationFilter;
079import org.opencms.report.I_CmsReport;
080import org.opencms.security.CmsOrganizationalUnit;
081import org.opencms.security.I_CmsPrincipal;
082import org.opencms.staticexport.CmsStaticExportManager;
083import org.opencms.util.CmsPair;
084import org.opencms.util.CmsStringUtil;
085import org.opencms.util.CmsUUID;
086
087import java.io.ByteArrayInputStream;
088import java.io.ByteArrayOutputStream;
089import java.io.IOException;
090import java.io.ObjectInputStream;
091import java.io.ObjectOutputStream;
092import java.sql.Connection;
093import java.sql.PreparedStatement;
094import java.sql.ResultSet;
095import java.sql.SQLException;
096import java.util.ArrayList;
097import java.util.Collection;
098import java.util.Collections;
099import java.util.HashMap;
100import java.util.HashSet;
101import java.util.Iterator;
102import java.util.List;
103import java.util.Map;
104import java.util.Set;
105
106import org.apache.commons.logging.Log;
107
108import com.google.common.collect.Sets;
109
110/**
111 * Generic (ANSI-SQL) implementation of the project driver methods.<p>
112 *
113 * @since 6.0.0
114 */
115public class CmsProjectDriver implements I_CmsDriver, I_CmsProjectDriver {
116
117    /**
118     * This private class is a temporary storage for the method {@link CmsProjectDriver#readLocks(CmsDbContext)}.<p>
119     */
120    private class CmsTempResourceLock {
121
122        /** The lock type. */
123        private int m_lockType;
124
125        /** The project id. */
126        private CmsUUID m_projectId;
127
128        /** The resource path. */
129        private String m_resourcePath;
130
131        /** The user id. */
132        private CmsUUID m_userId;
133
134        /**
135         * The constructor.<p>
136         *
137         * @param resourcePath resource path
138         * @param userId user id
139         * @param projectId project id
140         * @param lockType lock type
141         */
142        public CmsTempResourceLock(String resourcePath, CmsUUID userId, CmsUUID projectId, int lockType) {
143
144            m_resourcePath = resourcePath;
145            m_userId = userId;
146            m_projectId = projectId;
147            m_lockType = lockType;
148        }
149
150        /**
151         * Returns the lockType.<p>
152         *
153         * @return the lockType
154         */
155        public int getLockType() {
156
157            return m_lockType;
158        }
159
160        /**
161         * Returns the projectId.<p>
162         *
163         * @return the projectId
164         */
165        public CmsUUID getProjectId() {
166
167            return m_projectId;
168        }
169
170        /**
171         * Returns the resourcePath.<p>
172         *
173         * @return the resourcePath
174         */
175        public String getResourcePath() {
176
177            return m_resourcePath;
178        }
179
180        /**
181         * Returns the userId.<p>
182         *
183         * @return the userId
184         */
185        public CmsUUID getUserId() {
186
187            return m_userId;
188        }
189
190    }
191
192    /** Attribute name for reading the project of a resource. */
193    public static final String DBC_ATTR_READ_PROJECT_FOR_RESOURCE = "DBC_ATTR_READ_PROJECT_FOR_RESOURCE";
194
195    /** The log object for this class. */
196    private static final Log LOG = CmsLog.getLog(org.opencms.db.generic.CmsProjectDriver.class);
197
198    /** The driver manager. */
199    protected CmsDriverManager m_driverManager;
200
201    /** The SQL manager. */
202    protected CmsSqlManager m_sqlManager;
203
204    /**
205     * @see org.opencms.db.I_CmsProjectDriver#cleanupPublishHistory(org.opencms.db.CmsDbContext, org.opencms.db.generic.CmsPublishHistoryCleanupFilter)
206     */
207    public int cleanupPublishHistory(CmsDbContext dbc, CmsPublishHistoryCleanupFilter filter)
208    throws CmsDataAccessException {
209
210        Connection conn = null;
211        PreparedStatement stmt = null;
212        int rowsAffected = 0;
213
214        try {
215            // get a JDBC connection from the OpenCms standard pool
216            conn = m_sqlManager.getConnection(dbc);
217            switch (filter.getMode()) {
218
219                case single:
220                default:
221                    stmt = m_sqlManager.getPreparedStatement(conn, "C_CLEANUP_PUBLISH_HISTORY_SINGLE");
222                    stmt.setString(1, filter.getHistoryId().toString());
223                    rowsAffected = stmt.executeUpdate();
224                    break;
225                case allUnreferenced:
226                    String statementText = m_sqlManager.readQuery("C_CLEANUP_PUBLISH_HISTORY_ALL");
227                    if (filter.getExceptions().size() > 0) {
228                        List<String> parts = new ArrayList<>();
229                        // it's safe to construct the clause as a string here because UUIDs can only contain dashes and hex digits
230                        parts.add("'" + CmsUUID.getNullUUID() + "'");
231                        for (CmsUUID id : filter.getExceptions()) {
232                            parts.add("'" + id.toString() + "'");
233                        }
234                        String exceptionListStr = "(" + CmsStringUtil.listAsString(parts, ",") + ")";
235                        statementText += " AND CMS_PUBLISH_HISTORY.HISTORY_ID NOT IN " + exceptionListStr;
236                    }
237                    stmt = m_sqlManager.getPreparedStatementForSql(conn, statementText);
238                    rowsAffected = stmt.executeUpdate();
239                    break;
240            }
241            LOG.info(
242                "executed publish list cleanup in mode " + filter.getMode() + ", " + rowsAffected + " rows deleted");
243            return rowsAffected;
244        } catch (SQLException e) {
245            throw new CmsDbSqlException(
246                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
247                e);
248        } finally {
249            m_sqlManager.closeAll(dbc, conn, stmt, null);
250
251        }
252
253    }
254
255    /**
256     * @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)
257     */
258    public CmsProject createProject(
259        CmsDbContext dbc,
260        CmsUUID id,
261        CmsUser owner,
262        CmsGroup group,
263        CmsGroup managergroup,
264        String projectFqn,
265        String description,
266        int flags,
267        CmsProject.CmsProjectType type)
268    throws CmsDataAccessException {
269
270        CmsProject project = null;
271
272        if ((description == null) || (description.length() < 1)) {
273            description = " ";
274        }
275
276        Connection conn = null;
277        PreparedStatement stmt = null;
278
279        try {
280            // get a JDBC connection from the OpenCms standard pool
281            conn = m_sqlManager.getConnection(dbc);
282            stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_CREATE_10");
283
284            stmt.setString(1, id.toString());
285            stmt.setString(2, owner.getId().toString());
286            stmt.setString(3, group.getId().toString());
287            stmt.setString(4, managergroup.getId().toString());
288            stmt.setString(5, CmsOrganizationalUnit.getSimpleName(projectFqn));
289            stmt.setString(6, description);
290            stmt.setInt(7, flags);
291            stmt.setInt(9, type.getMode());
292            stmt.setString(10, CmsOrganizationalUnit.SEPARATOR + CmsOrganizationalUnit.getParentFqn(projectFqn));
293
294            synchronized (this) {
295                long createTime = System.currentTimeMillis();
296                stmt.setLong(8, createTime);
297                stmt.executeUpdate();
298                try {
299                    // this is an ugly hack, but for MySQL (and maybe other DBs as well)
300                    // there is a UNIQUE INDEX constraint on the project name+createTime
301                    // so theoretically if 2 projects with the same name are created very fast, this
302                    // SQL restraint would be violated if we don't wait here
303                    Thread.sleep(50);
304                } catch (InterruptedException e) {
305                    // continue
306                }
307                project = new CmsProject(
308                    id,
309                    projectFqn,
310                    description,
311                    owner.getId(),
312                    group.getId(),
313                    managergroup.getId(),
314                    flags,
315                    createTime,
316                    type);
317            }
318        } catch (SQLException e) {
319            throw new CmsDbSqlException(
320                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
321                e);
322        } finally {
323            m_sqlManager.closeAll(dbc, conn, stmt, null);
324        }
325
326        return project;
327    }
328
329    /**
330     * @see org.opencms.db.I_CmsProjectDriver#createProjectResource(org.opencms.db.CmsDbContext, CmsUUID, java.lang.String)
331     */
332    public void createProjectResource(CmsDbContext dbc, CmsUUID projectId, String resourcePath)
333    throws CmsDataAccessException {
334
335        // do not create entries for online-project
336        PreparedStatement stmt = null;
337        Connection conn = null;
338
339        boolean projectResourceExists = false;
340        try {
341            readProjectResource(dbc, projectId, resourcePath);
342            projectResourceExists = true;
343        } catch (CmsVfsResourceNotFoundException e) {
344            // resource does not exist yet, everything is okay
345            projectResourceExists = false;
346        }
347
348        if (projectResourceExists) {
349            throw new CmsVfsResourceAlreadyExistsException(
350                Messages.get().container(
351                    Messages.ERR_RESOURCE_WITH_NAME_ALREADY_EXISTS_1,
352                    dbc.removeSiteRoot(resourcePath)));
353        }
354
355        try {
356            conn = getSqlManager().getConnection(dbc);
357            stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTRESOURCES_CREATE_2");
358
359            // write new resource to the database
360            stmt.setString(1, projectId.toString());
361            stmt.setString(2, resourcePath);
362
363            stmt.executeUpdate();
364        } catch (SQLException e) {
365            throw new CmsDbSqlException(
366                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
367                e);
368        } finally {
369            m_sqlManager.closeAll(dbc, conn, stmt, null);
370        }
371    }
372
373    /**
374     * @see org.opencms.db.I_CmsProjectDriver#createPublishJob(org.opencms.db.CmsDbContext, org.opencms.publish.CmsPublishJobInfoBean)
375     */
376    public void createPublishJob(CmsDbContext dbc, CmsPublishJobInfoBean publishJob) throws CmsDataAccessException {
377
378        Connection conn = null;
379        PreparedStatement stmt = null;
380
381        try {
382            CmsPublishJobInfoBean currentJob = readPublishJob(dbc, publishJob.getPublishHistoryId());
383            LOG.error("wanted to write: " + publishJob);
384            LOG.error("already on db: " + currentJob);
385            return;
386        } catch (CmsDbEntryNotFoundException e) {
387            // ok, this is the expected behavior
388        }
389        try {
390            conn = m_sqlManager.getConnection(dbc);
391            stmt = m_sqlManager.getPreparedStatement(conn, "C_PUBLISHJOB_CREATE");
392
393            stmt.setString(1, publishJob.getPublishHistoryId().toString());
394            stmt.setString(2, publishJob.getProjectId().toString());
395            stmt.setString(3, publishJob.getProjectName());
396            stmt.setString(4, publishJob.getUserId().toString());
397            stmt.setString(5, publishJob.getLocale().toString());
398            stmt.setInt(6, publishJob.getFlags());
399            stmt.setInt(7, publishJob.getSize());
400            stmt.setLong(8, publishJob.getEnqueueTime());
401            stmt.setLong(9, publishJob.getStartTime());
402            stmt.setLong(10, publishJob.getFinishTime());
403
404            byte[] publishList = internalSerializePublishList(publishJob.getPublishList());
405            if (publishList.length < 2000) {
406                stmt.setBytes(11, publishList);
407            } else {
408                stmt.setBinaryStream(11, new ByteArrayInputStream(publishList), publishList.length);
409            }
410
411            stmt.executeUpdate();
412        } catch (SQLException e) {
413            throw new CmsDbSqlException(
414                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
415                e);
416        } catch (IOException e) {
417            throw new CmsDbIoException(
418                Messages.get().container(
419                    Messages.ERR_SERIALIZING_PUBLISHLIST_1,
420                    publishJob.getPublishHistoryId().toString()),
421                e);
422        } finally {
423            m_sqlManager.closeAll(dbc, conn, stmt, null);
424        }
425    }
426
427    /**
428     * @see org.opencms.db.I_CmsProjectDriver#deleteAllStaticExportPublishedResources(org.opencms.db.CmsDbContext, int)
429     */
430    public void deleteAllStaticExportPublishedResources(CmsDbContext dbc, int linkType) throws CmsDataAccessException {
431
432        Connection conn = null;
433        PreparedStatement stmt = null;
434
435        try {
436            conn = m_sqlManager.getConnection(dbc);
437            stmt = m_sqlManager.getPreparedStatement(conn, "C_STATICEXPORT_DELETE_ALL_PUBLISHED_LINKS");
438            stmt.setInt(1, linkType);
439            stmt.executeUpdate();
440        } catch (SQLException e) {
441            throw new CmsDbSqlException(
442                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
443                e);
444        } finally {
445            m_sqlManager.closeAll(dbc, conn, stmt, null);
446        }
447    }
448
449    /**
450     * @see org.opencms.db.I_CmsProjectDriver#deleteLog(org.opencms.db.CmsDbContext, org.opencms.db.log.CmsLogFilter)
451     */
452    public void deleteLog(CmsDbContext dbc, CmsLogFilter filter) throws CmsDataAccessException {
453
454        Connection conn = null;
455        PreparedStatement stmt = null;
456
457        try {
458            conn = m_sqlManager.getConnection(dbc);
459            // compose statement
460            StringBuffer queryBuf = new StringBuffer(256);
461            queryBuf.append(m_sqlManager.readQuery("C_LOG_DELETE_ENTRIES"));
462
463            CmsPair<String, List<I_CmsPreparedStatementParameter>> conditionsAndParams = prepareLogConditions(filter);
464            queryBuf.append(conditionsAndParams.getFirst());
465            if (LOG.isDebugEnabled()) {
466                LOG.debug(queryBuf.toString());
467            }
468            stmt = m_sqlManager.getPreparedStatementForSql(conn, queryBuf.toString());
469            List<I_CmsPreparedStatementParameter> params = conditionsAndParams.getSecond();
470            for (int i = 0; i < params.size(); i++) {
471                I_CmsPreparedStatementParameter param = conditionsAndParams.getSecond().get(i);
472                param.insertIntoStatement(stmt, i + 1);
473            }
474
475            // execute
476            stmt.executeUpdate();
477        } catch (SQLException e) {
478            throw new CmsDbSqlException(
479                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
480                e);
481        } finally {
482            m_sqlManager.closeAll(dbc, conn, stmt, null);
483        }
484    }
485
486    /**
487     * @see org.opencms.db.I_CmsProjectDriver#deleteProject(org.opencms.db.CmsDbContext, org.opencms.file.CmsProject)
488     */
489    public void deleteProject(CmsDbContext dbc, CmsProject project) throws CmsDataAccessException {
490
491        // delete the resources from project_resources
492        deleteProjectResources(dbc, project);
493
494        // remove the project id form all resources within their project
495        unmarkProjectResources(dbc, project);
496
497        // finally delete the project
498        Connection conn = null;
499        PreparedStatement stmt = null;
500        try {
501            conn = m_sqlManager.getConnection(dbc);
502            stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_DELETE_1");
503            // create the statement
504            stmt.setString(1, project.getUuid().toString());
505            stmt.executeUpdate();
506        } catch (SQLException e) {
507            throw new CmsDbSqlException(
508                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
509                e);
510        } finally {
511            m_sqlManager.closeAll(dbc, conn, stmt, null);
512        }
513    }
514
515    /**
516     * @see org.opencms.db.I_CmsProjectDriver#deleteProjectResource(org.opencms.db.CmsDbContext, CmsUUID, java.lang.String)
517     */
518    public void deleteProjectResource(CmsDbContext dbc, CmsUUID projectId, String resourceName)
519    throws CmsDataAccessException {
520
521        Connection conn = null;
522        PreparedStatement stmt = null;
523        try {
524            conn = m_sqlManager.getConnection(dbc);
525            stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTRESOURCES_DELETE_2");
526            // delete resource from the database
527            stmt.setString(1, projectId.toString());
528            stmt.setString(2, resourceName);
529            stmt.executeUpdate();
530        } catch (SQLException e) {
531            throw new CmsDbSqlException(
532                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
533                e);
534        } finally {
535            m_sqlManager.closeAll(dbc, conn, stmt, null);
536        }
537    }
538
539    /**
540     * @see org.opencms.db.I_CmsProjectDriver#deleteProjectResources(org.opencms.db.CmsDbContext, org.opencms.file.CmsProject)
541     */
542    public void deleteProjectResources(CmsDbContext dbc, CmsProject project) throws CmsDataAccessException {
543
544        Connection conn = null;
545        PreparedStatement stmt = null;
546
547        try {
548            conn = m_sqlManager.getConnection(dbc);
549            stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTRESOURCES_DELETEALL_1");
550            stmt.setString(1, project.getUuid().toString());
551            stmt.executeUpdate();
552        } catch (SQLException e) {
553            throw new CmsDbSqlException(
554                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
555                e);
556        } finally {
557            m_sqlManager.closeAll(dbc, conn, stmt, null);
558        }
559    }
560
561    /**
562     * @see org.opencms.db.I_CmsProjectDriver#deletePublishHistory(org.opencms.db.CmsDbContext, CmsUUID, int)
563     */
564    public void deletePublishHistory(CmsDbContext dbc, CmsUUID projectId, int maxpublishTag)
565    throws CmsDataAccessException {
566
567        PreparedStatement stmt = null;
568        Connection conn = null;
569
570        try {
571            conn = m_sqlManager.getConnection(dbc);
572            stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_DELETE_PUBLISH_HISTORY");
573            stmt.setInt(1, maxpublishTag);
574            stmt.executeUpdate();
575        } catch (SQLException e) {
576            throw new CmsDbSqlException(
577                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
578                e);
579        } finally {
580            m_sqlManager.closeAll(dbc, conn, stmt, null);
581        }
582    }
583
584    /**
585     * @see org.opencms.db.I_CmsProjectDriver#deletePublishHistoryEntry(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID, org.opencms.db.CmsPublishedResource)
586     */
587    public void deletePublishHistoryEntry(
588        CmsDbContext dbc,
589        CmsUUID publishHistoryId,
590        CmsPublishedResource publishedResource)
591    throws CmsDataAccessException {
592
593        Connection conn = null;
594        PreparedStatement stmt = null;
595
596        try {
597            conn = m_sqlManager.getConnection(dbc);
598            stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_DELETE_PUBLISH_HISTORY_ENTRY");
599            stmt.setString(1, publishHistoryId.toString());
600            stmt.setInt(2, publishedResource.getPublishTag());
601            stmt.setString(3, publishedResource.getStructureId().toString());
602            stmt.setString(4, publishedResource.getRootPath());
603            stmt.executeUpdate();
604        } catch (SQLException e) {
605            throw new CmsDbSqlException(
606                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
607                e);
608        } finally {
609            m_sqlManager.closeAll(dbc, conn, stmt, null);
610        }
611    }
612
613    /**
614     * @see org.opencms.db.I_CmsProjectDriver#deletePublishJob(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID)
615     */
616    public void deletePublishJob(CmsDbContext dbc, CmsUUID publishHistoryId) throws CmsDataAccessException {
617
618        Connection conn = null;
619        PreparedStatement stmt = null;
620
621        try {
622            conn = m_sqlManager.getConnection(dbc);
623            stmt = m_sqlManager.getPreparedStatement(conn, "C_PUBLISHJOB_DELETE");
624            stmt.setString(1, publishHistoryId.toString());
625            stmt.executeUpdate();
626        } catch (SQLException e) {
627            throw new CmsDbSqlException(
628                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
629                e);
630        } finally {
631            m_sqlManager.closeAll(dbc, conn, stmt, null);
632        }
633    }
634
635    /**
636     * @see org.opencms.db.I_CmsProjectDriver#deletePublishList(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID)
637     */
638    public void deletePublishList(CmsDbContext dbc, CmsUUID publishHistoryId) throws CmsDataAccessException {
639
640        Connection conn = null;
641        PreparedStatement stmt = null;
642
643        try {
644            conn = m_sqlManager.getConnection(dbc);
645            stmt = m_sqlManager.getPreparedStatement(conn, "C_PUBLISHJOB_DELETE_PUBLISHLIST");
646            stmt.setString(1, publishHistoryId.toString());
647            stmt.executeUpdate();
648        } catch (SQLException e) {
649            throw new CmsDbSqlException(
650                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
651                e);
652        } finally {
653            m_sqlManager.closeAll(dbc, conn, stmt, null);
654        }
655    }
656
657    /**
658     * @see org.opencms.db.I_CmsProjectDriver#deleteStaticExportPublishedResource(org.opencms.db.CmsDbContext, java.lang.String, int, java.lang.String)
659     */
660    public void deleteStaticExportPublishedResource(
661        CmsDbContext dbc,
662        String resourceName,
663        int linkType,
664        String linkParameter)
665    throws CmsDataAccessException {
666
667        Connection conn = null;
668        PreparedStatement stmt = null;
669
670        try {
671            conn = m_sqlManager.getConnection(dbc);
672            if (linkParameter == null) {
673                stmt = m_sqlManager.getPreparedStatement(conn, "C_STATICEXPORT_DELETE_RFSPATH_PUBLISHED_LINKS");
674                stmt.setString(1, resourceName);
675                stmt.setInt(2, linkType);
676                stmt.executeUpdate();
677            } else {
678                stmt = m_sqlManager.getPreparedStatement(conn, "C_STATICEXPORT_DELETE_PUBLISHED_LINKS");
679                stmt.setString(1, resourceName);
680                stmt.setInt(2, linkType);
681                stmt.setString(3, linkParameter);
682                stmt.executeUpdate();
683            }
684        } catch (SQLException e) {
685            throw new CmsDbSqlException(
686                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
687                e);
688        } finally {
689            m_sqlManager.closeAll(dbc, conn, stmt, null);
690        }
691    }
692
693    /**
694     * @see org.opencms.db.I_CmsProjectDriver#deleteUserPublishListEntries(org.opencms.db.CmsDbContext, java.util.List)
695     */
696    public void deleteUserPublishListEntries(CmsDbContext dbc, List<CmsUserPublishListEntry> publishListDeletions)
697    throws CmsDbSqlException {
698
699        if (publishListDeletions.isEmpty()) {
700            return;
701        }
702        Connection conn = null;
703        PreparedStatement stmt = null;
704
705        try {
706            conn = m_sqlManager.getConnection(dbc);
707            String sql = m_sqlManager.readQuery("C_USER_PUBLISH_LIST_DELETE_3");
708            stmt = m_sqlManager.getPreparedStatementForSql(conn, sql);
709            for (CmsUserPublishListEntry entry : publishListDeletions) {
710                stmt.setString(1, entry.getStructureId().toString());
711                stmt.setString(2, entry.getUserId() != null ? entry.getUserId().toString() : null);
712                stmt.setInt(3, entry.getUserId() == null ? 1 : 0);
713                stmt.addBatch();
714            }
715            stmt.executeBatch();
716        } catch (SQLException e) {
717            throw new CmsDbSqlException(
718                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
719                e);
720        } finally {
721            m_sqlManager.closeAll(dbc, conn, stmt, null);
722        }
723
724    }
725
726    /**
727     * @see org.opencms.db.I_CmsProjectDriver#destroy()
728     */
729    public void destroy() throws Throwable {
730
731        m_sqlManager = null;
732        m_driverManager = null;
733
734        if (CmsLog.INIT.isInfoEnabled()) {
735            CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_SHUTDOWN_DRIVER_1, getClass().getName()));
736        }
737    }
738
739    /**
740     * @see org.opencms.db.I_CmsProjectDriver#fillDefaults(org.opencms.db.CmsDbContext)
741     */
742    public void fillDefaults(CmsDbContext dbc) throws CmsDataAccessException {
743
744        try {
745            if (readProject(dbc, CmsProject.ONLINE_PROJECT_ID) != null) {
746                // online-project exists - no need of filling defaults
747                return;
748            }
749        } catch (CmsDataAccessException exc) {
750            // ignore the exception - the project was not readable so fill in the defaults
751        }
752
753        if (CmsLog.INIT.isInfoEnabled()) {
754            CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_FILL_DEFAULTS_0));
755        }
756
757        String adminUser = OpenCms.getDefaultUsers().getUserAdmin();
758        CmsUser admin = m_driverManager.readUser(dbc, adminUser);
759
760        String administratorsGroup = OpenCms.getDefaultUsers().getGroupAdministrators();
761        CmsGroup administrators = m_driverManager.readGroup(dbc, administratorsGroup);
762
763        String usersGroup = OpenCms.getDefaultUsers().getGroupUsers();
764        CmsGroup users = m_driverManager.readGroup(dbc, usersGroup);
765
766        ////////////////////////////////////////////////////////////////////////////////////////////
767        // online project stuff
768        ////////////////////////////////////////////////////////////////////////////////////////////
769
770        // create the online project
771        CmsProject onlineProject = createProject(
772            dbc,
773            CmsProject.ONLINE_PROJECT_ID,
774            admin,
775            users,
776            administrators,
777            CmsProject.ONLINE_PROJECT_NAME,
778            "The Online project",
779            I_CmsPrincipal.FLAG_ENABLED,
780            CmsProject.PROJECT_TYPE_NORMAL);
781
782        // create the root-folder for the online project
783        CmsFolder rootFolder = new CmsFolder(
784            new CmsUUID(),
785            new CmsUUID(),
786            "/",
787            CmsResourceTypeFolder.RESOURCE_TYPE_ID,
788            0,
789            onlineProject.getUuid(),
790            CmsResource.STATE_CHANGED,
791            0,
792            admin.getId(),
793            0,
794            admin.getId(),
795            CmsResource.DATE_RELEASED_DEFAULT,
796            CmsResource.DATE_EXPIRED_DEFAULT,
797            0);
798
799        m_driverManager.getVfsDriver(dbc).createResource(dbc, onlineProject.getUuid(), rootFolder, null);
800
801        // important: must access through driver manager to ensure proper cascading
802        m_driverManager.getProjectDriver(dbc).createProjectResource(
803            dbc,
804            onlineProject.getUuid(),
805            rootFolder.getRootPath());
806
807        // create the system-folder for the online project
808        CmsFolder systemFolder = new CmsFolder(
809            new CmsUUID(),
810            new CmsUUID(),
811            "/system",
812            CmsResourceTypeFolder.RESOURCE_TYPE_ID,
813            0,
814            onlineProject.getUuid(),
815            CmsResource.STATE_CHANGED,
816            0,
817            admin.getId(),
818            0,
819            admin.getId(),
820            CmsResource.DATE_RELEASED_DEFAULT,
821            CmsResource.DATE_EXPIRED_DEFAULT,
822            0);
823
824        m_driverManager.getVfsDriver(dbc).createResource(dbc, onlineProject.getUuid(), systemFolder, null);
825
826        ////////////////////////////////////////////////////////////////////////////////////////////
827        // setup project stuff
828        ////////////////////////////////////////////////////////////////////////////////////////////
829
830        // important: must access through driver manager to ensure proper cascading
831        CmsProject setupProject = m_driverManager.getProjectDriver(dbc).createProject(
832            dbc,
833            CmsUUID.getConstantUUID(SETUP_PROJECT_NAME),
834            admin,
835            administrators,
836            administrators,
837            SETUP_PROJECT_NAME,
838            "The Project for the initial import",
839            I_CmsPrincipal.FLAG_ENABLED,
840            CmsProject.PROJECT_TYPE_TEMPORARY);
841
842        rootFolder.setState(CmsResource.STATE_CHANGED);
843        // create the root-folder for the offline project
844        CmsResource offlineRootFolder = m_driverManager.getVfsDriver(
845            dbc).createResource(dbc, setupProject.getUuid(), rootFolder, null);
846
847        offlineRootFolder.setState(CmsResource.STATE_UNCHANGED);
848
849        m_driverManager.getVfsDriver(
850            dbc).writeResource(dbc, setupProject.getUuid(), offlineRootFolder, CmsDriverManager.NOTHING_CHANGED);
851
852        // important: must access through driver manager to ensure proper cascading
853        m_driverManager.getProjectDriver(dbc).createProjectResource(
854            dbc,
855            setupProject.getUuid(),
856            offlineRootFolder.getRootPath());
857
858        systemFolder.setState(CmsResource.STATE_CHANGED);
859        // create the system-folder for the offline project
860        CmsResource offlineSystemFolder = m_driverManager.getVfsDriver(
861            dbc).createResource(dbc, setupProject.getUuid(), systemFolder, null);
862
863        offlineSystemFolder.setState(CmsResource.STATE_UNCHANGED);
864
865        m_driverManager.getVfsDriver(
866            dbc).writeResource(dbc, setupProject.getUuid(), offlineSystemFolder, CmsDriverManager.NOTHING_CHANGED);
867    }
868
869    /**
870     * @see org.opencms.db.I_CmsProjectDriver#getSqlManager()
871     */
872    public CmsSqlManager getSqlManager() {
873
874        return m_sqlManager;
875    }
876
877    /**
878     * @see org.opencms.db.I_CmsProjectDriver#getUsersPubList(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID)
879     */
880    public List<CmsResource> getUsersPubList(CmsDbContext dbc, CmsUUID userId) throws CmsDataAccessException {
881
882        List<CmsResource> result = new ArrayList<CmsResource>();
883        Connection conn = null;
884        PreparedStatement stmt = null;
885        ResultSet res = null;
886        try {
887            conn = m_sqlManager.getConnection(dbc);
888            String sql = m_sqlManager.readQuery("C_USER_PUBLISH_LIST_READ_1");
889            sql = sql.replace("${PROJECT}", "OFFLINE");
890            stmt = m_sqlManager.getPreparedStatementForSql(conn, sql);
891            stmt.setString(1, userId.toString());
892            res = stmt.executeQuery();
893            while (res.next()) {
894                CmsResource resource = m_driverManager.getVfsDriver(dbc).createResource(
895                    res,
896                    dbc.currentProject().getUuid());
897                long date = res.getLong("DATE_CHANGED");
898                resource.setDateLastModified(date);
899                result.add(resource);
900            }
901            return result;
902        } catch (SQLException e) {
903            throw new CmsDbSqlException(
904                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
905                e);
906        } finally {
907            m_sqlManager.closeAll(dbc, conn, stmt, res);
908        }
909    }
910
911    /**
912     * @see org.opencms.db.I_CmsDriver#init(CmsDbContext, CmsConfigurationManager, List, CmsDriverManager)
913     */
914    public void init(
915        CmsDbContext dbc,
916        CmsConfigurationManager configurationManager,
917        List<String> successiveDrivers,
918        CmsDriverManager driverManager) {
919
920        CmsParameterConfiguration configuration = configurationManager.getConfiguration();
921        String poolUrl = configuration.get("db.project.pool");
922        String classname = configuration.get("db.project.sqlmanager");
923        m_sqlManager = initSqlManager(classname);
924        m_sqlManager.init(I_CmsProjectDriver.DRIVER_TYPE_ID, poolUrl);
925
926        m_driverManager = driverManager;
927
928        if (CmsLog.INIT.isInfoEnabled()) {
929            CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_ASSIGNED_POOL_1, poolUrl));
930        }
931
932        if ((successiveDrivers != null) && !successiveDrivers.isEmpty()) {
933            if (LOG.isWarnEnabled()) {
934                LOG.warn(
935                    Messages.get().getBundle().key(
936                        Messages.LOG_SUCCESSIVE_DRIVERS_UNSUPPORTED_1,
937                        getClass().getName()));
938            }
939        }
940    }
941
942    /**
943     * @see org.opencms.db.I_CmsProjectDriver#initSqlManager(String)
944     */
945    public org.opencms.db.generic.CmsSqlManager initSqlManager(String classname) {
946
947        return CmsSqlManager.getInstance(classname);
948    }
949
950    /**
951     * @see org.opencms.db.I_CmsProjectDriver#log(org.opencms.db.CmsDbContext, java.util.List)
952     */
953    public void log(CmsDbContext dbc, List<CmsLogEntry> logEntries) throws CmsDbSqlException {
954
955        Connection conn = null;
956        PreparedStatement stmt = null;
957
958        try {
959            conn = m_sqlManager.getConnection(dbc);
960            stmt = m_sqlManager.getPreparedStatement(conn, "C_LOG_CREATE_5");
961
962            for (CmsLogEntry logEntry : logEntries) {
963                stmt.setString(1, logEntry.getUserId().toString());
964                stmt.setLong(2, logEntry.getDate());
965                stmt.setString(3, logEntry.getStructureId() == null ? null : logEntry.getStructureId().toString());
966                stmt.setInt(4, logEntry.getType().getId());
967                stmt.setString(5, CmsStringUtil.arrayAsString(logEntry.getData(), "|"));
968                try {
969                    stmt.executeUpdate();
970                } catch (SQLException e) {
971                    // ignore, most likely a duplicate entry
972                    LOG.debug(
973                        Messages.get().container(
974                            Messages.ERR_GENERIC_SQL_1,
975                            CmsDbSqlException.getErrorQuery(stmt)).key(),
976                        e);
977                }
978            }
979        } catch (SQLException e) {
980            throw new CmsDbSqlException(
981                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
982                e);
983        } finally {
984            try {
985                m_sqlManager.closeAll(dbc, conn, stmt, null);
986            } catch (Throwable t) {
987                // this could happen during shutdown
988                LOG.debug(t.getLocalizedMessage(), t);
989            }
990        }
991    }
992
993    /**
994     * @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)
995     */
996    public void publishDeletedFolder(
997        CmsDbContext dbc,
998        I_CmsReport report,
999        int m,
1000        int n,
1001        CmsProject onlineProject,
1002        CmsFolder currentFolder,
1003        CmsUUID publishHistoryId,
1004        int publishTag)
1005    throws CmsDataAccessException {
1006
1007        try {
1008            report.print(
1009                org.opencms.report.Messages.get().container(
1010                    org.opencms.report.Messages.RPT_SUCCESSION_2,
1011                    String.valueOf(m),
1012                    String.valueOf(n)),
1013                I_CmsReport.FORMAT_NOTE);
1014            report.print(Messages.get().container(Messages.RPT_DELETE_FOLDER_0), I_CmsReport.FORMAT_NOTE);
1015            report.print(
1016                org.opencms.report.Messages.get().container(
1017                    org.opencms.report.Messages.RPT_ARGUMENT_1,
1018                    dbc.removeSiteRoot(currentFolder.getRootPath())));
1019            report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0));
1020
1021            CmsResourceState folderState = fixMovedResource(
1022                dbc,
1023                onlineProject,
1024                currentFolder,
1025                publishHistoryId,
1026                publishTag);
1027
1028            // read the folder online
1029            CmsFolder onlineFolder = m_driverManager.readFolder(
1030                dbc,
1031                currentFolder.getRootPath(),
1032                CmsResourceFilter.ALL);
1033
1034            // if the folder in the online-project contains any files, these need to be removed.
1035            // this can occur if these files were moved in the offline-project
1036            List<CmsResource> movedFiles = null;
1037            I_CmsVfsDriver vfsDriver = m_driverManager.getVfsDriver(dbc);
1038            movedFiles = vfsDriver.readResourceTree(
1039                dbc,
1040                onlineProject.getUuid(),
1041                currentFolder.getRootPath(),
1042                CmsDriverManager.READ_IGNORE_TYPE,
1043                null,
1044                CmsDriverManager.READ_IGNORE_TIME,
1045                CmsDriverManager.READ_IGNORE_TIME,
1046                CmsDriverManager.READ_IGNORE_TIME,
1047                CmsDriverManager.READ_IGNORE_TIME,
1048                CmsDriverManager.READ_IGNORE_TIME,
1049                CmsDriverManager.READ_IGNORE_TIME,
1050                CmsDriverManager.READMODE_INCLUDE_TREE);
1051
1052            for (CmsResource delFile : movedFiles) {
1053                try {
1054                    CmsResource offlineResource = vfsDriver.readResource(
1055                        dbc,
1056                        dbc.currentProject().getUuid(),
1057                        delFile.getStructureId(),
1058                        true);
1059                    if (offlineResource.isFile()) {
1060                        CmsFile offlineFile = new CmsFile(offlineResource);
1061                        offlineFile.setContents(
1062                            vfsDriver.readContent(dbc, dbc.currentProject().getUuid(), offlineFile.getResourceId()));
1063                        internalWriteHistory(
1064                            dbc,
1065                            offlineFile,
1066                            CmsResource.STATE_DELETED,
1067                            null,
1068                            publishHistoryId,
1069                            publishTag);
1070                        vfsDriver.deletePropertyObjects(
1071                            dbc,
1072                            onlineProject.getUuid(),
1073                            delFile,
1074                            CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES);
1075                        vfsDriver.removeFile(dbc, onlineProject.getUuid(), delFile);
1076                    } else if (offlineResource.isFolder()) {
1077
1078                        internalWriteHistory(
1079                            dbc,
1080                            offlineResource,
1081                            CmsResource.STATE_DELETED,
1082                            null,
1083                            publishHistoryId,
1084                            publishTag);
1085                        vfsDriver.deletePropertyObjects(
1086                            dbc,
1087                            onlineProject.getUuid(),
1088                            delFile,
1089                            CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES);
1090                        vfsDriver.removeFolder(dbc, onlineProject, delFile);
1091                    }
1092                } catch (CmsDataAccessException e) {
1093                    if (LOG.isWarnEnabled()) {
1094                        LOG.warn(
1095                            Messages.get().getBundle().key(Messages.LOG_REMOVING_RESOURCE_1, delFile.getName()),
1096                            e);
1097                    }
1098                }
1099            }
1100
1101            // write history before deleting
1102            internalWriteHistory(dbc, currentFolder, folderState, null, publishHistoryId, publishTag);
1103
1104            try {
1105                // delete the properties online and offline
1106                vfsDriver.deletePropertyObjects(
1107                    dbc,
1108                    onlineProject.getUuid(),
1109                    onlineFolder,
1110                    CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES);
1111                vfsDriver.deletePropertyObjects(
1112                    dbc,
1113                    dbc.currentProject().getUuid(),
1114                    currentFolder,
1115                    CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES);
1116            } catch (CmsDataAccessException e) {
1117                if (LOG.isErrorEnabled()) {
1118                    LOG.error(
1119                        Messages.get().getBundle().key(Messages.LOG_DELETING_PROPERTIES_1, currentFolder.getRootPath()),
1120                        e);
1121                }
1122                throw e;
1123            }
1124
1125            try {
1126                // remove the folder online and offline
1127                vfsDriver.removeFolder(dbc, dbc.currentProject(), currentFolder);
1128                vfsDriver.removeFolder(dbc, onlineProject, currentFolder);
1129            } catch (CmsDataAccessException e) {
1130                if (LOG.isErrorEnabled()) {
1131                    LOG.error(
1132                        Messages.get().getBundle().key(Messages.LOG_REMOVING_RESOURCE_1, currentFolder.getRootPath()),
1133                        e);
1134                }
1135                throw e;
1136            }
1137
1138            try {
1139                // remove the ACL online and offline
1140                m_driverManager.getUserDriver(dbc).removeAccessControlEntries(
1141                    dbc,
1142                    onlineProject,
1143                    onlineFolder.getResourceId());
1144                m_driverManager.getUserDriver(dbc).removeAccessControlEntries(
1145                    dbc,
1146                    dbc.currentProject(),
1147                    currentFolder.getResourceId());
1148            } catch (CmsDataAccessException e) {
1149                if (LOG.isErrorEnabled()) {
1150                    LOG.error(
1151                        Messages.get().getBundle().key(Messages.LOG_REMOVING_ACL_1, currentFolder.getRootPath()),
1152                        e);
1153                }
1154                throw e;
1155            }
1156
1157            // remove relations
1158            try {
1159                vfsDriver.deleteRelations(dbc, onlineProject.getUuid(), onlineFolder, CmsRelationFilter.TARGETS);
1160                vfsDriver.deleteRelations(
1161                    dbc,
1162                    dbc.currentProject().getUuid(),
1163                    currentFolder,
1164                    CmsRelationFilter.TARGETS);
1165            } catch (CmsDataAccessException e) {
1166                if (LOG.isErrorEnabled()) {
1167                    LOG.error(
1168                        Messages.get().getBundle().key(Messages.LOG_REMOVING_RELATIONS_1, currentFolder.getRootPath()),
1169                        e);
1170                }
1171                throw e;
1172            }
1173
1174            // remove project resources
1175            String deletedResourceRootPath = currentFolder.getRootPath();
1176            Iterator<CmsProject> itProjects = readProjectsForResource(dbc, deletedResourceRootPath).iterator();
1177            while (itProjects.hasNext()) {
1178                CmsProject project = itProjects.next();
1179                deleteProjectResource(dbc, project.getUuid(), deletedResourceRootPath);
1180            }
1181
1182            try {
1183                m_driverManager.getVfsDriver(dbc).deleteAliases(
1184                    dbc,
1185                    onlineProject,
1186                    new CmsAliasFilter(null, null, currentFolder.getStructureId()));
1187            } catch (CmsDataAccessException e) {
1188                LOG.error("Could not delete aliases: " + e.getLocalizedMessage(), e);
1189            }
1190
1191            report.println(
1192                org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0),
1193                I_CmsReport.FORMAT_OK);
1194
1195            if (LOG.isDebugEnabled()) {
1196                if (LOG.isDebugEnabled()) {
1197                    LOG.debug(
1198                        Messages.get().getBundle().key(
1199                            Messages.LOG_DEL_FOLDER_3,
1200                            currentFolder.getRootPath(),
1201                            String.valueOf(m),
1202                            String.valueOf(n)));
1203                }
1204            }
1205        } finally {
1206            // notify the app. that the published folder and it's properties have been modified offline
1207            OpenCms.fireCmsEvent(
1208                new CmsEvent(
1209                    I_CmsEventListener.EVENT_RESOURCE_AND_PROPERTIES_MODIFIED,
1210                    Collections.<String, Object> singletonMap(I_CmsEventListener.KEY_RESOURCE, currentFolder)));
1211        }
1212    }
1213
1214    /**
1215     * @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)
1216     */
1217    public void publishFile(
1218        CmsDbContext dbc,
1219        I_CmsReport report,
1220        int m,
1221        int n,
1222        CmsProject onlineProject,
1223        CmsResource offlineResource,
1224        Set<CmsUUID> publishedContentIds,
1225        CmsUUID publishHistoryId,
1226        int publishTag)
1227    throws CmsDataAccessException {
1228
1229        /*
1230         * Never use onlineResource.getState() here!
1231         * Only use offlineResource.getState() to determine the state of an offline resource!
1232         *
1233         * In case a resource has siblings, after a sibling was published the structure
1234         * and resource states are reset to UNCHANGED -> the state of the corresponding
1235         * onlineResource is still NEW, DELETED or CHANGED.
1236         * Thus, using onlineResource.getState() will inevitably result in unpublished resources!
1237         */
1238
1239        try {
1240            report.print(
1241                org.opencms.report.Messages.get().container(
1242                    org.opencms.report.Messages.RPT_SUCCESSION_2,
1243                    String.valueOf(m),
1244                    String.valueOf(n)),
1245                I_CmsReport.FORMAT_NOTE);
1246
1247            if (offlineResource.getState().isDeleted()) {
1248                report.print(Messages.get().container(Messages.RPT_DELETE_FILE_0), I_CmsReport.FORMAT_NOTE);
1249                report.print(
1250                    org.opencms.report.Messages.get().container(
1251                        org.opencms.report.Messages.RPT_ARGUMENT_1,
1252                        dbc.removeSiteRoot(offlineResource.getRootPath())));
1253                report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0));
1254
1255                publishDeletedFile(dbc, onlineProject, offlineResource, publishHistoryId, publishTag);
1256
1257                dbc.pop();
1258                List<CmsProperty> props = m_driverManager.readPropertyObjects(dbc, offlineResource, true);
1259                boolean removeDeleted = Boolean.parseBoolean(
1260                    CmsProperty.get(CmsPropertyDefinition.PROPERTY_HISTORY_REMOVE_DELETED, props).getValue("false"));
1261                // delete old historical entries
1262                m_driverManager.getHistoryDriver(dbc).deleteEntries(
1263                    dbc,
1264                    new CmsHistoryFile(offlineResource),
1265                    removeDeleted ? 0 : OpenCms.getSystemInfo().getHistoryVersionsAfterDeletion(),
1266                    -1);
1267
1268                report.println(
1269                    org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0),
1270                    I_CmsReport.FORMAT_OK);
1271
1272                if (LOG.isDebugEnabled()) {
1273                    LOG.debug(
1274                        Messages.get().getBundle().key(
1275                            Messages.LOG_DEL_FILE_3,
1276                            String.valueOf(m),
1277                            String.valueOf(n),
1278                            offlineResource.getRootPath()));
1279                }
1280
1281            } else if (offlineResource.getState().isChanged()) {
1282                report.print(Messages.get().container(Messages.RPT_PUBLISH_FILE_0), I_CmsReport.FORMAT_NOTE);
1283                report.print(
1284                    org.opencms.report.Messages.get().container(
1285                        org.opencms.report.Messages.RPT_ARGUMENT_1,
1286                        dbc.removeSiteRoot(offlineResource.getRootPath())));
1287                report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0));
1288
1289                publishChangedFile(
1290                    dbc,
1291                    onlineProject,
1292                    offlineResource,
1293                    publishedContentIds,
1294                    publishHistoryId,
1295                    publishTag);
1296
1297                dbc.pop();
1298                // delete old historical entries
1299                m_driverManager.getHistoryDriver(dbc).deleteEntries(
1300                    dbc,
1301                    new CmsHistoryFile(offlineResource),
1302                    OpenCms.getSystemInfo().getHistoryVersions(),
1303                    -1);
1304
1305                report.println(
1306                    org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0),
1307                    I_CmsReport.FORMAT_OK);
1308
1309                if (LOG.isDebugEnabled()) {
1310                    LOG.debug(
1311                        Messages.get().getBundle().key(
1312                            Messages.LOG_PUBLISHING_FILE_3,
1313                            offlineResource.getRootPath(),
1314                            String.valueOf(m),
1315                            String.valueOf(n)));
1316                }
1317            } else if (offlineResource.getState().isNew()) {
1318                report.print(Messages.get().container(Messages.RPT_PUBLISH_FILE_0), I_CmsReport.FORMAT_NOTE);
1319                report.print(
1320                    org.opencms.report.Messages.get().container(
1321                        org.opencms.report.Messages.RPT_ARGUMENT_1,
1322                        dbc.removeSiteRoot(offlineResource.getRootPath())));
1323                report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0));
1324
1325                publishNewFile(dbc, onlineProject, offlineResource, publishedContentIds, publishHistoryId, publishTag);
1326
1327                dbc.pop();
1328                // delete old historical entries
1329                m_driverManager.getHistoryDriver(dbc).deleteEntries(
1330                    dbc,
1331                    new CmsHistoryFile(offlineResource),
1332                    OpenCms.getSystemInfo().getHistoryVersions(),
1333                    -1);
1334
1335                report.println(
1336                    org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0),
1337                    I_CmsReport.FORMAT_OK);
1338
1339                if (LOG.isDebugEnabled()) {
1340                    if (LOG.isDebugEnabled()) {
1341                        LOG.debug(
1342                            Messages.get().getBundle().key(
1343                                Messages.LOG_PUBLISHING_FILE_3,
1344                                offlineResource.getRootPath(),
1345                                String.valueOf(m),
1346                                String.valueOf(n)));
1347                    }
1348                }
1349            } else {
1350                // state == unchanged !!?? something went really wrong
1351                report.print(Messages.get().container(Messages.RPT_PUBLISH_FILE_0), I_CmsReport.FORMAT_NOTE);
1352                report.print(
1353                    org.opencms.report.Messages.get().container(
1354                        org.opencms.report.Messages.RPT_ARGUMENT_1,
1355                        dbc.removeSiteRoot(offlineResource.getRootPath())));
1356                report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0));
1357                report.println(
1358                    org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_FAILED_0),
1359                    I_CmsReport.FORMAT_ERROR);
1360
1361                if (LOG.isErrorEnabled()) {
1362                    // the whole resource is printed out here
1363                    LOG.error(
1364                        Messages.get().getBundle().key(
1365                            Messages.LOG_PUBLISHING_FILE_3,
1366                            String.valueOf(m),
1367                            String.valueOf(n),
1368                            offlineResource));
1369                }
1370            }
1371            m_driverManager.publishUrlNameMapping(dbc, offlineResource);
1372            if (offlineResource.getState().isDeleted()) {
1373                m_driverManager.getVfsDriver(dbc).deleteAliases(
1374                    dbc,
1375                    onlineProject,
1376                    new CmsAliasFilter(null, null, offlineResource.getStructureId()));
1377            }
1378        } catch (CmsException e) {
1379            throw new CmsDataAccessException(e.getMessageContainer(), e);
1380        } finally {
1381            // notify the app. that the published file and it's properties have been modified offline
1382            Map<String, Object> data = new HashMap<String, Object>(2);
1383            data.put(I_CmsEventListener.KEY_RESOURCE, offlineResource);
1384            data.put(I_CmsEventListener.KEY_SKIPINDEX, Boolean.valueOf(true));
1385
1386            OpenCms.fireCmsEvent(new CmsEvent(I_CmsEventListener.EVENT_RESOURCE_AND_PROPERTIES_MODIFIED, data));
1387        }
1388    }
1389
1390    /**
1391     * @see org.opencms.db.I_CmsProjectDriver#publishFileContent(CmsDbContext, CmsProject, CmsProject, CmsResource, Set, boolean, int)
1392     */
1393    public CmsFile publishFileContent(
1394        CmsDbContext dbc,
1395        CmsProject offlineProject,
1396        CmsProject onlineProject,
1397        CmsResource offlineResource,
1398        Set<CmsUUID> publishedResourceIds,
1399        boolean needToUpdateContent,
1400        int publishTag)
1401    throws CmsDataAccessException {
1402
1403        CmsFile newFile = null;
1404        try {
1405            // read the file content offline
1406            CmsUUID projectId = dbc.getProjectId();
1407            boolean dbcHasProjectId = (projectId != null) && !projectId.isNullUUID();
1408            CmsUUID projectIdForReading = (!dbcHasProjectId ? offlineProject.getUuid() : CmsProject.ONLINE_PROJECT_ID);
1409            dbc.setProjectId(offlineProject.getUuid());
1410            byte[] offlineContent = m_driverManager.getVfsDriver(dbc).readContent(
1411                dbc,
1412                projectIdForReading,
1413                offlineResource.getResourceId());
1414            CmsFile offlineFile = new CmsFile(offlineResource);
1415            offlineFile.setContents(offlineContent);
1416            dbc.setProjectId(projectId);
1417
1418            // create the file online
1419            newFile = (CmsFile)offlineFile.clone();
1420            newFile.setState(CmsResource.STATE_UNCHANGED);
1421
1422            boolean createSibling = true;
1423            // check if we are facing with a create new sibling operation
1424            if (!offlineFile.getState().isNew()) {
1425                createSibling = false;
1426            } else {
1427                // check if the resource entry already exists
1428                if (!m_driverManager.getVfsDriver(dbc).validateResourceIdExists(
1429                    dbc,
1430                    onlineProject.getUuid(),
1431                    offlineFile.getResourceId())) {
1432                    // we are creating a normal resource and not a sibling
1433                    createSibling = false;
1434                }
1435            }
1436
1437            // only update the content if it was not updated before
1438            boolean alreadyPublished = publishedResourceIds.contains(offlineResource.getResourceId());
1439            needToUpdateContent &= !alreadyPublished;
1440
1441            if (createSibling) {
1442                if (!alreadyPublished) {
1443                    // create the file online, the first time a sibling is published also the resource entry has to be actualized
1444                    m_driverManager.getVfsDriver(dbc).createResource(dbc, onlineProject.getUuid(), newFile, null);
1445                } else {
1446                    // create the sibling online
1447                    m_driverManager.getVfsDriver(dbc).createSibling(dbc, onlineProject, offlineResource);
1448                }
1449                newFile = new CmsFile(offlineResource);
1450                newFile.setContents(offlineContent);
1451            } else {
1452                // update the online/offline structure and resource records of the file
1453                m_driverManager.getVfsDriver(dbc).publishResource(dbc, onlineProject, newFile, offlineFile);
1454            }
1455            // update version numbers
1456            m_driverManager.getVfsDriver(dbc).publishVersions(dbc, offlineResource, !alreadyPublished);
1457
1458            // create/update the content
1459            m_driverManager.getVfsDriver(dbc).createOnlineContent(
1460                dbc,
1461                offlineFile.getResourceId(),
1462                offlineFile.getContents(),
1463                publishTag,
1464                true,
1465                needToUpdateContent);
1466
1467            // mark the resource as written to avoid that the same content is written for each sibling instance
1468            publishedResourceIds.add(offlineResource.getResourceId());
1469        } catch (CmsDataAccessException e) {
1470            if (LOG.isErrorEnabled()) {
1471                LOG.error(
1472                    Messages.get().getBundle().key(Messages.LOG_PUBLISHING_FILE_CONTENT_1, offlineResource.toString()),
1473                    e);
1474            }
1475            throw e;
1476        }
1477        return newFile;
1478    }
1479
1480    /**
1481     * @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)
1482     */
1483    public void publishFolder(
1484        CmsDbContext dbc,
1485        I_CmsReport report,
1486        int m,
1487        int n,
1488        CmsProject onlineProject,
1489        CmsFolder offlineFolder,
1490        CmsUUID publishHistoryId,
1491        int publishTag)
1492    throws CmsDataAccessException {
1493
1494        try {
1495            report.print(
1496                org.opencms.report.Messages.get().container(
1497                    org.opencms.report.Messages.RPT_SUCCESSION_2,
1498                    String.valueOf(m),
1499                    String.valueOf(n)),
1500                I_CmsReport.FORMAT_NOTE);
1501            report.print(Messages.get().container(Messages.RPT_PUBLISH_FOLDER_0), I_CmsReport.FORMAT_NOTE);
1502            report.print(
1503                org.opencms.report.Messages.get().container(
1504                    org.opencms.report.Messages.RPT_ARGUMENT_1,
1505                    dbc.removeSiteRoot(offlineFolder.getRootPath())));
1506            report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0));
1507
1508            CmsResourceState resourceState = fixMovedResource(
1509                dbc,
1510                onlineProject,
1511                offlineFolder,
1512                publishHistoryId,
1513                publishTag);
1514
1515            CmsResource onlineFolder = null;
1516            if (offlineFolder.getState().isNew()) {
1517                try {
1518                    // create the folder online
1519                    CmsResource newFolder = (CmsFolder)offlineFolder.clone();
1520                    newFolder.setState(CmsResource.STATE_UNCHANGED);
1521
1522                    onlineFolder = m_driverManager.getVfsDriver(
1523                        dbc).createResource(dbc, onlineProject.getUuid(), newFolder, null);
1524                    m_driverManager.getVfsDriver(dbc).publishResource(dbc, onlineProject, onlineFolder, offlineFolder);
1525                    // update version numbers
1526                    m_driverManager.getVfsDriver(dbc).publishVersions(dbc, offlineFolder, true);
1527                } catch (CmsVfsResourceAlreadyExistsException e) {
1528                    if (!offlineFolder.getRootPath().equals("/")
1529                        && !offlineFolder.getRootPath().equals("/system/")
1530                        && LOG.isWarnEnabled()) {
1531                        LOG.warn(
1532                            Messages.get().getBundle().key(
1533                                Messages.LOG_WARN_FOLDER_WRONG_STATE_CN_1,
1534                                offlineFolder.getRootPath()));
1535                    }
1536                    try {
1537                        onlineFolder = m_driverManager.getVfsDriver(dbc).readFolder(
1538                            dbc,
1539                            onlineProject.getUuid(),
1540                            offlineFolder.getRootPath());
1541                        m_driverManager.getVfsDriver(
1542                            dbc).publishResource(dbc, onlineProject, onlineFolder, offlineFolder);
1543                        // update version numbers
1544                        m_driverManager.getVfsDriver(dbc).publishVersions(dbc, offlineFolder, true);
1545                    } catch (CmsDataAccessException e1) {
1546                        if (LOG.isErrorEnabled()) {
1547                            LOG.error(
1548                                Messages.get().getBundle().key(
1549                                    Messages.LOG_READING_RESOURCE_1,
1550                                    offlineFolder.getRootPath()),
1551                                e);
1552                        }
1553                        throw e1;
1554                    }
1555                } catch (CmsDataAccessException e) {
1556                    if (LOG.isErrorEnabled()) {
1557                        LOG.error(
1558                            Messages.get().getBundle().key(
1559                                Messages.LOG_PUBLISHING_RESOURCE_1,
1560                                offlineFolder.getRootPath()),
1561                            e);
1562                    }
1563                    throw e;
1564                }
1565            } else if (offlineFolder.getState().isChanged()) {
1566                try {
1567                    // read the folder online
1568                    onlineFolder = m_driverManager.getVfsDriver(dbc).readFolder(
1569                        dbc,
1570                        onlineProject.getUuid(),
1571                        offlineFolder.getStructureId());
1572                } catch (CmsVfsResourceNotFoundException e) {
1573                    if (LOG.isWarnEnabled()) {
1574                        LOG.warn(
1575                            Messages.get().getBundle().key(
1576                                Messages.LOG_WARN_FOLDER_WRONG_STATE_NC_1,
1577                                offlineFolder.getRootPath()));
1578                    }
1579                    try {
1580                        onlineFolder = m_driverManager.getVfsDriver(
1581                            dbc).createResource(dbc, onlineProject.getUuid(), offlineFolder, null);
1582                        internalResetResourceState(dbc, onlineFolder);
1583                    } catch (CmsDataAccessException e1) {
1584                        if (LOG.isErrorEnabled()) {
1585                            LOG.error(
1586                                Messages.get().getBundle().key(
1587                                    Messages.LOG_PUBLISHING_RESOURCE_1,
1588                                    offlineFolder.getRootPath()),
1589                                e);
1590                        }
1591                        throw e1;
1592                    }
1593                }
1594
1595                try {
1596                    // update the folder online
1597                    m_driverManager.getVfsDriver(dbc).publishResource(dbc, onlineProject, onlineFolder, offlineFolder);
1598                    // update version numbers
1599                    m_driverManager.getVfsDriver(dbc).publishVersions(dbc, offlineFolder, true);
1600                } catch (CmsDataAccessException e) {
1601                    if (LOG.isErrorEnabled()) {
1602                        LOG.error(
1603                            Messages.get().getBundle().key(
1604                                Messages.LOG_PUBLISHING_RESOURCE_1,
1605                                offlineFolder.getRootPath()),
1606                            e);
1607                    }
1608                    throw e;
1609                }
1610            }
1611
1612            if (onlineFolder != null) {
1613                try {
1614                    // write the ACL online
1615                    m_driverManager.getUserDriver(dbc).publishAccessControlEntries(
1616                        dbc,
1617                        dbc.currentProject(),
1618                        onlineProject,
1619                        offlineFolder.getResourceId(),
1620                        onlineFolder.getResourceId());
1621                } catch (CmsDataAccessException e) {
1622                    if (LOG.isErrorEnabled()) {
1623                        LOG.error(
1624                            Messages.get().getBundle().key(Messages.LOG_PUBLISHING_ACL_1, offlineFolder.getRootPath()),
1625                            e);
1626                    }
1627                    throw e;
1628                }
1629            }
1630
1631            List<CmsProperty> offlineProperties = null;
1632            try {
1633                // write the properties online
1634                m_driverManager.getVfsDriver(dbc).deletePropertyObjects(
1635                    dbc,
1636                    onlineProject.getUuid(),
1637                    onlineFolder,
1638                    CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES);
1639                offlineProperties = m_driverManager.getVfsDriver(dbc).readPropertyObjects(
1640                    dbc,
1641                    dbc.currentProject(),
1642                    offlineFolder);
1643                CmsProperty.setAutoCreatePropertyDefinitions(offlineProperties, true);
1644                m_driverManager.getVfsDriver(
1645                    dbc).writePropertyObjects(dbc, onlineProject, onlineFolder, offlineProperties);
1646            } catch (CmsDataAccessException e) {
1647                if (LOG.isErrorEnabled()) {
1648                    LOG.error(
1649                        Messages.get().getBundle().key(
1650                            Messages.LOG_PUBLISHING_PROPERTIES_1,
1651                            offlineFolder.getRootPath()),
1652                        e);
1653                }
1654                throw e;
1655            }
1656
1657            internalWriteHistory(dbc, offlineFolder, resourceState, offlineProperties, publishHistoryId, publishTag);
1658
1659            m_driverManager.getVfsDriver(dbc).updateRelations(dbc, onlineProject, offlineFolder);
1660
1661            report.println(
1662                org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0),
1663                I_CmsReport.FORMAT_OK);
1664
1665            if (LOG.isDebugEnabled()) {
1666                LOG.debug(
1667                    Messages.get().getBundle().key(
1668                        Messages.LOG_PUBLISHING_FOLDER_3,
1669                        String.valueOf(m),
1670                        String.valueOf(n),
1671                        offlineFolder.getRootPath()));
1672            }
1673        } finally {
1674            // notify the app. that the published folder and it's properties have been modified offline
1675            OpenCms.fireCmsEvent(
1676                new CmsEvent(
1677                    I_CmsEventListener.EVENT_RESOURCE_AND_PROPERTIES_MODIFIED,
1678                    Collections.<String, Object> singletonMap(I_CmsEventListener.KEY_RESOURCE, offlineFolder)));
1679        }
1680    }
1681
1682    /**
1683     * @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)
1684     */
1685    public void publishProject(
1686        CmsDbContext dbc,
1687        I_CmsReport report,
1688        CmsProject onlineProject,
1689        CmsPublishList publishList,
1690        int publishTag)
1691    throws CmsException {
1692
1693        int publishedFolderCount = 0;
1694        int deletedFolderCount = 0;
1695        int publishedFileCount = 0;
1696        Set<CmsUUID> publishedContentIds = new HashSet<CmsUUID>();
1697        Set<CmsUUID> publishedIds = new HashSet<CmsUUID>();
1698
1699        try {
1700
1701            ////////////////////////////////////////////////////////////////////////////////////////
1702            // write the historical project entry
1703
1704            if (OpenCms.getSystemInfo().isHistoryEnabled()) {
1705                try {
1706                    // write an entry in the publish project log
1707                    m_driverManager.getHistoryDriver(dbc).writeProject(dbc, publishTag, System.currentTimeMillis());
1708                    dbc.pop();
1709                } catch (Throwable t) {
1710                    dbc.report(
1711                        report,
1712                        Messages.get().container(
1713                            Messages.ERR_WRITING_HISTORY_OF_PROJECT_1,
1714                            dbc.currentProject().getName()),
1715                        t);
1716                }
1717            }
1718
1719            ///////////////////////////////////////////////////////////////////////////////////////
1720            // publish new/changed folders
1721
1722            if (LOG.isDebugEnabled()) {
1723                LOG.debug(
1724                    Messages.get().getBundle().key(
1725                        Messages.LOG_START_PUBLISHING_PROJECT_2,
1726                        dbc.currentProject().getName(),
1727                        dbc.currentUser().getName()));
1728            }
1729
1730            publishedFolderCount = 0;
1731            int foldersSize = publishList.getFolderList().size();
1732            if (foldersSize > 0) {
1733                report.println(
1734                    Messages.get().container(Messages.RPT_PUBLISH_FOLDERS_BEGIN_0),
1735                    I_CmsReport.FORMAT_HEADLINE);
1736            }
1737
1738            Iterator<CmsResource> itFolders = publishList.getFolderList().iterator();
1739            I_CmsProjectDriver projectDriver = m_driverManager.getProjectDriver(dbc);
1740            I_CmsHistoryDriver historyDriver = m_driverManager.getHistoryDriver(dbc);
1741            while (itFolders.hasNext()) {
1742                CmsResource currentFolder = itFolders.next();
1743                try {
1744                    if (currentFolder.getState().isNew() || currentFolder.getState().isChanged()) {
1745                        // bounce the current publish task through all project drivers
1746                        projectDriver.publishFolder(
1747                            dbc,
1748                            report,
1749                            ++publishedFolderCount,
1750                            foldersSize,
1751                            onlineProject,
1752                            new CmsFolder(currentFolder),
1753                            publishList.getPublishHistoryId(),
1754                            publishTag);
1755
1756                        dbc.pop();
1757
1758                        publishedIds.add(currentFolder.getStructureId());
1759                        // log it
1760                        CmsLogEntryType type = currentFolder.getState().isNew()
1761                        ? CmsLogEntryType.RESOURCE_PUBLISHED_NEW
1762                        : CmsLogEntryType.RESOURCE_PUBLISHED_MODIFIED;
1763                        m_driverManager.log(
1764                            dbc,
1765                            new CmsLogEntry(
1766                                dbc,
1767                                currentFolder.getStructureId(),
1768                                type,
1769                                new String[] {currentFolder.getRootPath()}),
1770                            true);
1771
1772                        // delete old historical entries
1773                        historyDriver.deleteEntries(
1774                            dbc,
1775                            new CmsHistoryFile(currentFolder),
1776                            OpenCms.getSystemInfo().getHistoryVersions(),
1777                            -1);
1778
1779                        // reset the resource state to UNCHANGED and the last-modified-in-project-ID to 0
1780                        internalResetResourceState(dbc, currentFolder);
1781
1782                        if (!CmsModificationContext.isInOnlineFolder(currentFolder.getRootPath())) {
1783                            m_driverManager.unlockResource(dbc, currentFolder, true, true);
1784                        }
1785                    } else {
1786                        // state == unchanged !!?? something went really wrong
1787                        report.print(Messages.get().container(Messages.RPT_PUBLISH_FOLDER_0), I_CmsReport.FORMAT_NOTE);
1788                        report.print(
1789                            org.opencms.report.Messages.get().container(
1790                                org.opencms.report.Messages.RPT_ARGUMENT_1,
1791                                dbc.removeSiteRoot(currentFolder.getRootPath())));
1792                        report.print(
1793                            org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0));
1794                        report.println(
1795                            org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_FAILED_0),
1796                            I_CmsReport.FORMAT_ERROR);
1797
1798                        if (LOG.isErrorEnabled()) {
1799                            // the whole resource is printed out here
1800                            LOG.error(
1801                                Messages.get().getBundle().key(
1802                                    Messages.LOG_PUBLISHING_FILE_3,
1803                                    String.valueOf(++publishedFolderCount),
1804                                    String.valueOf(foldersSize),
1805                                    currentFolder));
1806                        }
1807                    }
1808
1809                    dbc.pop();
1810                } catch (Throwable t) {
1811                    dbc.report(
1812                        report,
1813                        Messages.get().container(Messages.ERR_ERROR_PUBLISHING_FOLDER_1, currentFolder.getRootPath()),
1814                        t);
1815                }
1816            }
1817
1818            if (foldersSize > 0) {
1819                report.println(
1820                    Messages.get().container(Messages.RPT_PUBLISH_FOLDERS_END_0),
1821                    I_CmsReport.FORMAT_HEADLINE);
1822            }
1823
1824            ///////////////////////////////////////////////////////////////////////////////////////
1825            // publish changed/new/deleted files
1826
1827            publishedFileCount = 0;
1828            int filesSize = publishList.getFileList().size();
1829
1830            if (filesSize > 0) {
1831                report.println(
1832                    Messages.get().container(Messages.RPT_PUBLISH_FILES_BEGIN_0),
1833                    I_CmsReport.FORMAT_HEADLINE);
1834            }
1835
1836            Set<CmsUUID> deletedResourceIds = new HashSet<CmsUUID>();
1837            Set<CmsUUID> changedResourceIds = new HashSet<CmsUUID>();
1838            for (CmsResource res : publishList.getFileList()) {
1839                if (res.getState().isDeleted()) {
1840                    deletedResourceIds.add(res.getResourceId());
1841                } else {
1842                    changedResourceIds.add(res.getResourceId());
1843                }
1844            }
1845            Set<CmsUUID> changedAndDeletedResourceIds = Sets.intersection(deletedResourceIds, changedResourceIds);
1846            dbc.setAttribute(CmsDriverManager.KEY_CHANGED_AND_DELETED, changedAndDeletedResourceIds);
1847
1848            Iterator<CmsResource> itFiles = publishList.getFileList().iterator();
1849            while (itFiles.hasNext()) {
1850                CmsResource currentResource = itFiles.next();
1851                try {
1852                    // bounce the current publish task through all project drivers
1853                    projectDriver.publishFile(
1854                        dbc,
1855                        report,
1856                        ++publishedFileCount,
1857                        filesSize,
1858                        onlineProject,
1859                        currentResource,
1860                        publishedContentIds,
1861                        publishList.getPublishHistoryId(),
1862                        publishTag);
1863
1864                    CmsResourceState state = currentResource.getState();
1865                    if (!state.isDeleted()) {
1866                        // reset the resource state to UNCHANGED and the last-modified-in-project-ID to 0
1867                        internalResetResourceState(dbc, currentResource);
1868                    }
1869
1870                    // unlock it
1871                    if (!CmsModificationContext.isInOnlineFolder(currentResource.getRootPath())) {
1872                        m_driverManager.unlockResource(dbc, currentResource, true, true);
1873                    }
1874                    // log it
1875                    CmsLogEntryType type = state.isNew()
1876                    ? CmsLogEntryType.RESOURCE_PUBLISHED_NEW
1877                    : (state.isDeleted()
1878                    ? CmsLogEntryType.RESOURCE_PUBLISHED_DELETED
1879                    : CmsLogEntryType.RESOURCE_PUBLISHED_MODIFIED);
1880                    m_driverManager.log(
1881                        dbc,
1882                        new CmsLogEntry(
1883                            dbc,
1884                            currentResource.getStructureId(),
1885                            type,
1886                            new String[] {currentResource.getRootPath()}),
1887                        true);
1888
1889                    publishedIds.add(currentResource.getStructureId());
1890                    dbc.pop();
1891                } catch (Throwable t) {
1892                    dbc.report(
1893                        report,
1894                        Messages.get().container(Messages.ERR_ERROR_PUBLISHING_FILE_1, currentResource.getRootPath()),
1895                        t);
1896                }
1897            }
1898
1899            if (filesSize > 0) {
1900                report.println(Messages.get().container(Messages.RPT_PUBLISH_FILES_END_0), I_CmsReport.FORMAT_HEADLINE);
1901            }
1902
1903            ////////////////////////////////////////////////////////////////////////////////////////
1904
1905            // publish deleted folders
1906            List<CmsResource> deletedFolders = publishList.getDeletedFolderList();
1907            if (deletedFolders.isEmpty()) {
1908                return;
1909            }
1910
1911            deletedFolderCount = 0;
1912            int deletedFoldersSize = deletedFolders.size();
1913            if (deletedFoldersSize > 0) {
1914                report.println(
1915                    Messages.get().container(Messages.RPT_DELETE_FOLDERS_BEGIN_0),
1916                    I_CmsReport.FORMAT_HEADLINE);
1917            }
1918
1919            Iterator<CmsResource> itDeletedFolders = deletedFolders.iterator();
1920            while (itDeletedFolders.hasNext()) {
1921                CmsResource currentFolder = itDeletedFolders.next();
1922
1923                try {
1924                    // bounce the current publish task through all project drivers
1925                    projectDriver.publishDeletedFolder(
1926                        dbc,
1927                        report,
1928                        ++deletedFolderCount,
1929                        deletedFoldersSize,
1930                        onlineProject,
1931                        new CmsFolder(currentFolder),
1932                        publishList.getPublishHistoryId(),
1933                        publishTag);
1934
1935                    dbc.pop();
1936                    // delete old historical entries
1937                    m_driverManager.getHistoryDriver(dbc).deleteEntries(
1938                        dbc,
1939                        new CmsHistoryFile(currentFolder),
1940                        OpenCms.getSystemInfo().getHistoryVersionsAfterDeletion(),
1941                        -1);
1942
1943                    publishedIds.add(currentFolder.getStructureId());
1944                    // unlock it
1945                    if (!CmsModificationContext.isInOnlineFolder(currentFolder.getRootPath())) {
1946                        m_driverManager.unlockResource(dbc, currentFolder, true, true);
1947                    }
1948                    // log it
1949                    m_driverManager.log(
1950                        dbc,
1951                        new CmsLogEntry(
1952                            dbc,
1953                            currentFolder.getStructureId(),
1954                            CmsLogEntryType.RESOURCE_PUBLISHED_DELETED,
1955                            new String[] {currentFolder.getRootPath()}),
1956                        true);
1957
1958                    dbc.pop();
1959                } catch (Throwable t) {
1960                    dbc.report(
1961                        report,
1962                        Messages.get().container(
1963                            Messages.ERR_ERROR_PUBLISHING_DELETED_FOLDER_1,
1964                            currentFolder.getRootPath()),
1965                        t);
1966                }
1967            }
1968
1969            if (deletedFoldersSize > 0) {
1970                report.println(
1971                    Messages.get().container(Messages.RPT_DELETE_FOLDERS_END_0),
1972                    I_CmsReport.FORMAT_HEADLINE);
1973            }
1974        } catch (OutOfMemoryError o) {
1975            // clear all caches to reclaim memory
1976            OpenCms.fireCmsEvent(
1977                new CmsEvent(I_CmsEventListener.EVENT_CLEAR_CACHES, Collections.<String, Object> emptyMap()));
1978
1979            CmsMessageContainer message = Messages.get().container(Messages.ERR_OUT_OF_MEMORY_0);
1980            if (LOG.isErrorEnabled()) {
1981                LOG.error(message.key(), o);
1982            }
1983            throw new CmsDataAccessException(message, o);
1984        } finally {
1985            // reset vfs driver internal info after publishing
1986            m_driverManager.getVfsDriver(dbc).publishVersions(dbc, null, false);
1987            Object[] msgArgs = new Object[] {
1988                String.valueOf(publishedFileCount),
1989                String.valueOf(publishedFolderCount),
1990                String.valueOf(deletedFolderCount),
1991                report.formatRuntime()};
1992
1993            CmsMessageContainer message = Messages.get().container(Messages.RPT_PUBLISH_STAT_4, msgArgs);
1994            if (LOG.isInfoEnabled()) {
1995                LOG.info(message.key());
1996            }
1997            report.println(message);
1998        }
1999    }
2000
2001    /**
2002     * @see org.opencms.db.I_CmsProjectDriver#readLocks(org.opencms.db.CmsDbContext)
2003     */
2004    public List<CmsLock> readLocks(CmsDbContext dbc) throws CmsDataAccessException {
2005
2006        Connection conn = null;
2007        PreparedStatement stmt = null;
2008        List<CmsTempResourceLock> tmpLocks = new ArrayList<CmsTempResourceLock>(256);
2009        List<CmsLock> locks = new ArrayList<CmsLock>(256);
2010        try {
2011            conn = m_sqlManager.getConnection(dbc);
2012            stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCE_LOCKS_READALL");
2013            ResultSet rs = stmt.executeQuery();
2014            while (rs.next()) {
2015                String resourcePath = rs.getString(m_sqlManager.readQuery("C_RESOURCE_LOCKS_RESOURCE_PATH"));
2016                CmsUUID userId = new CmsUUID(rs.getString(m_sqlManager.readQuery("C_RESOURCE_LOCKS_USER_ID")));
2017                CmsUUID projectId = new CmsUUID(rs.getString(m_sqlManager.readQuery("C_RESOURCE_LOCKS_PROJECT_ID")));
2018                int lockType = rs.getInt(m_sqlManager.readQuery("C_RESOURCE_LOCKS_LOCK_TYPE"));
2019                CmsTempResourceLock tmpLock = new CmsTempResourceLock(resourcePath, userId, projectId, lockType);
2020                tmpLocks.add(tmpLock);
2021            }
2022        } catch (SQLException e) {
2023            throw new CmsDbSqlException(
2024                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2025                e);
2026        } finally {
2027            m_sqlManager.closeAll(dbc, conn, stmt, null);
2028        }
2029
2030        for (CmsTempResourceLock tmpLock : tmpLocks) {
2031            CmsProject project;
2032            try {
2033                project = readProject(dbc, tmpLock.getProjectId());
2034            } catch (CmsDataAccessException dae) {
2035                // the project does not longer exist, ignore this lock (should usually not happen)
2036                project = null;
2037            }
2038            if (project != null) {
2039                CmsLock lock = new CmsLock(
2040                    tmpLock.getResourcePath(),
2041                    tmpLock.getUserId(),
2042                    project,
2043                    CmsLockType.valueOf(tmpLock.getLockType()));
2044                locks.add(lock);
2045            }
2046        }
2047        if (LOG.isDebugEnabled()) {
2048            LOG.debug(Messages.get().getBundle().key(Messages.LOG_DBG_READ_LOCKS_1, Integer.valueOf(locks.size())));
2049        }
2050        return locks;
2051    }
2052
2053    /**
2054     * @see org.opencms.db.I_CmsProjectDriver#readLog(org.opencms.db.CmsDbContext, org.opencms.db.log.CmsLogFilter)
2055     */
2056    public List<CmsLogEntry> readLog(CmsDbContext dbc, CmsLogFilter filter) throws CmsDataAccessException {
2057
2058        List<CmsLogEntry> entries = new ArrayList<CmsLogEntry>();
2059
2060        Connection conn = null;
2061        PreparedStatement stmt = null;
2062        ResultSet res = null;
2063
2064        try {
2065            conn = m_sqlManager.getConnection(dbc);
2066            // compose statement
2067            StringBuffer queryBuf = new StringBuffer(256);
2068            queryBuf.append(m_sqlManager.readQuery("C_LOG_READ_ENTRIES"));
2069            CmsPair<String, List<I_CmsPreparedStatementParameter>> conditionsAndParameters = prepareLogConditions(
2070                filter);
2071            List<I_CmsPreparedStatementParameter> params = conditionsAndParameters.getSecond();
2072            queryBuf.append(conditionsAndParameters.getFirst());
2073
2074            if (LOG.isDebugEnabled()) {
2075                LOG.debug(queryBuf.toString());
2076            }
2077            stmt = m_sqlManager.getPreparedStatementForSql(conn, queryBuf.toString());
2078            for (int i = 0; i < params.size(); i++) {
2079                I_CmsPreparedStatementParameter param = params.get(i);
2080                param.insertIntoStatement(stmt, i + 1);
2081            }
2082
2083            // execute
2084            res = stmt.executeQuery();
2085            while (res.next()) {
2086                // get results
2087                entries.add(internalReadLogEntry(res));
2088            }
2089        } catch (SQLException e) {
2090            throw new CmsDbSqlException(
2091                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2092                e);
2093        } finally {
2094            m_sqlManager.closeAll(dbc, conn, stmt, res);
2095        }
2096        return entries;
2097    }
2098
2099    /**
2100     * @see org.opencms.db.I_CmsProjectDriver#readProject(org.opencms.db.CmsDbContext, CmsUUID)
2101     */
2102    public CmsProject readProject(CmsDbContext dbc, CmsUUID id) throws CmsDataAccessException {
2103
2104        PreparedStatement stmt = null;
2105        CmsProject project = null;
2106        ResultSet res = null;
2107        Connection conn = null;
2108
2109        try {
2110            conn = m_sqlManager.getConnection(dbc);
2111            stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_READ_1");
2112
2113            stmt.setString(1, id.toString());
2114            res = stmt.executeQuery();
2115
2116            if (res.next()) {
2117                project = internalCreateProject(res);
2118                while (res.next()) {
2119                    // do nothing only move through all rows because of mssql odbc driver
2120                }
2121            } else {
2122                throw new CmsDbEntryNotFoundException(
2123                    Messages.get().container(Messages.ERR_NO_PROJECT_WITH_ID_1, String.valueOf(id)));
2124            }
2125        } catch (SQLException e) {
2126            throw new CmsDbSqlException(
2127                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2128                e);
2129        } finally {
2130            m_sqlManager.closeAll(dbc, conn, stmt, res);
2131        }
2132
2133        return project;
2134    }
2135
2136    /**
2137     * @see org.opencms.db.I_CmsProjectDriver#readProject(org.opencms.db.CmsDbContext, java.lang.String)
2138     */
2139    public CmsProject readProject(CmsDbContext dbc, String projectFqn) throws CmsDataAccessException {
2140
2141        PreparedStatement stmt = null;
2142        CmsProject project = null;
2143        ResultSet res = null;
2144        Connection conn = null;
2145
2146        try {
2147            conn = m_sqlManager.getConnection(dbc);
2148            stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_READ_BYNAME_2");
2149
2150            stmt.setString(1, CmsOrganizationalUnit.getSimpleName(projectFqn));
2151            stmt.setString(2, CmsOrganizationalUnit.SEPARATOR + CmsOrganizationalUnit.getParentFqn(projectFqn));
2152            res = stmt.executeQuery();
2153
2154            if (res.next()) {
2155                project = internalCreateProject(res);
2156                while (res.next()) {
2157                    // do nothing only move through all rows because of mssql odbc driver
2158                }
2159            } else {
2160                throw new CmsDbEntryNotFoundException(
2161                    Messages.get().container(Messages.ERR_NO_PROJECT_WITH_NAME_1, projectFqn));
2162            }
2163        } catch (SQLException e) {
2164            throw new CmsDbSqlException(
2165                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2166                e);
2167        } finally {
2168            m_sqlManager.closeAll(dbc, conn, stmt, res);
2169        }
2170
2171        return project;
2172    }
2173
2174    /**
2175     * @see org.opencms.db.I_CmsProjectDriver#readProjectResource(org.opencms.db.CmsDbContext, CmsUUID, java.lang.String)
2176     */
2177    public String readProjectResource(CmsDbContext dbc, CmsUUID projectId, String resourcePath)
2178    throws CmsDataAccessException {
2179
2180        PreparedStatement stmt = null;
2181        Connection conn = null;
2182        ResultSet res = null;
2183        String resName = null;
2184
2185        try {
2186            conn = getSqlManager().getConnection(dbc);
2187            stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTRESOURCES_READ_2");
2188
2189            // select resource from the database
2190            stmt.setString(1, projectId.toString());
2191            stmt.setString(2, resourcePath);
2192            res = stmt.executeQuery();
2193
2194            if (res.next()) {
2195                resName = res.getString("RESOURCE_PATH");
2196                while (res.next()) {
2197                    // do nothing only move through all rows because of mssql odbc driver
2198                }
2199            } else {
2200                throw new CmsVfsResourceNotFoundException(
2201                    Messages.get().container(Messages.ERR_NO_PROJECTRESOURCE_1, resourcePath));
2202            }
2203        } catch (SQLException e) {
2204            throw new CmsDbSqlException(
2205                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2206                e);
2207        } finally {
2208            m_sqlManager.closeAll(dbc, conn, stmt, res);
2209        }
2210        return resName;
2211    }
2212
2213    /**
2214     * @see org.opencms.db.I_CmsProjectDriver#readProjectResources(org.opencms.db.CmsDbContext, org.opencms.file.CmsProject)
2215     */
2216    public List<String> readProjectResources(CmsDbContext dbc, CmsProject project) throws CmsDataAccessException {
2217
2218        PreparedStatement stmt = null;
2219        Connection conn = null;
2220        ResultSet res = null;
2221        List<String> result = new ArrayList<String>();
2222
2223        try {
2224            conn = m_sqlManager.getConnection(dbc);
2225            stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTRESOURCES_READ_BY_ID_1");
2226            stmt.setString(1, project.getUuid().toString());
2227            res = stmt.executeQuery();
2228
2229            while (res.next()) {
2230                result.add(res.getString("RESOURCE_PATH"));
2231            }
2232        } catch (SQLException e) {
2233            throw new CmsDbSqlException(
2234                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2235                e);
2236        } finally {
2237            m_sqlManager.closeAll(dbc, conn, stmt, res);
2238        }
2239
2240        return result;
2241    }
2242
2243    /**
2244     * @see org.opencms.db.I_CmsProjectDriver#readProjects(org.opencms.db.CmsDbContext, String)
2245     */
2246    public List<CmsProject> readProjects(CmsDbContext dbc, String ouFqn) throws CmsDataAccessException {
2247
2248        if ((dbc.getRequestContext() != null)
2249            && (dbc.getRequestContext().getAttribute(DBC_ATTR_READ_PROJECT_FOR_RESOURCE) != null)) {
2250            dbc.getRequestContext().removeAttribute(DBC_ATTR_READ_PROJECT_FOR_RESOURCE);
2251            // TODO: this should get its own method in the interface
2252            return readProjectsForResource(dbc, ouFqn);
2253        }
2254        List<CmsProject> projects = new ArrayList<CmsProject>();
2255        ResultSet res = null;
2256        PreparedStatement stmt = null;
2257        Connection conn = null;
2258
2259        try {
2260            // create the statement
2261            conn = m_sqlManager.getConnection(dbc);
2262            stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_READ_BYOU_1");
2263
2264            stmt.setString(1, CmsOrganizationalUnit.SEPARATOR + ouFqn + "%");
2265            res = stmt.executeQuery();
2266
2267            while (res.next()) {
2268                projects.add(internalCreateProject(res));
2269            }
2270        } catch (SQLException e) {
2271            throw new CmsDbSqlException(
2272                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2273                e);
2274        } finally {
2275            m_sqlManager.closeAll(dbc, conn, stmt, res);
2276        }
2277
2278        return (projects);
2279    }
2280
2281    /**
2282     * @see org.opencms.db.I_CmsProjectDriver#readProjectsForGroup(org.opencms.db.CmsDbContext, org.opencms.file.CmsGroup)
2283     */
2284    public List<CmsProject> readProjectsForGroup(CmsDbContext dbc, CmsGroup group) throws CmsDataAccessException {
2285
2286        List<CmsProject> projects = new ArrayList<CmsProject>();
2287        ResultSet res = null;
2288        Connection conn = null;
2289        PreparedStatement stmt = null;
2290
2291        try {
2292            // create the statement
2293            conn = m_sqlManager.getConnection(dbc);
2294            stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_READ_BYGROUP_2");
2295
2296            stmt.setString(1, group.getId().toString());
2297            stmt.setString(2, group.getId().toString());
2298            res = stmt.executeQuery();
2299
2300            while (res.next()) {
2301                projects.add(internalCreateProject(res));
2302            }
2303        } catch (SQLException e) {
2304            throw new CmsDbSqlException(
2305                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2306                e);
2307        } finally {
2308            m_sqlManager.closeAll(dbc, conn, stmt, res);
2309        }
2310        return (projects);
2311    }
2312
2313    /**
2314     * @see org.opencms.db.I_CmsProjectDriver#readProjectsForManagerGroup(org.opencms.db.CmsDbContext, org.opencms.file.CmsGroup)
2315     */
2316    public List<CmsProject> readProjectsForManagerGroup(CmsDbContext dbc, CmsGroup group)
2317    throws CmsDataAccessException {
2318
2319        List<CmsProject> projects = new ArrayList<CmsProject>();
2320        ResultSet res = null;
2321        PreparedStatement stmt = null;
2322        Connection conn = null;
2323
2324        try {
2325            // create the statement
2326            conn = m_sqlManager.getConnection(dbc);
2327            stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_READ_BYMANAGER_1");
2328
2329            stmt.setString(1, group.getId().toString());
2330            res = stmt.executeQuery();
2331
2332            while (res.next()) {
2333                projects.add(internalCreateProject(res));
2334            }
2335        } catch (SQLException e) {
2336            throw new CmsDbSqlException(
2337                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2338                e);
2339        } finally {
2340            m_sqlManager.closeAll(dbc, conn, stmt, res);
2341        }
2342        return (projects);
2343    }
2344
2345    /**
2346     * Returns the projects of a given resource.<p>
2347     *
2348     * @param dbc the database context
2349     * @param rootPath the resource root path
2350     *
2351     * @return the projects of the resource, as a list of projects
2352     *
2353     * @throws CmsDataAccessException if something goes wrong
2354     */
2355    public List<CmsProject> readProjectsForResource(CmsDbContext dbc, String rootPath) throws CmsDataAccessException {
2356
2357        PreparedStatement stmt = null;
2358        List<CmsProject> projects = new ArrayList<CmsProject>();
2359        ResultSet res = null;
2360        Connection conn = null;
2361
2362        try {
2363            conn = m_sqlManager.getConnection(dbc);
2364            stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_READ_BYRESOURCE_1");
2365
2366            stmt.setString(1, rootPath + "%");
2367            res = stmt.executeQuery();
2368
2369            if (res.next()) {
2370                projects.add(internalCreateProject(res));
2371                while (res.next()) {
2372                    // do nothing only move through all rows because of mssql odbc driver
2373                }
2374            }
2375        } catch (SQLException e) {
2376            throw new CmsDbSqlException(
2377                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2378                e);
2379        } finally {
2380            m_sqlManager.closeAll(dbc, conn, stmt, res);
2381        }
2382
2383        return projects;
2384    }
2385
2386    /**
2387     * @see org.opencms.db.I_CmsProjectDriver#readProjectsForUser(org.opencms.db.CmsDbContext, org.opencms.file.CmsUser)
2388     */
2389    public List<CmsProject> readProjectsForUser(CmsDbContext dbc, CmsUser user) throws CmsDataAccessException {
2390
2391        List<CmsProject> projects = new ArrayList<CmsProject>();
2392        ResultSet res = null;
2393        PreparedStatement stmt = null;
2394        Connection conn = null;
2395
2396        try {
2397            // create the statement
2398            conn = m_sqlManager.getConnection(dbc);
2399            stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_READ_BYUSER_1");
2400
2401            stmt.setString(1, user.getId().toString());
2402            res = stmt.executeQuery();
2403
2404            while (res.next()) {
2405                projects.add(internalCreateProject(res));
2406            }
2407        } catch (SQLException e) {
2408            throw new CmsDbSqlException(
2409                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2410                e);
2411        } finally {
2412            m_sqlManager.closeAll(dbc, conn, stmt, res);
2413        }
2414        return (projects);
2415    }
2416
2417    /**
2418     * @see org.opencms.db.I_CmsProjectDriver#readPublishedResources(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID)
2419     */
2420    public List<CmsPublishedResource> readPublishedResources(CmsDbContext dbc, CmsUUID publishHistoryId)
2421    throws CmsDataAccessException {
2422
2423        Connection conn = null;
2424        PreparedStatement stmt = null;
2425        ResultSet res = null;
2426        List<CmsPublishedResource> publishedResources = new ArrayList<CmsPublishedResource>();
2427
2428        try {
2429            conn = m_sqlManager.getConnection(dbc);
2430            stmt = m_sqlManager.getPreparedStatement(conn, "C_SELECT_PUBLISHED_RESOURCES");
2431            stmt.setString(1, publishHistoryId.toString());
2432            res = stmt.executeQuery();
2433
2434            while (res.next()) {
2435                CmsUUID structureId = new CmsUUID(res.getString("STRUCTURE_ID"));
2436                CmsUUID resourceId = new CmsUUID(res.getString("RESOURCE_ID"));
2437                String rootPath = res.getString("RESOURCE_PATH");
2438                int resourceState = res.getInt("RESOURCE_STATE");
2439                int resourceType = res.getInt("RESOURCE_TYPE");
2440                int siblingCount = res.getInt("SIBLING_COUNT");
2441                int publishTag = res.getInt("PUBLISH_TAG");
2442
2443                // compose the resource state
2444                CmsResourceState state;
2445                if (resourceState == CmsPublishedResource.STATE_MOVED_SOURCE.getState()) {
2446                    state = CmsPublishedResource.STATE_MOVED_SOURCE;
2447                } else if (resourceState == CmsPublishedResource.STATE_MOVED_DESTINATION.getState()) {
2448                    state = CmsPublishedResource.STATE_MOVED_DESTINATION;
2449                } else {
2450                    state = CmsResourceState.valueOf(resourceState);
2451                }
2452
2453                publishedResources.add(
2454                    new CmsPublishedResource(
2455                        structureId,
2456                        resourceId,
2457                        publishTag,
2458                        rootPath,
2459                        resourceType,
2460                        structureId.isNullUUID() ? false : CmsFolder.isFolderType(resourceType),
2461                        state,
2462                        siblingCount));
2463            }
2464        } catch (SQLException e) {
2465            throw new CmsDbSqlException(
2466                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2467                e);
2468        } finally {
2469            m_sqlManager.closeAll(dbc, conn, stmt, res);
2470        }
2471
2472        return publishedResources;
2473    }
2474
2475    /**
2476     * @see org.opencms.db.I_CmsProjectDriver#readPublishJob(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID)
2477     */
2478    public CmsPublishJobInfoBean readPublishJob(CmsDbContext dbc, CmsUUID publishHistoryId)
2479    throws CmsDataAccessException {
2480
2481        Connection conn = null;
2482        PreparedStatement stmt = null;
2483        ResultSet res = null;
2484
2485        CmsPublishJobInfoBean result = null;
2486        try {
2487            conn = m_sqlManager.getConnection(dbc);
2488            stmt = m_sqlManager.getPreparedStatement(conn, "C_PUBLISHJOB_READ_JOB");
2489            stmt.setString(1, publishHistoryId.toString());
2490            res = stmt.executeQuery();
2491
2492            if (res.next()) {
2493                result = createPublishJobInfoBean(res);
2494                while (res.next()) {
2495                    // do nothing only move through all rows because of mssql odbc driver
2496                }
2497            } else {
2498                throw new CmsDbEntryNotFoundException(
2499                    Messages.get().container(Messages.ERR_READ_PUBLISH_JOB_1, publishHistoryId.toString()));
2500            }
2501        } catch (SQLException e) {
2502            throw new CmsDbSqlException(
2503                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2504                e);
2505        } finally {
2506            m_sqlManager.closeAll(dbc, conn, stmt, res);
2507        }
2508
2509        return result;
2510    }
2511
2512    /**
2513     * @see org.opencms.db.I_CmsProjectDriver#readPublishJobs(org.opencms.db.CmsDbContext, long, long)
2514     */
2515    public List<CmsPublishJobInfoBean> readPublishJobs(CmsDbContext dbc, long startTime, long endTime)
2516    throws CmsDataAccessException {
2517
2518        Connection conn = null;
2519        PreparedStatement stmt = null;
2520        ResultSet res = null;
2521
2522        List<CmsPublishJobInfoBean> result = null;
2523        try {
2524            conn = m_sqlManager.getConnection(dbc);
2525            stmt = m_sqlManager.getPreparedStatement(conn, "C_PUBLISHJOB_READ_JOBS_IN_TIMERANGE");
2526            stmt.setLong(1, startTime);
2527            stmt.setLong(2, endTime);
2528            res = stmt.executeQuery();
2529
2530            result = new ArrayList<CmsPublishJobInfoBean>();
2531            while (res.next()) {
2532                result.add(createPublishJobInfoBean(res));
2533            }
2534        } catch (SQLException e) {
2535            throw new CmsDbSqlException(
2536                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2537                e);
2538        } finally {
2539            m_sqlManager.closeAll(dbc, conn, stmt, res);
2540        }
2541
2542        return result;
2543    }
2544
2545    /**
2546     * @see org.opencms.db.I_CmsProjectDriver#readPublishList(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID)
2547     */
2548    public CmsPublishList readPublishList(CmsDbContext dbc, CmsUUID publishHistoryId) throws CmsDataAccessException {
2549
2550        Connection conn = null;
2551        PreparedStatement stmt = null;
2552        ResultSet res = null;
2553        CmsPublishList publishList = null;
2554
2555        try {
2556            conn = m_sqlManager.getConnection(dbc);
2557            stmt = m_sqlManager.getPreparedStatement(conn, "C_PUBLISHJOB_READ_PUBLISHLIST");
2558            stmt.setString(1, publishHistoryId.toString());
2559            res = stmt.executeQuery();
2560
2561            if (res.next()) {
2562                byte[] bytes = m_sqlManager.getBytes(res, "PUBLISH_LIST");
2563                publishList = internalDeserializePublishList(bytes);
2564                while (res.next()) {
2565                    // do nothing only move through all rows because of mssql odbc driver
2566                }
2567            } else {
2568                throw new CmsDataAccessException(
2569                    Messages.get().container(Messages.ERR_READ_PUBLISH_JOB_1, publishHistoryId.toString()));
2570            }
2571        } catch (SQLException e) {
2572            throw new CmsDbSqlException(
2573                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2574                e);
2575        } catch (Exception e) {
2576            throw new CmsDataAccessException(
2577                Messages.get().container(Messages.ERR_PUBLISHLIST_DESERIALIZATION_FAILED_1, publishHistoryId),
2578                e);
2579        } finally {
2580            m_sqlManager.closeAll(dbc, conn, stmt, res);
2581        }
2582
2583        return publishList;
2584    }
2585
2586    /**
2587     * @see org.opencms.db.I_CmsProjectDriver#readPublishReportContents(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID)
2588     */
2589    public byte[] readPublishReportContents(CmsDbContext dbc, CmsUUID publishHistoryId) throws CmsDataAccessException {
2590
2591        PreparedStatement stmt = null;
2592        ResultSet res = null;
2593        Connection conn = null;
2594        byte[] bytes = null;
2595
2596        try {
2597            conn = m_sqlManager.getConnection(dbc);
2598
2599            stmt = m_sqlManager.getPreparedStatement(conn, "C_PUBLISHJOB_READ_REPORT");
2600            stmt.setString(1, publishHistoryId.toString());
2601            res = stmt.executeQuery();
2602
2603            if (res.next()) {
2604                // query to read Array of bytes for the given attribute
2605                bytes = m_sqlManager.getBytes(res, "PUBLISH_REPORT");
2606                while (res.next()) {
2607                    // do nothing only move through all rows because of mssql odbc driver
2608                }
2609            } else {
2610                throw new CmsDataAccessException(
2611                    Messages.get().container(Messages.ERR_READ_PUBLISH_JOB_1, publishHistoryId.toString()));
2612            }
2613        } catch (SQLException e) {
2614            LOG.error(CmsDbSqlException.getErrorQuery(stmt), e);
2615            bytes = Messages.get().container(
2616                Messages.ERR_GENERIC_SQL_1,
2617                CmsDbSqlException.getErrorQuery(stmt)).key().getBytes();
2618        } finally {
2619            m_sqlManager.closeAll(dbc, conn, stmt, res);
2620        }
2621        return bytes;
2622    }
2623
2624    /**
2625     * @see org.opencms.db.I_CmsProjectDriver#readStaticExportPublishedResourceParameters(org.opencms.db.CmsDbContext, java.lang.String)
2626     */
2627    public String readStaticExportPublishedResourceParameters(CmsDbContext dbc, String rfsName)
2628    throws CmsDataAccessException {
2629
2630        String returnValue = null;
2631        Connection conn = null;
2632        PreparedStatement stmt = null;
2633        ResultSet res = null;
2634
2635        try {
2636            conn = m_sqlManager.getConnection(dbc);
2637            stmt = m_sqlManager.getPreparedStatement(conn, "C_STATICEXPORT_READ_PUBLISHED_LINK_PARAMETERS");
2638            stmt.setString(1, rfsName);
2639            res = stmt.executeQuery();
2640            // add all resourcenames to the list of return values
2641            if (res.next()) {
2642                returnValue = res.getString(1);
2643                while (res.next()) {
2644                    // do nothing only move through all rows because of mssql odbc driver
2645                }
2646            }
2647        } catch (SQLException e) {
2648            throw new CmsDbSqlException(
2649                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2650                e);
2651        } finally {
2652            m_sqlManager.closeAll(dbc, conn, stmt, res);
2653        }
2654
2655        return returnValue;
2656    }
2657
2658    /**
2659     * @see org.opencms.db.I_CmsProjectDriver#readStaticExportResources(org.opencms.db.CmsDbContext, int, long)
2660     */
2661    public List<String> readStaticExportResources(CmsDbContext dbc, int parameterResources, long timestamp)
2662    throws CmsDataAccessException {
2663
2664        Connection conn = null;
2665        PreparedStatement stmt = null;
2666        ResultSet res = null;
2667        List<String> returnValue = new ArrayList<String>();
2668
2669        if (parameterResources == CmsStaticExportManager.EXPORT_LINK_WITHOUT_PARAMETER) {
2670            timestamp = 0;
2671        }
2672        try {
2673            conn = m_sqlManager.getConnection(dbc);
2674            stmt = m_sqlManager.getPreparedStatement(conn, "C_STATICEXPORT_READ_ALL_PUBLISHED_LINKS");
2675            stmt.setInt(1, parameterResources);
2676            stmt.setLong(2, timestamp);
2677            res = stmt.executeQuery();
2678            // add all resourcenames to the list of return values
2679            while (res.next()) {
2680                returnValue.add(res.getString(1));
2681            }
2682        } catch (SQLException e) {
2683            throw new CmsDbSqlException(
2684                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2685                e);
2686        } finally {
2687            m_sqlManager.closeAll(dbc, conn, stmt, res);
2688        }
2689
2690        return returnValue;
2691    }
2692
2693    /**
2694     * @see org.opencms.db.I_CmsProjectDriver#setDriverManager(org.opencms.db.CmsDriverManager)
2695     */
2696    public void setDriverManager(CmsDriverManager driverManager) {
2697
2698        m_driverManager = driverManager;
2699    }
2700
2701    /**
2702     * @see org.opencms.db.I_CmsProjectDriver#setSqlManager(org.opencms.db.CmsSqlManager)
2703     */
2704    public void setSqlManager(org.opencms.db.CmsSqlManager manager) {
2705
2706        m_sqlManager = (CmsSqlManager)manager;
2707    }
2708
2709    /**
2710     * @see org.opencms.db.I_CmsProjectDriver#unmarkProjectResources(org.opencms.db.CmsDbContext, org.opencms.file.CmsProject)
2711     */
2712    public void unmarkProjectResources(CmsDbContext dbc, CmsProject project) throws CmsDataAccessException {
2713
2714        // finally remove the project id form all resources
2715
2716        Connection conn = null;
2717        PreparedStatement stmt = null;
2718        try {
2719            conn = m_sqlManager.getConnection(dbc);
2720            stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_UNMARK");
2721            // create the statement
2722            stmt.setString(1, project.getUuid().toString());
2723            stmt.executeUpdate();
2724        } catch (SQLException e) {
2725            throw new CmsDbSqlException(
2726                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2727                e);
2728        } finally {
2729            m_sqlManager.closeAll(dbc, conn, stmt, null);
2730        }
2731    }
2732
2733    /**
2734     * @see org.opencms.db.I_CmsProjectDriver#writeLocks(org.opencms.db.CmsDbContext, java.util.List)
2735     */
2736    public void writeLocks(CmsDbContext dbc, List<CmsLock> locks) throws CmsDataAccessException {
2737
2738        Connection conn = null;
2739        PreparedStatement stmt = null;
2740        try {
2741            conn = m_sqlManager.getConnection(dbc);
2742            stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCE_LOCKS_DELETEALL");
2743            int deleted = stmt.executeUpdate();
2744            if (LOG.isDebugEnabled()) {
2745                LOG.debug(Messages.get().getBundle().key(Messages.LOG_DBG_CLEAR_LOCKS_1, Integer.valueOf(deleted)));
2746            }
2747            stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCE_LOCK_WRITE");
2748            if (LOG.isDebugEnabled()) {
2749                LOG.debug("SQL :" + m_sqlManager.readQuery("C_RESOURCE_LOCK_WRITE"));
2750            }
2751            Iterator<CmsLock> i = locks.iterator();
2752            int count = 0;
2753            while (i.hasNext()) {
2754                CmsLock lock = i.next();
2755                // only persist locks that should be written to the DB
2756                CmsLock sysLock = lock.getSystemLock();
2757                if (sysLock.isPersistent()) {
2758                    // persist system lock
2759                    stmt.setString(1, sysLock.getResourceName());
2760                    stmt.setString(2, sysLock.getUserId().toString());
2761                    stmt.setString(3, sysLock.getProjectId().toString());
2762                    stmt.setInt(4, sysLock.getType().hashCode());
2763                    stmt.executeUpdate();
2764                    count++;
2765                }
2766                CmsLock editLock = lock.getEditionLock();
2767                if (editLock.isPersistent()) {
2768                    // persist edition lock
2769                    stmt.setString(1, editLock.getResourceName());
2770                    stmt.setString(2, editLock.getUserId().toString());
2771                    stmt.setString(3, editLock.getProjectId().toString());
2772                    stmt.setInt(4, editLock.getType().hashCode());
2773                    stmt.executeUpdate();
2774                    count++;
2775                }
2776            }
2777            if (LOG.isDebugEnabled()) {
2778                LOG.debug(Messages.get().getBundle().key(Messages.LOG_DBG_WRITE_LOCKS_1, Integer.valueOf(count)));
2779            }
2780        } catch (SQLException e) {
2781            throw new CmsDbSqlException(
2782                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2783                e);
2784        } finally {
2785            m_sqlManager.closeAll(dbc, conn, stmt, null);
2786        }
2787    }
2788
2789    /**
2790     * @see org.opencms.db.I_CmsProjectDriver#writeProject(org.opencms.db.CmsDbContext, org.opencms.file.CmsProject)
2791     */
2792    public void writeProject(CmsDbContext dbc, CmsProject project) throws CmsDataAccessException {
2793
2794        if (CmsStringUtil.isEmptyOrWhitespaceOnly(project.getDescription())) {
2795            project.setDescription(" ");
2796        }
2797        Connection conn = null;
2798        PreparedStatement stmt = null;
2799
2800        try {
2801            // get a JDBC connection from the OpenCms standard pools
2802            conn = m_sqlManager.getConnection(dbc);
2803
2804            stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_WRITE_6");
2805            stmt.setString(1, project.getDescription());
2806            stmt.setString(2, project.getGroupId().toString());
2807            stmt.setString(3, project.getManagerGroupId().toString());
2808            stmt.setInt(4, project.getFlags());
2809            stmt.setInt(5, project.getType().getMode());
2810            stmt.setString(6, project.getUuid().toString());
2811            stmt.executeUpdate();
2812        } catch (SQLException e) {
2813            throw new CmsDbSqlException(
2814                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2815                e);
2816        } finally {
2817            m_sqlManager.closeAll(dbc, conn, stmt, null);
2818        }
2819    }
2820
2821    /**
2822     * @see org.opencms.db.I_CmsProjectDriver#writePublishHistory(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID, org.opencms.db.CmsPublishedResource)
2823     */
2824    public void writePublishHistory(CmsDbContext dbc, CmsUUID publishId, CmsPublishedResource resource)
2825    throws CmsDataAccessException {
2826
2827        Connection conn = null;
2828        PreparedStatement stmt = null;
2829
2830        try {
2831            conn = m_sqlManager.getConnection(dbc);
2832            stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_WRITE_PUBLISH_HISTORY");
2833            stmt.setInt(1, resource.getPublishTag());
2834            stmt.setString(2, resource.getStructureId().toString());
2835            stmt.setString(3, resource.getResourceId().toString());
2836            stmt.setString(4, resource.getRootPath());
2837            stmt.setInt(5, resource.getMovedState().getState());
2838            stmt.setInt(6, resource.getType());
2839            stmt.setString(7, publishId.toString());
2840            stmt.setInt(8, resource.getSiblingCount());
2841            stmt.executeUpdate();
2842        } catch (SQLException e) {
2843            throw new CmsDbSqlException(
2844                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2845                e);
2846        } finally {
2847            m_sqlManager.closeAll(dbc, conn, stmt, null);
2848        }
2849    }
2850
2851    /**
2852     * @see org.opencms.db.I_CmsProjectDriver#writePublishJob(org.opencms.db.CmsDbContext, org.opencms.publish.CmsPublishJobInfoBean)
2853     */
2854    public void writePublishJob(CmsDbContext dbc, CmsPublishJobInfoBean publishJob) throws CmsDataAccessException {
2855
2856        Connection conn = null;
2857        PreparedStatement stmt = null;
2858
2859        try {
2860            conn = m_sqlManager.getConnection(dbc);
2861            stmt = m_sqlManager.getPreparedStatement(conn, "C_PUBLISHJOB_WRITE");
2862            stmt.setString(1, publishJob.getProjectId().toString());
2863            stmt.setString(2, publishJob.getProjectName());
2864            stmt.setString(3, publishJob.getUserId().toString());
2865            stmt.setString(4, publishJob.getLocale().toString());
2866            stmt.setInt(5, publishJob.getFlags());
2867            stmt.setInt(6, publishJob.getSize());
2868            stmt.setLong(7, publishJob.getEnqueueTime());
2869            stmt.setLong(8, publishJob.getStartTime());
2870            stmt.setLong(9, publishJob.getFinishTime());
2871            stmt.setString(10, publishJob.getPublishHistoryId().toString());
2872            stmt.executeUpdate();
2873        } catch (SQLException e) {
2874            throw new CmsDbSqlException(
2875                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2876                e);
2877        } finally {
2878            m_sqlManager.closeAll(dbc, conn, stmt, null);
2879        }
2880    }
2881
2882    /**
2883     * @see org.opencms.db.I_CmsProjectDriver#writePublishReport(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID, byte[])
2884     */
2885    public void writePublishReport(CmsDbContext dbc, CmsUUID publishId, byte[] content) throws CmsDataAccessException {
2886
2887        Connection conn = null;
2888        PreparedStatement stmt = null;
2889
2890        try {
2891            conn = m_sqlManager.getConnection(dbc);
2892            stmt = m_sqlManager.getPreparedStatement(conn, "C_PUBLISHJOB_WRITE_REPORT");
2893
2894            if (content.length < 2000) {
2895                stmt.setBytes(1, content);
2896            } else {
2897                stmt.setBinaryStream(1, new ByteArrayInputStream(content), content.length);
2898            }
2899
2900            stmt.setString(2, publishId.toString());
2901            stmt.executeUpdate();
2902        } catch (SQLException e) {
2903            throw new CmsDbSqlException(
2904                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2905                e);
2906        } finally {
2907            m_sqlManager.closeAll(dbc, conn, stmt, null);
2908        }
2909    }
2910
2911    /**
2912     * @see org.opencms.db.I_CmsProjectDriver#writeStaticExportPublishedResource(org.opencms.db.CmsDbContext, java.lang.String, int, java.lang.String, long)
2913     */
2914    public void writeStaticExportPublishedResource(
2915        CmsDbContext dbc,
2916        String resourceName,
2917        int linkType,
2918        String linkParameter,
2919        long timestamp)
2920    throws CmsDataAccessException {
2921
2922        Connection conn = null;
2923        PreparedStatement stmt = null;
2924        ResultSet res = null;
2925        int returnValue = 0;
2926        // first check if a record with this resource name does already exist
2927        try {
2928            conn = m_sqlManager.getConnection(dbc);
2929            stmt = m_sqlManager.getPreparedStatement(conn, "C_STATICEXPORT_READ_PUBLISHED_RESOURCES");
2930            stmt.setString(1, resourceName);
2931            res = stmt.executeQuery();
2932            if (res.next()) {
2933                returnValue = res.getInt(1);
2934                while (res.next()) {
2935                    // do nothing only move through all rows because of mssql odbc driver
2936                }
2937            }
2938        } catch (SQLException e) {
2939            throw new CmsDbSqlException(
2940                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2941                e);
2942        } finally {
2943            m_sqlManager.closeAll(dbc, conn, stmt, res);
2944        }
2945
2946        // there was no entry found, so add it to the database
2947        if (returnValue == 0) {
2948            try {
2949                conn = m_sqlManager.getConnection(dbc);
2950                stmt = m_sqlManager.getPreparedStatement(conn, "C_STATICEXPORT_WRITE_PUBLISHED_LINKS");
2951                stmt.setString(1, new CmsUUID().toString());
2952                stmt.setString(2, resourceName);
2953                stmt.setInt(3, linkType);
2954                stmt.setString(4, linkParameter);
2955                stmt.setLong(5, timestamp);
2956                stmt.executeUpdate();
2957            } catch (SQLException e) {
2958                throw new CmsDbSqlException(Messages.get().container(Messages.ERR_GENERIC_SQL_1, stmt), e);
2959            } finally {
2960                m_sqlManager.closeAll(dbc, conn, stmt, null);
2961            }
2962        }
2963    }
2964
2965    /**
2966     * @see org.opencms.db.I_CmsProjectDriver#writeUserPublishListEntries(org.opencms.db.CmsDbContext, java.util.List)
2967     */
2968    public void writeUserPublishListEntries(CmsDbContext dbc, List<CmsUserPublishListEntry> publishListAdditions)
2969    throws CmsDbSqlException {
2970
2971        if (publishListAdditions.isEmpty()) {
2972            return;
2973        }
2974
2975        // first remove all entries with the same keys
2976        deleteUserPublishListEntries(dbc, publishListAdditions);
2977
2978        Connection conn = null;
2979        PreparedStatement stmt = null;
2980        try {
2981            conn = m_sqlManager.getConnection(dbc);
2982            String sql = m_sqlManager.readQuery("C_USER_PUBLISH_LIST_INSERT_3");
2983            stmt = m_sqlManager.getPreparedStatementForSql(conn, sql);
2984            for (CmsUserPublishListEntry entry : publishListAdditions) {
2985                stmt.setString(1, entry.getUserId().toString());
2986                stmt.setString(2, entry.getStructureId().toString());
2987                stmt.setLong(3, entry.getDateChanged());
2988                stmt.addBatch();
2989            }
2990            stmt.executeBatch();
2991        } catch (SQLException e) {
2992            throw new CmsDbSqlException(
2993                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2994                e);
2995        } finally {
2996            m_sqlManager.closeAll(dbc, conn, stmt, null);
2997        }
2998
2999    }
3000
3001    /**
3002     * Creates a <code>CmsPublishJobInfoBean</code> from a result set.<p>
3003     *
3004     * @param res the result set
3005     * @return an initialized <code>CmsPublishJobInfoBean</code>
3006     * @throws SQLException if something goes wrong
3007     */
3008    protected CmsPublishJobInfoBean createPublishJobInfoBean(ResultSet res) throws SQLException {
3009
3010        return new CmsPublishJobInfoBean(
3011            new CmsUUID(res.getString("HISTORY_ID")),
3012            new CmsUUID(res.getString("PROJECT_ID")),
3013            res.getString("PROJECT_NAME"),
3014            new CmsUUID(res.getString("USER_ID")),
3015            res.getString("PUBLISH_LOCALE"),
3016            res.getInt("PUBLISH_FLAGS"),
3017            res.getInt("RESOURCE_COUNT"),
3018            res.getLong("ENQUEUE_TIME"),
3019            res.getLong("START_TIME"),
3020            res.getLong("FINISH_TIME"));
3021    }
3022
3023    /**
3024     * Checks if the given resource (by id) is available in the online project,
3025     * if there exists a resource with a different path (a moved file), then the
3026     * online entry is moved to the right (new) location before publishing.<p>
3027     *
3028     * @param dbc the db context
3029     * @param onlineProject the online project
3030     * @param offlineResource the offline resource to check
3031     * @param publishHistoryId the publish history id
3032     * @param publishTag the publish tag
3033     *
3034     * @return <code>true</code> if the resource has actually been moved
3035     *
3036     * @throws CmsDataAccessException if something goes wrong
3037     */
3038    protected CmsResourceState fixMovedResource(
3039        CmsDbContext dbc,
3040        CmsProject onlineProject,
3041        CmsResource offlineResource,
3042        CmsUUID publishHistoryId,
3043        int publishTag)
3044    throws CmsDataAccessException {
3045
3046        CmsResource onlineResource;
3047        // check if the resource has been moved since last publishing
3048        try {
3049            onlineResource = m_driverManager.getVfsDriver(
3050                dbc).readResource(dbc, onlineProject.getUuid(), offlineResource.getStructureId(), true);
3051            if (onlineResource.getRootPath().equals(offlineResource.getRootPath())) {
3052                // resource changed, not moved
3053                return offlineResource.getState();
3054            }
3055        } catch (CmsVfsResourceNotFoundException e) {
3056            // ok, resource new, not moved
3057            return offlineResource.getState();
3058        }
3059
3060        // move the online resource to the new position
3061        m_driverManager.getVfsDriver(
3062            dbc).moveResource(dbc, onlineProject.getUuid(), onlineResource, offlineResource.getRootPath());
3063
3064        try {
3065            // write the resource to the publish history
3066            m_driverManager.getProjectDriver(dbc).writePublishHistory(
3067                dbc,
3068                publishHistoryId,
3069                new CmsPublishedResource(onlineResource, publishTag, CmsPublishedResource.STATE_MOVED_SOURCE));
3070        } catch (CmsDataAccessException e) {
3071            if (LOG.isErrorEnabled()) {
3072                LOG.error(
3073                    Messages.get().getBundle().key(
3074                        Messages.LOG_WRITING_PUBLISHING_HISTORY_1,
3075                        onlineResource.getRootPath()),
3076                    e);
3077            }
3078            throw e;
3079        }
3080        return offlineResource.getState().isDeleted()
3081        ? CmsResource.STATE_DELETED
3082        : CmsPublishedResource.STATE_MOVED_DESTINATION;
3083    }
3084
3085    /**
3086     * Returns a SQL parameter string for the given data.<p>
3087     *
3088     * @param data the data
3089     *
3090     * @return the SQL parameter
3091     */
3092    protected String getParameterString(Collection<?> data) {
3093
3094        StringBuffer conditions = new StringBuffer();
3095        conditions.append(BEGIN_CONDITION);
3096        Iterator<?> it = data.iterator();
3097        while (it.hasNext()) {
3098            it.next();
3099            conditions.append("?");
3100            if (it.hasNext()) {
3101                conditions.append(", ");
3102            }
3103        }
3104        conditions.append(END_CONDITION);
3105        return conditions.toString();
3106    }
3107
3108    /**
3109     * Implementation of reading the user publish list which uses the log table.<p>
3110     *
3111     * This is the old implementation of the user publish list and can get pretty slow.<p>
3112     *
3113     * @param dbc the current database context
3114     * @param userId the id of the user for which we want the user publish list
3115     *
3116     * @return the publish list for the given user
3117     *
3118     * @throws CmsDataAccessException if something goes wrong
3119     */
3120    protected List<CmsResource> getUsersPubListFromLog(CmsDbContext dbc, CmsUUID userId) throws CmsDataAccessException {
3121
3122        Connection conn = null;
3123        PreparedStatement stmt = null;
3124        ResultSet res = null;
3125
3126        List<CmsResource> result = null;
3127        try {
3128            conn = m_sqlManager.getConnection(dbc);
3129            stmt = m_sqlManager.getPreparedStatement(conn, dbc.currentProject().getUuid(), "C_LOG_READ_PUBLISH_LIST_2");
3130            stmt.setString(1, userId.toString());
3131            stmt.setString(2, userId.toString());
3132            res = stmt.executeQuery();
3133
3134            result = new ArrayList<CmsResource>();
3135            while (res.next()) {
3136                CmsResource resource = m_driverManager.getVfsDriver(dbc).createResource(
3137                    res,
3138                    dbc.currentProject().getUuid());
3139                long date = res.getLong(m_sqlManager.readQuery("C_LOG_DATE"));
3140                resource.setDateLastModified(date);
3141                result.add(resource);
3142            }
3143        } catch (SQLException e) {
3144            throw new CmsDbSqlException(
3145                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
3146                e);
3147        } finally {
3148            m_sqlManager.closeAll(dbc, conn, stmt, res);
3149        }
3150        return result;
3151    }
3152
3153    /**
3154     * Creates a new project from the current row of the given result set.<p>
3155     *
3156     * @param res the result set
3157     *
3158     * @return the new project
3159     *
3160     * @throws SQLException is something goes wrong
3161     */
3162    protected CmsProject internalCreateProject(ResultSet res) throws SQLException {
3163
3164        String ou = CmsOrganizationalUnit.removeLeadingSeparator(
3165            res.getString(m_sqlManager.readQuery("C_PROJECTS_PROJECT_OU_0")));
3166        return new CmsProject(
3167            new CmsUUID(res.getString(m_sqlManager.readQuery("C_PROJECTS_PROJECT_ID_0"))),
3168            ou + res.getString(m_sqlManager.readQuery("C_PROJECTS_PROJECT_NAME_0")),
3169            res.getString(m_sqlManager.readQuery("C_PROJECTS_PROJECT_DESCRIPTION_0")),
3170            new CmsUUID(res.getString(m_sqlManager.readQuery("C_PROJECTS_USER_ID_0"))),
3171            new CmsUUID(res.getString(m_sqlManager.readQuery("C_PROJECTS_GROUP_ID_0"))),
3172            new CmsUUID(res.getString(m_sqlManager.readQuery("C_PROJECTS_MANAGERGROUP_ID_0"))),
3173            res.getInt(m_sqlManager.readQuery("C_PROJECTS_PROJECT_FLAGS_0")),
3174            res.getLong(m_sqlManager.readQuery("C_PROJECTS_DATE_CREATED_0")),
3175            CmsProject.CmsProjectType.valueOf(res.getInt(m_sqlManager.readQuery("C_PROJECTS_PROJECT_TYPE_0"))));
3176    }
3177
3178    /**
3179     * Builds a publish list from serialized data.<p>
3180     *
3181     * @param bytes the byte array containing the serailized data for the publish list
3182     * @return the initialized publish list
3183     *
3184     * @throws IOException if deserialization fails
3185     * @throws ClassNotFoundException if deserialization fails
3186     */
3187    protected CmsPublishList internalDeserializePublishList(byte[] bytes) throws IOException, ClassNotFoundException {
3188
3189        ByteArrayInputStream bin = new ByteArrayInputStream(bytes);
3190        ObjectInputStream oin = new ObjectInputStream(bin);
3191        return (CmsPublishList)oin.readObject();
3192    }
3193
3194    /**
3195     * Creates a new {@link CmsLogEntry} object from the given result set entry.<p>
3196     *
3197     * @param res the result set
3198     *
3199     * @return the new {@link CmsLogEntry} object
3200     *
3201     * @throws SQLException if something goes wrong
3202     */
3203    protected CmsLogEntry internalReadLogEntry(ResultSet res) throws SQLException {
3204
3205        CmsUUID userId = new CmsUUID(res.getString(m_sqlManager.readQuery("C_LOG_USER_ID")));
3206        long date = res.getLong(m_sqlManager.readQuery("C_LOG_DATE"));
3207        CmsUUID structureId = new CmsUUID(res.getString(m_sqlManager.readQuery("C_LOG_STRUCTURE_ID")));
3208        CmsLogEntryType type = CmsLogEntryType.valueOf(res.getInt(m_sqlManager.readQuery("C_LOG_TYPE")));
3209        String[] data = CmsStringUtil.splitAsArray(res.getString(m_sqlManager.readQuery("C_LOG_DATA")), '|');
3210        return new CmsLogEntry(userId, date, structureId, type, data);
3211    }
3212
3213    /**
3214     * Resets the state to UNCHANGED for a specified resource.<p>
3215     *
3216     * @param dbc the current database context
3217     * @param resource the Cms resource
3218     *
3219     * @throws CmsDataAccessException if something goes wrong
3220     */
3221    protected void internalResetResourceState(CmsDbContext dbc, CmsResource resource) throws CmsDataAccessException {
3222
3223        try {
3224            // reset the resource state
3225            resource.setState(CmsResource.STATE_UNCHANGED);
3226            m_driverManager.getVfsDriver(
3227                dbc).writeResourceState(dbc, dbc.currentProject(), resource, CmsDriverManager.UPDATE_ALL, true);
3228        } catch (CmsDataAccessException e) {
3229            if (LOG.isErrorEnabled()) {
3230                LOG.error(
3231                    Messages.get().getBundle().key(
3232                        Messages.LOG_ERROR_RESETTING_RESOURCE_STATE_1,
3233                        resource.getRootPath()),
3234                    e);
3235            }
3236            throw e;
3237        }
3238    }
3239
3240    /**
3241     * Serialize publish list to write it as byte array to the database.<p>
3242     *
3243     * @param publishList the publish list
3244     * @return byte array containing the publish list data
3245     * @throws IOException if something goes wrong
3246     */
3247    protected byte[] internalSerializePublishList(CmsPublishList publishList) throws IOException {
3248
3249        // serialize the publish list
3250        ByteArrayOutputStream bout = new ByteArrayOutputStream();
3251        ObjectOutputStream oout = new ObjectOutputStream(bout);
3252        oout.writeObject(publishList);
3253        oout.close();
3254        return bout.toByteArray();
3255    }
3256
3257    /**
3258     * Writes the needed history entries.<p>
3259     *
3260     * @param dbc the current database context
3261     * @param resource the offline resource
3262     * @param state the state to store in the publish history entry
3263     * @param properties the offline properties
3264     * @param publishHistoryId the current publish process id
3265     * @param publishTag the current publish process tag
3266     *
3267     * @throws CmsDataAccessException if something goes wrong
3268     */
3269    protected void internalWriteHistory(
3270        CmsDbContext dbc,
3271        CmsResource resource,
3272        CmsResourceState state,
3273        List<CmsProperty> properties,
3274        CmsUUID publishHistoryId,
3275        int publishTag)
3276    throws CmsDataAccessException {
3277
3278        try {
3279            if (OpenCms.getSystemInfo().isHistoryEnabled()) {
3280                // write the resource to the historical archive
3281                if (properties == null) {
3282                    properties = m_driverManager.getVfsDriver(dbc).readPropertyObjects(
3283                        dbc,
3284                        dbc.currentProject(),
3285                        resource);
3286                }
3287                m_driverManager.getHistoryDriver(dbc).writeResource(dbc, resource, properties, publishTag);
3288            }
3289            // write the resource to the publish history
3290            m_driverManager.getProjectDriver(dbc).writePublishHistory(
3291                dbc,
3292                publishHistoryId,
3293                new CmsPublishedResource(resource, publishTag, state));
3294        } catch (CmsDataAccessException e) {
3295            if (LOG.isErrorEnabled()) {
3296                LOG.error(
3297                    Messages.get().getBundle().key(Messages.LOG_WRITING_PUBLISHING_HISTORY_1, resource.getRootPath()),
3298                    e);
3299            }
3300            throw e;
3301        }
3302    }
3303
3304    /**
3305     * Build the whole WHERE SQL statement part for the given log entry filter.<p>
3306     *
3307     * @param filter the filter
3308     *
3309     * @return a pair containing both the SQL and the parameters for it
3310     */
3311    protected CmsPair<String, List<I_CmsPreparedStatementParameter>> prepareLogConditions(CmsLogFilter filter) {
3312
3313        List<I_CmsPreparedStatementParameter> params = new ArrayList<I_CmsPreparedStatementParameter>();
3314        StringBuffer conditions = new StringBuffer();
3315
3316        // user id filter
3317        if (filter.getUserId() != null) {
3318            if (conditions.length() == 0) {
3319                conditions.append(BEGIN_CONDITION);
3320            } else {
3321                conditions.append(BEGIN_INCLUDE_CONDITION);
3322            }
3323            conditions.append(m_sqlManager.readQuery("C_LOG_FILTER_USER_ID"));
3324            params.add(new CmsPreparedStatementStringParameter(filter.getUserId().toString()));
3325            conditions.append(END_CONDITION);
3326        }
3327
3328        // resource id filter
3329        if (filter.getStructureId() != null) {
3330            if (conditions.length() == 0) {
3331                conditions.append(BEGIN_CONDITION);
3332            } else {
3333                conditions.append(BEGIN_INCLUDE_CONDITION);
3334            }
3335            conditions.append(m_sqlManager.readQuery("C_LOG_FILTER_RESOURCE_ID"));
3336            params.add(new CmsPreparedStatementStringParameter(filter.getStructureId().toString()));
3337            conditions.append(END_CONDITION);
3338        }
3339
3340        // date from filter
3341        if (filter.getDateFrom() != CmsResource.DATE_RELEASED_DEFAULT) {
3342            if (conditions.length() == 0) {
3343                conditions.append(BEGIN_CONDITION);
3344            } else {
3345                conditions.append(BEGIN_INCLUDE_CONDITION);
3346            }
3347            conditions.append(m_sqlManager.readQuery("C_LOG_FILTER_DATE_FROM"));
3348            params.add(new CmsPreparedStatementLongParameter(filter.getDateFrom()));
3349            conditions.append(END_CONDITION);
3350        }
3351
3352        // date to filter
3353        if (filter.getDateTo() != CmsResource.DATE_RELEASED_DEFAULT) {
3354            if (conditions.length() == 0) {
3355                conditions.append(BEGIN_CONDITION);
3356            } else {
3357                conditions.append(BEGIN_INCLUDE_CONDITION);
3358            }
3359            conditions.append(m_sqlManager.readQuery("C_LOG_FILTER_DATE_TO"));
3360            params.add(new CmsPreparedStatementLongParameter(filter.getDateTo()));
3361            conditions.append(END_CONDITION);
3362        }
3363
3364        // include type filter
3365        Set<CmsLogEntryType> includeTypes = filter.getIncludeTypes();
3366        if (!includeTypes.isEmpty()) {
3367            if (conditions.length() == 0) {
3368                conditions.append(BEGIN_CONDITION);
3369            } else {
3370                conditions.append(BEGIN_INCLUDE_CONDITION);
3371            }
3372            conditions.append(m_sqlManager.readQuery("C_LOG_FILTER_INCLUDE_TYPE"));
3373            conditions.append(BEGIN_CONDITION);
3374            Iterator<CmsLogEntryType> it = includeTypes.iterator();
3375            while (it.hasNext()) {
3376                CmsLogEntryType type = it.next();
3377                conditions.append("?");
3378                params.add(new CmsPreparedStatementIntParameter(type.getId()));
3379                if (it.hasNext()) {
3380                    conditions.append(", ");
3381                }
3382            }
3383            conditions.append(END_CONDITION);
3384            conditions.append(END_CONDITION);
3385        }
3386
3387        // exclude type filter
3388        Set<CmsLogEntryType> excludeTypes = filter.getExcludeTypes();
3389        if (!excludeTypes.isEmpty()) {
3390            if (conditions.length() == 0) {
3391                conditions.append(BEGIN_CONDITION);
3392            } else {
3393                conditions.append(BEGIN_INCLUDE_CONDITION);
3394            }
3395            conditions.append(m_sqlManager.readQuery("C_LOG_FILTER_EXCLUDE_TYPE"));
3396            conditions.append(BEGIN_CONDITION);
3397            Iterator<CmsLogEntryType> it = excludeTypes.iterator();
3398            while (it.hasNext()) {
3399                CmsLogEntryType type = it.next();
3400                conditions.append("?");
3401                params.add(new CmsPreparedStatementIntParameter(type.getId()));
3402                if (it.hasNext()) {
3403                    conditions.append(", ");
3404                }
3405            }
3406            conditions.append(END_CONDITION);
3407            conditions.append(END_CONDITION);
3408        }
3409        return CmsPair.create(conditions.toString(), params);
3410    }
3411
3412    /**
3413     * Publishes a changed file.<p>
3414     *
3415     * @param dbc the current database context
3416     * @param onlineProject the online project
3417     * @param offlineResource the resource to publish
3418     * @param publishedResourceIds contains the UUIDs of already published content records
3419     * @param publishHistoryId the publish history id
3420     * @param publishTag the publish tag
3421     *
3422     * @throws CmsDataAccessException is something goes wrong
3423     */
3424    protected void publishChangedFile(
3425        CmsDbContext dbc,
3426        CmsProject onlineProject,
3427        CmsResource offlineResource,
3428        Set<CmsUUID> publishedResourceIds,
3429        CmsUUID publishHistoryId,
3430        int publishTag)
3431    throws CmsDataAccessException {
3432
3433        CmsResource onlineResource = null;
3434        boolean needToUpdateContent = true;
3435        boolean existsOnline = m_driverManager.getVfsDriver(dbc).validateStructureIdExists(
3436            dbc,
3437            CmsProject.ONLINE_PROJECT_ID,
3438            offlineResource.getStructureId());
3439        CmsResourceState resourceState = existsOnline
3440        ? fixMovedResource(dbc, onlineProject, offlineResource, publishHistoryId, publishTag)
3441        : offlineResource.getState();
3442        try {
3443            // reset the labeled link flag before writing the online file
3444            int flags = offlineResource.getFlags();
3445            flags &= ~CmsResource.FLAG_LABELED;
3446            offlineResource.setFlags(flags);
3447
3448            if (existsOnline) {
3449                // read the file header online
3450                onlineResource = m_driverManager.getVfsDriver(
3451                    dbc).readResource(dbc, onlineProject.getUuid(), offlineResource.getStructureId(), false);
3452                needToUpdateContent = (onlineResource.getDateContent() < offlineResource.getDateContent());
3453                // delete the properties online
3454                m_driverManager.getVfsDriver(dbc).deletePropertyObjects(
3455                    dbc,
3456                    onlineProject.getUuid(),
3457                    onlineResource,
3458                    CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES);
3459
3460                // if the offline file has a resource ID different from the online file
3461                // (probably because a deleted file was replaced by a new file with the
3462                // same name), the properties mapped to the "old" resource ID have to be
3463                // deleted also offline. if this is the case, the online and offline structure
3464                // ID's do match, but the resource ID's are different. structure IDs are reused
3465                // to prevent orphan structure records in the online project.
3466
3467                // Addendum (2023): It shouldn't be possible for resources to be in this state anymore,
3468                // since creating new resources over deleted ones isn't really possible anymore,
3469                // but apparently it can still happen, though I can't reproduce it.
3470                if (!onlineResource.getResourceId().equals(offlineResource.getResourceId())) {
3471                    List<CmsProperty> offlineProperties = m_driverManager.getVfsDriver(dbc).readPropertyObjects(
3472                        dbc,
3473                        dbc.currentProject(),
3474                        onlineResource);
3475                    if (offlineProperties.size() > 0) {
3476                        List<CmsProperty> newProperties = new ArrayList<>();
3477                        for (int i = 0; i < offlineProperties.size(); i++) {
3478                            CmsProperty oldProperty = offlineProperties.get(i);
3479                            // property may be frozen (non-modifiable), so create a new one
3480                            CmsProperty newProperty = new CmsProperty(
3481                                oldProperty.getName(),
3482                                null,
3483                                CmsProperty.DELETE_VALUE);
3484                            newProperties.add(newProperty);
3485                        }
3486                        m_driverManager.getVfsDriver(
3487                            dbc).writePropertyObjects(dbc, dbc.currentProject(), onlineResource, newProperties);
3488                    }
3489                }
3490            }
3491        } catch (CmsDataAccessException e) {
3492            if (LOG.isErrorEnabled()) {
3493                LOG.error(
3494                    Messages.get().getBundle().key(Messages.LOG_DELETING_PROPERTIES_1, offlineResource.toString()),
3495                    e);
3496            }
3497            throw e;
3498        }
3499
3500        CmsFile newFile;
3501        try {
3502            // publish the file content
3503            newFile = m_driverManager.getProjectDriver(dbc).publishFileContent(
3504                dbc,
3505                dbc.currentProject(),
3506                onlineProject,
3507                offlineResource,
3508                publishedResourceIds,
3509                needToUpdateContent,
3510                publishTag);
3511
3512        } catch (CmsDataAccessException e) {
3513            if (LOG.isErrorEnabled()) {
3514                LOG.error(
3515                    Messages.get().getBundle().key(Messages.LOG_PUBLISHING_RESOURCE_1, offlineResource.getRootPath()),
3516                    e);
3517            }
3518            throw e;
3519        }
3520
3521        List<CmsProperty> offlineProperties;
3522        try {
3523            // write the properties online
3524            offlineProperties = m_driverManager.getVfsDriver(dbc).readPropertyObjects(
3525                dbc,
3526                dbc.currentProject(),
3527                offlineResource);
3528            CmsProperty.setAutoCreatePropertyDefinitions(offlineProperties, true);
3529            m_driverManager.getVfsDriver(dbc).writePropertyObjects(dbc, onlineProject, newFile, offlineProperties);
3530        } catch (CmsDataAccessException e) {
3531            if (LOG.isErrorEnabled()) {
3532                LOG.error(
3533                    Messages.get().getBundle().key(Messages.LOG_PUBLISHING_PROPERTIES_1, newFile.getRootPath()),
3534                    e);
3535            }
3536            throw e;
3537        }
3538
3539        try {
3540            // write the ACL online
3541            m_driverManager.getUserDriver(dbc).publishAccessControlEntries(
3542                dbc,
3543                dbc.currentProject(),
3544                onlineProject,
3545                newFile.getResourceId(),
3546                offlineResource.getResourceId());
3547        } catch (CmsDataAccessException e) {
3548            if (LOG.isErrorEnabled()) {
3549                LOG.error(Messages.get().getBundle().key(Messages.LOG_PUBLISHING_ACL_1, newFile.getRootPath()), e);
3550            }
3551            throw e;
3552        }
3553
3554        CmsFile offlineFile = new CmsFile(offlineResource);
3555        offlineFile.setContents(newFile.getContents());
3556        internalWriteHistory(dbc, offlineFile, resourceState, offlineProperties, publishHistoryId, publishTag);
3557
3558        m_driverManager.getVfsDriver(dbc).updateRelations(dbc, onlineProject, offlineResource);
3559    }
3560
3561    /**
3562     * Publishes a deleted file.<p>
3563     *
3564     * @param dbc the current database context
3565     * @param onlineProject the online project
3566     * @param offlineResource the resource to publish
3567     * @param publishHistoryId the publish history id
3568     * @param publishTag the publish tag
3569     *
3570     * @throws CmsDataAccessException is something goes wrong
3571     */
3572    protected void publishDeletedFile(
3573        CmsDbContext dbc,
3574        CmsProject onlineProject,
3575        CmsResource offlineResource,
3576        CmsUUID publishHistoryId,
3577        int publishTag)
3578    throws CmsDataAccessException {
3579
3580        CmsResourceState resourceState = fixMovedResource(
3581            dbc,
3582            onlineProject,
3583            offlineResource,
3584            publishHistoryId,
3585            publishTag);
3586
3587        boolean existsOnline = m_driverManager.getVfsDriver(dbc).validateStructureIdExists(
3588            dbc,
3589            CmsProject.ONLINE_PROJECT_ID,
3590            offlineResource.getStructureId());
3591        CmsResource onlineResource = null;
3592        if (existsOnline) {
3593            try {
3594                // read the file header online
3595                onlineResource = m_driverManager.getVfsDriver(
3596                    dbc).readResource(dbc, onlineProject.getUuid(), offlineResource.getStructureId(), true);
3597            } catch (CmsDataAccessException e) {
3598                if (LOG.isErrorEnabled()) {
3599                    LOG.error(
3600                        Messages.get().getBundle().key(Messages.LOG_READING_RESOURCE_1, offlineResource.getRootPath()),
3601                        e);
3602                }
3603                throw e;
3604            }
3605        }
3606        if (offlineResource.isLabeled() && !m_driverManager.labelResource(dbc, offlineResource, null, 2)) {
3607            // update the resource flags to "unlabeled" of the siblings of the offline resource
3608            int flags = offlineResource.getFlags();
3609            flags &= ~CmsResource.FLAG_LABELED;
3610            offlineResource.setFlags(flags);
3611        }
3612
3613        // write history before deleting
3614        CmsFile offlineFile = new CmsFile(offlineResource);
3615        offlineFile.setContents(
3616            m_driverManager.getVfsDriver(dbc).readContent(
3617                dbc,
3618                dbc.currentProject().getUuid(),
3619                offlineFile.getResourceId()));
3620        internalWriteHistory(dbc, offlineFile, resourceState, null, publishHistoryId, publishTag);
3621
3622        int propertyDeleteOption = -1;
3623        try {
3624            // delete the properties online and offline
3625            if (offlineResource.getSiblingCount() > 1) {
3626                // there are other siblings- delete only structure property values and keep the resource property values
3627                propertyDeleteOption = CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_VALUES;
3628            } else {
3629                // there are no other siblings- delete both the structure and resource property values
3630                propertyDeleteOption = CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES;
3631            }
3632
3633            if (existsOnline) {
3634                m_driverManager.getVfsDriver(
3635                    dbc).deletePropertyObjects(dbc, onlineProject.getUuid(), onlineResource, propertyDeleteOption);
3636            }
3637            m_driverManager.getVfsDriver(
3638                dbc).deletePropertyObjects(dbc, dbc.currentProject().getUuid(), offlineResource, propertyDeleteOption);
3639
3640            // if the offline file has a resource ID different from the online file
3641            // (probably because a (deleted) file was replaced by a new file with the
3642            // same name), the properties with the "old" resource ID have to be
3643            // deleted also offline
3644            if (existsOnline
3645                && (onlineResource != null)
3646                && !onlineResource.getResourceId().equals(offlineResource.getResourceId())) {
3647                m_driverManager.getVfsDriver(dbc).deletePropertyObjects(
3648                    dbc,
3649                    dbc.currentProject().getUuid(),
3650                    onlineResource,
3651                    CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES);
3652            }
3653        } catch (CmsDataAccessException e) {
3654            if (LOG.isErrorEnabled()) {
3655                LOG.error(
3656                    Messages.get().getBundle().key(Messages.LOG_DELETING_PROPERTIES_1, offlineResource.getRootPath()),
3657                    e);
3658            }
3659            throw e;
3660        }
3661
3662        try {
3663            // remove the file online and offline
3664            m_driverManager.getVfsDriver(dbc).removeFile(dbc, dbc.currentProject().getUuid(), offlineResource);
3665            if (existsOnline && (onlineResource != null)) {
3666                m_driverManager.getVfsDriver(dbc).removeFile(dbc, onlineProject.getUuid(), onlineResource);
3667            }
3668        } catch (CmsDataAccessException e) {
3669            if (LOG.isErrorEnabled()) {
3670                LOG.error(
3671                    Messages.get().getBundle().key(Messages.LOG_REMOVING_RESOURCE_1, offlineResource.getRootPath()),
3672                    e);
3673            }
3674            throw e;
3675        }
3676
3677        // delete the ACL online and offline
3678        try {
3679            if (existsOnline && (onlineResource != null) && (onlineResource.getSiblingCount() == 1)) {
3680                // only if no siblings left
3681                m_driverManager.getUserDriver(dbc).removeAccessControlEntries(
3682                    dbc,
3683                    onlineProject,
3684                    onlineResource.getResourceId());
3685            }
3686            if (offlineResource.getSiblingCount() == 1) {
3687                // only if no siblings left
3688                m_driverManager.getUserDriver(dbc).removeAccessControlEntries(
3689                    dbc,
3690                    dbc.currentProject(),
3691                    offlineResource.getResourceId());
3692            }
3693        } catch (CmsDataAccessException e) {
3694            if (LOG.isErrorEnabled()) {
3695                LOG.error(Messages.get().getBundle().key(Messages.LOG_REMOVING_ACL_1, offlineResource.toString()), e);
3696            }
3697            throw e;
3698        }
3699
3700        try {
3701            // delete relations online and offline
3702            m_driverManager.getVfsDriver(
3703                dbc).deleteRelations(dbc, onlineProject.getUuid(), offlineResource, CmsRelationFilter.TARGETS);
3704            m_driverManager.getVfsDriver(
3705                dbc).deleteRelations(dbc, dbc.currentProject().getUuid(), offlineResource, CmsRelationFilter.TARGETS);
3706        } catch (CmsDataAccessException e) {
3707            if (LOG.isErrorEnabled()) {
3708                LOG.error(
3709                    Messages.get().getBundle().key(Messages.LOG_REMOVING_RELATIONS_1, offlineResource.toString()),
3710                    e);
3711            }
3712            throw e;
3713        }
3714
3715        if (OpenCms.getSubscriptionManager().isEnabled()) {
3716            try {
3717                // delete visited information for resource from log
3718                CmsVisitEntryFilter filter = CmsVisitEntryFilter.ALL.filterResource(offlineResource.getStructureId());
3719                m_driverManager.getSubscriptionDriver().deleteVisits(
3720                    dbc,
3721                    OpenCms.getSubscriptionManager().getPoolName(),
3722                    filter);
3723            } catch (CmsDataAccessException e) {
3724                if (LOG.isErrorEnabled()) {
3725                    LOG.error(
3726                        Messages.get().getBundle().key(Messages.LOG_REMOVING_VISITEDLOG_1, offlineResource.toString()),
3727                        e);
3728                }
3729                throw e;
3730            }
3731
3732            try {
3733                // mark the subscribed resource as deleted
3734                /* changed to subscription driver */
3735                //                m_driverManager.getUserDriver(dbc).setSubscribedResourceAsDeleted(
3736                //                    dbc,
3737                //                    OpenCms.getSubscriptionManager().getPoolName(),
3738                //                    offlineResource);
3739                m_driverManager.getSubscriptionDriver().setSubscribedResourceAsDeleted(
3740                    dbc,
3741                    OpenCms.getSubscriptionManager().getPoolName(),
3742                    offlineResource);
3743            } catch (CmsDataAccessException e) {
3744                if (LOG.isErrorEnabled()) {
3745                    LOG.error(
3746                        Messages.get().getBundle().key(
3747                            Messages.LOG_REMOVING_SUBSCRIPTIONS_1,
3748                            offlineResource.toString()),
3749                        e);
3750                }
3751                throw e;
3752            }
3753        }
3754    }
3755
3756    /**
3757     * Publishes a new file.<p>
3758     *
3759     * @param dbc the current database context
3760     * @param onlineProject the online project
3761     * @param offlineResource the resource to publish
3762     * @param publishedContentIds contains the UUIDs of already published content records
3763     * @param publishHistoryId the publish history id
3764     * @param publishTag the publish tag
3765     *
3766     * @throws CmsDataAccessException is something goes wrong
3767     */
3768    protected void publishNewFile(
3769        CmsDbContext dbc,
3770        CmsProject onlineProject,
3771        CmsResource offlineResource,
3772        Set<CmsUUID> publishedContentIds,
3773        CmsUUID publishHistoryId,
3774        int publishTag)
3775    throws CmsDataAccessException {
3776
3777        CmsResourceState resourceState = fixMovedResource(
3778            dbc,
3779            onlineProject,
3780            offlineResource,
3781            publishHistoryId,
3782            publishTag);
3783
3784        CmsFile newFile;
3785        try {
3786            // reset the labeled link flag before writing the online file
3787            int flags = offlineResource.getFlags();
3788            flags &= ~CmsResource.FLAG_LABELED;
3789            offlineResource.setFlags(flags);
3790
3791            // publish the file content
3792            newFile = m_driverManager.getProjectDriver(dbc).publishFileContent(
3793                dbc,
3794                dbc.currentProject(),
3795                onlineProject,
3796                offlineResource,
3797                publishedContentIds,
3798                true,
3799                publishTag);
3800
3801        } catch (CmsVfsResourceAlreadyExistsException e) {
3802            try {
3803                // remove the existing file and ensure that it's content is written
3804                // in any case by removing it's resource ID from the set of published resource IDs
3805                m_driverManager.getVfsDriver(dbc).removeFile(dbc, onlineProject.getUuid(), offlineResource);
3806                publishedContentIds.remove(offlineResource.getResourceId());
3807                newFile = m_driverManager.getProjectDriver(dbc).publishFileContent(
3808                    dbc,
3809                    dbc.currentProject(),
3810                    onlineProject,
3811                    offlineResource,
3812                    publishedContentIds,
3813                    true,
3814                    publishTag);
3815
3816            } catch (CmsDataAccessException e1) {
3817                if (LOG.isErrorEnabled()) {
3818                    LOG.error(
3819                        Messages.get().getBundle().key(
3820                            Messages.LOG_PUBLISHING_RESOURCE_1,
3821                            offlineResource.getRootPath()),
3822                        e);
3823                }
3824                throw e1;
3825            }
3826        } catch (CmsDataAccessException e) {
3827            if (LOG.isErrorEnabled()) {
3828                LOG.error(
3829                    Messages.get().getBundle().key(Messages.LOG_PUBLISHING_RESOURCE_1, offlineResource.getRootPath()),
3830                    e);
3831            }
3832            throw e;
3833        }
3834
3835        List<CmsProperty> offlineProperties;
3836        try {
3837            // write the properties online
3838            offlineProperties = m_driverManager.getVfsDriver(dbc).readPropertyObjects(
3839                dbc,
3840                dbc.currentProject(),
3841                offlineResource);
3842            CmsProperty.setAutoCreatePropertyDefinitions(offlineProperties, true);
3843            m_driverManager.getVfsDriver(dbc).writePropertyObjects(dbc, onlineProject, newFile, offlineProperties);
3844        } catch (CmsDataAccessException e) {
3845            if (LOG.isErrorEnabled()) {
3846                LOG.error(
3847                    Messages.get().getBundle().key(Messages.LOG_PUBLISHING_PROPERTIES_1, newFile.getRootPath()),
3848                    e);
3849            }
3850
3851            throw e;
3852        }
3853
3854        try {
3855            // write the ACL online
3856            m_driverManager.getUserDriver(dbc).publishAccessControlEntries(
3857                dbc,
3858                dbc.currentProject(),
3859                onlineProject,
3860                offlineResource.getResourceId(),
3861                newFile.getResourceId());
3862        } catch (CmsDataAccessException e) {
3863            if (LOG.isErrorEnabled()) {
3864                LOG.error(Messages.get().getBundle().key(Messages.LOG_PUBLISHING_ACL_1, newFile.getRootPath()), e);
3865            }
3866            throw e;
3867        }
3868
3869        CmsFile offlineFile = new CmsFile(offlineResource);
3870        offlineFile.setContents(newFile.getContents());
3871        internalWriteHistory(dbc, offlineFile, resourceState, offlineProperties, publishHistoryId, publishTag);
3872
3873        m_driverManager.getVfsDriver(dbc).updateRelations(dbc, onlineProject, offlineResource);
3874    }
3875
3876}