Adding in new TaskEngine (I stole it from Matt)

git-svn-id: http://svn.igniterealtime.org/svn/repos/spark/trunk@7571 b35dd754-fafc-0310-a699-88a17e54d16e
This commit is contained in:
Derek DeMoro
2007-03-16 04:44:51 +00:00
committed by derek
parent 0e8f6a06ee
commit cd03301b33
8 changed files with 387 additions and 79 deletions

View File

@ -11,6 +11,7 @@
package org.jivesoftware.spark;
import org.jivesoftware.resource.SoundsRes;
import org.jivesoftware.spark.util.TaskEngine;
import org.jivesoftware.spark.util.log.Log;
import java.applet.Applet;
@ -59,7 +60,10 @@ public class SoundManager {
*
* @param clip the audioclip to play.
*/
public void playClip(AudioClip clip) {
public void playClip(final AudioClip clip) {
final Runnable playThread = new Runnable() {
public void run() {
try {
clip.play();
}
@ -67,6 +71,10 @@ public class SoundManager {
System.err.println("Unable to load sound file");
}
}
};
TaskEngine.getInstance().submit(playThread);
}
/**
* Plays an AudioClip.
@ -89,7 +97,7 @@ public class SoundManager {
* @param soundFile the File object representing the wav file.
*/
public void playClip(final File soundFile) {
Thread soundThread = new Thread(new Runnable() {
final Runnable playThread = new Runnable() {
public void run() {
try {
final URL url = soundFile.toURL();
@ -104,9 +112,9 @@ public class SoundManager {
Log.error(e);
}
}
});
};
soundThread.start();
TaskEngine.getInstance().submit(playThread);
}
/**

View File

@ -23,6 +23,7 @@ import org.jivesoftware.smackx.debugger.EnhancedDebuggerWindow;
import org.jivesoftware.smackx.packet.DelayInformation;
import org.jivesoftware.spark.component.tabbedPane.SparkTabbedPane;
import org.jivesoftware.spark.filetransfer.SparkTransferManager;
import org.jivesoftware.spark.phone.PhoneManager;
import org.jivesoftware.spark.search.SearchManager;
import org.jivesoftware.spark.ui.ChatContainer;
import org.jivesoftware.spark.ui.ChatRoom;
@ -32,9 +33,8 @@ import org.jivesoftware.spark.ui.ContactItem;
import org.jivesoftware.spark.ui.ContactList;
import org.jivesoftware.spark.ui.conferences.ConferencePlugin;
import org.jivesoftware.spark.ui.status.StatusBar;
import org.jivesoftware.spark.util.SwingWorker;
import org.jivesoftware.spark.util.TaskEngine;
import org.jivesoftware.spark.util.log.Log;
import org.jivesoftware.spark.phone.PhoneManager;
import org.jivesoftware.sparkimpl.plugin.manager.Enterprise;
import org.jivesoftware.sparkimpl.plugin.transcripts.ChatTranscriptPlugin;
@ -45,9 +45,7 @@ import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.AbstractAction;
@ -236,32 +234,17 @@ public class Workspace extends JPanel implements PacketListener {
final Presence presence = SparkManager.getWorkspace().getStatusBar().getPresence();
SparkManager.getSessionManager().changePresence(presence);
// Load Plugins
SwingWorker worker = new SwingWorker() {
public Object construct() {
try {
Thread.sleep(2000);
}
catch (InterruptedException e) {
Log.error("Unable to sleep thread.", e);
}
return "ok";
}
public void finished() {
// Schedule loading of the plugins after two seconds.
TaskEngine.getInstance().schedule(new TimerTask() {
public void run() {
final PluginManager pluginManager = PluginManager.getInstance();
pluginManager.loadPlugins();
pluginManager.initializePlugins();
}
};
worker.start();
}, 2000);
int numberOfMillisecondsInTheFuture = 10000; // 5 sec
Date timeToRun = new Date(System.currentTimeMillis() + numberOfMillisecondsInTheFuture);
Timer timer = new Timer();
timer.schedule(new TimerTask() {
// Load the offline messages after 10 seconds.
TaskEngine.getInstance().schedule(new TimerTask() {
public void run() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
@ -273,7 +256,7 @@ public class Workspace extends JPanel implements PacketListener {
}
});
}
}, timeToRun);
}, 10000);
}

View File

@ -23,6 +23,7 @@ import org.jivesoftware.spark.PresenceManager;
import org.jivesoftware.spark.SparkManager;
import org.jivesoftware.spark.util.GraphicUtils;
import org.jivesoftware.spark.util.ModelUtil;
import org.jivesoftware.spark.util.TaskEngine;
import org.jivesoftware.spark.util.log.Log;
import org.jivesoftware.sparkimpl.profile.VCardManager;
@ -295,7 +296,7 @@ public class ContactItem extends JPanel {
* @param hash the new hash.
*/
private void updateAvatar(final String hash) {
Thread updateAvatarThread = new Thread(new Runnable() {
Runnable updateRunnable = new Runnable() {
public void run() {
contactsDir.mkdirs();
@ -318,9 +319,9 @@ public class ContactItem extends JPanel {
Log.error("Unable to update avatar in Contact Item.", e);
}
}
});
};
updateAvatarThread.start();
TaskEngine.getInstance().submit(updateRunnable);
}
public String toString() {

View File

@ -0,0 +1,307 @@
/**
* $Revision: 4005 $
* $Date: 2006-06-16 08:58:27 -0700 (Fri, 16 Jun 2006) $
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.spark.util;
import java.util.Date;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Performs tasks using worker threads. It also allows tasks to be scheduled to be
* run at future dates. This class mimics relevant methods in both
* {@link ExecutorService} and {@link Timer}. Any {@link TimerTask} that's
* scheduled to be run in the future will automatically be run using the thread
* executor's thread pool. This means that the standard restriction that TimerTasks
* should run quickly does not apply.
*
* @author Matt Tucker
*/
public class TaskEngine {
private static TaskEngine instance = new TaskEngine();
/**
* Returns a task engine instance (singleton).
*
* @return a task engine.
*/
public static TaskEngine getInstance() {
return instance;
}
private Timer timer;
private ExecutorService executor;
private Map<TimerTask, TimerTaskWrapper> wrappedTasks = new ConcurrentHashMap<TimerTask, TimerTaskWrapper>();
/**
* Constructs a new task engine.
*/
private TaskEngine() {
timer = new Timer("timer-spark", true);
executor = Executors.newCachedThreadPool(new ThreadFactory() {
final AtomicInteger threadNumber = new AtomicInteger(1);
public Thread newThread(Runnable runnable) {
// Use our own naming scheme for the threads.
Thread thread = new Thread(Thread.currentThread().getThreadGroup(), runnable,
"pool-spark" + threadNumber.getAndIncrement(), 0);
// Make workers daemon threads.
thread.setDaemon(true);
if (thread.getPriority() != Thread.NORM_PRIORITY) {
thread.setPriority(Thread.NORM_PRIORITY);
}
return thread;
}
});
}
/**
* Submits a Runnable task for execution and returns a Future
* representing that task.
*
* @param task the task to submit.
* @return a Future representing pending completion of the task,
* and whose <tt>get()</tt> method will return <tt>null</tt>
* upon completion.
* @throws java.util.concurrent.RejectedExecutionException
* if task cannot be scheduled
* for execution.
* @throws NullPointerException if task null.
*/
public Future<?> submit(Runnable task) {
return executor.submit(task);
}
/**
* Schedules the specified task for execution after the specified delay.
*
* @param task task to be scheduled.
* @param delay delay in milliseconds before task is to be executed.
* @throws IllegalArgumentException if <tt>delay</tt> is negative, or
* <tt>delay + System.currentTimeMillis()</tt> is negative.
* @throws IllegalStateException if task was already scheduled or
* cancelled, or timer was cancelled.
*/
public void schedule(TimerTask task, long delay) {
timer.schedule(new TimerTaskWrapper(task), delay);
}
/**
* Schedules the specified task for execution at the specified time. If
* the time is in the past, the task is scheduled for immediate execution.
*
* @param task task to be scheduled.
* @param time time at which task is to be executed.
* @throws IllegalArgumentException if <tt>time.getTime()</tt> is negative.
* @throws IllegalStateException if task was already scheduled or
* cancelled, timer was cancelled, or timer thread terminated.
*/
public void schedule(TimerTask task, Date time) {
timer.schedule(new TimerTaskWrapper(task), time);
}
/**
* Schedules the specified task for repeated <i>fixed-delay execution</i>,
* beginning after the specified delay. Subsequent executions take place
* at approximately regular intervals separated by the specified period.
* <p/>
* <p>In fixed-delay execution, each execution is scheduled relative to
* the actual execution time of the previous execution. If an execution
* is delayed for any reason (such as garbage collection or other
* background activity), subsequent executions will be delayed as well.
* In the long run, the frequency of execution will generally be slightly
* lower than the reciprocal of the specified period (assuming the system
* clock underlying <tt>Object.wait(long)</tt> is accurate).
* <p/>
* <p>Fixed-delay execution is appropriate for recurring activities
* that require "smoothness." In other words, it is appropriate for
* activities where it is more important to keep the frequency accurate
* in the short run than in the long run. This includes most animation
* tasks, such as blinking a cursor at regular intervals. It also includes
* tasks wherein regular activity is performed in response to human
* input, such as automatically repeating a character as long as a key
* is held down.
*
* @param task task to be scheduled.
* @param delay delay in milliseconds before task is to be executed.
* @param period time in milliseconds between successive task executions.
* @throws IllegalArgumentException if <tt>delay</tt> is negative, or
* <tt>delay + System.currentTimeMillis()</tt> is negative.
* @throws IllegalStateException if task was already scheduled or
* cancelled, timer was cancelled, or timer thread terminated.
*/
public void schedule(TimerTask task, long delay, long period) {
TimerTaskWrapper taskWrapper = new TimerTaskWrapper(task);
wrappedTasks.put(task, taskWrapper);
timer.schedule(taskWrapper, delay, period);
}
/**
* Schedules the specified task for repeated <i>fixed-delay execution</i>,
* beginning at the specified time. Subsequent executions take place at
* approximately regular intervals, separated by the specified period.
* <p/>
* <p>In fixed-delay execution, each execution is scheduled relative to
* the actual execution time of the previous execution. If an execution
* is delayed for any reason (such as garbage collection or other
* background activity), subsequent executions will be delayed as well.
* In the long run, the frequency of execution will generally be slightly
* lower than the reciprocal of the specified period (assuming the system
* clock underlying <tt>Object.wait(long)</tt> is accurate).
* <p/>
* <p>Fixed-delay execution is appropriate for recurring activities
* that require "smoothness." In other words, it is appropriate for
* activities where it is more important to keep the frequency accurate
* in the short run than in the long run. This includes most animation
* tasks, such as blinking a cursor at regular intervals. It also includes
* tasks wherein regular activity is performed in response to human
* input, such as automatically repeating a character as long as a key
* is held down.
*
* @param task task to be scheduled.
* @param firstTime First time at which task is to be executed.
* @param period time in milliseconds between successive task executions.
* @throws IllegalArgumentException if <tt>time.getTime()</tt> is negative.
* @throws IllegalStateException if task was already scheduled or
* cancelled, timer was cancelled, or timer thread terminated.
*/
public void schedule(TimerTask task, Date firstTime, long period) {
TimerTaskWrapper taskWrapper = new TimerTaskWrapper(task);
wrappedTasks.put(task, taskWrapper);
timer.schedule(taskWrapper, firstTime, period);
}
/**
* Schedules the specified task for repeated <i>fixed-rate execution</i>,
* beginning after the specified delay. Subsequent executions take place
* at approximately regular intervals, separated by the specified period.
* <p/>
* <p>In fixed-rate execution, each execution is scheduled relative to the
* scheduled execution time of the initial execution. If an execution is
* delayed for any reason (such as garbage collection or other background
* activity), two or more executions will occur in rapid succession to
* "catch up." In the long run, the frequency of execution will be
* exactly the reciprocal of the specified period (assuming the system
* clock underlying <tt>Object.wait(long)</tt> is accurate).
* <p/>
* <p>Fixed-rate execution is appropriate for recurring activities that
* are sensitive to <i>absolute</i> time, such as ringing a chime every
* hour on the hour, or running scheduled maintenance every day at a
* particular time. It is also appropriate for recurring activities
* where the total time to perform a fixed number of executions is
* important, such as a countdown timer that ticks once every second for
* ten seconds. Finally, fixed-rate execution is appropriate for
* scheduling multiple repeating timer tasks that must remain synchronized
* with respect to one another.
*
* @param task task to be scheduled.
* @param delay delay in milliseconds before task is to be executed.
* @param period time in milliseconds between successive task executions.
* @throws IllegalArgumentException if <tt>delay</tt> is negative, or
* <tt>delay + System.currentTimeMillis()</tt> is negative.
* @throws IllegalStateException if task was already scheduled or
* cancelled, timer was cancelled, or timer thread terminated.
*/
public void scheduleAtFixedRate(TimerTask task, long delay, long period) {
TimerTaskWrapper taskWrapper = new TimerTaskWrapper(task);
wrappedTasks.put(task, taskWrapper);
timer.scheduleAtFixedRate(taskWrapper, delay, period);
}
/**
* Schedules the specified task for repeated <i>fixed-rate execution</i>,
* beginning at the specified time. Subsequent executions take place at
* approximately regular intervals, separated by the specified period.
* <p/>
* <p>In fixed-rate execution, each execution is scheduled relative to the
* scheduled execution time of the initial execution. If an execution is
* delayed for any reason (such as garbage collection or other background
* activity), two or more executions will occur in rapid succession to
* "catch up." In the long run, the frequency of execution will be
* exactly the reciprocal of the specified period (assuming the system
* clock underlying <tt>Object.wait(long)</tt> is accurate).
* <p/>
* <p>Fixed-rate execution is appropriate for recurring activities that
* are sensitive to <i>absolute</i> time, such as ringing a chime every
* hour on the hour, or running scheduled maintenance every day at a
* particular time. It is also appropriate for recurring activities
* where the total time to perform a fixed number of executions is
* important, such as a countdown timer that ticks once every second for
* ten seconds. Finally, fixed-rate execution is appropriate for
* scheduling multiple repeating timer tasks that must remain synchronized
* with respect to one another.
*
* @param task task to be scheduled.
* @param firstTime First time at which task is to be executed.
* @param period time in milliseconds between successive task executions.
* @throws IllegalArgumentException if <tt>time.getTime()</tt> is negative.
* @throws IllegalStateException if task was already scheduled or
* cancelled, timer was cancelled, or timer thread terminated.
*/
public void scheduleAtFixedRate(TimerTask task, Date firstTime, long period) {
TimerTaskWrapper taskWrapper = new TimerTaskWrapper(task);
wrappedTasks.put(task, taskWrapper);
timer.scheduleAtFixedRate(taskWrapper, firstTime, period);
}
/**
* Cancels the execution of a scheduled task. {@link java.util.TimerTask#cancel()}
*
* @param task the scheduled task to cancel.
*/
public void cancelScheduledTask(TimerTask task) {
TaskEngine.TimerTaskWrapper taskWrapper = wrappedTasks.remove(task);
if (taskWrapper != null) {
taskWrapper.cancel();
}
}
/**
* Shuts down the task engine service.
*/
public void shutdown() {
if (executor != null) {
executor.shutdownNow();
executor = null;
}
if (timer != null) {
timer.cancel();
timer = null;
}
}
/**
* Wrapper class for a standard TimerTask. It simply executes the TimerTask
* using the executor's thread pool.
*/
private class TimerTaskWrapper extends TimerTask {
private TimerTask task;
public TimerTaskWrapper(TimerTask task) {
this.task = task;
}
public void run() {
executor.submit(task);
}
}
}

View File

@ -23,6 +23,7 @@ import org.jivesoftware.smackx.ServiceDiscoveryManager;
import org.jivesoftware.smackx.packet.DiscoverInfo;
import org.jivesoftware.spark.SparkManager;
import org.jivesoftware.spark.util.log.Log;
import org.jivesoftware.spark.util.TaskEngine;
import org.jivesoftware.sparkimpl.plugin.gateways.GatewayPrivateData;
import java.util.Collection;
@ -43,14 +44,20 @@ public class TransportUtils {
static {
PrivateDataManager.addPrivateDataProvider(GatewayPrivateData.ELEMENT, GatewayPrivateData.NAMESPACE, new GatewayPrivateData.ConferencePrivateDataProvider());
PrivateDataManager pdm = SparkManager.getSessionManager().getPersonalDataManager();
final Runnable loadGateways = new Runnable() {
public void run() {
try {
PrivateDataManager pdm = SparkManager.getSessionManager().getPersonalDataManager();
gatewayPreferences = (GatewayPrivateData)pdm.getPrivateData(GatewayPrivateData.ELEMENT, GatewayPrivateData.NAMESPACE);
}
catch (XMPPException e) {
Log.error("Unable to load private data for Gateways", e);
}
}
};
TaskEngine.getInstance().submit(loadGateways);
}
public static boolean autoJoinService(String serviceName) {
return gatewayPreferences.autoLogin(serviceName);

View File

@ -35,9 +35,16 @@ import org.jivesoftware.spark.ui.rooms.ChatRoomImpl;
import org.jivesoftware.spark.util.ModelUtil;
import org.jivesoftware.spark.util.ResourceUtils;
import org.jivesoftware.spark.util.SwingWorker;
import org.jivesoftware.spark.util.TaskEngine;
import org.jivesoftware.spark.util.log.Log;
import org.jivesoftware.sparkimpl.plugin.alerts.SparkToaster;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JFrame;
@ -45,12 +52,6 @@ import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
public class PhonePlugin implements Plugin {
public static PhoneClient phoneClient;
private DialPanel dialPanel;
@ -260,7 +261,7 @@ public class PhonePlugin implements Plugin {
}
public void callExtension(final String number) {
Thread thread = new Thread(new Runnable() {
final Runnable caller = new Runnable() {
public void run() {
try {
phoneClient.dialByExtension(number);
@ -269,13 +270,13 @@ public class PhonePlugin implements Plugin {
Log.error(e);
}
}
});
};
thread.start();
TaskEngine.getInstance().submit(caller);
}
public void callJID(final String jid) {
Thread thread = new Thread(new Runnable() {
final Runnable caller = new Runnable() {
public void run() {
try {
phoneClient.dialByJID(jid);
@ -284,11 +285,9 @@ public class PhonePlugin implements Plugin {
Log.error(e);
}
}
});
thread.start();
};
TaskEngine.getInstance().submit(caller);
}

View File

@ -25,6 +25,7 @@ import org.jivesoftware.spark.plugin.Plugin;
import org.jivesoftware.spark.ui.ChatRoom;
import org.jivesoftware.spark.ui.ChatRoomListener;
import org.jivesoftware.spark.ui.MessageListener;
import org.jivesoftware.spark.util.TaskEngine;
import java.io.File;
@ -53,13 +54,14 @@ public class SoundPlugin implements Plugin, MessageListener, ChatRoomListener {
}
}, new PacketTypeFilter(Presence.class));
Thread thread = new Thread(new Runnable() {
// Load sound preferences.
final Runnable soundLoader = new Runnable() {
public void run() {
soundPreference.loadFromFile();
}
});
thread.start();
};
TaskEngine.getInstance().submit(soundLoader);
MultiUserChat.addInvitationListener(SparkManager.getConnection(), new InvitationListener() {
public void invitationReceived(XMPPConnection xmppConnection, String string, String string1, String string2, String string3, Message message) {

View File

@ -30,6 +30,7 @@ import org.jivesoftware.spark.util.GraphicUtils;
import org.jivesoftware.spark.util.ModelUtil;
import org.jivesoftware.spark.util.ResourceUtils;
import org.jivesoftware.spark.util.SwingWorker;
import org.jivesoftware.spark.util.TaskEngine;
import org.jivesoftware.spark.util.log.Log;
import org.jivesoftware.sparkimpl.plugin.manager.Enterprise;
import org.jivesoftware.sparkimpl.profile.ext.JabberAvatarExtension;
@ -38,13 +39,6 @@ import org.xmlpull.mxp1.MXParser;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
@ -63,6 +57,13 @@ import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
/**
* VCardManager handles all VCard loading/caching within Spark.
*
@ -154,7 +155,7 @@ public class VCardManager {
* Listens for new VCards to lookup in a queue.
*/
private void startQueueListener() {
final Thread thread = new Thread(new Runnable() {
final Runnable queueListener = new Runnable() {
public void run() {
while (true) {
try {
@ -165,10 +166,10 @@ public class VCardManager {
e.printStackTrace();
}
}
}
});
thread.start();
};
TaskEngine.getInstance().submit(queueListener);
}
/**