001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://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: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://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.publish;
029
030import org.opencms.db.CmsDbContext;
031import org.opencms.db.CmsDriverManager;
032import org.opencms.db.generic.CmsPublishHistoryCleanupFilter;
033import org.opencms.main.CmsException;
034import org.opencms.main.CmsLog;
035import org.opencms.main.OpenCms;
036import org.opencms.monitor.CmsMemoryMonitor;
037
038import java.util.ArrayList;
039import java.util.Collections;
040import java.util.Iterator;
041import java.util.List;
042
043import org.apache.commons.collections.Buffer;
044import org.apache.commons.collections.BufferUtils;
045import org.apache.commons.collections.buffer.CircularFifoBuffer;
046import org.apache.commons.collections.buffer.TypedBuffer;
047import org.apache.commons.logging.Log;
048
049/**
050 * List of already finished publish jobs.<p>
051 *
052 * @since 6.5.5
053 */
054public class CmsPublishHistory {
055
056    /** The log object for this class. */
057    protected static final Log LOG = CmsLog.getLog(CmsPublishHistory.class);
058
059    /** The publish engine. */
060    protected final CmsPublishEngine m_publishEngine;
061
062    /**
063     * Default constructor.<p>
064     *
065     * @param publishEngine the publish engine instance
066     */
067    protected CmsPublishHistory(final CmsPublishEngine publishEngine) {
068
069        m_publishEngine = publishEngine;
070    }
071
072    /**
073     * Returns (and initializes) the queue.<p>
074     *
075     * @param size the history size
076     *
077     * @return the queue buffer
078     */
079    public static Buffer getQueue(int size) {
080
081        if (CmsLog.INIT.isInfoEnabled()) {
082            CmsLog.INIT.info(
083                Messages.get().getBundle().key(Messages.INIT_PUBLISH_HISTORY_SIZE_SET_1, Integer.valueOf(size)));
084        }
085
086        return BufferUtils.synchronizedBuffer(TypedBuffer.decorate(new CircularFifoBuffer(size) {
087
088            /** The serialization version id constant. */
089            private static final long serialVersionUID = -6257542123241183114L;
090
091            /**
092             * Called when the queue is full to remove the oldest element.<p>
093             *
094             * @see org.apache.commons.collections.buffer.BoundedFifoBuffer#remove()
095             */
096            @Override
097            public Object remove() {
098
099                CmsPublishJobInfoBean publishJob = (CmsPublishJobInfoBean)super.remove();
100                try {
101                    OpenCms.getPublishManager().getEngine().getPublishHistory().remove(publishJob);
102                } catch (CmsException exc) {
103                    if (LOG.isErrorEnabled()) {
104                        LOG.error(exc.getLocalizedMessage(), exc);
105                    }
106                }
107                return publishJob;
108            }
109        }, CmsPublishJobInfoBean.class));
110    }
111
112    /**
113     * Adds the given publish job to the list.<p>
114     *
115     * @param publishJob the publish job object to add
116     *
117     * @throws CmsException if something goes wrong
118     */
119    protected void add(CmsPublishJobInfoBean publishJob) throws CmsException {
120
121        OpenCms.getMemoryMonitor().cachePublishJobInHistory(publishJob);
122        // write job to db if necessary
123        if (OpenCms.getMemoryMonitor().requiresPersistency()) {
124            CmsDbContext dbc = m_publishEngine.getDbContext(null);
125            try {
126                m_publishEngine.getDriverManager().writePublishJob(dbc, publishJob);
127                // additionally, write the publish report
128                m_publishEngine.getDriverManager().writePublishReport(dbc, publishJob);
129                // delete publish list of started job
130                m_publishEngine.getDriverManager().deletePublishList(dbc, publishJob.getPublishHistoryId());
131            } catch (CmsException e) {
132                dbc.rollback();
133                LOG.error(e.getLocalizedMessage(), e);
134                throw e;
135            } finally {
136                dbc.clear();
137            }
138        }
139    }
140
141    /**
142     * Returns an unmodifiable list representation of this list.<p>
143     *
144     * @return a list of {@link CmsPublishJobFinished} objects
145     */
146    protected List<CmsPublishJobFinished> asList() {
147
148        List<CmsPublishJobInfoBean> cachedPublishJobs = OpenCms.getMemoryMonitor().getAllCachedPublishJobsInHistory();
149        List<CmsPublishJobFinished> result = new ArrayList<CmsPublishJobFinished>(cachedPublishJobs.size());
150        Iterator<CmsPublishJobInfoBean> it = cachedPublishJobs.iterator();
151        while (it.hasNext()) {
152            CmsPublishJobInfoBean publishJob = it.next();
153            result.add(new CmsPublishJobFinished(publishJob));
154        }
155        return Collections.unmodifiableList(result);
156    }
157
158    /**
159     * Initializes the internal FIFO queue with publish jobs from the database.<p>
160     */
161    protected void initialize() {
162
163        CmsDriverManager driverManager = m_publishEngine.getDriverManager();
164        CmsDbContext dbc = m_publishEngine.getDbContext(null);
165
166        try {
167            OpenCms.getMemoryMonitor().flushCache(CmsMemoryMonitor.CacheType.PUBLISH_HISTORY);
168            // read all finished published jobs from the database
169            List<CmsPublishJobInfoBean> publishJobs = driverManager.readPublishJobs(dbc, 1L, Long.MAX_VALUE);
170            for (Iterator<CmsPublishJobInfoBean> i = publishJobs.iterator(); i.hasNext();) {
171                CmsPublishJobInfoBean job = i.next();
172                OpenCms.getMemoryMonitor().cachePublishJobInHistory(job);
173            }
174        } catch (CmsException exc) {
175            dbc.rollback();
176            if (LOG.isErrorEnabled()) {
177                LOG.error(exc.getLocalizedMessage(), exc);
178            }
179        } finally {
180            dbc.clear();
181        }
182    }
183
184    /**
185     * Removes the given job from the list.<p>
186     *
187     * @param publishJob the publish job to remove
188     *
189     * @throws CmsException if something goes wrong
190     */
191    protected void remove(CmsPublishJobInfoBean publishJob) throws CmsException {
192
193        OpenCms.getMemoryMonitor().uncachePublishJobInHistory(publishJob);
194        // delete job from db if necessary
195        if (OpenCms.getMemoryMonitor().requiresPersistency()) {
196            CmsDbContext dbc = m_publishEngine.getDbContext(null);
197            try {
198                OpenCms.getPublishManager().getEngine().getDriverManager().deletePublishJob(
199                    dbc,
200                    publishJob.getPublishHistoryId());
201                if (OpenCms.getPublishManager().isAutoCleanupHistoryEntries()) {
202                    OpenCms.getPublishManager().getEngine().getDriverManager().cleanupPublishHistory(
203                        dbc,
204                        CmsPublishHistoryCleanupFilter.forHistoryId(publishJob.getPublishHistoryId()));
205                }
206            } catch (CmsException e) {
207                dbc.rollback();
208                LOG.error(e.getLocalizedMessage(), e);
209                throw e;
210            } finally {
211                dbc.clear();
212            }
213        }
214
215        m_publishEngine.publishJobRemoved(publishJob);
216    }
217}