KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectstyle > cayenne > modeler > util > LongRunningTask


1 /* ====================================================================
2  *
3  * The ObjectStyle Group Software License, version 1.1
4  * ObjectStyle Group - http://objectstyle.org/
5  *
6  * Copyright (c) 2002-2005, Andrei (Andrus) Adamchik and individual authors
7  * of the software. All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in
18  * the documentation and/or other materials provided with the
19  * distribution.
20  *
21  * 3. The end-user documentation included with the redistribution, if any,
22  * must include the following acknowlegement:
23  * "This product includes software developed by independent contributors
24  * and hosted on ObjectStyle Group web site (http://objectstyle.org/)."
25  * Alternately, this acknowlegement may appear in the software itself,
26  * if and wherever such third-party acknowlegements normally appear.
27  *
28  * 4. The names "ObjectStyle Group" and "Cayenne" must not be used to endorse
29  * or promote products derived from this software without prior written
30  * permission. For written permission, email
31  * "andrus at objectstyle dot org".
32  *
33  * 5. Products derived from this software may not be called "ObjectStyle"
34  * or "Cayenne", nor may "ObjectStyle" or "Cayenne" appear in their
35  * names without prior written permission.
36  *
37  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40  * DISCLAIMED. IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
41  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48  * SUCH DAMAGE.
49  * ====================================================================
50  *
51  * This software consists of voluntary contributions made by many
52  * individuals and hosted on ObjectStyle Group web site. For more
53  * information on the ObjectStyle Group, please see
54  * <http://objectstyle.org/>.
55  */

56 package org.objectstyle.cayenne.modeler.util;
57
58 import java.awt.event.ActionEvent JavaDoc;
59 import java.awt.event.ActionListener JavaDoc;
60
61 import javax.swing.JFrame JavaDoc;
62 import javax.swing.JProgressBar JavaDoc;
63 import javax.swing.SwingUtilities JavaDoc;
64 import javax.swing.Timer JavaDoc;
65
66 import org.apache.log4j.Logger;
67 import org.objectstyle.cayenne.CayenneRuntimeException;
68
69 /**
70  * A base class for monitoring progress of long running tasks. It can runshowing the exact
71  * percentage of the task progress or in "indeterminate" mode.
72  * <p>
73  * <i>Warning: If the task started via "startAndWait()", caller must ensure that she is
74  * not running in the Swing EventDispatchThread, otherwise an exception is thrown, as the
75  * EvenDispatchThread will be blocked, preventing LongRunningTask from showing progress
76  * dialog. </i>
77  * </p>
78  *
79  * @author Andrei Adamchik
80  */

