cmspublishengine.java

来自「找了很久才找到到源代码」· Java 代码 · 共 773 行 · 第 1/2 页

JAVA
773
字号
/*
 * File   : $Source: /usr/local/cvs/opencms/src/org/opencms/publish/CmsPublishEngine.java,v $
 * Date   : $Date: 2007-08-24 08:39:07 $
 * Version: $Revision: 1.6 $
 *
 * This library is part of OpenCms -
 * the Open Source Content Management System
 *
 * Copyright (c) 2002 - 2007 Alkacon Software GmbH (http://www.alkacon.com)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * For further information about Alkacon Software GmbH, please see the
 * company website: http://www.alkacon.com
 *
 * For further information about OpenCms, please see the
 * project website: http://www.opencms.org
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package org.opencms.publish;

import org.opencms.db.CmsDbContext;
import org.opencms.db.CmsDriverManager;
import org.opencms.db.CmsPublishList;
import org.opencms.db.CmsUserSettings;
import org.opencms.db.I_CmsDbContextFactory;
import org.opencms.file.CmsObject;
import org.opencms.file.CmsResource;
import org.opencms.file.CmsUser;
import org.opencms.lock.CmsLockType;
import org.opencms.main.CmsEvent;
import org.opencms.main.CmsException;
import org.opencms.main.CmsInitException;
import org.opencms.main.CmsLog;
import org.opencms.main.I_CmsEventListener;
import org.opencms.main.OpenCms;
import org.opencms.report.I_CmsReport;
import org.opencms.security.CmsAuthentificationException;
import org.opencms.security.CmsRole;
import org.opencms.util.CmsUUID;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;

/**
 * This class is responsible for the publish process.<p>
 * 
 * @author Michael Moossen
 * 
 * @version $Revision: 1.6 $
 * 
 * @since 6.5.5
 */
public final class CmsPublishEngine implements Runnable {

    /** The log object for this class. */
    private static final Log LOG = CmsLog.getLog(CmsPublishEngine.class);

    /** The id of the admin user. */
    private CmsUUID m_adminUserId;

    /** The current running publish job. */
    private CmsPublishThread m_currentPublishThread;

    /** The runtime info factory used during publishing. */
    private final I_CmsDbContextFactory m_dbContextFactory;

    /** The driver manager instance. */
    private CmsDriverManager m_driverManager;

    /** The engine state. */
    private CmsPublishEngineState m_engineState;

    /** The publish listeners. */
    private final CmsPublishListenerCollection m_listeners;

    /** The publish history list with already publish job. */
    private final CmsPublishHistory m_publishHistory;

    /** The queue with still waiting publish job. */
    private final CmsPublishQueue m_publishQueue;

    /** The amount of time the system will wait for a running publish job during shutdown. */
    private int m_publishQueueShutdowntime;

    /** Is set during shutdown. */
    private boolean m_shuttingDown;

