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                            delFile,
1067                            CmsResource.STATE_DELETED,
1068                            null,
1069                            publishHistoryId,
1070                            publishTag);
1071                        vfsDriver.deletePropertyObjects(
1072                            dbc,
1073                            onlineProject.getUuid(),
1074                            delFile,
1075                            CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES);
1076                        vfsDriver.removeFile(dbc, onlineProject.getUuid(), delFile);
1077                    } else if (offlineResource.isFolder()) {
1078
1079                        internalWriteHistory(
1080                            dbc,
1081                            offlineResource,
1082                            delFile,
1083                            CmsResource.STATE_DELETED,
1084                            null,
1085                            publishHistoryId,
1086                            publishTag);
1087                        vfsDriver.deletePropertyObjects(
1088                            dbc,
1089                            onlineProject.getUuid(),
1090                            delFile,
1091                            CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES);
1092                        vfsDriver.removeFolder(dbc, onlineProject, delFile);
1093                    }
1094                } catch (CmsDataAccessException e) {
1095                    if (LOG.isWarnEnabled()) {
1096                        LOG.warn(
1097                            Messages.get().getBundle().key(Messages.LOG_REMOVING_RESOURCE_1, delFile.getName()),
1098                            e);
1099                    }
1100                }
1101            }
1102
1103            // write history before deleting
1104            internalWriteHistory(dbc, currentFolder, null, folderState, null, publishHistoryId, publishTag);
1105
1106            try {
1107                // delete the properties online and offline
1108                vfsDriver.deletePropertyObjects(
1109                    dbc,
1110                    onlineProject.getUuid(),
1111                    onlineFolder,
1112                    CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES);
1113                vfsDriver.deletePropertyObjects(
1114                    dbc,
1115                    dbc.currentProject().getUuid(),
1116                    currentFolder,
1117                    CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES);
1118            } catch (CmsDataAccessException e) {
1119                if (LOG.isErrorEnabled()) {
1120                    LOG.error(
1121                        Messages.get().getBundle().key(Messages.LOG_DELETING_PROPERTIES_1, currentFolder.getRootPath()),
1122                        e);
1123                }
1124                throw e;
1125            }
1126
1127            try {
1128                // remove the folder online and offline
1129                vfsDriver.removeFolder(dbc, dbc.currentProject(), currentFolder);
1130                vfsDriver.removeFolder(dbc, onlineProject, currentFolder);
1131            } catch (CmsDataAccessException e) {
1132                if (LOG.isErrorEnabled()) {
1133                    LOG.error(
1134                        Messages.get().getBundle().key(Messages.LOG_REMOVING_RESOURCE_1, currentFolder.getRootPath()),
1135                        e);
1136                }
1137                throw e;
1138            }
1139
1140            try {
1141                // remove the ACL online and offline
1142                m_driverManager.getUserDriver(dbc).removeAccessControlEntries(
1143                    dbc,
1144                    onlineProject,
1145                    onlineFolder.getResourceId());
1146                m_driverManager.getUserDriver(dbc).removeAccessControlEntries(
1147                    dbc,
1148                    dbc.currentProject(),
1149                    currentFolder.getResourceId());
1150            } catch (CmsDataAccessException e) {
1151                if (LOG.isErrorEnabled()) {
1152                    LOG.error(
1153                        Messages.get().getBundle().key(Messages.LOG_REMOVING_ACL_1, currentFolder.getRootPath()),
1154                        e);
1155                }
1156                throw e;
1157            }
1158
1159            // remove relations
1160            try {
1161                vfsDriver.deleteRelations(dbc, onlineProject.getUuid(), onlineFolder, CmsRelationFilter.TARGETS);
1162                vfsDriver.deleteRelations(
1163                    dbc,
1164                    dbc.currentProject().getUuid(),
1165                    currentFolder,
1166                    CmsRelationFilter.TARGETS);
1167            } catch (CmsDataAccessException e) {
1168                if (LOG.isErrorEnabled()) {
1169                    LOG.error(
1170                        Messages.get().getBundle().key(Messages.LOG_REMOVING_RELATIONS_1, currentFolder.getRootPath()),
1171                        e);
1172                }
1173                throw e;
1174            }
1175
1176            // remove project resources
1177            String deletedResourceRootPath = currentFolder.getRootPath();
1178            Iterator<CmsProject> itProjects = readProjectsForResource(dbc, deletedResourceRootPath).iterator();
1179            while (itProjects.hasNext()) {
1180                CmsProject project = itProjects.next();
1181                deleteProjectResource(dbc, project.getUuid(), deletedResourceRootPath);
1182            }
1183
1184            try {
1185                m_driverManager.getVfsDriver(dbc).deleteAliases(
1186                    dbc,
1187                    onlineProject,
1188                    new CmsAliasFilter(null, null, currentFolder.getStructureId()));
1189            } catch (CmsDataAccessException e) {
1190                LOG.error("Could not delete aliases: " + e.getLocalizedMessage(), e);
1191            }
1192
1193            report.println(
1194                org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0),
1195                I_CmsReport.FORMAT_OK);
1196
1197            if (LOG.isDebugEnabled()) {
1198                if (LOG.isDebugEnabled()) {
1199                    LOG.debug(
1200                        Messages.get().getBundle().key(
1201                            Messages.LOG_DEL_FOLDER_3,
1202                            currentFolder.getRootPath(),
1203                            String.valueOf(m),
1204                            String.valueOf(n)));
1205                }
1206            }
1207        } finally {
1208            // notify the app. that the published folder and it's properties have been modified offline
1209            OpenCms.fireCmsEvent(
1210                new CmsEvent(
1211                    I_CmsEventListener.EVENT_RESOURCE_AND_PROPERTIES_MODIFIED,
1212                    Collections.<String, Object> singletonMap(I_CmsEventListener.KEY_RESOURCE, currentFolder)));
1213        }
1214    }
1215
1216    /**
1217     * @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)
1218     */
1219    public void publishFile(
1220        CmsDbContext dbc,
1221        I_CmsReport report,
1222        int m,
1223        int n,
1224        CmsProject onlineProject,
1225        CmsResource offlineResource,
1226        Set<CmsUUID> publishedContentIds,
1227        CmsUUID publishHistoryId,
1228        int publishTag)
1229    throws CmsDataAccessException {
1230
1231        /*
1232         * Never use onlineResource.getState() here!
1233         * Only use offlineResource.getState() to determine the state of an offline resource!
1234         *
1235         * In case a resource has siblings, after a sibling was published the structure
1236         * and resource states are reset to UNCHANGED -> the state of the corresponding
1237         * onlineResource is still NEW, DELETED or CHANGED.
1238         * Thus, using onlineResource.getState() will inevitably result in unpublished resources!
1239         */
1240
1241        try {
1242            report.print(
1243                org.opencms.report.Messages.get().container(
1244                    org.opencms.report.Messages.RPT_SUCCESSION_2,
1245                    String.valueOf(m),
1246                    String.valueOf(n)),
1247                I_CmsReport.FORMAT_NOTE);
1248
1249            if (offlineResource.getState().isDeleted()) {
1250                report.print(Messages.get().container(Messages.RPT_DELETE_FILE_0), I_CmsReport.FORMAT_NOTE);
1251                report.print(
1252                    org.opencms.report.Messages.get().container(
1253                        org.opencms.report.Messages.RPT_ARGUMENT_1,
1254                        dbc.removeSiteRoot(offlineResource.getRootPath())));
1255                report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0));
1256
1257                publishDeletedFile(dbc, onlineProject, offlineResource, publishHistoryId, publishTag);
1258
1259                dbc.pop();
1260                List<CmsProperty> props = m_driverManager.readPropertyObjects(dbc, offlineResource, true);
1261                boolean removeDeleted = Boolean.parseBoolean(
1262                    CmsProperty.get(CmsPropertyDefinition.PROPERTY_HISTORY_REMOVE_DELETED, props).getValue("false"));
1263                // delete old historical entries
1264                m_driverManager.getHistoryDriver(dbc).deleteEntries(
1265                    dbc,
1266                    new CmsHistoryFile(offlineResource),
1267                    removeDeleted ? 0 : OpenCms.getSystemInfo().getHistoryVersionsAfterDeletion(),
1268                    -1);
1269
1270                report.println(
1271                    org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0),
1272                    I_CmsReport.FORMAT_OK);
1273
1274                if (LOG.isDebugEnabled()) {
1275                    LOG.debug(
1276                        Messages.get().getBundle().key(
1277                            Messages.LOG_DEL_FILE_3,
1278                            String.valueOf(m),
1279                            String.valueOf(n),
1280                            offlineResource.getRootPath()));
1281                }
1282
1283            } else if (offlineResource.getState().isChanged()) {
1284                report.print(Messages.get().container(Messages.RPT_PUBLISH_FILE_0), I_CmsReport.FORMAT_NOTE);
1285                report.print(
1286                    org.opencms.report.Messages.get().container(
1287                        org.opencms.report.Messages.RPT_ARGUMENT_1,
1288                        dbc.removeSiteRoot(offlineResource.getRootPath())));
1289                report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0));
1290
1291                publishChangedFile(
1292                    dbc,
1293                    onlineProject,
1294                    offlineResource,
1295                    publishedContentIds,
1296                    publishHistoryId,
1297                    publishTag);
1298
1299                dbc.pop();
1300                // delete old historical entries
1301                m_driverManager.getHistoryDriver(dbc).deleteEntries(
1302                    dbc,
1303                    new CmsHistoryFile(offlineResource),
1304                    OpenCms.getSystemInfo().getHistoryVersions(),
1305                    -1);
1306
1307                report.println(
1308                    org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0),
1309                    I_CmsReport.FORMAT_OK);
1310
1311                if (LOG.isDebugEnabled()) {
1312                    LOG.debug(
1313                        Messages.get().getBundle().key(
1314                            Messages.LOG_PUBLISHING_FILE_3,
1315                            offlineResource.getRootPath(),
1316                            String.valueOf(m),
1317                            String.valueOf(n)));
1318                }
1319            } else if (offlineResource.getState().isNew()) {
1320                report.print(Messages.get().container(Messages.RPT_PUBLISH_FILE_0), I_CmsReport.FORMAT_NOTE);
1321                report.print(
1322                    org.opencms.report.Messages.get().container(
1323                        org.opencms.report.Messages.RPT_ARGUMENT_1,
1324                        dbc.removeSiteRoot(offlineResource.getRootPath())));
1325                report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0));
1326
1327                publishNewFile(dbc, onlineProject, offlineResource, publishedContentIds, publishHistoryId, publishTag);
1328
1329                dbc.pop();
1330                // delete old historical entries
1331                m_driverManager.getHistoryDriver(dbc).deleteEntries(
1332                    dbc,
1333                    new CmsHistoryFile(offlineResource),
1334                    OpenCms.getSystemInfo().getHistoryVersions(),
1335                    -1);
1336
1337                report.println(
1338                    org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0),
1339                    I_CmsReport.FORMAT_OK);
1340
1341                if (LOG.isDebugEnabled()) {
1342                    if (LOG.isDebugEnabled()) {
1343                        LOG.debug(
1344                            Messages.get().getBundle().key(
1345                                Messages.LOG_PUBLISHING_FILE_3,
1346                                offlineResource.getRootPath(),
1347                                String.valueOf(m),
1348                                String.valueOf(n)));
1349                    }
1350                }
1351            } else {
1352                // state == unchanged !!?? something went really wrong
1353                report.print(Messages.get().container(Messages.RPT_PUBLISH_FILE_0), I_CmsReport.FORMAT_NOTE);
1354                report.print(
1355                    org.opencms.report.Messages.get().container(
1356                        org.opencms.report.Messages.RPT_ARGUMENT_1,
1357                        dbc.removeSiteRoot(offlineResource.getRootPath())));
1358                report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0));
1359                report.println(
1360                    org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_FAILED_0),
1361                    I_CmsReport.FORMAT_ERROR);
1362
1363                if (LOG.isErrorEnabled()) {
1364                    // the whole resource is printed out here
1365                    LOG.error(
1366                        Messages.get().getBundle().key(
1367                            Messages.LOG_PUBLISHING_FILE_3,
1368                            String.valueOf(m),
1369                            String.valueOf(n),
1370                            offlineResource));
1371                }
1372            }
1373            m_driverManager.publishUrlNameMapping(dbc, offlineResource);
1374            if (offlineResource.getState().isDeleted()) {
1375                m_driverManager.getVfsDriver(dbc).deleteAliases(
1376                    dbc,
1377                    onlineProject,
1378                    new CmsAliasFilter(null, null, offlineResource.getStructureId()));
1379            }
1380        } catch (CmsException e) {
1381            throw new CmsDataAccessException(e.getMessageContainer(), e);
1382        } finally {
1383            // notify the app. that the published file and it's properties have been modified offline
1384            Map<String, Object> data = new HashMap<String, Object>(2);
1385            data.put(I_CmsEventListener.KEY_RESOURCE, offlineResource);
1386            data.put(I_CmsEventListener.KEY_SKIPINDEX, Boolean.valueOf(true));
1387
1388            OpenCms.fireCmsEvent(new CmsEvent(I_CmsEventListener.EVENT_RESOURCE_AND_PROPERTIES_MODIFIED, data));
1389        }
1390    }
1391
1392    /**
1393     * @see org.opencms.db.I_CmsProjectDriver#publishFileContent(CmsDbContext, CmsProject, CmsProject, CmsResource, Set, boolean, int)
1394     */
1395    public CmsFile publishFileContent(
1396        CmsDbContext dbc,
1397        CmsProject offlineProject,
1398        CmsProject onlineProject,
1399        CmsResource offlineResource,
1400        Set<CmsUUID> publishedResourceIds,
1401        boolean needToUpdateContent,
1402        int publishTag)
1403    throws CmsDataAccessException {
1404
1405        CmsFile newFile = null;
1406        try {
1407            // read the file content offline
1408            CmsUUID projectId = dbc.getProjectId();
1409            boolean dbcHasProjectId = (projectId != null) && !projectId.isNullUUID();
1410            CmsUUID projectIdForReading = (!dbcHasProjectId ? offlineProject.getUuid() : CmsProject.ONLINE_PROJECT_ID);
1411            dbc.setProjectId(offlineProject.getUuid());
1412            byte[] offlineContent = m_driverManager.getVfsDriver(dbc).readContent(
1413                dbc,
1414                projectIdForReading,
1415                offlineResource.getResourceId());
1416            CmsFile offlineFile = new CmsFile(offlineResource);
1417            offlineFile.setContents(offlineContent);
1418            dbc.setProjectId(projectId);
1419
1420            // create the file online
1421            newFile = (CmsFile)offlineFile.clone();
1422            newFile.setState(CmsResource.STATE_UNCHANGED);
1423
1424            boolean createSibling = true;
1425            // check if we are facing with a create new sibling operation
1426            if (!offlineFile.getState().isNew()) {
1427                createSibling = false;
1428            } else {
1429                // check if the resource entry already exists
1430                if (!m_driverManager.getVfsDriver(dbc).validateResourceIdExists(
1431                    dbc,
1432                    onlineProject.getUuid(),
1433                    offlineFile.getResourceId())) {
1434                    // we are creating a normal resource and not a sibling
1435                    createSibling = false;
1436                }
1437            }
1438
1439            // only update the content if it was not updated before
1440            boolean alreadyPublished = publishedResourceIds.contains(offlineResource.getResourceId());
1441            needToUpdateContent &= !alreadyPublished;
1442
1443            if (createSibling) {
1444                if (!alreadyPublished) {
1445                    // create the file online, the first time a sibling is published also the resource entry has to be actualized
1446                    m_driverManager.getVfsDriver(dbc).createResource(dbc, onlineProject.getUuid(), newFile, null);
1447                } else {
1448                    // create the sibling online
1449                    m_driverManager.getVfsDriver(dbc).createSibling(dbc, onlineProject, offlineResource);
1450                }
1451                newFile = new CmsFile(offlineResource);
1452                newFile.setContents(offlineContent);
1453            } else {
1454                // update the online/offline structure and resource records of the file
1455                m_driverManager.getVfsDriver(dbc).publishResource(dbc, onlineProject, newFile, offlineFile);
1456            }
1457            // update version numbers
1458            m_driverManager.getVfsDriver(dbc).publishVersions(dbc, offlineResource, !alreadyPublished);
1459
1460            // create/update the content
1461            m_driverManager.getVfsDriver(dbc).createOnlineContent(
1462                dbc,
1463                offlineFile.getResourceId(),
1464                offlineFile.getContents(),
1465                publishTag,
1466                true,
1467                needToUpdateContent);
1468
1469            // mark the resource as written to avoid that the same content is written for each sibling instance
1470            publishedResourceIds.add(offlineResource.getResourceId());
1471        } catch (CmsDataAccessException e) {
1472            if (LOG.isErrorEnabled()) {
1473                LOG.error(
1474                    Messages.get().getBundle().key(Messages.LOG_PUBLISHING_FILE_CONTENT_1, offlineResource.toString()),
1475                    e);
1476            }
1477            throw e;
1478        }
1479        return newFile;
1480    }
1481
1482    /**
1483     * @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)
1484     */
1485    public void publishFolder(
1486        CmsDbContext dbc,
1487        I_CmsReport report,
1488        int m,
1489        int n,
1490        CmsProject onlineProject,
1491        CmsFolder offlineFolder,
1492        CmsUUID publishHistoryId,
1493        int publishTag)
1494    throws CmsDataAccessException {
1495
1496        try {
1497            report.print(
1498                org.opencms.report.Messages.get().container(
1499                    org.opencms.report.Messages.RPT_SUCCESSION_2,
1500                    String.valueOf(m),
1501                    String.valueOf(n)),
1502                I_CmsReport.FORMAT_NOTE);
1503            report.print(Messages.get().container(Messages.RPT_PUBLISH_FOLDER_0), I_CmsReport.FORMAT_NOTE);
1504            report.print(
1505                org.opencms.report.Messages.get().container(
1506                    org.opencms.report.Messages.RPT_ARGUMENT_1,
1507                    dbc.removeSiteRoot(offlineFolder.getRootPath())));
1508            report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0));
1509
1510            CmsResourceState resourceState = fixMovedResource(
1511                dbc,
1512                onlineProject,
1513                offlineFolder,
1514                publishHistoryId,
1515                publishTag);
1516
1517            CmsResource onlineFolder = null;
1518            if (offlineFolder.getState().isNew()) {
1519                try {
1520                    // create the folder online
1521                    CmsResource newFolder = (CmsFolder)offlineFolder.clone();
1522                    newFolder.setState(CmsResource.STATE_UNCHANGED);
1523
1524                    onlineFolder = m_driverManager.getVfsDriver(
1525                        dbc).createResource(dbc, onlineProject.getUuid(), newFolder, null);
1526                    m_driverManager.getVfsDriver(dbc).publishResource(dbc, onlineProject, onlineFolder, offlineFolder);
1527                    // update version numbers
1528                    m_driverManager.getVfsDriver(dbc).publishVersions(dbc, offlineFolder, true);
1529                } catch (CmsVfsResourceAlreadyExistsException e) {
1530                    if (!offlineFolder.getRootPath().equals("/")
1531                        && !offlineFolder.getRootPath().equals("/system/")
1532                        && LOG.isWarnEnabled()) {
1533                        LOG.warn(
1534                            Messages.get().getBundle().key(
1535                                Messages.LOG_WARN_FOLDER_WRONG_STATE_CN_1,
1536                                offlineFolder.getRootPath()));
1537                    }
1538                    try {
1539                        onlineFolder = m_driverManager.getVfsDriver(dbc).readFolder(
1540                            dbc,
1541                            onlineProject.getUuid(),
1542                            offlineFolder.getRootPath());
1543                        m_driverManager.getVfsDriver(
1544                            dbc).publishResource(dbc, onlineProject, onlineFolder, offlineFolder);
1545                        // update version numbers
1546                        m_driverManager.getVfsDriver(dbc).publishVersions(dbc, offlineFolder, true);
1547                    } catch (CmsDataAccessException e1) {
1548                        if (LOG.isErrorEnabled()) {
1549                            LOG.error(
1550                                Messages.get().getBundle().key(
1551                                    Messages.LOG_READING_RESOURCE_1,
1552                                    offlineFolder.getRootPath()),
1553                                e);
1554                        }
1555                        throw e1;
1556                    }
1557                } catch (CmsDataAccessException e) {
1558                    if (LOG.isErrorEnabled()) {
1559                        LOG.error(
1560                            Messages.get().getBundle().key(
1561                                Messages.LOG_PUBLISHING_RESOURCE_1,
1562                                offlineFolder.getRootPath()),
1563                            e);
1564                    }
1565                    throw e;
1566                }
1567            } else if (offlineFolder.getState().isChanged()) {
1568                try {
1569                    // read the folder online
1570                    onlineFolder = m_driverManager.getVfsDriver(dbc).readFolder(
1571                        dbc,
1572                        onlineProject.getUuid(),
1573                        offlineFolder.getStructureId());
1574                } catch (CmsVfsResourceNotFoundException e) {
1575                    if (LOG.isWarnEnabled()) {
1576                        LOG.warn(
1577                            Messages.get().getBundle().key(
1578                                Messages.LOG_WARN_FOLDER_WRONG_STATE_NC_1,
1579                                offlineFolder.getRootPath()));
1580                    }
1581                    try {
1582                        onlineFolder = m_driverManager.getVfsDriver(
1583                            dbc).createResource(dbc, onlineProject.getUuid(), offlineFolder, null);
1584                        internalResetResourceState(dbc, onlineFolder);
1585                    } catch (CmsDataAccessException e1) {
1586                        if (LOG.isErrorEnabled()) {
1587                            LOG.error(
1588                                Messages.get().getBundle().key(
1589                                    Messages.LOG_PUBLISHING_RESOURCE_1,
1590                                    offlineFolder.getRootPath()),
1591                                e);
1592                        }
1593                        throw e1;
1594                    }
1595                }
1596
1597                try {
1598                    // update the folder online
1599                    m_driverManager.getVfsDriver(dbc).publishResource(dbc, onlineProject, onlineFolder, offlineFolder);
1600                    // update version numbers
1601                    m_driverManager.getVfsDriver(dbc).publishVersions(dbc, offlineFolder, true);
1602                } catch (CmsDataAccessException e) {
1603                    if (LOG.isErrorEnabled()) {
1604                        LOG.error(
1605                            Messages.get().getBundle().key(
1606                                Messages.LOG_PUBLISHING_RESOURCE_1,
1607                                offlineFolder.getRootPath()),
1608                            e);
1609                    }
1610                    throw e;
1611                }
1612            }
1613
1614            if (onlineFolder != null) {
1615                try {
1616                    // write the ACL online
1617                    m_driverManager.getUserDriver(dbc).publishAccessControlEntries(
1618                        dbc,
1619                        dbc.currentProject(),
1620                        onlineProject,
1621                        offlineFolder.getResourceId(),
1622                        onlineFolder.getResourceId());
1623                } catch (CmsDataAccessException e) {
1624                    if (LOG.isErrorEnabled()) {
1625                        LOG.error(
1626                            Messages.get().getBundle().key(Messages.LOG_PUBLISHING_ACL_1, offlineFolder.getRootPath()),
1627                            e);
1628                    }
1629                    throw e;
1630                }
1631            }
1632
1633            List<CmsProperty> offlineProperties = null;
1634            try {
1635                // write the properties online
1636                m_driverManager.getVfsDriver(dbc).deletePropertyObjects(
1637                    dbc,
1638                    onlineProject.getUuid(),
1639                    onlineFolder,
1640                    CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES);
1641                offlineProperties = m_driverManager.getVfsDriver(dbc).readPropertyObjects(
1642                    dbc,
1643                    dbc.currentProject(),
1644                    offlineFolder);
1645                CmsProperty.setAutoCreatePropertyDefinitions(offlineProperties, true);
1646                m_driverManager.getVfsDriver(
1647                    dbc).writePropertyObjects(dbc, onlineProject, onlineFolder, offlineProperties);
1648            } catch (CmsDataAccessException e) {
1649                if (LOG.isErrorEnabled()) {
1650                    LOG.error(
1651                        Messages.get().getBundle().key(
1652                            Messages.LOG_PUBLISHING_PROPERTIES_1,
1653                            offlineFolder.getRootPath()),
1654                        e);
1655                }
1656                throw e;
1657            }
1658
1659            internalWriteHistory(
1660                dbc,
1661                offlineFolder,
1662                null,
1663                resourceState,
1664                offlineProperties,
1665                publishHistoryId,
1666                publishTag);
1667
1668            m_driverManager.getVfsDriver(dbc).updateRelations(dbc, onlineProject, offlineFolder);
1669
1670            report.println(
1671                org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0),
1672                I_CmsReport.FORMAT_OK);
1673
1674            if (LOG.isDebugEnabled()) {
1675                LOG.debug(
1676                    Messages.get().getBundle().key(
1677                        Messages.LOG_PUBLISHING_FOLDER_3,
1678                        String.valueOf(m),
1679                        String.valueOf(n),
1680                        offlineFolder.getRootPath()));
1681            }
1682        } finally {
1683            // notify the app. that the published folder and it's properties have been modified offline
1684            OpenCms.fireCmsEvent(
1685                new CmsEvent(
1686                    I_CmsEventListener.EVENT_RESOURCE_AND_PROPERTIES_MODIFIED,
1687                    Collections.<String, Object> singletonMap(I_CmsEventListener.KEY_RESOURCE, offlineFolder)));
1688        }
1689    }
1690
1691    /**
1692     * @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)
1693     */
1694    public void publishProject(
1695        CmsDbContext dbc,
1696        I_CmsReport report,
1697        CmsProject onlineProject,
1698        CmsPublishList publishList,
1699        int publishTag)
1700    throws CmsException {
1701
1702        int publishedFolderCount = 0;
1703        int deletedFolderCount = 0;
1704        int publishedFileCount = 0;
1705        Set<CmsUUID> publishedContentIds = new HashSet<CmsUUID>();
1706        Set<CmsUUID> publishedIds = new HashSet<CmsUUID>();
1707
1708        try {
1709
1710            /////////////////////////////////////////////////////////////////////////////////
1711            // write the historical project entry
1712
1713            if (OpenCms.getSystemInfo().isHistoryEnabled()) {
1714                try {
1715                    // write an entry in the publish project log
1716                    m_driverManager.getHistoryDriver(dbc).writeProject(dbc, publishTag, System.currentTimeMillis());
1717                    dbc.pop();
1718                } catch (Throwable t) {
1719                    dbc.report(
1720                        report,
1721                        Messages.get().container(
1722                            Messages.ERR_WRITING_HISTORY_OF_PROJECT_1,
1723                            dbc.currentProject().getName()),
1724                        t);
1725                }
1726            }
1727
1728            ////////////////////////////////////////////////////////////////////////////////
1729            // publish new/changed folders
1730
1731            if (LOG.isDebugEnabled()) {
1732                LOG.debug(
1733                    Messages.get().getBundle().key(
1734                        Messages.LOG_START_PUBLISHING_PROJECT_2,
1735                        dbc.currentProject().getName(),
1736                        dbc.currentUser().getName()));
1737            }
1738
1739            publishedFolderCount = 0;
1740            int foldersSize = publishList.getFolderList().size();
1741            if (foldersSize > 0) {
1742                report.println(
1743                    Messages.get().container(Messages.RPT_PUBLISH_FOLDERS_BEGIN_0),
1744                    I_CmsReport.FORMAT_HEADLINE);
1745            }
1746
1747            Iterator<CmsResource> itFolders = publishList.getFolderList().iterator();
1748            I_CmsProjectDriver projectDriver = m_driverManager.getProjectDriver(dbc);
1749            I_CmsHistoryDriver historyDriver = m_driverManager.getHistoryDriver(dbc);
1750            while (itFolders.hasNext()) {
1751                CmsResource currentFolder = itFolders.next();
1752                try {
1753                    if (currentFolder.getState().isNew() || currentFolder.getState().isChanged()) {
1754                        // bounce the current publish task through all project drivers
1755                        projectDriver.publishFolder(
1756                            dbc,
1757                            report,
1758                            ++publishedFolderCount,
1759                            foldersSize,
1760                            onlineProject,
1761                            new CmsFolder(currentFolder),
1762                            publishList.getPublishHistoryId(),
1763                            publishTag);
1764
1765                        dbc.pop();
1766
1767                        publishedIds.add(currentFolder.getStructureId());
1768                        // log it
1769                        CmsLogEntryType type = currentFolder.getState().isNew()
1770                        ? CmsLogEntryType.RESOURCE_PUBLISHED_NEW
1771                        : CmsLogEntryType.RESOURCE_PUBLISHED_MODIFIED;
1772                        m_driverManager.log(
1773                            dbc,
1774                            new CmsLogEntry(
1775                                dbc,
1776                                currentFolder.getStructureId(),
1777                                type,
1778                                new String[] {currentFolder.getRootPath()}),
1779                            true);
1780
1781                        // delete old historical entries
1782                        historyDriver.deleteEntries(
1783                            dbc,
1784                            new CmsHistoryFile(currentFolder),
1785                            OpenCms.getSystemInfo().getHistoryVersions(),
1786                            -1);
1787
1788                        // reset the resource state to UNCHANGED and the last-modified-in-project-ID to 0
1789                        internalResetResourceState(dbc, currentFolder);
1790
1791                        if (!CmsModificationContext.isInOnlineFolder(currentFolder.getRootPath())) {
1792                            m_driverManager.unlockResource(dbc, currentFolder, true, true);
1793                        }
1794                    } else {
1795                        // state == unchanged !!?? something went really wrong
1796                        report.print(Messages.get().container(Messages.RPT_PUBLISH_FOLDER_0), I_CmsReport.FORMAT_NOTE);
1797                        report.print(
1798                            org.opencms.report.Messages.get().container(
1799                                org.opencms.report.Messages.RPT_ARGUMENT_1,
1800                                dbc.removeSiteRoot(currentFolder.getRootPath())));
1801                        report.print(
1802                            org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0));
1803                        report.println(
1804                            org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_FAILED_0),
1805                            I_CmsReport.FORMAT_ERROR);
1806
1807                        if (LOG.isErrorEnabled()) {
1808                            // the whole resource is printed out here
1809                            LOG.error(
1810                                Messages.get().getBundle().key(
1811                                    Messages.LOG_PUBLISHING_FILE_3,
1812                                    String.valueOf(++publishedFolderCount),
1813                                    String.valueOf(foldersSize),
1814                                    currentFolder));
1815                        }
1816                    }
1817
1818                    dbc.pop();
1819                } catch (Throwable t) {
1820                    dbc.report(
1821                        report,
1822                        Messages.get().container(Messages.ERR_ERROR_PUBLISHING_FOLDER_1, currentFolder.getRootPath()),
1823                        t);
1824                }
1825            }
1826
1827            if (foldersSize > 0) {
1828                report.println(
1829                    Messages.get().container(Messages.RPT_PUBLISH_FOLDERS_END_0),
1830                    I_CmsReport.FORMAT_HEADLINE);
1831            }
1832
1833            ////////////////////////////////////////////////////////////////////////////////
1834            // publish changed/new/deleted files
1835
1836            publishedFileCount = 0;
1837            int filesSize = publishList.getFileList().size();
1838
1839            if (filesSize > 0) {
1840                report.println(
1841                    Messages.get().container(Messages.RPT_PUBLISH_FILES_BEGIN_0),
1842                    I_CmsReport.FORMAT_HEADLINE);
1843            }
1844
1845            Set<CmsUUID> deletedResourceIds = new HashSet<CmsUUID>();
1846            Set<CmsUUID> changedResourceIds = new HashSet<CmsUUID>();
1847            for (CmsResource res : publishList.getFileList()) {
1848                if (res.getState().isDeleted()) {
1849                    deletedResourceIds.add(res.getResourceId());
1850                } else {
1851                    changedResourceIds.add(res.getResourceId());
1852                }
1853            }
1854            Set<CmsUUID> changedAndDeletedResourceIds = Sets.intersection(deletedResourceIds, changedResourceIds);
1855            dbc.setAttribute(CmsDriverManager.KEY_CHANGED_AND_DELETED, changedAndDeletedResourceIds);
1856
1857            Iterator<CmsResource> itFiles = publishList.getFileList().iterator();
1858            while (itFiles.hasNext()) {
1859                CmsResource currentResource = itFiles.next();
1860                try {
1861                    // bounce the current publish task through all project drivers
1862                    projectDriver.publishFile(
1863                        dbc,
1864                        report,
1865                        ++publishedFileCount,
1866                        filesSize,
1867                        onlineProject,
1868                        currentResource,
1869                        publishedContentIds,
1870                        publishList.getPublishHistoryId(),
1871                        publishTag);
1872
1873                    CmsResourceState state = currentResource.getState();
1874                    if (!state.isDeleted()) {
1875                        // reset the resource state to UNCHANGED and the last-modified-in-project-ID to 0
1876                        internalResetResourceState(dbc, currentResource);
1877                    }
1878
1879                    // unlock it
1880                    if (!CmsModificationContext.isInOnlineFolder(currentResource.getRootPath())) {
1881                        m_driverManager.unlockResource(dbc, currentResource, true, true);
1882                    }
1883                    // log it
1884                    CmsLogEntryType type = state.isNew()
1885                    ? CmsLogEntryType.RESOURCE_PUBLISHED_NEW
1886                    : (state.isDeleted()
1887                    ? CmsLogEntryType.RESOURCE_PUBLISHED_DELETED
1888                    : CmsLogEntryType.RESOURCE_PUBLISHED_MODIFIED);
1889                    m_driverManager.log(
1890                        dbc,
1891                        new CmsLogEntry(
1892                            dbc,
1893                            currentResource.getStructureId(),
1894                            type,
1895                            new String[] {currentResource.getRootPath()}),
1896                        true);
1897
1898                    publishedIds.add(currentResource.getStructureId());
1899                    dbc.pop();
1900                } catch (Throwable t) {
1901                    dbc.report(
1902                        report,
1903                        Messages.get().container(Messages.ERR_ERROR_PUBLISHING_FILE_1, currentResource.getRootPath()),
1904                        t);
1905                }
1906            }
1907
1908            if (filesSize > 0) {
1909                report.println(Messages.get().container(Messages.RPT_PUBLISH_FILES_END_0), I_CmsReport.FORMAT_HEADLINE);
1910            }
1911
1912            /////////////////////////////////////////////////////////////////////////////////
1913
1914            // publish deleted folders
1915            List<CmsResource> deletedFolders = publishList.getDeletedFolderList();
1916            if (deletedFolders.isEmpty()) {
1917                return;
1918            }
1919
1920            deletedFolderCount = 0;
1921            int deletedFoldersSize = deletedFolders.size();
1922            if (deletedFoldersSize > 0) {
1923                report.println(
1924                    Messages.get().container(Messages.RPT_DELETE_FOLDERS_BEGIN_0),
1925                    I_CmsReport.FORMAT_HEADLINE);
1926            }
1927
1928            Iterator<CmsResource> itDeletedFolders = deletedFolders.iterator();
1929            while (itDeletedFolders.hasNext()) {
1930                CmsResource currentFolder = itDeletedFolders.next();
1931
1932                try {
1933                    // bounce the current publish task through all project drivers
1934                    projectDriver.publishDeletedFolder(
1935                        dbc,
1936                        report,
1937                        ++deletedFolderCount,
1938                        deletedFoldersSize,
1939                        onlineProject,
1940                        new CmsFolder(currentFolder),
1941                        publishList.getPublishHistoryId(),
1942                        publishTag);
1943
1944                    dbc.pop();
1945                    // delete old historical entries
1946                    m_driverManager.getHistoryDriver(dbc).deleteEntries(
1947                        dbc,
1948                        new CmsHistoryFile(currentFolder),
1949                        OpenCms.getSystemInfo().getHistoryVersionsAfterDeletion(),
1950                        -1);
1951
1952                    publishedIds.add(currentFolder.getStructureId());
1953                    // unlock it
1954                    if (!CmsModificationContext.isInOnlineFolder(currentFolder.getRootPath())) {
1955                        m_driverManager.unlockResource(dbc, currentFolder, true, true);
1956                    }
1957                    // log it
1958                    m_driverManager.log(
1959                        dbc,
1960                        new CmsLogEntry(
1961                            dbc,
1962                            currentFolder.getStructureId(),
1963                            CmsLogEntryType.RESOURCE_PUBLISHED_DELETED,
1964                            new String[] {currentFolder.getRootPath()}),
1965                        true);
1966
1967                    dbc.pop();
1968                } catch (Throwable t) {
1969                    dbc.report(
1970                        report,
1971                        Messages.get().container(
1972                            Messages.ERR_ERROR_PUBLISHING_DELETED_FOLDER_1,
1973                            currentFolder.getRootPath()),
1974                        t);
1975                }
1976            }
1977
1978            if (deletedFoldersSize > 0) {
1979                report.println(
1980                    Messages.get().container(Messages.RPT_DELETE_FOLDERS_END_0),
1981                    I_CmsReport.FORMAT_HEADLINE);
1982            }
1983        } catch (OutOfMemoryError o) {
1984            // clear all caches to reclaim memory
1985            OpenCms.fireCmsEvent(
1986                new CmsEvent(I_CmsEventListener.EVENT_CLEAR_CACHES, Collections.<String, Object> emptyMap()));
1987
1988            CmsMessageContainer message = Messages.get().container(Messages.ERR_OUT_OF_MEMORY_0);
1989            if (LOG.isErrorEnabled()) {
1990                LOG.error(message.key(), o);
1991            }
1992            throw new CmsDataAccessException(message, o);
1993        } finally {
1994            // reset vfs driver internal info after publishing
1995            m_driverManager.getVfsDriver(dbc).publishVersions(dbc, null, false);
1996            Object[] msgArgs = new Object[] {
1997                String.valueOf(publishedFileCount),
1998                String.valueOf(publishedFolderCount),
1999                String.valueOf(deletedFolderCount),
2000                report.formatRuntime()};
2001
2002            CmsMessageContainer message = Messages.get().container(Messages.RPT_PUBLISH_STAT_4, msgArgs);
2003            if (LOG.isInfoEnabled()) {
2004                LOG.info(message.key());
2005            }
2006            report.println(message);
2007        }
2008    }
2009
2010    /**
2011     * @see org.opencms.db.I_CmsProjectDriver#readLocks(org.opencms.db.CmsDbContext)
2012     */
2013    public List<CmsLock> readLocks(CmsDbContext dbc) throws CmsDataAccessException {
2014
2015        Connection conn = null;
2016        PreparedStatement stmt = null;
2017        List<CmsTempResourceLock> tmpLocks = new ArrayList<CmsTempResourceLock>(256);
2018        List<CmsLock> locks = new ArrayList<CmsLock>(256);
2019        try {
2020            conn = m_sqlManager.getConnection(dbc);
2021            stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCE_LOCKS_READALL");
2022            ResultSet rs = stmt.executeQuery();
2023            while (rs.next()) {
2024                String resourcePath = rs.getString(m_sqlManager.readQuery("C_RESOURCE_LOCKS_RESOURCE_PATH"));
2025                CmsUUID userId = new CmsUUID(rs.getString(m_sqlManager.readQuery("C_RESOURCE_LOCKS_USER_ID")));
2026                CmsUUID projectId = new CmsUUID(rs.getString(m_sqlManager.readQuery("C_RESOURCE_LOCKS_PROJECT_ID")));
2027                int lockType = rs.getInt(m_sqlManager.readQuery("C_RESOURCE_LOCKS_LOCK_TYPE"));
2028                CmsTempResourceLock tmpLock = new CmsTempResourceLock(resourcePath, userId, projectId, lockType);
2029                tmpLocks.add(tmpLock);
2030            }
2031        } catch (SQLException e) {
2032            throw new CmsDbSqlException(
2033                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2034                e);
2035        } finally {
2036            m_sqlManager.closeAll(dbc, conn, stmt, null);
2037        }
2038
2039        for (CmsTempResourceLock tmpLock : tmpLocks) {
2040            CmsProject project;
2041            try {
2042                project = readProject(dbc, tmpLock.getProjectId());
2043            } catch (CmsDataAccessException dae) {
2044                // the project does not longer exist, ignore this lock (should usually not happen)
2045                project = null;
2046            }
2047            if (project != null) {
2048                CmsLock lock = new CmsLock(
2049                    tmpLock.getResourcePath(),
2050                    tmpLock.getUserId(),
2051                    project,
2052                    CmsLockType.valueOf(tmpLock.getLockType()));
2053                locks.add(lock);
2054            }
2055        }
2056        if (LOG.isDebugEnabled()) {
2057            LOG.debug(Messages.get().getBundle().key(Messages.LOG_DBG_READ_LOCKS_1, Integer.valueOf(locks.size())));
2058        }
2059        return locks;
2060    }
2061
2062    /**
2063     * @see org.opencms.db.I_CmsProjectDriver#readLog(org.opencms.db.CmsDbContext, org.opencms.db.log.CmsLogFilter)
2064     */
2065    public List<CmsLogEntry> readLog(CmsDbContext dbc, CmsLogFilter filter) throws CmsDataAccessException {
2066
2067        List<CmsLogEntry> entries = new ArrayList<CmsLogEntry>();
2068
2069        Connection conn = null;
2070        PreparedStatement stmt = null;
2071        ResultSet res = null;
2072
2073        try {
2074            conn = m_sqlManager.getConnection(dbc);
2075            // compose statement
2076            StringBuffer queryBuf = new StringBuffer(256);
2077            queryBuf.append(m_sqlManager.readQuery("C_LOG_READ_ENTRIES"));
2078            CmsPair<String, List<I_CmsPreparedStatementParameter>> conditionsAndParameters = prepareLogConditions(
2079                filter);
2080            List<I_CmsPreparedStatementParameter> params = conditionsAndParameters.getSecond();
2081            queryBuf.append(conditionsAndParameters.getFirst());
2082
2083            if (LOG.isDebugEnabled()) {
2084                LOG.debug(queryBuf.toString());
2085            }
2086            stmt = m_sqlManager.getPreparedStatementForSql(conn, queryBuf.toString());
2087            for (int i = 0; i < params.size(); i++) {
2088                I_CmsPreparedStatementParameter param = params.get(i);
2089                param.insertIntoStatement(stmt, i + 1);
2090            }
2091
2092            // execute
2093            res = stmt.executeQuery();
2094            while (res.next()) {
2095                // get results
2096                entries.add(internalReadLogEntry(res));
2097            }
2098        } catch (SQLException e) {
2099            throw new CmsDbSqlException(
2100                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2101                e);
2102        } finally {
2103            m_sqlManager.closeAll(dbc, conn, stmt, res);
2104        }
2105        return entries;
2106    }
2107
2108    /**
2109     * @see org.opencms.db.I_CmsProjectDriver#readProject(org.opencms.db.CmsDbContext, CmsUUID)
2110     */
2111    public CmsProject readProject(CmsDbContext dbc, CmsUUID id) throws CmsDataAccessException {
2112
2113        PreparedStatement stmt = null;
2114        CmsProject project = null;
2115        ResultSet res = null;
2116        Connection conn = null;
2117
2118        try {
2119            conn = m_sqlManager.getConnection(dbc);
2120            stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_READ_1");
2121
2122            stmt.setString(1, id.toString());
2123            res = stmt.executeQuery();
2124
2125            if (res.next()) {
2126                project = internalCreateProject(res);
2127                while (res.next()) {
2128                    // do nothing only move through all rows because of mssql odbc driver
2129                }
2130            } else {
2131                throw new CmsDbEntryNotFoundException(
2132                    Messages.get().container(Messages.ERR_NO_PROJECT_WITH_ID_1, String.valueOf(id)));
2133            }
2134        } catch (SQLException e) {
2135            throw new CmsDbSqlException(
2136                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2137                e);
2138        } finally {
2139            m_sqlManager.closeAll(dbc, conn, stmt, res);
2140        }
2141
2142        return project;
2143    }
2144
2145    /**
2146     * @see org.opencms.db.I_CmsProjectDriver#readProject(org.opencms.db.CmsDbContext, java.lang.String)
2147     */
2148    public CmsProject readProject(CmsDbContext dbc, String projectFqn) throws CmsDataAccessException {
2149
2150        PreparedStatement stmt = null;
2151        CmsProject project = null;
2152        ResultSet res = null;
2153        Connection conn = null;
2154
2155        try {
2156            conn = m_sqlManager.getConnection(dbc);
2157            stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_READ_BYNAME_2");
2158
2159            stmt.setString(1, CmsOrganizationalUnit.getSimpleName(projectFqn));
2160            stmt.setString(2, CmsOrganizationalUnit.SEPARATOR + CmsOrganizationalUnit.getParentFqn(projectFqn));
2161            res = stmt.executeQuery();
2162
2163            if (res.next()) {
2164                project = internalCreateProject(res);
2165                while (res.next()) {
2166                    // do nothing only move through all rows because of mssql odbc driver
2167                }
2168            } else {
2169                throw new CmsDbEntryNotFoundException(
2170                    Messages.get().container(Messages.ERR_NO_PROJECT_WITH_NAME_1, projectFqn));
2171            }
2172        } catch (SQLException e) {
2173            throw new CmsDbSqlException(
2174                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2175                e);
2176        } finally {
2177            m_sqlManager.closeAll(dbc, conn, stmt, res);
2178        }
2179
2180        return project;
2181    }
2182
2183    /**
2184     * @see org.opencms.db.I_CmsProjectDriver#readProjectResource(org.opencms.db.CmsDbContext, CmsUUID, java.lang.String)
2185     */
2186    public String readProjectResource(CmsDbContext dbc, CmsUUID projectId, String resourcePath)
2187    throws CmsDataAccessException {
2188
2189        PreparedStatement stmt = null;
2190        Connection conn = null;
2191        ResultSet res = null;
2192        String resName = null;
2193
2194        try {
2195            conn = getSqlManager().getConnection(dbc);
2196            stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTRESOURCES_READ_2");
2197
2198            // select resource from the database
2199            stmt.setString(1, projectId.toString());
2200            stmt.setString(2, resourcePath);
2201            res = stmt.executeQuery();
2202
2203            if (res.next()) {
2204                resName = res.getString("RESOURCE_PATH");
2205                while (res.next()) {
2206                    // do nothing only move through all rows because of mssql odbc driver
2207                }
2208            } else {
2209                throw new CmsVfsResourceNotFoundException(
2210                    Messages.get().container(Messages.ERR_NO_PROJECTRESOURCE_1, resourcePath));
2211            }
2212        } catch (SQLException e) {
2213            throw new CmsDbSqlException(
2214                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2215                e);
2216        } finally {
2217            m_sqlManager.closeAll(dbc, conn, stmt, res);
2218        }
2219        return resName;
2220    }
2221
2222    /**
2223     * @see org.opencms.db.I_CmsProjectDriver#readProjectResources(org.opencms.db.CmsDbContext, org.opencms.file.CmsProject)
2224     */
2225    public List<String> readProjectResources(CmsDbContext dbc, CmsProject project) throws CmsDataAccessException {
2226
2227        PreparedStatement stmt = null;
2228        Connection conn = null;
2229        ResultSet res = null;
2230        List<String> result = new ArrayList<String>();
2231
2232        try {
2233            conn = m_sqlManager.getConnection(dbc);
2234            stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTRESOURCES_READ_BY_ID_1");
2235            stmt.setString(1, project.getUuid().toString());
2236            res = stmt.executeQuery();
2237
2238            while (res.next()) {
2239                result.add(res.getString("RESOURCE_PATH"));
2240            }
2241        } catch (SQLException e) {
2242            throw new CmsDbSqlException(
2243                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2244                e);
2245        } finally {
2246            m_sqlManager.closeAll(dbc, conn, stmt, res);
2247        }
2248
2249        return result;
2250    }
2251
2252    /**
2253     * @see org.opencms.db.I_CmsProjectDriver#readProjects(org.opencms.db.CmsDbContext, String)
2254     */
2255    public List<CmsProject> readProjects(CmsDbContext dbc, String ouFqn) throws CmsDataAccessException {
2256
2257        if ((dbc.getRequestContext() != null)
2258            && (dbc.getRequestContext().getAttribute(DBC_ATTR_READ_PROJECT_FOR_RESOURCE) != null)) {
2259            dbc.getRequestContext().removeAttribute(DBC_ATTR_READ_PROJECT_FOR_RESOURCE);
2260            // TODO: this should get its own method in the interface
2261            return readProjectsForResource(dbc, ouFqn);
2262        }
2263        List<CmsProject> projects = new ArrayList<CmsProject>();
2264        ResultSet res = null;
2265        PreparedStatement stmt = null;
2266        Connection conn = null;
2267
2268        try {
2269            // create the statement
2270            conn = m_sqlManager.getConnection(dbc);
2271            stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_READ_BYOU_1");
2272
2273            stmt.setString(1, CmsOrganizationalUnit.SEPARATOR + ouFqn + "%");
2274            res = stmt.executeQuery();
2275
2276            while (res.next()) {
2277                projects.add(internalCreateProject(res));
2278            }
2279        } catch (SQLException e) {
2280            throw new CmsDbSqlException(
2281                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2282                e);
2283        } finally {
2284            m_sqlManager.closeAll(dbc, conn, stmt, res);
2285        }
2286
2287        return (projects);
2288    }
2289
2290    /**
2291     * @see org.opencms.db.I_CmsProjectDriver#readProjectsForGroup(org.opencms.db.CmsDbContext, org.opencms.file.CmsGroup)
2292     */
2293    public List<CmsProject> readProjectsForGroup(CmsDbContext dbc, CmsGroup group) throws CmsDataAccessException {
2294
2295        List<CmsProject> projects = new ArrayList<CmsProject>();
2296        ResultSet res = null;
2297        Connection conn = null;
2298        PreparedStatement stmt = null;
2299
2300        try {
2301            // create the statement
2302            conn = m_sqlManager.getConnection(dbc);
2303            stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_READ_BYGROUP_2");
2304
2305            stmt.setString(1, group.getId().toString());
2306            stmt.setString(2, group.getId().toString());
2307            res = stmt.executeQuery();
2308
2309            while (res.next()) {
2310                projects.add(internalCreateProject(res));
2311            }
2312        } catch (SQLException e) {
2313            throw new CmsDbSqlException(
2314                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2315                e);
2316        } finally {
2317            m_sqlManager.closeAll(dbc, conn, stmt, res);
2318        }
2319        return (projects);
2320    }
2321
2322    /**
2323     * @see org.opencms.db.I_CmsProjectDriver#readProjectsForManagerGroup(org.opencms.db.CmsDbContext, org.opencms.file.CmsGroup)
2324     */
2325    public List<CmsProject> readProjectsForManagerGroup(CmsDbContext dbc, CmsGroup group)
2326    throws CmsDataAccessException {
2327
2328        List<CmsProject> projects = new ArrayList<CmsProject>();
2329        ResultSet res = null;
2330        PreparedStatement stmt = null;
2331        Connection conn = null;
2332
2333        try {
2334            // create the statement
2335            conn = m_sqlManager.getConnection(dbc);
2336            stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_READ_BYMANAGER_1");
2337
2338            stmt.setString(1, group.getId().toString());
2339            res = stmt.executeQuery();
2340
2341            while (res.next()) {
2342                projects.add(internalCreateProject(res));
2343            }
2344        } catch (SQLException e) {
2345            throw new CmsDbSqlException(
2346                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2347                e);
2348        } finally {
2349            m_sqlManager.closeAll(dbc, conn, stmt, res);
2350        }
2351        return (projects);
2352    }
2353
2354    /**
2355     * Returns the projects of a given resource.<p>
2356     *
2357     * @param dbc the database context
2358     * @param rootPath the resource root path
2359     *
2360     * @return the projects of the resource, as a list of projects
2361     *
2362     * @throws CmsDataAccessException if something goes wrong
2363     */
2364    public List<CmsProject> readProjectsForResource(CmsDbContext dbc, String rootPath) throws CmsDataAccessException {
2365
2366        PreparedStatement stmt = null;
2367        List<CmsProject> projects = new ArrayList<CmsProject>();
2368        ResultSet res = null;
2369        Connection conn = null;
2370
2371        try {
2372            conn = m_sqlManager.getConnection(dbc);
2373            stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_READ_BYRESOURCE_1");
2374
2375            stmt.setString(1, rootPath + "%");
2376            res = stmt.executeQuery();
2377
2378            if (res.next()) {
2379                projects.add(internalCreateProject(res));
2380                while (res.next()) {
2381                    // do nothing only move through all rows because of mssql odbc driver
2382                }
2383            }
2384        } catch (SQLException e) {
2385            throw new CmsDbSqlException(
2386                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2387                e);
2388        } finally {
2389            m_sqlManager.closeAll(dbc, conn, stmt, res);
2390        }
2391
2392        return projects;
2393    }
2394
2395    /**
2396     * @see org.opencms.db.I_CmsProjectDriver#readProjectsForUser(org.opencms.db.CmsDbContext, org.opencms.file.CmsUser)
2397     */
2398    public List<CmsProject> readProjectsForUser(CmsDbContext dbc, CmsUser user) throws CmsDataAccessException {
2399
2400        List<CmsProject> projects = new ArrayList<CmsProject>();
2401        ResultSet res = null;
2402        PreparedStatement stmt = null;
2403        Connection conn = null;
2404
2405        try {
2406            // create the statement
2407            conn = m_sqlManager.getConnection(dbc);
2408            stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_READ_BYUSER_1");
2409
2410            stmt.setString(1, user.getId().toString());
2411            res = stmt.executeQuery();
2412
2413            while (res.next()) {
2414                projects.add(internalCreateProject(res));
2415            }
2416        } catch (SQLException e) {
2417            throw new CmsDbSqlException(
2418                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2419                e);
2420        } finally {
2421            m_sqlManager.closeAll(dbc, conn, stmt, res);
2422        }
2423        return (projects);
2424    }
2425
2426    /**
2427     * @see org.opencms.db.I_CmsProjectDriver#readPublishedResources(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID)
2428     */
2429    public List<CmsPublishedResource> readPublishedResources(CmsDbContext dbc, CmsUUID publishHistoryId)
2430    throws CmsDataAccessException {
2431
2432        Connection conn = null;
2433        PreparedStatement stmt = null;
2434        ResultSet res = null;
2435        List<CmsPublishedResource> publishedResources = new ArrayList<CmsPublishedResource>();
2436
2437        try {
2438            conn = m_sqlManager.getConnection(dbc);
2439            stmt = m_sqlManager.getPreparedStatement(conn, "C_SELECT_PUBLISHED_RESOURCES");
2440            stmt.setString(1, publishHistoryId.toString());
2441            res = stmt.executeQuery();
2442
2443            while (res.next()) {
2444                CmsUUID structureId = new CmsUUID(res.getString("STRUCTURE_ID"));
2445                CmsUUID resourceId = new CmsUUID(res.getString("RESOURCE_ID"));
2446                String rootPath = res.getString("RESOURCE_PATH");
2447                int resourceState = res.getInt("RESOURCE_STATE");
2448                int resourceType = res.getInt("RESOURCE_TYPE");
2449                int siblingCount = res.getInt("SIBLING_COUNT");
2450                int publishTag = res.getInt("PUBLISH_TAG");
2451
2452                // compose the resource state
2453                CmsResourceState state;
2454                if (resourceState == CmsPublishedResource.STATE_MOVED_SOURCE.getState()) {
2455                    state = CmsPublishedResource.STATE_MOVED_SOURCE;
2456                } else if (resourceState == CmsPublishedResource.STATE_MOVED_DESTINATION.getState()) {
2457                    state = CmsPublishedResource.STATE_MOVED_DESTINATION;
2458                } else {
2459                    state = CmsResourceState.valueOf(resourceState);
2460                }
2461
2462                publishedResources.add(
2463                    new CmsPublishedResource(
2464                        structureId,
2465                        resourceId,
2466                        publishTag,
2467                        rootPath,
2468                        resourceType,
2469                        structureId.isNullUUID() ? false : CmsFolder.isFolderType(resourceType),
2470                        state,
2471                        siblingCount));
2472            }
2473        } catch (SQLException e) {
2474            throw new CmsDbSqlException(
2475                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2476                e);
2477        } finally {
2478            m_sqlManager.closeAll(dbc, conn, stmt, res);
2479        }
2480
2481        return publishedResources;
2482    }
2483
2484    /**
2485     * @see org.opencms.db.I_CmsProjectDriver#readPublishJob(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID)
2486     */
2487    public CmsPublishJobInfoBean readPublishJob(CmsDbContext dbc, CmsUUID publishHistoryId)
2488    throws CmsDataAccessException {
2489
2490        Connection conn = null;
2491        PreparedStatement stmt = null;
2492        ResultSet res = null;
2493
2494        CmsPublishJobInfoBean result = null;
2495        try {
2496            conn = m_sqlManager.getConnection(dbc);
2497            stmt = m_sqlManager.getPreparedStatement(conn, "C_PUBLISHJOB_READ_JOB");
2498            stmt.setString(1, publishHistoryId.toString());
2499            res = stmt.executeQuery();
2500
2501            if (res.next()) {
2502                result = createPublishJobInfoBean(res);
2503                while (res.next()) {
2504                    // do nothing only move through all rows because of mssql odbc driver
2505                }
2506            } else {
2507                throw new CmsDbEntryNotFoundException(
2508                    Messages.get().container(Messages.ERR_READ_PUBLISH_JOB_1, publishHistoryId.toString()));
2509            }
2510        } catch (SQLException e) {
2511            throw new CmsDbSqlException(
2512                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2513                e);
2514        } finally {
2515            m_sqlManager.closeAll(dbc, conn, stmt, res);
2516        }
2517
2518        return result;
2519    }
2520
2521    /**
2522     * @see org.opencms.db.I_CmsProjectDriver#readPublishJobs(org.opencms.db.CmsDbContext, long, long)
2523     */
2524    public List<CmsPublishJobInfoBean> readPublishJobs(CmsDbContext dbc, long startTime, long endTime)
2525    throws CmsDataAccessException {
2526
2527        Connection conn = null;
2528        PreparedStatement stmt = null;
2529        ResultSet res = null;
2530
2531        List<CmsPublishJobInfoBean> result = null;
2532        try {
2533            conn = m_sqlManager.getConnection(dbc);
2534            stmt = m_sqlManager.getPreparedStatement(conn, "C_PUBLISHJOB_READ_JOBS_IN_TIMERANGE");
2535            stmt.setLong(1, startTime);
2536            stmt.setLong(2, endTime);
2537            res = stmt.executeQuery();
2538
2539            result = new ArrayList<CmsPublishJobInfoBean>();
2540            while (res.next()) {
2541                result.add(createPublishJobInfoBean(res));
2542            }
2543        } catch (SQLException e) {
2544            throw new CmsDbSqlException(
2545                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2546                e);
2547        } finally {
2548            m_sqlManager.closeAll(dbc, conn, stmt, res);
2549        }
2550
2551        return result;
2552    }
2553
2554    /**
2555     * @see org.opencms.db.I_CmsProjectDriver#readPublishList(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID)
2556     */
2557    public CmsPublishList readPublishList(CmsDbContext dbc, CmsUUID publishHistoryId) throws CmsDataAccessException {
2558
2559        Connection conn = null;
2560        PreparedStatement stmt = null;
2561        ResultSet res = null;
2562        CmsPublishList publishList = null;
2563
2564        try {
2565            conn = m_sqlManager.getConnection(dbc);
2566            stmt = m_sqlManager.getPreparedStatement(conn, "C_PUBLISHJOB_READ_PUBLISHLIST");
2567            stmt.setString(1, publishHistoryId.toString());
2568            res = stmt.executeQuery();
2569
2570            if (res.next()) {
2571                byte[] bytes = m_sqlManager.getBytes(res, "PUBLISH_LIST");
2572                publishList = internalDeserializePublishList(bytes);
2573                while (res.next()) {
2574                    // do nothing only move through all rows because of mssql odbc driver
2575                }
2576            } else {
2577                throw new CmsDataAccessException(
2578                    Messages.get().container(Messages.ERR_READ_PUBLISH_JOB_1, publishHistoryId.toString()));
2579            }
2580        } catch (SQLException e) {
2581            throw new CmsDbSqlException(
2582                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2583                e);
2584        } catch (Exception e) {
2585            throw new CmsDataAccessException(
2586                Messages.get().container(Messages.ERR_PUBLISHLIST_DESERIALIZATION_FAILED_1, publishHistoryId),
2587                e);
2588        } finally {
2589            m_sqlManager.closeAll(dbc, conn, stmt, res);
2590        }
2591
2592        return publishList;
2593    }
2594
2595    /**
2596     * @see org.opencms.db.I_CmsProjectDriver#readPublishReportContents(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID)
2597     */
2598    public byte[] readPublishReportContents(CmsDbContext dbc, CmsUUID publishHistoryId) throws CmsDataAccessException {
2599
2600        PreparedStatement stmt = null;
2601        ResultSet res = null;
2602        Connection conn = null;
2603        byte[] bytes = null;
2604
2605        try {
2606            conn = m_sqlManager.getConnection(dbc);
2607
2608            stmt = m_sqlManager.getPreparedStatement(conn, "C_PUBLISHJOB_READ_REPORT");
2609            stmt.setString(1, publishHistoryId.toString());
2610            res = stmt.executeQuery();
2611
2612            if (res.next()) {
2613                // query to read Array of bytes for the given attribute
2614                bytes = m_sqlManager.getBytes(res, "PUBLISH_REPORT");
2615                while (res.next()) {
2616                    // do nothing only move through all rows because of mssql odbc driver
2617                }
2618            } else {
2619                throw new CmsDataAccessException(
2620                    Messages.get().container(Messages.ERR_READ_PUBLISH_JOB_1, publishHistoryId.toString()));
2621            }
2622        } catch (SQLException e) {
2623            LOG.error(CmsDbSqlException.getErrorQuery(stmt), e);
2624            bytes = Messages.get().container(
2625                Messages.ERR_GENERIC_SQL_1,
2626                CmsDbSqlException.getErrorQuery(stmt)).key().getBytes();
2627        } finally {
2628            m_sqlManager.closeAll(dbc, conn, stmt, res);
2629        }
2630        return bytes;
2631    }
2632
2633    /**
2634     * @see org.opencms.db.I_CmsProjectDriver#readStaticExportPublishedResourceParameters(org.opencms.db.CmsDbContext, java.lang.String)
2635     */
2636    public String readStaticExportPublishedResourceParameters(CmsDbContext dbc, String rfsName)
2637    throws CmsDataAccessException {
2638
2639        String returnValue = null;
2640        Connection conn = null;
2641        PreparedStatement stmt = null;
2642        ResultSet res = null;
2643
2644        try {
2645            conn = m_sqlManager.getConnection(dbc);
2646            stmt = m_sqlManager.getPreparedStatement(conn, "C_STATICEXPORT_READ_PUBLISHED_LINK_PARAMETERS");
2647            stmt.setString(1, rfsName);
2648            res = stmt.executeQuery();
2649            // add all resourcenames to the list of return values
2650            if (res.next()) {
2651                returnValue = res.getString(1);
2652                while (res.next()) {
2653                    // do nothing only move through all rows because of mssql odbc driver
2654                }
2655            }
2656        } catch (SQLException e) {
2657            throw new CmsDbSqlException(
2658                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2659                e);
2660        } finally {
2661            m_sqlManager.closeAll(dbc, conn, stmt, res);
2662        }
2663
2664        return returnValue;
2665    }
2666
2667    /**
2668     * @see org.opencms.db.I_CmsProjectDriver#readStaticExportResources(org.opencms.db.CmsDbContext, int, long)
2669     */
2670    public List<String> readStaticExportResources(CmsDbContext dbc, int parameterResources, long timestamp)
2671    throws CmsDataAccessException {
2672
2673        Connection conn = null;
2674        PreparedStatement stmt = null;
2675        ResultSet res = null;
2676        List<String> returnValue = new ArrayList<String>();
2677
2678        if (parameterResources == CmsStaticExportManager.EXPORT_LINK_WITHOUT_PARAMETER) {
2679            timestamp = 0;
2680        }
2681        try {
2682            conn = m_sqlManager.getConnection(dbc);
2683            stmt = m_sqlManager.getPreparedStatement(conn, "C_STATICEXPORT_READ_ALL_PUBLISHED_LINKS");
2684            stmt.setInt(1, parameterResources);
2685            stmt.setLong(2, timestamp);
2686            res = stmt.executeQuery();
2687            // add all resourcenames to the list of return values
2688            while (res.next()) {
2689                returnValue.add(res.getString(1));
2690            }
2691        } catch (SQLException e) {
2692            throw new CmsDbSqlException(
2693                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2694                e);
2695        } finally {
2696            m_sqlManager.closeAll(dbc, conn, stmt, res);
2697        }
2698
2699        return returnValue;
2700    }
2701
2702    /**
2703     * @see org.opencms.db.I_CmsProjectDriver#setDriverManager(org.opencms.db.CmsDriverManager)
2704     */
2705    public void setDriverManager(CmsDriverManager driverManager) {
2706
2707        m_driverManager = driverManager;
2708    }
2709
2710    /**
2711     * @see org.opencms.db.I_CmsProjectDriver#setSqlManager(org.opencms.db.CmsSqlManager)
2712     */
2713    public void setSqlManager(org.opencms.db.CmsSqlManager manager) {
2714
2715        m_sqlManager = (CmsSqlManager)manager;
2716    }
2717
2718    /**
2719     * @see org.opencms.db.I_CmsProjectDriver#unmarkProjectResources(org.opencms.db.CmsDbContext, org.opencms.file.CmsProject)
2720     */
2721    public void unmarkProjectResources(CmsDbContext dbc, CmsProject project) throws CmsDataAccessException {
2722
2723        // finally remove the project id form all resources
2724
2725        Connection conn = null;
2726        PreparedStatement stmt = null;
2727        try {
2728            conn = m_sqlManager.getConnection(dbc);
2729            stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_UNMARK");
2730            // create the statement
2731            stmt.setString(1, project.getUuid().toString());
2732            stmt.executeUpdate();
2733        } catch (SQLException e) {
2734            throw new CmsDbSqlException(
2735                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2736                e);
2737        } finally {
2738            m_sqlManager.closeAll(dbc, conn, stmt, null);
2739        }
2740    }
2741
2742    /**
2743     * @see org.opencms.db.I_CmsProjectDriver#writeLocks(org.opencms.db.CmsDbContext, java.util.List)
2744     */
2745    public void writeLocks(CmsDbContext dbc, List<CmsLock> locks) throws CmsDataAccessException {
2746
2747        Connection conn = null;
2748        PreparedStatement stmt = null;
2749        try {
2750            conn = m_sqlManager.getConnection(dbc);
2751            stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCE_LOCKS_DELETEALL");
2752            int deleted = stmt.executeUpdate();
2753            if (LOG.isDebugEnabled()) {
2754                LOG.debug(Messages.get().getBundle().key(Messages.LOG_DBG_CLEAR_LOCKS_1, Integer.valueOf(deleted)));
2755            }
2756            stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCE_LOCK_WRITE");
2757            if (LOG.isDebugEnabled()) {
2758                LOG.debug("SQL :" + m_sqlManager.readQuery("C_RESOURCE_LOCK_WRITE"));
2759            }
2760            Iterator<CmsLock> i = locks.iterator();
2761            int count = 0;
2762            while (i.hasNext()) {
2763                CmsLock lock = i.next();
2764                // only persist locks that should be written to the DB
2765                CmsLock sysLock = lock.getSystemLock();
2766                if (sysLock.isPersistent()) {
2767                    // persist system lock
2768                    stmt.setString(1, sysLock.getResourceName());
2769                    stmt.setString(2, sysLock.getUserId().toString());
2770                    stmt.setString(3, sysLock.getProjectId().toString());
2771                    stmt.setInt(4, sysLock.getType().hashCode());
2772                    stmt.executeUpdate();
2773                    count++;
2774                }
2775                CmsLock editLock = lock.getEditionLock();
2776                if (editLock.isPersistent()) {
2777                    // persist edition lock
2778                    stmt.setString(1, editLock.getResourceName());
2779                    stmt.setString(2, editLock.getUserId().toString());
2780                    stmt.setString(3, editLock.getProjectId().toString());
2781                    stmt.setInt(4, editLock.getType().hashCode());
2782                    stmt.executeUpdate();
2783                    count++;
2784                }
2785            }
2786            if (LOG.isDebugEnabled()) {
2787                LOG.debug(Messages.get().getBundle().key(Messages.LOG_DBG_WRITE_LOCKS_1, Integer.valueOf(count)));
2788            }
2789        } catch (SQLException e) {
2790            throw new CmsDbSqlException(
2791                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2792                e);
2793        } finally {
2794            m_sqlManager.closeAll(dbc, conn, stmt, null);
2795        }
2796    }
2797
2798    /**
2799     * @see org.opencms.db.I_CmsProjectDriver#writeProject(org.opencms.db.CmsDbContext, org.opencms.file.CmsProject)
2800     */
2801    public void writeProject(CmsDbContext dbc, CmsProject project) throws CmsDataAccessException {
2802
2803        if (CmsStringUtil.isEmptyOrWhitespaceOnly(project.getDescription())) {
2804            project.setDescription(" ");
2805        }
2806        Connection conn = null;
2807        PreparedStatement stmt = null;
2808
2809        try {
2810            // get a JDBC connection from the OpenCms standard pools
2811            conn = m_sqlManager.getConnection(dbc);
2812
2813            stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_WRITE_6");
2814            stmt.setString(1, project.getDescription());
2815            stmt.setString(2, project.getGroupId().toString());
2816            stmt.setString(3, project.getManagerGroupId().toString());
2817            stmt.setInt(4, project.getFlags());
2818            stmt.setInt(5, project.getType().getMode());
2819            stmt.setString(6, project.getUuid().toString());
2820            stmt.executeUpdate();
2821        } catch (SQLException e) {
2822            throw new CmsDbSqlException(
2823                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2824                e);
2825        } finally {
2826            m_sqlManager.closeAll(dbc, conn, stmt, null);
2827        }
2828    }
2829
2830    /**
2831     * @see org.opencms.db.I_CmsProjectDriver#writePublishHistory(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID, org.opencms.db.CmsPublishedResource)
2832     */
2833    public void writePublishHistory(CmsDbContext dbc, CmsUUID publishId, CmsPublishedResource resource)
2834    throws CmsDataAccessException {
2835
2836        Connection conn = null;
2837        PreparedStatement stmt = null;
2838
2839        try {
2840            conn = m_sqlManager.getConnection(dbc);
2841            stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_WRITE_PUBLISH_HISTORY");
2842            stmt.setInt(1, resource.getPublishTag());
2843            stmt.setString(2, resource.getStructureId().toString());
2844            stmt.setString(3, resource.getResourceId().toString());
2845            stmt.setString(4, resource.getRootPath());
2846            stmt.setInt(5, resource.getMovedState().getState());
2847            stmt.setInt(6, resource.getType());
2848            stmt.setString(7, publishId.toString());
2849            stmt.setInt(8, resource.getSiblingCount());
2850            stmt.executeUpdate();
2851        } catch (SQLException e) {
2852            throw new CmsDbSqlException(
2853                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2854                e);
2855        } finally {
2856            m_sqlManager.closeAll(dbc, conn, stmt, null);
2857        }
2858    }
2859
2860    /**
2861     * @see org.opencms.db.I_CmsProjectDriver#writePublishJob(org.opencms.db.CmsDbContext, org.opencms.publish.CmsPublishJobInfoBean)
2862     */
2863    public void writePublishJob(CmsDbContext dbc, CmsPublishJobInfoBean publishJob) throws CmsDataAccessException {
2864
2865        Connection conn = null;
2866        PreparedStatement stmt = null;
2867
2868        try {
2869            conn = m_sqlManager.getConnection(dbc);
2870            stmt = m_sqlManager.getPreparedStatement(conn, "C_PUBLISHJOB_WRITE");
2871            stmt.setString(1, publishJob.getProjectId().toString());
2872            stmt.setString(2, publishJob.getProjectName());
2873            stmt.setString(3, publishJob.getUserId().toString());
2874            stmt.setString(4, publishJob.getLocale().toString());
2875            stmt.setInt(5, publishJob.getFlags());
2876            stmt.setInt(6, publishJob.getSize());
2877            stmt.setLong(7, publishJob.getEnqueueTime());
2878            stmt.setLong(8, publishJob.getStartTime());
2879            stmt.setLong(9, publishJob.getFinishTime());
2880            stmt.setString(10, publishJob.getPublishHistoryId().toString());
2881            stmt.executeUpdate();
2882        } catch (SQLException e) {
2883            throw new CmsDbSqlException(
2884                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2885                e);
2886        } finally {
2887            m_sqlManager.closeAll(dbc, conn, stmt, null);
2888        }
2889    }
2890
2891    /**
2892     * @see org.opencms.db.I_CmsProjectDriver#writePublishReport(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID, byte[])
2893     */
2894    public void writePublishReport(CmsDbContext dbc, CmsUUID publishId, byte[] content) throws CmsDataAccessException {
2895
2896        Connection conn = null;
2897        PreparedStatement stmt = null;
2898
2899        try {
2900            conn = m_sqlManager.getConnection(dbc);
2901            stmt = m_sqlManager.getPreparedStatement(conn, "C_PUBLISHJOB_WRITE_REPORT");
2902
2903            if (content.length < 2000) {
2904                stmt.setBytes(1, content);
2905            } else {
2906                stmt.setBinaryStream(1, new ByteArrayInputStream(content), content.length);
2907            }
2908
2909            stmt.setString(2, publishId.toString());
2910            stmt.executeUpdate();
2911        } catch (SQLException e) {
2912            throw new CmsDbSqlException(
2913                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2914                e);
2915        } finally {
2916            m_sqlManager.closeAll(dbc, conn, stmt, null);
2917        }
2918    }
2919
2920    /**
2921     * @see org.opencms.db.I_CmsProjectDriver#writeStaticExportPublishedResource(org.opencms.db.CmsDbContext, java.lang.String, int, java.lang.String, long)
2922     */
2923    public void writeStaticExportPublishedResource(
2924        CmsDbContext dbc,
2925        String resourceName,
2926        int linkType,
2927        String linkParameter,
2928        long timestamp)
2929    throws CmsDataAccessException {
2930
2931        Connection conn = null;
2932        PreparedStatement stmt = null;
2933        ResultSet res = null;
2934        int returnValue = 0;
2935        // first check if a record with this resource name does already exist
2936        try {
2937            conn = m_sqlManager.getConnection(dbc);
2938            stmt = m_sqlManager.getPreparedStatement(conn, "C_STATICEXPORT_READ_PUBLISHED_RESOURCES");
2939            stmt.setString(1, resourceName);
2940            res = stmt.executeQuery();
2941            if (res.next()) {
2942                returnValue = res.getInt(1);
2943                while (res.next()) {
2944                    // do nothing only move through all rows because of mssql odbc driver
2945                }
2946            }
2947        } catch (SQLException e) {
2948            throw new CmsDbSqlException(
2949                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
2950                e);
2951        } finally {
2952            m_sqlManager.closeAll(dbc, conn, stmt, res);
2953        }
2954
2955        // there was no entry found, so add it to the database
2956        if (returnValue == 0) {
2957            try {
2958                conn = m_sqlManager.getConnection(dbc);
2959                stmt = m_sqlManager.getPreparedStatement(conn, "C_STATICEXPORT_WRITE_PUBLISHED_LINKS");
2960                stmt.setString(1, new CmsUUID().toString());
2961                stmt.setString(2, resourceName);
2962                stmt.setInt(3, linkType);
2963                stmt.setString(4, linkParameter);
2964                stmt.setLong(5, timestamp);
2965                stmt.executeUpdate();
2966            } catch (SQLException e) {
2967                throw new CmsDbSqlException(Messages.get().container(Messages.ERR_GENERIC_SQL_1, stmt), e);
2968            } finally {
2969                m_sqlManager.closeAll(dbc, conn, stmt, null);
2970            }
2971        }
2972    }
2973
2974    /**
2975     * @see org.opencms.db.I_CmsProjectDriver#writeUserPublishListEntries(org.opencms.db.CmsDbContext, java.util.List)
2976     */
2977    public void writeUserPublishListEntries(CmsDbContext dbc, List<CmsUserPublishListEntry> publishListAdditions)
2978    throws CmsDbSqlException {
2979
2980        if (publishListAdditions.isEmpty()) {
2981            return;
2982        }
2983
2984        // first remove all entries with the same keys
2985        deleteUserPublishListEntries(dbc, publishListAdditions);
2986
2987        Connection conn = null;
2988        PreparedStatement stmt = null;
2989        try {
2990            conn = m_sqlManager.getConnection(dbc);
2991            String sql = m_sqlManager.readQuery("C_USER_PUBLISH_LIST_INSERT_3");
2992            stmt = m_sqlManager.getPreparedStatementForSql(conn, sql);
2993            for (CmsUserPublishListEntry entry : publishListAdditions) {
2994                stmt.setString(1, entry.getUserId().toString());
2995                stmt.setString(2, entry.getStructureId().toString());
2996                stmt.setLong(3, entry.getDateChanged());
2997                stmt.addBatch();
2998            }
2999            stmt.executeBatch();
3000        } catch (SQLException e) {
3001            throw new CmsDbSqlException(
3002                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
3003                e);
3004        } finally {
3005            m_sqlManager.closeAll(dbc, conn, stmt, null);
3006        }
3007
3008    }
3009
3010    /**
3011     * Creates a <code>CmsPublishJobInfoBean</code> from a result set.<p>
3012     *
3013     * @param res the result set
3014     * @return an initialized <code>CmsPublishJobInfoBean</code>
3015     * @throws SQLException if something goes wrong
3016     */
3017    protected CmsPublishJobInfoBean createPublishJobInfoBean(ResultSet res) throws SQLException {
3018
3019        return new CmsPublishJobInfoBean(
3020            new CmsUUID(res.getString("HISTORY_ID")),
3021            new CmsUUID(res.getString("PROJECT_ID")),
3022            res.getString("PROJECT_NAME"),
3023            new CmsUUID(res.getString("USER_ID")),
3024            res.getString("PUBLISH_LOCALE"),
3025            res.getInt("PUBLISH_FLAGS"),
3026            res.getInt("RESOURCE_COUNT"),
3027            res.getLong("ENQUEUE_TIME"),
3028            res.getLong("START_TIME"),
3029            res.getLong("FINISH_TIME"));
3030    }
3031
3032    /**
3033     * Checks if the given resource (by id) is available in the online project,
3034     * if there exists a resource with a different path (a moved file), then the
3035     * online entry is moved to the right (new) location before publishing.<p>
3036     *
3037     * @param dbc the db context
3038     * @param onlineProject the online project
3039     * @param offlineResource the offline resource to check
3040     * @param publishHistoryId the publish history id
3041     * @param publishTag the publish tag
3042     *
3043     * @return <code>true</code> if the resource has actually been moved
3044     *
3045     * @throws CmsDataAccessException if something goes wrong
3046     */
3047    protected CmsResourceState fixMovedResource(
3048        CmsDbContext dbc,
3049        CmsProject onlineProject,
3050        CmsResource offlineResource,
3051        CmsUUID publishHistoryId,
3052        int publishTag)
3053    throws CmsDataAccessException {
3054
3055        CmsResource onlineResource;
3056        // check if the resource has been moved since last publishing
3057        try {
3058            onlineResource = m_driverManager.getVfsDriver(
3059                dbc).readResource(dbc, onlineProject.getUuid(), offlineResource.getStructureId(), true);
3060            if (onlineResource.getRootPath().equals(offlineResource.getRootPath())) {
3061                // resource changed, not moved
3062                return offlineResource.getState();
3063            }
3064        } catch (CmsVfsResourceNotFoundException e) {
3065            // ok, resource new, not moved
3066            return offlineResource.getState();
3067        }
3068
3069        // move the online resource to the new position
3070        m_driverManager.getVfsDriver(
3071            dbc).moveResource(dbc, onlineProject.getUuid(), onlineResource, offlineResource.getRootPath());
3072
3073        try {
3074            // write the resource to the publish history
3075            m_driverManager.getProjectDriver(dbc).writePublishHistory(
3076                dbc,
3077                publishHistoryId,
3078                new CmsPublishedResource(onlineResource, publishTag, CmsPublishedResource.STATE_MOVED_SOURCE));
3079        } catch (CmsDataAccessException e) {
3080            if (LOG.isErrorEnabled()) {
3081                LOG.error(
3082                    Messages.get().getBundle().key(
3083                        Messages.LOG_WRITING_PUBLISHING_HISTORY_1,
3084                        onlineResource.getRootPath()),
3085                    e);
3086            }
3087            throw e;
3088        }
3089        return offlineResource.getState().isDeleted()
3090        ? CmsResource.STATE_DELETED
3091        : CmsPublishedResource.STATE_MOVED_DESTINATION;
3092    }
3093
3094    /**
3095     * Returns a SQL parameter string for the given data.<p>
3096     *
3097     * @param data the data
3098     *
3099     * @return the SQL parameter
3100     */
3101    protected String getParameterString(Collection<?> data) {
3102
3103        StringBuffer conditions = new StringBuffer();
3104        conditions.append(BEGIN_CONDITION);
3105        Iterator<?> it = data.iterator();
3106        while (it.hasNext()) {
3107            it.next();
3108            conditions.append("?");
3109            if (it.hasNext()) {
3110                conditions.append(", ");
3111            }
3112        }
3113        conditions.append(END_CONDITION);
3114        return conditions.toString();
3115    }
3116
3117    /**
3118     * Implementation of reading the user publish list which uses the log table.<p>
3119     *
3120     * This is the old implementation of the user publish list and can get pretty slow.<p>
3121     *
3122     * @param dbc the current database context
3123     * @param userId the id of the user for which we want the user publish list
3124     *
3125     * @return the publish list for the given user
3126     *
3127     * @throws CmsDataAccessException if something goes wrong
3128     */
3129    protected List<CmsResource> getUsersPubListFromLog(CmsDbContext dbc, CmsUUID userId) throws CmsDataAccessException {
3130
3131        Connection conn = null;
3132        PreparedStatement stmt = null;
3133        ResultSet res = null;
3134
3135        List<CmsResource> result = null;
3136        try {
3137            conn = m_sqlManager.getConnection(dbc);
3138            stmt = m_sqlManager.getPreparedStatement(conn, dbc.currentProject().getUuid(), "C_LOG_READ_PUBLISH_LIST_2");
3139            stmt.setString(1, userId.toString());
3140            stmt.setString(2, userId.toString());
3141            res = stmt.executeQuery();
3142
3143            result = new ArrayList<CmsResource>();
3144            while (res.next()) {
3145                CmsResource resource = m_driverManager.getVfsDriver(dbc).createResource(
3146                    res,
3147                    dbc.currentProject().getUuid());
3148                long date = res.getLong(m_sqlManager.readQuery("C_LOG_DATE"));
3149                resource.setDateLastModified(date);
3150                result.add(resource);
3151            }
3152        } catch (SQLException e) {
3153            throw new CmsDbSqlException(
3154                Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)),
3155                e);
3156        } finally {
3157            m_sqlManager.closeAll(dbc, conn, stmt, res);
3158        }
3159        return result;
3160    }
3161
3162    /**
3163     * Creates a new project from the current row of the given result set.<p>
3164     *
3165     * @param res the result set
3166     *
3167     * @return the new project
3168     *
3169     * @throws SQLException is something goes wrong
3170     */
3171    protected CmsProject internalCreateProject(ResultSet res) throws SQLException {
3172
3173        String ou = CmsOrganizationalUnit.removeLeadingSeparator(
3174            res.getString(m_sqlManager.readQuery("C_PROJECTS_PROJECT_OU_0")));
3175        return new CmsProject(
3176            new CmsUUID(res.getString(m_sqlManager.readQuery("C_PROJECTS_PROJECT_ID_0"))),
3177            ou + res.getString(m_sqlManager.readQuery("C_PROJECTS_PROJECT_NAME_0")),
3178            res.getString(m_sqlManager.readQuery("C_PROJECTS_PROJECT_DESCRIPTION_0")),
3179            new CmsUUID(res.getString(m_sqlManager.readQuery("C_PROJECTS_USER_ID_0"))),
3180            new CmsUUID(res.getString(m_sqlManager.readQuery("C_PROJECTS_GROUP_ID_0"))),
3181            new CmsUUID(res.getString(m_sqlManager.readQuery("C_PROJECTS_MANAGERGROUP_ID_0"))),
3182            res.getInt(m_sqlManager.readQuery("C_PROJECTS_PROJECT_FLAGS_0")),
3183            res.getLong(m_sqlManager.readQuery("C_PROJECTS_DATE_CREATED_0")),
3184            CmsProject.CmsProjectType.valueOf(res.getInt(m_sqlManager.readQuery("C_PROJECTS_PROJECT_TYPE_0"))));
3185    }
3186
3187    /**
3188     * Builds a publish list from serialized data.<p>
3189     *
3190     * @param bytes the byte array containing the serailized data for the publish list
3191     * @return the initialized publish list
3192     *
3193     * @throws IOException if deserialization fails
3194     * @throws ClassNotFoundException if deserialization fails
3195     */
3196    protected CmsPublishList internalDeserializePublishList(byte[] bytes) throws IOException, ClassNotFoundException {
3197
3198        ByteArrayInputStream bin = new ByteArrayInputStream(bytes);
3199        ObjectInputStream oin = new ObjectInputStream(bin);
3200        return (CmsPublishList)oin.readObject();
3201    }
3202
3203    /**
3204     * Creates a new {@link CmsLogEntry} object from the given result set entry.<p>
3205     *
3206     * @param res the result set
3207     *
3208     * @return the new {@link CmsLogEntry} object
3209     *
3210     * @throws SQLException if something goes wrong
3211     */
3212    protected CmsLogEntry internalReadLogEntry(ResultSet res) throws SQLException {
3213
3214        CmsUUID userId = new CmsUUID(res.getString(m_sqlManager.readQuery("C_LOG_USER_ID")));
3215        long date = res.getLong(m_sqlManager.readQuery("C_LOG_DATE"));
3216        CmsUUID structureId = new CmsUUID(res.getString(m_sqlManager.readQuery("C_LOG_STRUCTURE_ID")));
3217        CmsLogEntryType type = CmsLogEntryType.valueOf(res.getInt(m_sqlManager.readQuery("C_LOG_TYPE")));
3218        String[] data = CmsStringUtil.splitAsArray(res.getString(m_sqlManager.readQuery("C_LOG_DATA")), '|');
3219        return new CmsLogEntry(userId, date, structureId, type, data);
3220    }
3221
3222    /**
3223     * Resets the state to UNCHANGED for a specified resource.<p>
3224     *
3225     * @param dbc the current database context
3226     * @param resource the Cms resource
3227     *
3228     * @throws CmsDataAccessException if something goes wrong
3229     */
3230    protected void internalResetResourceState(CmsDbContext dbc, CmsResource resource) throws CmsDataAccessException {
3231
3232        try {
3233            // reset the resource state
3234            resource.setState(CmsResource.STATE_UNCHANGED);
3235            m_driverManager.getVfsDriver(
3236                dbc).writeResourceState(dbc, dbc.currentProject(), resource, CmsDriverManager.UPDATE_ALL, true);
3237        } catch (CmsDataAccessException e) {
3238            if (LOG.isErrorEnabled()) {
3239                LOG.error(
3240                    Messages.get().getBundle().key(
3241                        Messages.LOG_ERROR_RESETTING_RESOURCE_STATE_1,
3242                        resource.getRootPath()),
3243                    e);
3244            }
3245            throw e;
3246        }
3247    }
3248
3249    /**
3250     * Serialize publish list to write it as byte array to the database.<p>
3251     *
3252     * @param publishList the publish list
3253     * @return byte array containing the publish list data
3254     * @throws IOException if something goes wrong
3255     */
3256    protected byte[] internalSerializePublishList(CmsPublishList publishList) throws IOException {
3257
3258        // serialize the publish list
3259        ByteArrayOutputStream bout = new ByteArrayOutputStream();
3260        ObjectOutputStream oout = new ObjectOutputStream(bout);
3261        oout.writeObject(publishList);
3262        oout.close();
3263        return bout.toByteArray();
3264    }
3265
3266    /**
3267     * Writes the needed history entries.<p>
3268     *
3269     * @param dbc the current database context
3270     * @param resource the offline resource
3271     * @param publishHistoryResource the resource to use for the publish history (if null, uses the value of resource instead)
3272     * @param state the state to store in the publish history entry
3273     * @param properties the offline properties
3274     * @param publishHistoryId the current publish process id
3275     * @param publishTag the current publish process tag
3276     *
3277     * @throws CmsDataAccessException if something goes wrong
3278     */
3279    protected void internalWriteHistory(
3280        CmsDbContext dbc,
3281        CmsResource resource,
3282        CmsResource publishHistoryResource,
3283        CmsResourceState state,
3284        List<CmsProperty> properties,
3285        CmsUUID publishHistoryId,
3286        int publishTag)
3287    throws CmsDataAccessException {
3288
3289        try {
3290            if (OpenCms.getSystemInfo().isHistoryEnabled()) {
3291                // write the resource to the historical archive
3292                if (properties == null) {
3293                    properties = m_driverManager.getVfsDriver(dbc).readPropertyObjects(
3294                        dbc,
3295                        dbc.currentProject(),
3296                        resource);
3297                }
3298                m_driverManager.getHistoryDriver(dbc).writeResource(dbc, resource, properties, publishTag);
3299            }
3300            // write the resource to the publish history
3301            m_driverManager.getProjectDriver(dbc).writePublishHistory(
3302                dbc,
3303                publishHistoryId,
3304                new CmsPublishedResource(
3305                    publishHistoryResource != null ? publishHistoryResource : resource,
3306                    publishTag,
3307                    state));
3308        } catch (CmsDataAccessException e) {
3309            if (LOG.isErrorEnabled()) {
3310                LOG.error(
3311                    Messages.get().getBundle().key(Messages.LOG_WRITING_PUBLISHING_HISTORY_1, resource.getRootPath()),
3312                    e);
3313            }
3314            throw e;
3315        }
3316    }
3317
3318    /**
3319     * Build the whole WHERE SQL statement part for the given log entry filter.<p>
3320     *
3321     * @param filter the filter
3322     *
3323     * @return a pair containing both the SQL and the parameters for it
3324     */
3325    protected CmsPair<String, List<I_CmsPreparedStatementParameter>> prepareLogConditions(CmsLogFilter filter) {
3326
3327        List<I_CmsPreparedStatementParameter> params = new ArrayList<I_CmsPreparedStatementParameter>();
3328        StringBuffer conditions = new StringBuffer();
3329
3330        // user id filter
3331        if (filter.getUserId() != null) {
3332            if (conditions.length() == 0) {
3333                conditions.append(BEGIN_CONDITION);
3334            } else {
3335                conditions.append(BEGIN_INCLUDE_CONDITION);
3336            }
3337            conditions.append(m_sqlManager.readQuery("C_LOG_FILTER_USER_ID"));
3338            params.add(new CmsPreparedStatementStringParameter(filter.getUserId().toString()));
3339            conditions.append(END_CONDITION);
3340        }
3341
3342        // resource id filter
3343        if (filter.getStructureId() != null) {
3344            if (conditions.length() == 0) {
3345                conditions.append(BEGIN_CONDITION);
3346            } else {
3347                conditions.append(BEGIN_INCLUDE_CONDITION);
3348            }
3349            conditions.append(m_sqlManager.readQuery("C_LOG_FILTER_RESOURCE_ID"));
3350            params.add(new CmsPreparedStatementStringParameter(filter.getStructureId().toString()));
3351            conditions.append(END_CONDITION);
3352        }
3353
3354        // date from filter
3355        if (filter.getDateFrom() != CmsResource.DATE_RELEASED_DEFAULT) {
3356            if (conditions.length() == 0) {
3357                conditions.append(BEGIN_CONDITION);
3358            } else {
3359                conditions.append(BEGIN_INCLUDE_CONDITION);
3360            }
3361            conditions.append(m_sqlManager.readQuery("C_LOG_FILTER_DATE_FROM"));
3362            params.add(new CmsPreparedStatementLongParameter(filter.getDateFrom()));
3363            conditions.append(END_CONDITION);
3364        }
3365
3366        // date to filter
3367        if (filter.getDateTo() != CmsResource.DATE_RELEASED_DEFAULT) {
3368            if (conditions.length() == 0) {
3369                conditions.append(BEGIN_CONDITION);
3370            } else {
3371                conditions.append(BEGIN_INCLUDE_CONDITION);
3372            }
3373            conditions.append(m_sqlManager.readQuery("C_LOG_FILTER_DATE_TO"));
3374            params.add(new CmsPreparedStatementLongParameter(filter.getDateTo()));
3375            conditions.append(END_CONDITION);
3376        }
3377
3378        // include type filter
3379        Set<CmsLogEntryType> includeTypes = filter.getIncludeTypes();
3380        if (!includeTypes.isEmpty()) {
3381            if (conditions.length() == 0) {
3382                conditions.append(BEGIN_CONDITION);
3383            } else {
3384                conditions.append(BEGIN_INCLUDE_CONDITION);
3385            }
3386            conditions.append(m_sqlManager.readQuery("C_LOG_FILTER_INCLUDE_TYPE"));
3387            conditions.append(BEGIN_CONDITION);
3388            Iterator<CmsLogEntryType> it = includeTypes.iterator();
3389            while (it.hasNext()) {
3390                CmsLogEntryType type = it.next();
3391                conditions.append("?");
3392                params.add(new CmsPreparedStatementIntParameter(type.getId()));
3393                if (it.hasNext()) {
3394                    conditions.append(", ");
3395                }
3396            }
3397            conditions.append(END_CONDITION);
3398            conditions.append(END_CONDITION);
3399        }
3400
3401        // exclude type filter
3402        Set<CmsLogEntryType> excludeTypes = filter.getExcludeTypes();
3403        if (!excludeTypes.isEmpty()) {
3404            if (conditions.length() == 0) {
3405                conditions.append(BEGIN_CONDITION);
3406            } else {
3407                conditions.append(BEGIN_INCLUDE_CONDITION);
3408            }
3409            conditions.append(m_sqlManager.readQuery("C_LOG_FILTER_EXCLUDE_TYPE"));
3410            conditions.append(BEGIN_CONDITION);
3411            Iterator<CmsLogEntryType> it = excludeTypes.iterator();
3412            while (it.hasNext()) {
3413                CmsLogEntryType type = it.next();
3414                conditions.append("?");
3415                params.add(new CmsPreparedStatementIntParameter(type.getId()));
3416                if (it.hasNext()) {
3417                    conditions.append(", ");
3418                }
3419            }
3420            conditions.append(END_CONDITION);
3421            conditions.append(END_CONDITION);
3422        }
3423        return CmsPair.create(conditions.toString(), params);
3424    }
3425
3426    /**
3427     * Publishes a changed file.<p>
3428     *
3429     * @param dbc the current database context
3430     * @param onlineProject the online project
3431     * @param offlineResource the resource to publish
3432     * @param publishedResourceIds contains the UUIDs of already published content records
3433     * @param publishHistoryId the publish history id
3434     * @param publishTag the publish tag
3435     *
3436     * @throws CmsDataAccessException is something goes wrong
3437     */
3438    protected void publishChangedFile(
3439        CmsDbContext dbc,
3440        CmsProject onlineProject,
3441        CmsResource offlineResource,
3442        Set<CmsUUID> publishedResourceIds,
3443        CmsUUID publishHistoryId,
3444        int publishTag)
3445    throws CmsDataAccessException {
3446
3447        CmsResource onlineResource = null;
3448        boolean needToUpdateContent = true;
3449        boolean existsOnline = m_driverManager.getVfsDriver(dbc).validateStructureIdExists(
3450            dbc,
3451            CmsProject.ONLINE_PROJECT_ID,
3452            offlineResource.getStructureId());
3453        CmsResourceState resourceState = existsOnline
3454        ? fixMovedResource(dbc, onlineProject, offlineResource, publishHistoryId, publishTag)
3455        : offlineResource.getState();
3456        try {
3457            // reset the labeled link flag before writing the online file
3458            int flags = offlineResource.getFlags();
3459            flags &= ~CmsResource.FLAG_LABELED;
3460            offlineResource.setFlags(flags);
3461
3462            if (existsOnline) {
3463                // read the file header online
3464                onlineResource = m_driverManager.getVfsDriver(
3465                    dbc).readResource(dbc, onlineProject.getUuid(), offlineResource.getStructureId(), false);
3466                needToUpdateContent = (onlineResource.getDateContent() < offlineResource.getDateContent());
3467                // delete the properties online
3468                m_driverManager.getVfsDriver(dbc).deletePropertyObjects(
3469                    dbc,
3470                    onlineProject.getUuid(),
3471                    onlineResource,
3472                    CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES);
3473
3474                // if the offline file has a resource ID different from the online file
3475                // (probably because a deleted file was replaced by a new file with the
3476                // same name), the properties mapped to the "old" resource ID have to be
3477                // deleted also offline. if this is the case, the online and offline structure
3478                // ID's do match, but the resource ID's are different. structure IDs are reused
3479                // to prevent orphan structure records in the online project.
3480
3481                // Addendum (2023): It shouldn't be possible for resources to be in this state anymore,
3482                // since creating new resources over deleted ones isn't really possible anymore,
3483                // but apparently it can still happen, though I can't reproduce it.
3484                if (!onlineResource.getResourceId().equals(offlineResource.getResourceId())) {
3485                    List<CmsProperty> offlineProperties = m_driverManager.getVfsDriver(dbc).readPropertyObjects(
3486                        dbc,
3487                        dbc.currentProject(),
3488                        onlineResource);
3489                    if (offlineProperties.size() > 0) {
3490                        List<CmsProperty> newProperties = new ArrayList<>();
3491                        for (int i = 0; i < offlineProperties.size(); i++) {
3492                            CmsProperty oldProperty = offlineProperties.get(i);
3493                            // property may be frozen (non-modifiable), so create a new one
3494                            CmsProperty newProperty = new CmsProperty(
3495                                oldProperty.getName(),
3496                                null,
3497                                CmsProperty.DELETE_VALUE);
3498                            newProperties.add(newProperty);
3499                        }
3500                        m_driverManager.getVfsDriver(
3501                            dbc).writePropertyObjects(dbc, dbc.currentProject(), onlineResource, newProperties);
3502                    }
3503                }
3504            }
3505        } catch (CmsDataAccessException e) {
3506            if (LOG.isErrorEnabled()) {
3507                LOG.error(
3508                    Messages.get().getBundle().key(Messages.LOG_DELETING_PROPERTIES_1, offlineResource.toString()),
3509                    e);
3510            }
3511            throw e;
3512        }
3513
3514        CmsFile newFile;
3515        try {
3516            // publish the file content
3517            newFile = m_driverManager.getProjectDriver(dbc).publishFileContent(
3518                dbc,
3519                dbc.currentProject(),
3520                onlineProject,
3521                offlineResource,
3522                publishedResourceIds,
3523                needToUpdateContent,
3524                publishTag);
3525
3526        } catch (CmsDataAccessException e) {
3527            if (LOG.isErrorEnabled()) {
3528                LOG.error(
3529                    Messages.get().getBundle().key(Messages.LOG_PUBLISHING_RESOURCE_1, offlineResource.getRootPath()),
3530                    e);
3531            }
3532            throw e;
3533        }
3534
3535        List<CmsProperty> offlineProperties;
3536        try {
3537            // write the properties online
3538            offlineProperties = m_driverManager.getVfsDriver(dbc).readPropertyObjects(
3539                dbc,
3540                dbc.currentProject(),
3541                offlineResource);
3542            CmsProperty.setAutoCreatePropertyDefinitions(offlineProperties, true);
3543            m_driverManager.getVfsDriver(dbc).writePropertyObjects(dbc, onlineProject, newFile, offlineProperties);
3544        } catch (CmsDataAccessException e) {
3545            if (LOG.isErrorEnabled()) {
3546                LOG.error(
3547                    Messages.get().getBundle().key(Messages.LOG_PUBLISHING_PROPERTIES_1, newFile.getRootPath()),
3548                    e);
3549            }
3550            throw e;
3551        }
3552
3553        try {
3554            // write the ACL online
3555            m_driverManager.getUserDriver(dbc).publishAccessControlEntries(
3556                dbc,
3557                dbc.currentProject(),
3558                onlineProject,
3559                newFile.getResourceId(),
3560                offlineResource.getResourceId());
3561        } catch (CmsDataAccessException e) {
3562            if (LOG.isErrorEnabled()) {
3563                LOG.error(Messages.get().getBundle().key(Messages.LOG_PUBLISHING_ACL_1, newFile.getRootPath()), e);
3564            }
3565            throw e;
3566        }
3567
3568        CmsFile offlineFile = new CmsFile(offlineResource);
3569        offlineFile.setContents(newFile.getContents());
3570        internalWriteHistory(dbc, offlineFile, null, resourceState, offlineProperties, publishHistoryId, publishTag);
3571
3572        m_driverManager.getVfsDriver(dbc).updateRelations(dbc, onlineProject, offlineResource);
3573    }
3574
3575    /**
3576     * Publishes a deleted file.<p>
3577     *
3578     * @param dbc the current database context
3579     * @param onlineProject the online project
3580     * @param offlineResource the resource to publish
3581     * @param publishHistoryId the publish history id
3582     * @param publishTag the publish tag
3583     *
3584     * @throws CmsDataAccessException is something goes wrong
3585     */
3586    protected void publishDeletedFile(
3587        CmsDbContext dbc,
3588        CmsProject onlineProject,
3589        CmsResource offlineResource,
3590        CmsUUID publishHistoryId,
3591        int publishTag)
3592    throws CmsDataAccessException {
3593
3594        CmsResourceState resourceState = fixMovedResource(
3595            dbc,
3596            onlineProject,
3597            offlineResource,
3598            publishHistoryId,
3599            publishTag);
3600
3601        boolean existsOnline = m_driverManager.getVfsDriver(dbc).validateStructureIdExists(
3602            dbc,
3603            CmsProject.ONLINE_PROJECT_ID,
3604            offlineResource.getStructureId());
3605        CmsResource onlineResource = null;
3606        if (existsOnline) {
3607            try {
3608                // read the file header online
3609                onlineResource = m_driverManager.getVfsDriver(
3610                    dbc).readResource(dbc, onlineProject.getUuid(), offlineResource.getStructureId(), true);
3611            } catch (CmsDataAccessException e) {
3612                if (LOG.isErrorEnabled()) {
3613                    LOG.error(
3614                        Messages.get().getBundle().key(Messages.LOG_READING_RESOURCE_1, offlineResource.getRootPath()),
3615                        e);
3616                }
3617                throw e;
3618            }
3619        }
3620        if (offlineResource.isLabeled() && !m_driverManager.labelResource(dbc, offlineResource, null, 2)) {
3621            // update the resource flags to "unlabeled" of the siblings of the offline resource
3622            int flags = offlineResource.getFlags();
3623            flags &= ~CmsResource.FLAG_LABELED;
3624            offlineResource.setFlags(flags);
3625        }
3626
3627        // write history before deleting
3628        CmsFile offlineFile = new CmsFile(offlineResource);
3629        offlineFile.setContents(
3630            m_driverManager.getVfsDriver(dbc).readContent(
3631                dbc,
3632                dbc.currentProject().getUuid(),
3633                offlineFile.getResourceId()));
3634        internalWriteHistory(dbc, offlineFile, null, resourceState, null, publishHistoryId, publishTag);
3635
3636        int propertyDeleteOption = -1;
3637        try {
3638            // delete the properties online and offline
3639            if (offlineResource.getSiblingCount() > 1) {
3640                // there are other siblings- delete only structure property values and keep the resource property values
3641                propertyDeleteOption = CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_VALUES;
3642            } else {
3643                // there are no other siblings- delete both the structure and resource property values
3644                propertyDeleteOption = CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES;
3645            }
3646
3647            if (existsOnline) {
3648                m_driverManager.getVfsDriver(
3649                    dbc).deletePropertyObjects(dbc, onlineProject.getUuid(), onlineResource, propertyDeleteOption);
3650            }
3651            m_driverManager.getVfsDriver(
3652                dbc).deletePropertyObjects(dbc, dbc.currentProject().getUuid(), offlineResource, propertyDeleteOption);
3653
3654            // if the offline file has a resource ID different from the online file
3655            // (probably because a (deleted) file was replaced by a new file with the
3656            // same name), the properties with the "old" resource ID have to be
3657            // deleted also offline
3658            if (existsOnline
3659                && (onlineResource != null)
3660                && !onlineResource.getResourceId().equals(offlineResource.getResourceId())) {
3661                m_driverManager.getVfsDriver(dbc).deletePropertyObjects(
3662                    dbc,
3663                    dbc.currentProject().getUuid(),
3664                    onlineResource,
3665                    CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES);
3666            }
3667        } catch (CmsDataAccessException e) {
3668            if (LOG.isErrorEnabled()) {
3669                LOG.error(
3670                    Messages.get().getBundle().key(Messages.LOG_DELETING_PROPERTIES_1, offlineResource.getRootPath()),
3671                    e);
3672            }
3673            throw e;
3674        }
3675
3676        try {
3677            // remove the file online and offline
3678            m_driverManager.getVfsDriver(dbc).removeFile(dbc, dbc.currentProject().getUuid(), offlineResource);
3679            if (existsOnline && (onlineResource != null)) {
3680                m_driverManager.getVfsDriver(dbc).removeFile(dbc, onlineProject.getUuid(), onlineResource);
3681            }
3682        } catch (CmsDataAccessException e) {
3683            if (LOG.isErrorEnabled()) {
3684                LOG.error(
3685                    Messages.get().getBundle().key(Messages.LOG_REMOVING_RESOURCE_1, offlineResource.getRootPath()),
3686                    e);
3687            }
3688            throw e;
3689        }
3690
3691        // delete the ACL online and offline
3692        try {
3693            if (existsOnline && (onlineResource != null) && (onlineResource.getSiblingCount() == 1)) {
3694                // only if no siblings left
3695                m_driverManager.getUserDriver(dbc).removeAccessControlEntries(
3696                    dbc,
3697                    onlineProject,
3698                    onlineResource.getResourceId());
3699            }
3700            if (offlineResource.getSiblingCount() == 1) {
3701                // only if no siblings left
3702                m_driverManager.getUserDriver(dbc).removeAccessControlEntries(
3703                    dbc,
3704                    dbc.currentProject(),
3705                    offlineResource.getResourceId());
3706            }
3707        } catch (CmsDataAccessException e) {
3708            if (LOG.isErrorEnabled()) {
3709                LOG.error(Messages.get().getBundle().key(Messages.LOG_REMOVING_ACL_1, offlineResource.toString()), e);
3710            }
3711            throw e;
3712        }
3713
3714        try {
3715            // delete relations online and offline
3716            m_driverManager.getVfsDriver(
3717                dbc).deleteRelations(dbc, onlineProject.getUuid(), offlineResource, CmsRelationFilter.TARGETS);
3718            m_driverManager.getVfsDriver(
3719                dbc).deleteRelations(dbc, dbc.currentProject().getUuid(), offlineResource, CmsRelationFilter.TARGETS);
3720        } catch (CmsDataAccessException e) {
3721            if (LOG.isErrorEnabled()) {
3722                LOG.error(
3723                    Messages.get().getBundle().key(Messages.LOG_REMOVING_RELATIONS_1, offlineResource.toString()),
3724                    e);
3725            }
3726            throw e;
3727        }
3728
3729        if (OpenCms.getSubscriptionManager().isEnabled()) {
3730            try {
3731                // delete visited information for resource from log
3732                CmsVisitEntryFilter filter = CmsVisitEntryFilter.ALL.filterResource(offlineResource.getStructureId());
3733                m_driverManager.getSubscriptionDriver().deleteVisits(
3734                    dbc,
3735                    OpenCms.getSubscriptionManager().getPoolName(),
3736                    filter);
3737            } catch (CmsDataAccessException e) {
3738                if (LOG.isErrorEnabled()) {
3739                    LOG.error(
3740                        Messages.get().getBundle().key(Messages.LOG_REMOVING_VISITEDLOG_1, offlineResource.toString()),
3741                        e);
3742                }
3743                throw e;
3744            }
3745
3746            try {
3747                // mark the subscribed resource as deleted
3748                /* changed to subscription driver */
3749                //                m_driverManager.getUserDriver(dbc).setSubscribedResourceAsDeleted(
3750                //                    dbc,
3751                //                    OpenCms.getSubscriptionManager().getPoolName(),
3752                //                    offlineResource);
3753                m_driverManager.getSubscriptionDriver().setSubscribedResourceAsDeleted(
3754                    dbc,
3755                    OpenCms.getSubscriptionManager().getPoolName(),
3756                    offlineResource);
3757            } catch (CmsDataAccessException e) {
3758                if (LOG.isErrorEnabled()) {
3759                    LOG.error(
3760                        Messages.get().getBundle().key(
3761                            Messages.LOG_REMOVING_SUBSCRIPTIONS_1,
3762                            offlineResource.toString()),
3763                        e);
3764                }
3765                throw e;
3766            }
3767        }
3768    }
3769
3770    /**
3771     * Publishes a new file.<p>
3772     *
3773     * @param dbc the current database context
3774     * @param onlineProject the online project
3775     * @param offlineResource the resource to publish
3776     * @param publishedContentIds contains the UUIDs of already published content records
3777     * @param publishHistoryId the publish history id
3778     * @param publishTag the publish tag
3779     *
3780     * @throws CmsDataAccessException is something goes wrong
3781     */
3782    protected void publishNewFile(
3783        CmsDbContext dbc,
3784        CmsProject onlineProject,
3785        CmsResource offlineResource,
3786        Set<CmsUUID> publishedContentIds,
3787        CmsUUID publishHistoryId,
3788        int publishTag)
3789    throws CmsDataAccessException {
3790
3791        CmsResourceState resourceState = fixMovedResource(
3792            dbc,
3793            onlineProject,
3794            offlineResource,
3795            publishHistoryId,
3796            publishTag);
3797
3798        CmsFile newFile;
3799        try {
3800            // reset the labeled link flag before writing the online file
3801            int flags = offlineResource.getFlags();
3802            flags &= ~CmsResource.FLAG_LABELED;
3803            offlineResource.setFlags(flags);
3804
3805            // publish the file content
3806            newFile = m_driverManager.getProjectDriver(dbc).publishFileContent(
3807                dbc,
3808                dbc.currentProject(),
3809                onlineProject,
3810                offlineResource,
3811                publishedContentIds,
3812                true,
3813                publishTag);
3814
3815        } catch (CmsVfsResourceAlreadyExistsException e) {
3816            try {
3817                // remove the existing file and ensure that it's content is written
3818                // in any case by removing it's resource ID from the set of published resource IDs
3819                m_driverManager.getVfsDriver(dbc).removeFile(dbc, onlineProject.getUuid(), offlineResource);
3820                publishedContentIds.remove(offlineResource.getResourceId());
3821                newFile = m_driverManager.getProjectDriver(dbc).publishFileContent(
3822                    dbc,
3823                    dbc.currentProject(),
3824                    onlineProject,
3825                    offlineResource,
3826                    publishedContentIds,
3827                    true,
3828                    publishTag);
3829
3830            } catch (CmsDataAccessException e1) {
3831                if (LOG.isErrorEnabled()) {
3832                    LOG.error(
3833                        Messages.get().getBundle().key(
3834                            Messages.LOG_PUBLISHING_RESOURCE_1,
3835                            offlineResource.getRootPath()),
3836                        e);
3837                }
3838                throw e1;
3839            }
3840        } catch (CmsDataAccessException e) {
3841            if (LOG.isErrorEnabled()) {
3842                LOG.error(
3843                    Messages.get().getBundle().key(Messages.LOG_PUBLISHING_RESOURCE_1, offlineResource.getRootPath()),
3844                    e);
3845            }
3846            throw e;
3847        }
3848
3849        List<CmsProperty> offlineProperties;
3850        try {
3851            // write the properties online
3852            offlineProperties = m_driverManager.getVfsDriver(dbc).readPropertyObjects(
3853                dbc,
3854                dbc.currentProject(),
3855                offlineResource);
3856            CmsProperty.setAutoCreatePropertyDefinitions(offlineProperties, true);
3857            m_driverManager.getVfsDriver(dbc).writePropertyObjects(dbc, onlineProject, newFile, offlineProperties);
3858        } catch (CmsDataAccessException e) {
3859            if (LOG.isErrorEnabled()) {
3860                LOG.error(
3861                    Messages.get().getBundle().key(Messages.LOG_PUBLISHING_PROPERTIES_1, newFile.getRootPath()),
3862                    e);
3863            }
3864
3865            throw e;
3866        }
3867
3868        try {
3869            // write the ACL online
3870            m_driverManager.getUserDriver(dbc).publishAccessControlEntries(
3871                dbc,
3872                dbc.currentProject(),
3873                onlineProject,
3874                offlineResource.getResourceId(),
3875                newFile.getResourceId());
3876        } catch (CmsDataAccessException e) {
3877            if (LOG.isErrorEnabled()) {
3878                LOG.error(Messages.get().getBundle().key(Messages.LOG_PUBLISHING_ACL_1, newFile.getRootPath()), e);
3879            }
3880            throw e;
3881        }
3882
3883        CmsFile offlineFile = new CmsFile(offlineResource);
3884        offlineFile.setContents(newFile.getContents());
3885        internalWriteHistory(dbc, offlineFile, null, resourceState, offlineProperties, publishHistoryId, publishTag);
3886
3887        m_driverManager.getVfsDriver(dbc).updateRelations(dbc, onlineProject, offlineResource);
3888    }
3889
3890}