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.report;
029
030import org.opencms.file.CmsObject;
031import org.opencms.main.OpenCms;
032import org.opencms.util.CmsUUID;
033
034import java.util.List;
035import java.util.Locale;
036
037/**
038 * Provides a common Thread class for the reports.<p>
039 *
040 * @since 6.0.0
041 */
042public abstract class A_CmsReportThread extends Thread implements I_CmsReportThread {
043
044    /** The OpenCms request context to use. */
045    private CmsObject m_cms;
046
047    /** Indicates if the thread was already checked by the grim reaper. */
048    private boolean m_doomed;
049
050    /** The id of this report. */
051    private CmsUUID m_id;
052
053    /** The report that belongs to the thread. */
054    protected I_CmsReport m_report;
055
056    /** The time this report is running. */
057    private long m_starttime;
058
059    /**
060     * Constructs a new report Thread with the given name.<p>
061     *
062     * @param cms the current OpenCms context object
063     * @param name the name of the Thread
064     */
065    protected A_CmsReportThread(CmsObject cms, String name) {
066
067        super(OpenCms.getThreadStore().getThreadGroup(), name);
068        // report Threads are never daemon Threads
069        setDaemon(false);
070        // the session in the cms context must not be updated when it is used in a report
071        m_cms = cms;
072        m_cms.getRequestContext().setUpdateSessionEnabled(false);
073        // generate the report Thread id
074        m_id = new CmsUUID();
075        setName(name + " [" + m_id + "]");
076        // new Threads are not doomed
077        m_doomed = false;
078        // set start time
079        m_starttime = System.currentTimeMillis();
080        // add this Thread to the main Thread store
081        OpenCms.getThreadStore().addThread(this);
082    }
083
084    /**
085     * Adds an error object to the list of errors that occurred during the report.<p>
086     *
087     * @param obj the error object
088     */
089    public void addError(Object obj) {
090
091        if (getReport() != null) {
092            getReport().addError(obj);
093        }
094    }
095
096    /**
097     * Returns the error exception in case there was an error during the execution of
098     * this Thread, null otherwise.<p>
099     *
100     * @return the error exception in case there was an error, null otherwise
101     */
102    public Throwable getError() {
103
104        return null;
105    }
106
107    /**
108     * Returns a list of all errors that occurred during the report.<p>
109     *
110     * @return an error list that occurred during the report
111     */
112    public List<Object> getErrors() {
113
114        if (getReport() != null) {
115            return getReport().getErrors();
116        } else {
117            return null;
118        }
119    }
120
121    /**
122     * Returns the time of last report entry.<p>
123     *
124     * Will return zero if no entry has been written.<p>
125     *
126     * @return time of last report entry
127     */
128    public long getLastEntryTime() {
129
130        if (getReport() == null) {
131            return 0;
132        }
133        return getReport().getLastEntryTime();
134    }
135
136    /**
137     * Returns the logger to which the report output should also be directed.<p>
138     *
139     * If this returns null, report output is not sent to a logger.
140     *
141     * @return the logger to which report output should be sent.
142     */
143    public Object getLogChannel() {
144
145        return null;
146    }
147
148    /**
149     * Returns the part of the report that is ready for output.<p>
150     *
151     * @return the part of the report that is ready for output
152     */
153    public abstract String getReportUpdate();
154
155    /**
156     * Gets the report update content using the specified report update formatter.<p>
157     *
158     * @param formatter the report update formatter
159     *
160     * @return the report output
161     */
162    public String getReportUpdate(I_CmsReportUpdateFormatter formatter) {
163
164        return getReport().getReportUpdate(formatter);
165    }
166
167    /**
168     * Returns the time this report has been running.<p>
169     *
170     * @return the time this report has been running
171     */
172    public synchronized long getRuntime() {
173
174        if (m_doomed) {
175            return m_starttime;
176        } else {
177            return System.currentTimeMillis() - m_starttime;
178        }
179    }
180
181    /**
182     * Returns the OpenCms UUID of this report thread.<p>
183     *
184     * @return the OpenCms UUID of this report thread
185     */
186    public CmsUUID getUUID() {
187
188        return m_id;
189    }
190
191    /**
192     * Returns if the report generated an error output.<p>
193     *
194     * @return true if the report generated an error, otherwise false
195     */
196    public boolean hasError() {
197
198        if (getReport() != null) {
199            return (getReport().getErrors().size() > 0);
200        } else {
201            return false;
202        }
203    }
204
205    /**
206     * Returns true if this thread is already "doomed" to be deleted.<p>
207     *
208     * A OpenCms deamon Thread (the "Grim Reaper") will collect all
209     * doomed Threads, i.e. threads that are not longer active for some
210     * time.<p>
211     *
212     * @return true if this thread is already "doomed" to be deleted
213     */
214    public synchronized boolean isDoomed() {
215
216        if (isAlive()) {
217            // as long as the Thread is still active it is never doomed
218            return false;
219        }
220        if (m_doomed) {
221            // not longer active, and already doomed, so rest in peace...
222            return true;
223        }
224        // condemn the Thread to be collected by the grim reaper next time
225        m_starttime = getRuntime();
226        m_doomed = true;
227        return false;
228    }
229
230    /**
231     * Returns the OpenCms context object this Thread is initialized with.<p>
232     *
233     * @return the OpenCms context object this Thread is initialized with
234     */
235    protected CmsObject getCms() {
236
237        return m_cms;
238    }
239
240    /**
241     * Returns the report where the output of this Thread is written to.<p>
242     *
243     * @return the report where the output of this Thread is written to
244     */
245    protected I_CmsReport getReport() {
246
247        return m_report;
248    }
249
250    /**
251     * Initialize a HTML report for this Thread.<p>
252     *
253     * @param locale the locale for the report output messages
254     */
255    protected void initHtmlReport(Locale locale) {
256
257        m_report = new CmsWorkplaceReport(locale, m_cms.getRequestContext().getSiteRoot(), getLogChannel());
258    }
259
260    /**
261     * Initialize a HTML report for this Thread.<p>
262     *
263     * This method is reserved for older report threads that still use
264     * XML templates to generate their output.<p>
265     *
266     * <em>This report type will not work correctly with the new workplace, so don't use it anymore.</em>
267     *
268     * @param locale the locale for the report output messages
269     */
270    @Deprecated
271    protected void initOldHtmlReport(Locale locale) {
272
273        m_report = new CmsHtmlReport(locale, m_cms.getRequestContext().getSiteRoot(), true, false);
274    }
275}