81 public abstract class LongRunningTask {
82
83     private static final Logger logObj = Logger.getLogger(LongRunningTask.class);
84
85     protected static final int DEFAULT_MS_TO_DECIDE_TO_POPUP = 500;
86
87     protected ProgressDialog dialog;
88     protected JFrame JavaDoc frame;
89     protected String JavaDoc title;
90     protected Timer JavaDoc taskPollingTimer;
91     protected boolean canceled;
92     protected int minValue;
93     protected int maxValue;
94     protected boolean finished;
95
96     public LongRunningTask(JFrame JavaDoc frame, String JavaDoc title) {
97         this.frame = frame;
98         this.title = title;
99     }
100
101     /**
102      * Starts current task, and blocks current thread until the task is done.
103      */

104     public synchronized void startAndWait() {
105         // running from Event Dispatch Thread is bad, as this will block the timers...
106
if (SwingUtilities.isEventDispatchThread()) {
107             throw new CayenneRuntimeException(
108                     "Can't block EventDispatchThread. Call 'startAndWait' from another thread.");
109         }
110
111         start();
112
113         if (finished) {
114             return;
115         }
116
117         try {
118             wait();
119         }
120         catch (InterruptedException JavaDoc e) {
121             setCanceled(true);
122         }
123
124         notifyAll();
125     }
126
127     /**
128      * Configures the task to run in a separate thread, and immediately exits the method.
129      * This method is allowed to be invoked from EventDispatchThread.
130      */

131     public void start() {
132         // prepare...
133
setCanceled(false);
134         this.finished = false;
135
136         Thread JavaDoc task = new Thread JavaDoc(new Runnable JavaDoc() {
137
138             public void run() {
139                 internalExecute();
140             }
141         });
142
143         Timer JavaDoc progressDisplayTimer = new Timer JavaDoc(
144                 DEFAULT_MS_TO_DECIDE_TO_POPUP,
145                 new ActionListener JavaDoc() {
146
147                     public void actionPerformed(ActionEvent JavaDoc e) {
148                         showProgress();
149                     }
150                 });
151
152         progressDisplayTimer.setRepeats(false);
153
154         // start
155
progressDisplayTimer.start();
156         task.start();
157     }
158
159     /**
160      * Starts progress dialog if the task is not finished yet.
161      */

162     protected synchronized void showProgress() {
163         logObj.debug("will show progress...");
164
165         if (finished) {
166             return;
167         }
168
169         int currentValue = getCurrentValue();
170
171         if (!isCanceled() && currentValue < getMaxValue()) {
172
173             logObj.debug("task still in progress, will show progress dialog...");
174             this.dialog = new ProgressDialog(frame, "Progress...", title);
175             this.dialog.getCancelButton().addActionListener(new ActionListener JavaDoc() {
176
177                 public void actionPerformed(ActionEvent JavaDoc e) {
178                     setCanceled(true);
179                 }
180             });
181
182             dialog.getProgressBar().setMinimum(getMinValue());
183             dialog.getProgressBar().setMaximum(getMaxValue());
184             updateProgress();
185
186             this.taskPollingTimer = new Timer JavaDoc(500, new ActionListener JavaDoc() {
187
188                 public void actionPerformed(ActionEvent JavaDoc e) {
189                     updateProgress();
190                 }
191             });
192
193             this.taskPollingTimer.start();
194             this.dialog.setVisible(true);
195         }
196     }
197
198     /**
199      * Updates current state of the progress dialog.
200      */

201     protected void updateProgress() {
202         if (isCanceled()) {
203             stop();
204             return;
205         }
206
207         dialog.getStatusLabel().setText(getCurrentNote());
208
209         JProgressBar JavaDoc progressBar = dialog.getProgressBar();
210         if (!isIndeterminate()) {
211             progressBar.setValue(getCurrentValue());
212             progressBar.setIndeterminate(false);
213         }
214         else {
215             progressBar.setIndeterminate(true);
216         }
217     }
218
219     protected synchronized void stop() {
220         if (taskPollingTimer != null) {
221             taskPollingTimer.stop();
222         }
223
224         if (dialog != null) {
225             dialog.dispose();
226         }
227
228         // there maybe other threads waiting on this task to finish...
229
finished = true;
230         notifyAll();
231     }
232
233     public boolean isFinished() {
234         return finished;
235     }
236
237     public boolean isCanceled() {
238         return canceled;
239     }
240
241     public void setCanceled(boolean b) {
242         if (b) {
243             logObj.debug("task canceled");
244         }
245
246         this.canceled = b;
247     }
248
249     protected void internalExecute() {
250         try {
251             execute();
252         }
253         catch (Throwable JavaDoc th) {
254             setCanceled(true);
255             logObj.warn("task error", th);
256         }
257         finally {
258             stop();
259         }
260     }
261
262     /**
263      * Runs the actual task, consulting "isCanceled()" state to make sure that the task
264      * wasn't canceled.
265      */

266     protected abstract void execute();
267
268     protected abstract String JavaDoc getCurrentNote();
269
270     protected abstract int getCurrentValue();
271
272     protected abstract boolean isIndeterminate();
273
274     public int getMaxValue() {
275         return maxValue;
276     }
277
278     public void setMaxValue(int maxValue) {
279         this.maxValue = maxValue;
280     }
281
282     public int getMinValue() {
283         return minValue;
284     }
285
286     public void setMinValue(int minValue) {
287         this.minValue = minValue;
288     }
289 }
Popular Tags