    /**
     * Default constructor.<p>
     * 
     * @param dbContextFactory the initialized OpenCms runtime info factory
     * 
     * @throws CmsInitException if the configured path to store the publish reports is not accessible 
     */
    public CmsPublishEngine(I_CmsDbContextFactory dbContextFactory)
    throws CmsInitException {

        if (OpenCms.getRunLevel() > OpenCms.RUNLEVEL_2_INITIALIZING) {
            // OpenCms is already initialized
            throw new CmsInitException(org.opencms.main.Messages.get().container(
                org.opencms.main.Messages.ERR_ALREADY_INITIALIZED_0));
        }
        if (dbContextFactory == null) {
            throw new CmsInitException(org.opencms.main.Messages.get().container(
                org.opencms.main.Messages.ERR_CRITICAL_NO_DB_CONTEXT_0));
        }
        // initialize the db context factory
        m_dbContextFactory = dbContextFactory;
        // initialize publish queue
        m_publishQueue = new CmsPublishQueue(this);
        // initialize publish history
        m_publishHistory = new CmsPublishHistory(this);
        // initialize event handling
        m_listeners = new CmsPublishListenerCollection(this);
        // set engine state to normal processing
        m_engineState = CmsPublishEngineState.ENGINE_STARTED;
        if (CmsLog.INIT.isInfoEnabled()) {
            CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_PUBLISH_ENGINE_READY_0));
        }
    }

    /**
     * Enqueues a new publish job with the given information in publish queue.<p>
     * 
     * All resources should already be locked.<p>
     * 
     * If possible, the publish job starts immediately.<p>
     * 
     * @param cms the cms context to publish for
     * @param publishList the resources to publish
     * @param report the report to write to
     * 
     * @throws CmsException if something goes wrong while cloning the cms context  
     */
    public synchronized void enqueuePublishJob(CmsObject cms, CmsPublishList publishList, I_CmsReport report)
    throws CmsException {

        // check the driver manager
        if (m_driverManager == null || m_dbContextFactory == null) {
            // the resources are unlocked in the driver manager
            throw new CmsPublishException(Messages.get().container(Messages.ERR_PUBLISH_ENGINE_NOT_INITIALIZED_0));
        }
        // prevent new jobs if the engine is disabled
        if (m_shuttingDown || (!isEnabled() && !OpenCms.getRoleManager().hasRole(cms, CmsRole.ROOT_ADMIN))) {
            // the resources are unlocked in the driver manager
            throw new CmsPublishException(Messages.get().container(Messages.ERR_PUBLISH_ENGINE_DISABLED_0));
        }

        // get the state before enqueuing the job
        boolean isRunning = isRunning();
        // create the publish job
        CmsPublishJobInfoBean publishJob = new CmsPublishJobInfoBean(cms, publishList, report);
        // enqueue it and 
        m_publishQueue.add(publishJob);
        // notify all listeners
        m_listeners.fireEnqueued(new CmsPublishJobBase(publishJob));
        // start publish job immediately if possible
        if (!isRunning) {
            run();
        }
    }

    /**
     * Returns a publish job based on its publish history id.<p>
     * 
     * The returned publish job may be an enqueued, running or finished publish job.<p>
     * 
     * @param publishHistoryId the publish history id to search for
     * 
     * @return the publish job with the given publish history id, or <code>null</code>
     */
    public synchronized CmsPublishJobBase getJobByPublishHistoryId(CmsUUID publishHistoryId) {

        // try current running job
        if ((m_currentPublishThread != null)
            && m_currentPublishThread.getPublishJob().getPublishHistoryId().equals(publishHistoryId)) {
            return new CmsPublishJobRunning(m_currentPublishThread.getPublishJob());
        }
        // try enqueued jobs
        Iterator itEnqueuedJobs = getPublishQueue().asList().iterator();
        while (itEnqueuedJobs.hasNext()) {
            CmsPublishJobEnqueued enqueuedJob = (CmsPublishJobEnqueued)itEnqueuedJobs.next();
            if (enqueuedJob.getPublishList().getPublishHistoryId().equals(publishHistoryId)) {
                return enqueuedJob;
            }
        }
        // try finished jobs
        Iterator itFinishedJobs = getPublishHistory().asList().iterator();
        while (itFinishedJobs.hasNext()) {
            CmsPublishJobFinished finishedJob = (CmsPublishJobFinished)itFinishedJobs.next();
            if (finishedJob.getPublishHistoryId().equals(publishHistoryId)) {
                return finishedJob;
            }
        }
        return null;
    }

    /**
     * Controls the publish process.<p>
     */
    public synchronized void run() {

        try {
            try {
                // give the finishing publish thread enough time to clean up
                wait(200);
            } catch (InterruptedException e) {
                // ignore
            }

            // create a publish thread only if engine is started
            if (m_engineState != CmsPublishEngineState.ENGINE_STARTED) {
                return;
            }

            if (LOG.isDebugEnabled()) {
                LOG.debug(Messages.get().getBundle().key(Messages.LOG_PUBLISH_ENGINE_RUNNING_0));
            }

            // check the driver manager
            if ((m_driverManager == null) || (m_dbContextFactory == null)) {
                LOG.error(Messages.get().getBundle().key(Messages.ERR_PUBLISH_ENGINE_NOT_INITIALIZED_0));
                // without these there is nothing we can do
                return;
            }

            // there is no running publish job
            if (m_currentPublishThread == null) {
                // but something is waiting in the queue
                if (!m_publishQueue.isEmpty()) {
                    // start the next waiting publish job
                    CmsPublishJobInfoBean publishJob = m_publishQueue.next();
                    m_currentPublishThread = new CmsPublishThread(this, publishJob);
                    m_currentPublishThread.start();
                } else {
                    // nothing to do
                    if (LOG.isDebugEnabled()) {
                        LOG.debug(Messages.get().getBundle().key(Messages.LOG_PUBLISH_ENGINE_NO_RUNNING_JOB_0));
                    }
                }
                return;
            }
            // there is a still running publish job
            if (m_currentPublishThread.isAlive()) {

                // thread was interrupted (by the grim reaper)
                if (m_currentPublishThread.isInterrupted()) {

                    if (LOG.isDebugEnabled()) {
                        LOG.debug(Messages.get().getBundle().key(Messages.LOG_PUBLISH_ENGINE_INTERRUPTED_JOB_0));
                    }

                    // unlock publish list
                    try {
                        unlockPublishList(m_currentPublishThread.getPublishJob());
                    } catch (CmsException exc) {
                        LOG.error(exc.getLocalizedMessage(), exc);
                    }

                    // throw it away
                    m_currentPublishThread = null;

                    // and try again
                    run();
                } else {

                    // wait until it is finished
                    if (LOG.isDebugEnabled()) {
                        LOG.debug(Messages.get().getBundle().key(Messages.LOG_PUBLISH_ENGINE_WAITING_0));
                    }
                }
            } else {
                // why is it still set??
                if (LOG.isDebugEnabled()) {
                    LOG.debug(Messages.get().getBundle().key(Messages.LOG_PUBLISH_ENGINE_DEAD_JOB_0));
                }
                // just throw it away
                m_currentPublishThread = null;
                // and try again
                run();
            }
        } catch (Throwable e) {
            // catch every thing including runtime exceptions
            LOG.error(Messages.get().getBundle().key(Messages.ERR_PUBLISH_ENGINE_ERROR_0), e);
        }
    }

    /**
     * Sets the driver manager instance.<p>
     * 
     * @param driverManager the driver manager instance
     */
    public synchronized void setDriverManager(CmsDriverManager driverManager) {

        m_driverManager = driverManager;
        CmsDbContext dbc = m_dbContextFactory.getDbContext();
        try {
            m_adminUserId = m_driverManager.readUser(dbc, OpenCms.getDefaultUsers().getUserAdmin()).getId();
        } catch (CmsException e) {
            LOG.error(e.getLocalizedMessage(), e);
        } finally {
            dbc.clear();
        }
    }

    /**
     * Shuts down all this static export manager.<p>
     * NOTE: this method may or may NOT be called (i.e. killall in the stop script), if a system is stopped !
     * 
     * This is required since there may still be a thread running when the system is being shut down.<p>
     */
    public synchronized void shutDown() {

        if (CmsLog.INIT.isInfoEnabled()) {
            CmsLog.INIT.info(org.opencms.main.Messages.get().getBundle().key(
                org.opencms.main.Messages.INIT_SHUTDOWN_START_1,
                this.getClass().getName()));
        }

        // prevent new publish jobs are accepted
        m_shuttingDown = true;

        // if a job is currently running, 
        // wait the specified amount of time,
        // then write an abort message to the report
        if (m_currentPublishThread != null) {

            // if a shutdown time is defined, wait  if a publish process is running
            if (m_publishQueueShutdowntime > 0) {
                synchronized (this) {
                    try {
                        wait(m_publishQueueShutdowntime * 1000);
                    } catch (InterruptedException exc) {
                        // ignore
                    }
                }
            }

            CmsPublishJobInfoBean publishJob = m_currentPublishThread.getPublishJob();
            m_listeners.fireAbort(m_adminUserId, new CmsPublishJobEnqueued(publishJob));
            I_CmsReport report = m_currentPublishThread.getReport();
            report.println();
            report.println();
            report.println(
                Messages.get().container(Messages.RPT_PUBLISH_JOB_ABORT_SHUTDOWN_0),
                I_CmsReport.FORMAT_ERROR);
            report.println();

            try {
                // write report to db
                m_driverManager.writePublishReport(m_dbContextFactory.getDbContext(), publishJob);
            } catch (CmsException exc) {
                if (LOG.isErrorEnabled()) {
                    LOG.error(exc.getLocalizedMessage(), exc);
                }
            }
        }
        if (CmsLog.INIT.isInfoEnabled()) {
            CmsLog.INIT.info(org.opencms.staticexport.Messages.get().getBundle().key(
                org.opencms.staticexport.Messages.INIT_SHUTDOWN_1,
                this.getClass().getName()));
        }
    }

    /**
     * Aborts the given publish job.<p>
     * 
     * @param userId the id of user that wants to abort the given publish job 
     * @param publishJob the publish job to abort
     * @param removeJob indicates if the job will be removed or added to history

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?