1   /**
2    * JHylaFax - A java client for HylaFAX.
3    *
4    * Copyright (C) 2005 by Steffen Pingel <steffenp@gmx.de>
5    *
6    * This program is free software; you can redistribute it and/or modify
7    * it under the terms of the GNU General Public License as published by
8    * the Free Software Foundation; either version 2 of the License, or
9    * (at your option) any later version.
10   *
11   * This program is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   * GNU General Public License for more details.
15   *
16   * You should have received a copy of the GNU General Public License
17   * along with this program; if not, write to the Free Software
18   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19   */
20  package net.sf.jhylafax;
21  
22  import static net.sf.jhylafax.JHylaFAX.i18n;
23  import java.lang.reflect.InvocationTargetException;
24  import java.util.LinkedList;
25  import javax.swing.JDialog;
26  import javax.swing.SwingUtilities;
27  import org.xnap.commons.gui.ProgressDialog;
28  import org.xnap.commons.io.Job;
29  import org.xnap.commons.io.UserAbortProgressMonitor;
30  
31  public class JobQueue {
32  	
33  	private boolean jobRunning = false;
34  	private long lastUpdate;
35  	private LinkedList<Notification> notificationQueue = new LinkedList<Notification>();
36  	
37  	@SuppressWarnings("unchecked")
38  	public <T> T runJob(JDialog owner, final Job<T> job) throws Exception {
39  		if (jobRunning) {
40  			throw new RuntimeException("Concurrent job invocation");
41  		}
42  		
43  		final Object[] retSuccess = new Object[1];
44  		final Throwable[] ret = new Exception[1];
45  		final ProgressDialog dialog;
46  		
47  		if (owner != null) { dialog = new ProgressDialog(owner); } 
48  		else { dialog = new ProgressDialog(JHylaFAX.getInstance()); }
49  
50  		Runnable runner = new Runnable() {
51  			public void run()
52  			{
53  				try {
54  					retSuccess[0] = job.run(new UserAbortProgressMonitor(dialog));
55  				}
56  				catch (Throwable e) {
57  					ret[0] = e;
58  				}
59  				SwingUtilities.invokeLater(new Runnable() {
60  					public void run() {
61  						dialog.done();
62  					}
63  				});
64  			}
65  		};
66  
67          // make sure no other jobs are started
68          jobRunning = true;
69          
70  		Thread t = new Thread(runner, "Job");
71  		t.start();
72  		
73  		// show blocking dialog
74  		if (owner != null) { dialog.setLocationRelativeTo(owner); } 
75  		else { dialog.setLocationRelativeTo(JHylaFAX.getInstance()); }
76  		dialog.setTitle(i18n.tr("HylaFAX Server"));
77  		dialog.setModal(true);
78  		dialog.showDialog();
79  			
80  		// at this point t is guranteed to be finished
81  		jobRunning = false;
82  		
83  		// XXX what if the errordialog is displayed?
84  		processNotifications();
85  		
86  		if (ret[0] != null) {
87  			if (ret[0] instanceof Exception) {
88  				throw (Exception)ret[0];
89  			}
90  			else {
91  				throw new InvocationTargetException(ret[0]);
92  			}
93  		}
94  		return (T)retSuccess[0];
95  	}
96  	
97  	public void setLastUpdate(long lastUpdate)
98  	{
99  		this.lastUpdate = lastUpdate;
100 	}
101 	
102 	public boolean isJobRunning()
103 	{
104 		return jobRunning;
105 	}
106 
107 	public void addNotification(final Notification notification)
108 	{
109 		SwingUtilities.invokeLater(new Runnable() {
110 			public void run()
111 			{
112 				if (isJobRunning()) {
113 					addNotificationInternal(notification);
114 				}
115 				else {
116 					runNotification(notification);
117 				}
118 			}
119 		});
120 	}
121 	
122 	protected void runNotification(Notification notification)
123 	{
124 		notification.run();
125 	}
126 
127 	private void addNotificationInternal(Notification notification)
128 	{
129 		notificationQueue.add(notification);
130 	}
131 	
132 	private void processNotifications()
133 	{
134 		if (isJobRunning()) {
135 			throw new IllegalStateException();
136 		}
137 		
138 		while (!notificationQueue.isEmpty()) {
139 			Notification notification = notificationQueue.removeFirst();
140 			runNotification(notification);
141 		}
142 	}
143 	
144 }