001: /*
002: * File : $Source: /usr/local/cvs/opencms/src/org/opencms/publish/CmsPublishEngine.java,v $
003: * Date : $Date: 2008-02-27 12:05:27 $
004: * Version: $Revision: 1.10 $
005: *
006: * This library is part of OpenCms -
007: * the Open Source Content Management System
008: *
009: * Copyright (c) 2002 - 2008 Alkacon Software GmbH (http://www.alkacon.com)
010: *
011: * This library is free software; you can redistribute it and/or
012: * modify it under the terms of the GNU Lesser General Public
013: * License as published by the Free Software Foundation; either
014: * version 2.1 of the License, or (at your option) any later version.
015: *
016: * This library is distributed in the hope that it will be useful,
017: * but WITHOUT ANY WARRANTY; without even the implied warranty of
018: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019: * Lesser General Public License for more details.
020: *
021: * For further information about Alkacon Software GmbH, please see the
022: * company website: http://www.alkacon.com
023: *
024: * For further information about OpenCms, please see the
025: * project website: http://www.opencms.org
026: *
027: * You should have received a copy of the GNU Lesser General Public
028: * License along with this library; if not, write to the Free Software
029: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
030: */
031:
032: package org.opencms.publish;
033:
034: import org.opencms.db.CmsDbContext;
035: import org.opencms.db.CmsDriverManager;
036: import org.opencms.db.CmsPublishList;
037: import org.opencms.db.CmsUserSettings;
038: import org.opencms.db.I_CmsDbContextFactory;
039: import org.opencms.file.CmsObject;
040: import org.opencms.file.CmsResource;
041: import org.opencms.file.CmsUser;
042: import org.opencms.lock.CmsLockType;
043: import org.opencms.main.CmsEvent;
044: import org.opencms.main.CmsException;
045: import org.opencms.main.CmsInitException;
046: import org.opencms.main.CmsLog;
047: import org.opencms.main.I_CmsEventListener;
048: import org.opencms.main.OpenCms;
049: import org.opencms.report.I_CmsReport;
050: import org.opencms.security.CmsAuthentificationException;
051: import org.opencms.security.CmsRole;
052: import org.opencms.util.CmsUUID;
053:
054: import java.util.HashMap;
055: import java.util.Iterator;
056: import java.util.List;
057: import java.util.Map;
058:
059: import org.apache.commons.logging.Log;
060:
061: /**
062: * This class is responsible for the publish process.<p>
063: *
064: * @author Michael Moossen
065: *
066: * @version $Revision: 1.10 $
067: *
068: * @since 6.5.5
069: */
070: public final class CmsPublishEngine implements Runnable {
071:
072: /** The log object for this class. */
073: private static final Log LOG = CmsLog
074: .getLog(CmsPublishEngine.class);
075:
076: /** The id of the admin user. */
077: private CmsUUID m_adminUserId;
078:
079: /** The current running publish job. */
080: private CmsPublishThread m_currentPublishThread;
081:
082: /** The runtime info factory used during publishing. */
083: private final I_CmsDbContextFactory m_dbContextFactory;
084:
085: /** The driver manager instance. */
086: private CmsDriverManager m_driverManager;
087:
088: /** The engine state. */
089: private CmsPublishEngineState m_engineState;
090:
091: /** The publish listeners. */
092: private final CmsPublishListenerCollection m_listeners;
093:
094: /** The publish history list with already publish job. */
095: private final CmsPublishHistory m_publishHistory;
096:
097: /** The queue with still waiting publish job. */
098: private final CmsPublishQueue m_publishQueue;
099:
100: /** The amount of time the system will wait for a running publish job during shutdown. */
101: private int m_publishQueueShutdowntime;
102:
103: /** Is set during shutdown. */
104: private boolean m_shuttingDown;
105:
106: /**
107: * Default constructor.<p>
108: *
109: * @param dbContextFactory the initialized OpenCms runtime info factory
110: *
111: * @throws CmsInitException if the configured path to store the publish reports is not accessible
112: */
113: public CmsPublishEngine(I_CmsDbContextFactory dbContextFactory)
114: throws CmsInitException {
115:
116: if (OpenCms.getRunLevel() > OpenCms.RUNLEVEL_2_INITIALIZING) {
117: // OpenCms is already initialized
118: throw new CmsInitException(
119: org.opencms.main.Messages
120: .get()
121: .container(
122: org.opencms.main.Messages.ERR_ALREADY_INITIALIZED_0));
123: }
124: if (dbContextFactory == null) {
125: throw new CmsInitException(
126: org.opencms.main.Messages
127: .get()
128: .container(
129: org.opencms.main.Messages.ERR_CRITICAL_NO_DB_CONTEXT_0));
130: }
131: // initialize the db context factory
132: m_dbContextFactory = dbContextFactory;
133: // initialize publish queue
134: m_publishQueue = new CmsPublishQueue(this );
135: // initialize publish history
136: m_publishHistory = new CmsPublishHistory(this );
137: // initialize event handling
138: m_listeners = new CmsPublishListenerCollection(this );
139: // set engine state to normal processing
140: m_engineState = CmsPublishEngineState.ENGINE_STARTED;
141: if (CmsLog.INIT.isInfoEnabled()) {
142: CmsLog.INIT.info(Messages.get().getBundle().key(
143: Messages.INIT_PUBLISH_ENGINE_READY_0));
144: }
145: }
146:
147: /**
148: * Enqueues a new publish job with the given information in publish queue.<p>
149: *
150: * All resources should already be locked.<p>
151: *
152: * If possible, the publish job starts immediately.<p>
153: *
154: * @param cms the cms context to publish for
155: * @param publishList the resources to publish
156: * @param report the report to write to
157: *
158: * @throws CmsException if something goes wrong while cloning the cms context
159: */
160: public void enqueuePublishJob(CmsObject cms,
161: CmsPublishList publishList, I_CmsReport report)
162: throws CmsException {
163:
164: // check the driver manager
165: if ((m_driverManager == null) || (m_dbContextFactory == null)) {
166: // the resources are unlocked in the driver manager
167: throw new CmsPublishException(Messages.get().container(
168: Messages.ERR_PUBLISH_ENGINE_NOT_INITIALIZED_0));
169: }
170: // prevent new jobs if the engine is disabled
171: if (m_shuttingDown
172: || (!isEnabled() && !OpenCms.getRoleManager().hasRole(
173: cms, CmsRole.ROOT_ADMIN))) {
174: // the resources are unlocked in the driver manager
175: throw new CmsPublishException(Messages.get().container(
176: Messages.ERR_PUBLISH_ENGINE_DISABLED_0));
177: }
178:
179: // get the state before enqueuing the job
180: boolean isRunning = isRunning();
181: // create the publish job
182: CmsPublishJobInfoBean publishJob = new CmsPublishJobInfoBean(
183: cms, publishList, report);
184: // enqueue it and
185: m_publishQueue.add(publishJob);
186: // notify all listeners
187: m_listeners.fireEnqueued(new CmsPublishJobBase(publishJob));
188: // start publish job immediately if possible
189: if (!isRunning) {
190: run();
191: }
192: }
193:
194: /**
195: * Returns a publish job based on its publish history id.<p>
196: *
197: * The returned publish job may be an enqueued, running or finished publish job.<p>
198: *
199: * @param publishHistoryId the publish history id to search for
200: *
201: * @return the publish job with the given publish history id, or <code>null</code>
202: */
203: public CmsPublishJobBase getJobByPublishHistoryId(
204: CmsUUID publishHistoryId) {
205:
206: // try current running job
207: if ((m_currentPublishThread != null)
208: && m_currentPublishThread.getPublishJob()
209: .getPublishHistoryId().equals(publishHistoryId)) {
210: return new CmsPublishJobRunning(m_currentPublishThread
211: .getPublishJob());
212: }
213: // try enqueued jobs
214: Iterator itEnqueuedJobs = getPublishQueue().asList().iterator();
215: while (itEnqueuedJobs.hasNext()) {
216: CmsPublishJobEnqueued enqueuedJob = (CmsPublishJobEnqueued) itEnqueuedJobs
217: .next();
218: if (enqueuedJob.getPublishList().getPublishHistoryId()
219: .equals(publishHistoryId)) {
220: return enqueuedJob;
221: }
222: }
223: // try finished jobs
224: Iterator itFinishedJobs = getPublishHistory().asList()
225: .iterator();
226: while (itFinishedJobs.hasNext()) {
227: CmsPublishJobFinished finishedJob = (CmsPublishJobFinished) itFinishedJobs
228: .next();
229: if (finishedJob.getPublishHistoryId().equals(
230: publishHistoryId)) {
231: return finishedJob;
232: }
233: }
234: return null;
235: }
236:
237: /**
238: * Controls the publish process.<p>
239: */
240: public void run() {
241:
242: try {
243: synchronized (this ) {
244: try {
245: // give the finishing publish thread enough time to clean up
246: wait(200);
247: } catch (InterruptedException e) {
248: // ignore
249: }
250: }
251:
252: // create a publish thread only if engine is started
253: if (m_engineState != CmsPublishEngineState.ENGINE_STARTED) {
254: return;
255: }
256:
257: if (LOG.isDebugEnabled()) {
258: LOG.debug(Messages.get().getBundle().key(
259: Messages.LOG_PUBLISH_ENGINE_RUNNING_0));
260: }
261:
262: // check the driver manager
263: if ((m_driverManager == null)
264: || (m_dbContextFactory == null)) {
265: LOG.error(Messages.get().getBundle().key(
266: Messages.ERR_PUBLISH_ENGINE_NOT_INITIALIZED_0));
267: // without these there is nothing we can do
268: return;
269: }
270:
271: // there is no running publish job
272: if (m_currentPublishThread == null) {
273: // but something is waiting in the queue
274: if (!m_publishQueue.isEmpty()) {
275: // start the next waiting publish job
276: CmsPublishJobInfoBean publishJob = m_publishQueue
277: .next();
278: m_currentPublishThread = new CmsPublishThread(this ,
279: publishJob);
280: m_currentPublishThread.start();
281: } else {
282: // nothing to do
283: if (LOG.isDebugEnabled()) {
284: LOG
285: .debug(Messages
286: .get()
287: .getBundle()
288: .key(
289: Messages.LOG_PUBLISH_ENGINE_NO_RUNNING_JOB_0));
290: }
291: }
292: return;
293: }
294: // there is a still running publish job
295: if (m_currentPublishThread.isAlive()) {
296:
297: // thread was interrupted (by the grim reaper)
298: if (m_currentPublishThread.isInterrupted()) {
299:
300: if (LOG.isDebugEnabled()) {
301: LOG
302: .debug(Messages
303: .get()
304: .getBundle()
305: .key(
306: Messages.LOG_PUBLISH_ENGINE_INTERRUPTED_JOB_0));
307: }
308:
309: // unlock publish list
310: try {
311: unlockPublishList(m_currentPublishThread
312: .getPublishJob());
313: } catch (CmsException exc) {
314: LOG.error(exc.getLocalizedMessage(), exc);
315: }
316:
317: // throw it away
318: m_currentPublishThread = null;
319:
320: // and try again
321: run();
322: } else {
323:
324: // wait until it is finished
325: if (LOG.isDebugEnabled()) {
326: LOG.debug(Messages.get().getBundle().key(
327: Messages.LOG_PUBLISH_ENGINE_WAITING_0));
328: }
329: }
330: } else {
331: // why is it still set??
332: if (LOG.isDebugEnabled()) {
333: LOG.debug(Messages.get().getBundle().key(
334: Messages.LOG_PUBLISH_ENGINE_DEAD_JOB_0));
335: }
336: // just throw it away
337: m_currentPublishThread = null;
338: // and try again
339: run();
340: }
341: } catch (Throwable e) {
342: // catch every thing including runtime exceptions
343: LOG.error(Messages.get().getBundle().key(
344: Messages.ERR_PUBLISH_ENGINE_ERROR_0), e);
345: }
346: }
347:
348: /**
349: * Sets the driver manager instance.<p>
350: *
351: * @param driverManager the driver manager instance
352: */
353: public void setDriverManager(CmsDriverManager driverManager) {
354:
355: m_driverManager = driverManager;
356: CmsDbContext dbc = m_dbContextFactory.getDbContext();
357: try {
358: m_adminUserId = m_driverManager.readUser(dbc,
359: OpenCms.getDefaultUsers().getUserAdmin()).getId();
360: } catch (CmsException e) {
361: LOG.error(e.getLocalizedMessage(), e);
362: } finally {
363: dbc.clear();
364: }
365: }
366:
367: /**
368: * Shuts down all this static export manager.<p>
369: *
370: * NOTE: this method may or may NOT be called (i.e. kill -9 in the stop script), if a system is stopped.<p>
371: *
372: * This is required since there may still be a thread running when the system is being shut down.<p>
373: */
374: public void shutDown() {
375:
376: if (CmsLog.INIT.isInfoEnabled()) {
377: CmsLog.INIT
378: .info(org.opencms.main.Messages
379: .get()
380: .getBundle()
381: .key(
382: org.opencms.main.Messages.INIT_SHUTDOWN_START_1,
383: this .getClass().getName()));
384: }
385:
386: // prevent new publish jobs are accepted
387: m_shuttingDown = true;
388:
389: // if a job is currently running,
390: // wait the specified amount of time,
391: // then write an abort message to the report
392: if (m_currentPublishThread != null) {
393:
394: // if a shutdown time is defined, wait if a publish process is running
395: if (m_publishQueueShutdowntime > 0) {
396: synchronized (this ) {
397: try {
398: wait(m_publishQueueShutdowntime * 1000);
399: } catch (InterruptedException exc) {
400: // ignore
401: }
402: }
403: }
404:
405: if (m_currentPublishThread != null) {
406: CmsPublishJobInfoBean publishJob = m_currentPublishThread
407: .getPublishJob();
408: try {
409: abortPublishJob(m_adminUserId,
410: new CmsPublishJobEnqueued(publishJob),
411: false);
412: } catch (CmsException e) {
413: if (LOG.isErrorEnabled()) {
414: LOG.error(e.getLocalizedMessage(), e);
415: }
416: }
417: }
418: }
419: if (CmsLog.INIT.isInfoEnabled()) {
420: CmsLog.INIT
421: .info(org.opencms.staticexport.Messages
422: .get()
423: .getBundle()
424: .key(
425: org.opencms.staticexport.Messages.INIT_SHUTDOWN_1,
426: this .getClass().getName()));
427: }
428: }
429:
430: /**
431: * Aborts the given publish job.<p>
432: *
433: * @param userId the id of user that wants to abort the given publish job
434: * @param publishJob the publish job to abort
435: * @param removeJob indicates if the job will be removed or added to history
436: *
437: * @throws CmsException if there is some problem during unlocking the resources
438: * @throws CmsPublishException if the publish job can not be aborted
439: */
440: protected void abortPublishJob(CmsUUID userId,
441: CmsPublishJobEnqueued publishJob, boolean removeJob)
442: throws CmsException, CmsPublishException {
443:
444: // abort event should be raised before the job is removed implicitly
445: m_listeners.fireAbort(userId, publishJob);
446:
447: if ((m_currentPublishThread == null)
448: || !publishJob.m_publishJob
449: .equals(m_currentPublishThread.getPublishJob())) {
450: // engine is currently publishing another job or is not publishing
451: if (!m_publishQueue
452: .abortPublishJob(publishJob.m_publishJob)) {
453: // job not found
454: throw new CmsPublishException(
455: Messages
456: .get()
457: .container(
458: Messages.ERR_PUBLISH_ENGINE_MISSING_PUBLISH_JOB_0));
459: }
460: } else if (!m_shuttingDown) {
461: // engine is currently publishing the job to abort
462: m_currentPublishThread.abort();
463: } else if (m_shuttingDown && (m_currentPublishThread != null)) {
464: // aborting the current job during shut down
465: I_CmsReport report = m_currentPublishThread.getReport();
466: report.println();
467: report.println();
468: report.println(Messages.get().container(
469: Messages.RPT_PUBLISH_JOB_ABORT_SHUTDOWN_0),
470: I_CmsReport.FORMAT_ERROR);
471: report.println();
472: }
473:
474: // unlock all resources
475: if (publishJob.getPublishList() != null) {
476: unlockPublishList(publishJob.m_publishJob);
477: }
478: // keep job if requested
479: if (!removeJob) {
480: // set finish info
481: publishJob.m_publishJob.finish();
482: getPublishHistory().add(publishJob.m_publishJob);
483: } else {
484: getPublishQueue().remove(publishJob.m_publishJob);
485: }
486: }
487:
488: /**
489: * Adds a publish listener to listen on publish events.<p>
490: *
491: * @param listener the publish listener to add
492: */
493: protected void addPublishListener(I_CmsPublishEventListener listener) {
494:
495: m_listeners.add(listener);
496: }
497:
498: /**
499: * Disables the publish engine, i.e. publish jobs are not accepted.<p>
500: */
501: protected void disableEngine() {
502:
503: m_engineState = CmsPublishEngineState.ENGINE_DISABLED;
504: }
505:
506: /**
507: * Enables the publish engine, i.e. publish jobs are accepted.<p>
508: */
509: protected void enableEngine() {
510:
511: m_engineState = CmsPublishEngineState.ENGINE_STARTED;
512: // start publish job if jobs waiting
513: if ((m_currentPublishThread == null)
514: && !m_publishQueue.isEmpty()) {
515: run();
516: }
517: }
518:
519: /**
520: * Returns the current running publish job.<p>
521: *
522: * @return the current running publish job
523: */
524: protected CmsPublishThread getCurrentPublishJob() {
525:
526: return m_currentPublishThread;
527: }
528:
529: /**
530: * Returns the db context factory object.<p>
531: *
532: * @return the db context factory object
533: */
534: protected I_CmsDbContextFactory getDbContextFactory() {
535:
536: return m_dbContextFactory;
537: }
538:
539: /**
540: * Returns the driver manager instance.<p>
541: *
542: * @return the driver manager instance
543: */
544: protected CmsDriverManager getDriverManager() {
545:
546: return m_driverManager;
547: }
548:
549: /**
550: * Returns the publish history list with already publish job.<p>
551: *
552: * @return the publish history list with already publish job
553: */
554: protected CmsPublishHistory getPublishHistory() {
555:
556: return m_publishHistory;
557: }
558:
559: /**
560: * Returns the queue with still waiting publish job.<p>
561: *
562: * @return the queue with still waiting publish job
563: */
564: protected CmsPublishQueue getPublishQueue() {
565:
566: return m_publishQueue;
567: }
568:
569: /**
570: * Returns the content of the publish report assigned to the given publish job.<p>
571: *
572: * @param publishJob the published job
573: * @return the content of the assigned publish report
574: *
575: * @throws CmsException if something goes wrong
576: */
577: protected byte[] getReportContents(CmsPublishJobFinished publishJob)
578: throws CmsException {
579:
580: CmsDbContext dbc = m_dbContextFactory.getDbContext();
581: try {
582: return m_driverManager.readPublishReportContents(dbc,
583: publishJob.getPublishHistoryId());
584: } finally {
585: dbc.clear();
586: }
587: }
588:
589: /**
590: * Returns the user identified by the given id.<p>
591: *
592: * @param userId the id of the user to retrieve
593: *
594: * @return the user identified by the given id
595: */
596: protected CmsUser getUser(CmsUUID userId) {
597:
598: CmsDbContext dbc = m_dbContextFactory.getDbContext();
599: try {
600: return m_driverManager.readUser(dbc, userId);
601: } catch (CmsException e) {
602: LOG.error(e.getLocalizedMessage(), e);
603: } finally {
604: dbc.clear();
605: }
606: return null;
607: }
608:
609: /**
610: * Initializes the publish engine.<p>
611: *
612: * @param adminCms the admin cms
613: * @param publishQueuePersistance flag if the queue is persisted
614: * @param publishQueueShutdowntime amount of time to wait for a publish job during shutdown
615: *
616: * @throws CmsException if something goes wrong
617: */
618: protected void initialize(CmsObject adminCms,
619: boolean publishQueuePersistance,
620: int publishQueueShutdowntime) throws CmsException {
621:
622: // check the driver manager
623: if ((m_driverManager == null) || (m_dbContextFactory == null)) {
624: throw new CmsPublishException(Messages.get().container(
625: Messages.ERR_PUBLISH_ENGINE_NOT_INITIALIZED_0));
626: }
627:
628: m_publishQueueShutdowntime = publishQueueShutdowntime;
629:
630: // initially the engine is stopped, must be restartet after full system initialization
631: m_engineState = CmsPublishEngineState.ENGINE_STOPPED;
632: // read the publish history from the repository
633: m_publishHistory.initialize();
634: // read the queue from the repository
635: m_publishQueue.initialize(adminCms, publishQueuePersistance);
636: }
637:
638: /**
639: * Returns the working state, that is if no publish job
640: * is waiting to be processed and there is no current running
641: * publish job.<p>
642: *
643: * @return the working state
644: */
645: protected boolean isRunning() {
646:
647: return (((m_engineState == CmsPublishEngineState.ENGINE_STARTED) && !m_publishQueue
648: .isEmpty()) || (m_currentPublishThread != null));
649: }
650:
651: /**
652: * Sets publish locks of resources in a publish list.<p>
653: *
654: * @param publishJob the publish job
655: * @throws CmsException if something goes wrong
656: */
657: protected void lockPublishList(CmsPublishJobInfoBean publishJob)
658: throws CmsException {
659:
660: CmsPublishList publishList = publishJob.getPublishList();
661: // lock them
662: CmsDbContext dbc = getDbContextFactory().getDbContext(
663: publishJob.getCmsObject().getRequestContext());
664: try {
665: Iterator itResources = publishList.getAllResources()
666: .iterator();
667: while (itResources.hasNext()) {
668: CmsResource resource = (CmsResource) itResources.next();
669: m_driverManager.lockResource(dbc, resource,
670: CmsLockType.PUBLISH);
671: }
672: } finally {
673: dbc.clear();
674: }
675: }
676:
677: /**
678: * Signalizes that the publish thread finishes.<p>
679: *
680: * @param publishJob the finished publish job
681: *
682: * @throws CmsException if something goes wrong
683: */
684: protected void publishJobFinished(CmsPublishJobInfoBean publishJob)
685: throws CmsException {
686:
687: // in order to avoid not removable publish locks, unlock all assigned resources again
688: unlockPublishList(publishJob);
689:
690: if ((m_currentPublishThread != null)
691: && (m_currentPublishThread.isAborted())) {
692: // try to start a new publish job
693: new Thread(this ).start();
694: return;
695: }
696: // trigger the old event mechanism
697: CmsDbContext dbc = m_dbContextFactory.getDbContext(publishJob
698: .getCmsObject().getRequestContext());
699: try {
700: // fire an event that a project has been published
701: Map eventData = new HashMap();
702: eventData.put(I_CmsEventListener.KEY_REPORT, publishJob
703: .getPublishReport());
704: eventData.put(I_CmsEventListener.KEY_PUBLISHID, publishJob
705: .getPublishList().getPublishHistoryId().toString());
706: eventData.put(I_CmsEventListener.KEY_PROJECTID, dbc
707: .currentProject().getUuid());
708: eventData.put(I_CmsEventListener.KEY_DBCONTEXT, dbc);
709: CmsEvent afterPublishEvent = new CmsEvent(
710: I_CmsEventListener.EVENT_PUBLISH_PROJECT, eventData);
711: OpenCms.fireCmsEvent(afterPublishEvent);
712: } catch (Throwable t) {
713: // catch every thing including runtime exceptions
714: publishJob.getPublishReport().println(t);
715: } finally {
716: dbc.clear();
717: dbc = null;
718: }
719: // fire the publish finish event
720: m_listeners.fireFinish(new CmsPublishJobRunning(publishJob));
721: // finish the job
722: publishJob.finish();
723: // put the publish job into the history list
724: m_publishHistory.add(publishJob);
725: // wipe the dead thread
726: m_currentPublishThread = null;
727: // try to start a new publish job
728: new Thread(this ).start();
729: }
730:
731: /**
732: * A publish job has been permanently removed from the history.<p>
733: *
734: * @param publishJob the removed publish job
735: */
736: protected void publishJobRemoved(CmsPublishJobInfoBean publishJob) {
737:
738: // a publish job has been removed
739: m_listeners.fireRemove(new CmsPublishJobFinished(publishJob));
740: }
741:
742: /**
743: * Signalizes that the publish thread starts.<p>
744: *
745: * @param publishJob the started publish job
746: *
747: * @throws CmsException if something goes wrong
748: */
749: protected void publishJobStarted(CmsPublishJobInfoBean publishJob)
750: throws CmsException {
751:
752: // update the job
753: m_publishQueue.update(publishJob);
754:
755: // fire the publish start event
756: m_listeners.fireStart(new CmsPublishJobEnqueued(publishJob));
757: }
758:
759: /**
760: * Removes the given publish listener.<p>
761: *
762: * @param listener the publish listener to remove
763: */
764: protected void removePublishListener(
765: I_CmsPublishEventListener listener) {
766:
767: m_listeners.remove(listener);
768: }
769:
770: /**
771: * Sends a message to the given user, if publish notification is enabled or an error is shown in the message.<p>
772: *
773: * @param toUserId the id of the user to send the message to
774: * @param message the message to send
775: * @param hasErrors flag to determine if the message to send shows an error
776: */
777: protected void sendMessage(CmsUUID toUserId, String message,
778: boolean hasErrors) {
779:
780: CmsDbContext dbc = m_dbContextFactory.getDbContext();
781: try {
782: CmsUser toUser = m_driverManager.readUser(dbc, toUserId);
783: CmsUserSettings settings = new CmsUserSettings(toUser);
784: if (settings.getShowPublishNotification() || hasErrors) {
785: // only show message if publish notification is enabled or the message shows an error
786: OpenCms.getSessionManager().sendBroadcast(null,
787: message, toUser);
788: }
789: } catch (CmsException e) {
790: LOG.error(e.getLocalizedMessage(), e);
791: } finally {
792: dbc.clear();
793: }
794: }
795:
796: /**
797: * Starts the publish engine, i.e. publish jobs are accepted and processed.<p>
798: */
799: protected void startEngine() {
800:
801: if (m_engineState != CmsPublishEngineState.ENGINE_STARTED) {
802: m_engineState = CmsPublishEngineState.ENGINE_STARTED;
803: // start publish job if jobs waiting
804: if ((m_currentPublishThread == null)
805: && !m_publishQueue.isEmpty()) {
806: run();
807: }
808: }
809: }
810:
811: /**
812: * Stops the publish engine, i.e. publish jobs are still accepted but not published.<p>
813: */
814: protected void stopEngine() {
815:
816: m_engineState = CmsPublishEngineState.ENGINE_STOPPED;
817: }
818:
819: /**
820: * Removes all publish locks of resources in a publish list of a publish job.<p>
821: *
822: * @param publishJob the publish job
823: * @throws CmsException if something goes wrong
824: */
825: protected void unlockPublishList(CmsPublishJobInfoBean publishJob)
826: throws CmsException {
827:
828: CmsPublishList publishList = publishJob.getPublishList();
829: List allResources = publishList.getAllResources();
830: // unlock them
831: CmsDbContext dbc = getDbContextFactory().getDbContext(
832: publishJob.getCmsObject().getRequestContext());
833: try {
834: Iterator itResources = allResources.iterator();
835: while (itResources.hasNext()) {
836: CmsResource resource = (CmsResource) itResources.next();
837: m_driverManager.unlockResource(dbc, resource, true,
838: true);
839: }
840: } finally {
841: dbc.clear();
842: }
843: }
844:
845: /**
846: * Returns <code>true</code> if the login manager allows login.<p>
847: *
848: * @return if enabled
849: */
850: private boolean isEnabled() {
851:
852: try {
853: if ((m_engineState == CmsPublishEngineState.ENGINE_STOPPED)
854: || (m_engineState == CmsPublishEngineState.ENGINE_STARTED)) {
855: OpenCms.getLoginManager().checkLoginAllowed();
856: return true;
857: } else {
858: return false;
859: }
860: } catch (CmsAuthentificationException e) {
861: return false;
862: }
863: }
864: }
|