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.CmsPublishList;
031import org.opencms.db.CmsSecurityManager;
032import org.opencms.file.CmsObject;
033import org.opencms.file.CmsResource;
034import org.opencms.file.CmsResourceFilter;
035import org.opencms.file.CmsUser;
036import org.opencms.main.CmsException;
037import org.opencms.main.CmsRuntimeException;
038import org.opencms.main.OpenCms;
039import org.opencms.relations.CmsRelation;
040import org.opencms.relations.CmsRelationFilter;
041import org.opencms.report.CmsShellReport;
042import org.opencms.report.I_CmsReport;
043import org.opencms.security.CmsRole;
044import org.opencms.security.CmsSecurityException;
045import org.opencms.util.CmsUUID;
046
047import java.util.ArrayList;
048import java.util.Collection;
049import java.util.Iterator;
050import java.util.List;
051import java.util.Map;
052
053/**
054 * This manager provide access to the publish engine runtime information.<p>
055 *
056 * @since 6.5.5
057 */
058public class CmsPublishManager {
059
060    /**
061     * Enum for the different publish  list remove modes.<p>
062     */
063    public static enum PublishListRemoveMode {
064        /** Remove publish list entries for all users if a resource is published. */
065        allUsers, /** Remove publish list entry for the current user if a resource is published. */
066        currentUser
067    }
068
069    /** The default history size. */
070    public static final int DEFAULT_HISTORY_SIZE = 100;
071
072    /** The default persistence setting for the publish queue. */
073    public static final boolean DEFAULT_QUEUE_PERSISTANCE = false;
074
075    /** The default shutdown time for the running publish job. */
076    public static final int DEFAULT_QUEUE_SHUTDOWNTIME = 1;
077
078    /** Milliseconds in a second. */
079    private static final int MS_ONE_SECOND = 1000;
080
081    /** Indicates if the configuration can be modified. */
082    private boolean m_frozen;
083
084    /** The underlying publish engine. */
085    private CmsPublishEngine m_publishEngine;
086
087    /** The maximum size of the publish history. */
088    private int m_publishHistorySize;
089
090    /** Publish job verifier. */
091    private CmsPublishListVerifier m_publishListVerifier = new CmsPublishListVerifier();
092
093    /** The publish list remove mode. */
094    private CmsPublishManager.PublishListRemoveMode m_publishListRemoveMode;
095
096    /** Indicates if the publish queue is re-initialized on startup. */
097    private boolean m_publishQueuePersistance;
098
099    /** The amount of time to wait for a publish job during shutdown. */
100    private int m_publishQueueShutdowntime;
101
102    /** The security manager. */
103    private CmsSecurityManager m_securityManager;
104
105    /**
106     * Default constructor used in digester initialization.<p>
107     */
108    public CmsPublishManager() {
109
110        m_publishEngine = null;
111        m_frozen = false;
112    }
113
114    /**
115     * Constructor used to create a pre-initialized instance.<p>
116     *
117     * @param historySize the size of the publish history
118     * @param queuePersistance indicates if the queue is re-initialized on startup
119     * @param queueShutdowntime the amount of time to wait for a publish job during shutdown
120     */
121    public CmsPublishManager(int historySize, boolean queuePersistance, int queueShutdowntime) {
122
123        m_publishEngine = null;
124        m_publishHistorySize = historySize;
125        m_publishQueuePersistance = queuePersistance;
126        m_publishQueueShutdowntime = queueShutdowntime;
127        m_frozen = false;
128    }
129
130    /**
131     * Abandons the current publish thread.<p>
132     */
133    public void abandonThread() {
134
135        m_publishEngine.abandonThread();
136    }
137
138    /**
139     * Aborts the given publish job.<p>
140     *
141     * @param cms the cms context
142     * @param publishJob the publish job to abort
143     * @param removeJob indicates if the job will be removed or added to history
144     *
145     * @throws CmsException if there is some problem during unlocking the resources
146     * @throws CmsSecurityException if the current user has not enough permissions
147     * @throws CmsPublishException if the publish job can not been aborted
148     */
149    public void abortPublishJob(CmsObject cms, CmsPublishJobEnqueued publishJob, boolean removeJob)
150    throws CmsException, CmsSecurityException, CmsPublishException {
151
152        if (!OpenCms.getRoleManager().hasRole(cms, CmsRole.PROJECT_MANAGER)
153            && !cms.getRequestContext().getCurrentUser().getId().equals(publishJob.getUserId())) {
154            // Can only be executed by somebody with the role CmsRole#PROJECT_MANAGER or the owner of the job
155            throw new CmsSecurityException(
156                Messages.get().container(
157                    Messages.ERR_PUBLISH_ENGINE_ABORT_DENIED_1,
158                    cms.getRequestContext().getCurrentUser().getName()));
159        }
160        m_publishEngine.abortPublishJob(cms.getRequestContext().getCurrentUser().getId(), publishJob, removeJob);
161    }
162
163    /**
164     * Adds a publish listener to listen on publish events.<p>
165     *
166     * @param listener the publish listener to add
167     */
168    public void addPublishListener(I_CmsPublishEventListener listener) {
169
170        m_publishEngine.addPublishListener(listener);
171    }
172
173    /**
174     * Check if the thread for the current publish job is still active or was interrupted
175     * and so the next job in the queue can be started.<p>
176     */
177    public void checkCurrentPublishJobThread() {
178
179        m_publishEngine.checkCurrentPublishJobThread();
180    }
181
182    /**
183     * Disables the publishing of resources.<p>
184     */
185    public void disablePublishing() {
186
187        m_publishEngine.disableEngine();
188    }
189
190    /**
191     * Enables the enqeueing of resources for publishing.<p>
192     */
193    public void enablePublishing() {
194
195        m_publishEngine.enableEngine();
196    }
197
198    /**
199     * Returns the current running publish job.<p>
200     *
201     * @return the current running publish job
202     */
203    public CmsPublishJobRunning getCurrentPublishJob() {
204
205        if (m_publishEngine.getCurrentPublishJob() == null) {
206            return null;
207        }
208        return new CmsPublishJobRunning(m_publishEngine.getCurrentPublishJob().getPublishJob());
209    }
210
211    /**
212     * Returns a publish job based on its publish history id.<p>
213     *
214     * The returned publish job may be an enqueued, running or finished publish job.<p>
215     *
216     * @param publishHistoryId the publish history id to search for
217     *
218     * @return the publish job with the given publish history id, or <code>null</code>
219     */
220    public CmsPublishJobBase getJobByPublishHistoryId(CmsUUID publishHistoryId) {
221
222        return m_publishEngine.getJobByPublishHistoryId(publishHistoryId);
223    }
224
225    /**
226     * Returns the publish history list with already publish jobs.<p>
227     *
228     * @return a list of {@link CmsPublishJobFinished} objects
229     */
230    public List<CmsPublishJobFinished> getPublishHistory() {
231
232        return m_publishEngine.getPublishHistory().asList();
233    }
234
235    /**
236     * Returns the publish history list with already publish jobs, filtered by the given user.<p>
237     *
238     * @param user the user to filter the jobs with
239     *
240     * @return a list of {@link CmsPublishJobFinished} objects
241     */
242    public List<CmsPublishJobFinished> getPublishHistory(CmsUser user) {
243
244        List<CmsPublishJobFinished> result = new ArrayList<CmsPublishJobFinished>();
245        Iterator<CmsPublishJobFinished> it = getPublishHistory().iterator();
246        while (it.hasNext()) {
247            CmsPublishJobFinished publishJob = it.next();
248            if (publishJob.getUserId().equals(user.getId())) {
249                result.add(publishJob);
250            }
251        }
252        return result;
253    }
254
255    /**
256     * Returns the publish History Size.<p>
257     *
258     * @return the publish History Size
259     */
260    public int getPublishHistorySize() {
261
262        return m_publishHistorySize;
263    }
264
265    /**
266     * Gets the publish job verifier.<p>
267     *
268     * @return the publish job verifier
269     */
270    public CmsPublishListVerifier getPublishListVerifier() {
271
272        return m_publishListVerifier;
273    }
274
275    /**
276     * Returns a publish list with all new/changed/deleted resources of the current (offline)
277     * project that actually get published.<p>
278     *
279     * @param cms the cms request context
280     *
281     * @return a publish list
282     *
283     * @throws CmsException if something goes wrong
284     */
285    public CmsPublishList getPublishList(CmsObject cms) throws CmsException {
286
287        return m_securityManager.fillPublishList(
288            cms.getRequestContext(),
289            new CmsPublishList(cms.getRequestContext().getCurrentProject()));
290    }
291
292    /**
293     * Returns a publish list with all new/changed/deleted resources of the current (offline)
294     * project that actually get published for a direct publish of a single resource.<p>
295     *
296     * @param cms the cms request context
297     * @param directPublishResource the resource which will be directly published
298     * @param directPublishSiblings <code>true</code>, if all eventual siblings of the direct
299     *                      published resource should also get published.
300     *
301     * @return a publish list
302     *
303     * @throws CmsException if something goes wrong
304     */
305    public CmsPublishList getPublishList(
306        CmsObject cms,
307        CmsResource directPublishResource,
308        boolean directPublishSiblings) throws CmsException {
309
310        return m_securityManager.fillPublishList(
311            cms.getRequestContext(),
312            new CmsPublishList(directPublishResource, directPublishSiblings));
313    }
314
315    /**
316     * Returns a publish list with all new/changed/deleted resources of the current (offline)
317     * project that actually get published for a direct publish of a List of resources.<p>
318     *
319     * @param cms the cms request context
320     * @param directPublishResources the resources which will be directly published
321     * @param directPublishSiblings <code>true</code>, if all eventual siblings of the direct
322     *                      published resources should also get published.
323     *
324     * @return a publish list
325     *
326     * @throws CmsException if something goes wrong
327     */
328    public CmsPublishList getPublishList(
329        CmsObject cms,
330        List<CmsResource> directPublishResources,
331        boolean directPublishSiblings) throws CmsException {
332
333        return getPublishList(cms, directPublishResources, directPublishSiblings, true);
334    }
335
336    /**
337     * Returns a publish list with all new/changed/deleted resources of the current (offline)
338     * project that actually get published for a direct publish of a List of resources.<p>
339     *
340     * @param cms the cms request context
341     * @param directPublishResources the {@link CmsResource} objects which will be directly published
342     * @param directPublishSiblings <code>true</code>, if all eventual siblings of the direct
343     *                      published resources should also get published.
344     * @param publishSubResources indicates if sub-resources in folders should be published (for direct publish only)
345     *
346     * @return a publish list
347     *
348     * @throws CmsException if something goes wrong
349     */
350    public CmsPublishList getPublishList(
351        CmsObject cms,
352        List<CmsResource> directPublishResources,
353        boolean directPublishSiblings,
354        boolean publishSubResources) throws CmsException {
355
356        return m_securityManager.fillPublishList(
357            cms.getRequestContext(),
358            new CmsPublishList(directPublishResources, directPublishSiblings, publishSubResources));
359    }
360
361    /**
362     * Returns a publish list with all the given resources, filtered only by state.<p>
363     *
364     * @param cms the cms request context
365     * @param directPublishResources the {@link CmsResource} objects which will be directly published
366     * @param directPublishSiblings <code>true</code>, if all eventual siblings of the direct
367     *                      published resources should also get published
368     * @param isUserPublishList if true, the publish list consists of resources directly selected by the user to publish
369     *
370     * @return a publish list
371     *
372     * @throws CmsException if something goes wrong
373     */
374    public CmsPublishList getPublishListAll(
375        CmsObject cms,
376        List<CmsResource> directPublishResources,
377        boolean directPublishSiblings,
378        boolean isUserPublishList) throws CmsException {
379
380        CmsPublishList pubList = new CmsPublishList(true, directPublishResources, directPublishSiblings);
381        pubList.setUserPublishList(isUserPublishList);
382
383        return m_securityManager.fillPublishList(cms.getRequestContext(), pubList);
384    }
385
386    /**
387     * Gets the publish list remove mode.<p>
388     *
389     * @return the publish list remove mode
390     */
391    public CmsPublishManager.PublishListRemoveMode getPublishListRemoveMode() {
392
393        return m_publishListRemoveMode;
394    }
395
396    /**
397     * Returns the queue with still waiting publish jobs.<p>
398     *
399     * @return a list of {@link CmsPublishJobEnqueued} objects
400     */
401    public List<CmsPublishJobEnqueued> getPublishQueue() {
402
403        return m_publishEngine.getPublishQueue().asList();
404    }
405
406    /**
407     * Returns the amount of time in seconds the system will wait during shutdown for a running publish job.<p>
408     *
409     * @return the shutdown time for a running publish job
410     */
411    public int getPublishQueueShutdowntime() {
412
413        return m_publishQueueShutdowntime;
414    }
415
416    /**
417     * Returns a new publish list that contains the unpublished resources related
418     * to all resources in the given publish list, the related resources exclude
419     * all resources in the given publish list and also locked (by other users) resources.<p>
420     *
421     * @param cms the cms request context
422     * @param publishList the publish list to exclude from result
423     *
424     * @return a new publish list that contains the related resources
425     *
426     * @throws CmsException if something goes wrong
427     */
428    public CmsPublishList getRelatedResourcesToPublish(CmsObject cms, CmsPublishList publishList) throws CmsException {
429
430        return m_securityManager.getRelatedResourcesToPublish(
431            cms.getRequestContext(),
432            publishList,
433            CmsRelationFilter.TARGETS.filterStrong());
434    }
435
436    /**
437     * Returns the content of the publish report assigned to the given publish job.<p>
438     *
439     * @param publishJob the published job
440     * @return the content of the assigned publish report
441     *
442     * @throws CmsException if something goes wrong
443     */
444    public byte[] getReportContents(CmsPublishJobFinished publishJob) throws CmsException {
445
446        return m_publishEngine.getReportContents(publishJob);
447    }
448
449    /**
450     * Returns the current user's publish list.<p>
451     *
452     * @param cms the current cms context
453     *
454     * @return the current user's publish list
455     *
456     * @throws CmsException if something goes wrong
457     */
458    public List<CmsResource> getUsersPubList(CmsObject cms) throws CmsException {
459
460        return m_securityManager.getUsersPubList(cms.getRequestContext());
461    }
462
463    /**
464     * Initializes the publish manager and the publish engine finally.<p>
465     *
466     * @param cms an admin cms object
467     *
468     * @throws CmsException if something goes wrong
469     */
470    public void initialize(CmsObject cms) throws CmsException {
471
472        m_publishEngine.initialize(cms, m_publishQueuePersistance, m_publishQueueShutdowntime);
473        m_frozen = true;
474    }
475
476    /**
477     * Returns if the publish queue is persisted an will be re-initialized on startup.<p>
478     *
479     * @return <code>true</code> if the publish queue is persisted
480     */
481    public boolean isPublishQueuePersistanceEnabled() {
482
483        return m_publishQueuePersistance;
484    }
485
486    /**
487     * Returns the working state, that is if no publish job
488     * is waiting to be processed and there is no current running
489     * publish job.<p>
490     *
491     * @return the working state
492     */
493    public boolean isRunning() {
494
495        return m_publishEngine.isRunning();
496    }
497
498    /**
499     * Returns a new publish list that contains all resources of both given publish lists.<p>
500     *
501     * @param cms the cms request context
502     * @param pubList1 the first publish list
503     * @param pubList2 the second publish list
504     *
505     * @return a new publish list that contains all resources of both given publish lists
506     *
507     * @throws CmsException if something goes wrong
508     */
509    public CmsPublishList mergePublishLists(CmsObject cms, CmsPublishList pubList1, CmsPublishList pubList2)
510    throws CmsException {
511
512        return m_securityManager.mergePublishLists(cms.getRequestContext(), pubList1, pubList2);
513    }
514
515    /**
516     * Publishes the current project, printing messages to a shell report.<p>
517     *
518     * @param cms the cms request context
519     * @return the publish history id of the published project
520     *
521     * @throws Exception if something goes wrong
522     *
523     * @see CmsShellReport
524     */
525    public CmsUUID publishProject(CmsObject cms) throws Exception {
526
527        return publishProject(cms, new CmsShellReport(cms.getRequestContext().getLocale()));
528    }
529
530    /**
531     * Publishes the current project.<p>
532     *
533     * @param cms the cms request context
534     * @param report an instance of <code>{@link I_CmsReport}</code> to print messages
535     *
536     * @return the publish history id of the published project
537     *
538     * @throws CmsException if something goes wrong
539     */
540    public CmsUUID publishProject(CmsObject cms, I_CmsReport report) throws CmsException {
541
542        return publishProject(cms, report, getPublishList(cms));
543    }
544
545    /**
546     * Publishes the resources of a specified publish list.<p>
547     *
548     * @param cms the cms request context
549     * @param report an instance of <code>{@link I_CmsReport}</code> to print messages
550     * @param publishList a publish list
551     *
552     * @return the publish history id of the published project
553     *
554     * @throws CmsException if something goes wrong
555     *
556     * @see #getPublishList(CmsObject)
557     * @see #getPublishList(CmsObject, CmsResource, boolean)
558     * @see #getPublishList(CmsObject, List, boolean)
559     */
560    public CmsUUID publishProject(CmsObject cms, I_CmsReport report, CmsPublishList publishList) throws CmsException {
561
562        return m_securityManager.publishProject(cms, publishList, report);
563    }
564
565    /**
566     * Direct publishes a specified resource.<p>
567     *
568     * @param cms the cms request context
569     * @param report an instance of <code>{@link I_CmsReport}</code> to print messages
570     * @param directPublishResource a <code>{@link CmsResource}</code> that gets directly published;
571     *                          or <code>null</code> if an entire project gets published.
572     * @param directPublishSiblings if a <code>{@link CmsResource}</code> that should get published directly is
573     *                          provided as an argument, all eventual siblings of this resource
574     *                          get publish too, if this flag is <code>true</code>.
575     *
576     * @return the publish history id of the published project
577     *
578     * @throws CmsException if something goes wrong
579     */
580    public CmsUUID publishProject(
581        CmsObject cms,
582        I_CmsReport report,
583        CmsResource directPublishResource,
584        boolean directPublishSiblings) throws CmsException {
585
586        return publishProject(cms, report, getPublishList(cms, directPublishResource, directPublishSiblings));
587    }
588
589    /**
590     * Publishes a single resource, printing messages to a shell report.<p>
591     *
592     * The siblings of the resource will not be published.<p>
593     *
594     * @param cms the cms request context
595     * @param resourcename the name of the resource to be published
596     *
597     * @return the publish history id of the published project
598     *
599     * @throws Exception if something goes wrong
600     *
601     * @see CmsShellReport
602     */
603    public CmsUUID publishResource(CmsObject cms, String resourcename) throws Exception {
604
605        return publishResource(cms, resourcename, false, new CmsShellReport(cms.getRequestContext().getLocale()));
606    }
607
608    /**
609     * Publishes a single resource.<p>
610     *
611     * @param cms the cms request context
612     * @param resourcename the name of the resource to be published
613     * @param publishSiblings if <code>true</code>, all siblings of the resource are also published
614     * @param report the report to write the progress information to
615     *
616     * @return the publish history id of the published project
617     *
618     * @throws Exception if something goes wrong
619     */
620    public CmsUUID publishResource(CmsObject cms, String resourcename, boolean publishSiblings, I_CmsReport report)
621    throws Exception {
622
623        CmsResource resource = cms.readResource(resourcename, CmsResourceFilter.ALL);
624        return publishProject(cms, report, resource, publishSiblings);
625    }
626
627    /**
628     * Removes the given publish listener.<p>
629     *
630     * @param listener the publish listener to remove
631     */
632    public void removePublishListener(I_CmsPublishEventListener listener) {
633
634        m_publishEngine.removePublishListener(listener);
635    }
636
637    /**
638     * Removes the given resource to the given user's publish list.<p>
639     *
640     * @param cms the current cms context
641     * @param structureIds the collection of structure IDs to remove
642     *
643     * @throws CmsException if something goes wrong
644     */
645    public void removeResourceFromUsersPubList(CmsObject cms, Collection<CmsUUID> structureIds) throws CmsException {
646
647        m_securityManager.removeResourceFromUsersPubList(cms.getRequestContext(), structureIds);
648    }
649
650    /**
651     * Sets the publish engine during initialization.<p>
652     *
653     * @param publishEngine the publish engine instance
654     */
655    public void setPublishEngine(CmsPublishEngine publishEngine) {
656
657        if (m_frozen) {
658            throw new CmsRuntimeException(Messages.get().container(Messages.ERR_CONFIG_FROZEN_0));
659        }
660        m_publishEngine = publishEngine;
661    }
662
663    /**
664     * Sets the publish History Size.<p>
665     *
666     * @param publishHistorySize the publish History Size to set
667     */
668    public void setPublishHistorySize(String publishHistorySize) {
669
670        if (m_frozen) {
671            throw new CmsRuntimeException(Messages.get().container(Messages.ERR_CONFIG_FROZEN_0));
672        }
673        m_publishHistorySize = Integer.parseInt(publishHistorySize);
674    }
675
676    /**
677     * Sets the publish list remove mode.<p>
678     *
679     * @param publishListRemoveMode the publish list remove mode
680     */
681    public void setPublishListRemoveMode(CmsPublishManager.PublishListRemoveMode publishListRemoveMode) {
682
683        if (m_frozen) {
684            throw new CmsRuntimeException(Messages.get().container(Messages.ERR_CONFIG_FROZEN_0));
685        }
686        m_publishListRemoveMode = publishListRemoveMode;
687    }
688
689    /**
690     * Sets if the publish queue is re-initialized on startup.<p>
691     *
692     * @param publishQueuePersistance the persistence flag, parsed as <code>boolean</code>
693     */
694    public void setPublishQueuePersistance(String publishQueuePersistance) {
695
696        if (m_frozen) {
697            throw new CmsRuntimeException(Messages.get().container(Messages.ERR_CONFIG_FROZEN_0));
698        }
699        m_publishQueuePersistance = Boolean.valueOf(publishQueuePersistance).booleanValue();
700    }
701
702    /**
703     * Sets the publish queue shutdown time.
704     *
705     * @param publishQueueShutdowntime the shutdown time to set, parsed as <code>int</code>
706     */
707    public void setPublishQueueShutdowntime(String publishQueueShutdowntime) {
708
709        if (m_frozen) {
710            throw new CmsRuntimeException(Messages.get().container(Messages.ERR_CONFIG_FROZEN_0));
711        }
712        m_publishQueueShutdowntime = Integer.parseInt(publishQueueShutdowntime);
713    }
714
715    /**
716     * Sets the security manager during initialization.<p>
717     *
718     * @param securityManager the security manager
719     */
720    public void setSecurityManager(CmsSecurityManager securityManager) {
721
722        if (m_frozen) {
723            throw new CmsRuntimeException(Messages.get().container(Messages.ERR_CONFIG_FROZEN_0));
724        }
725        m_securityManager = securityManager;
726    }
727
728    /**
729     * Starts publishing of enqueued publish jobs.<p>
730     */
731    public void startPublishing() {
732
733        m_publishEngine.startEngine();
734    }
735
736    /**
737     * Stops the publishing of enqueued publish jobs.<p>
738     */
739    public void stopPublishing() {
740
741        m_publishEngine.stopEngine();
742    }
743
744    /**
745     * Validates the relations for the given resources.<p>
746     *
747     * @param cms the cms request context
748     * @param publishList the publish list to validate against the online project
749     * @param report a report to write the messages to
750     *
751     * @return a map with lists of invalid links
752     *          (<code>{@link org.opencms.relations.CmsRelation}}</code> objects)
753     *          keyed by root paths
754     *
755     * TODO: change return value to List of CmsRelation
756     *
757     * @throws Exception if something goes wrong
758     */
759    public Map<String, List<CmsRelation>> validateRelations(
760        CmsObject cms,
761        CmsPublishList publishList,
762        I_CmsReport report) throws Exception {
763
764        return m_securityManager.validateRelations(cms.getRequestContext(), publishList, report);
765    }
766
767    /**
768     * Waits until no publish jobs remain.<p>
769     */
770    public void waitWhileRunning() {
771
772        waitWhileRunning(Long.MAX_VALUE);
773    }
774
775    /**
776     * Waits until no publish jobs remain or the given max milliseconds.<p>
777     *
778     * @param ms the max milliseconds to wait
779     */
780    public void waitWhileRunning(long ms) {
781
782        int i = 0;
783        // wait until it is done or time is over
784        synchronized (this) {
785            try {
786                Thread.sleep(100); // wait a bit to give the publish engine the chance to actualize the state
787            } catch (InterruptedException e) {
788                // ignore
789                e.printStackTrace();
790            }
791            while (isRunning() && ((MS_ONE_SECOND * i) <= ms)) {
792                try {
793                    Thread.sleep(MS_ONE_SECOND); // wait a second
794                } catch (InterruptedException e) {
795                    // ignore
796                    e.printStackTrace();
797                }
798                i++;
799            }
800        }
801    }
802
803    /**
804     * Returns the currently used publish engine.<p>
805     *
806     * @return the publish engine
807     */
808    protected CmsPublishEngine getEngine() {
809
810        return m_publishEngine;
811    }
812}