View Javadoc

1   /**
2    *  MicroEmulator
3    *  Copyright (C) 2006-2007 Bartek Teodorczyk <barteo@barteo.net>
4    *  Copyright (C) 2006-2007 Vlad Skarzhevskyy
5    *
6    *  This library is free software; you can redistribute it and/or
7    *  modify it under the terms of the GNU Lesser General Public
8    *  License as published by the Free Software Foundation; either
9    *  version 2.1 of the License, or (at your option) any later version.
10   *
11   *  This library 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 GNU
14   *  Lesser General Public License for more details.
15   *
16   *  You should have received a copy of the GNU Lesser General Public
17   *  License along with this library; if not, write to the Free Software
18   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19   *
20   *  @version $Id: MIDletTimer.java 1152 2007-04-14 20:22:29Z vlads $
21   */
22  package org.microemu.app.util;
23  
24  import java.util.Date;
25  import java.util.HashMap;
26  import java.util.Iterator;
27  import java.util.Map;
28  import java.util.Timer;
29  import java.util.TimerTask;
30  import java.util.WeakHashMap;
31  
32  import org.microemu.MIDletBridge;
33  import org.microemu.MIDletContext;
34  import org.microemu.log.Logger;
35  
36  /**
37   * Terminate all timers on MIDlet exit.
38   * TODO Name all the timer Threads created by MIDlet in Java 5  
39   * @author vlads
40   */
41  public class MIDletTimer extends Timer {
42  
43  	private static Map midlets = new WeakHashMap();
44  	
45  	private class OneTimeTimerTaskWrapper extends TimerTask {
46  
47  		TimerTask task;
48  		
49  		OneTimeTimerTaskWrapper(TimerTask task) {
50  			this.task = task;
51  		}
52  		
53  		public void run() {
54  			unregister(MIDletTimer.this);
55  			task.run();
56  		}
57  		
58  	}
59  	
60  	private String name;
61  	
62  	private MIDletContext midletContext;
63  	
64  	public MIDletTimer() {
65  		super();
66  		StackTraceElement[] ste = new Throwable().getStackTrace();
67  		name = ste[1].getClassName() + "." + ste[1].getMethodName(); 
68  	}
69  	
70  	public void schedule(TimerTask task, Date time) {
71  		register(this);
72  		super.schedule(new OneTimeTimerTaskWrapper(task), time);
73  	}
74  	
75  	public void schedule(TimerTask task, Date firstTime, long period) {
76  		register(this);
77  		super.schedule(task, firstTime, period);
78  	}
79  	
80  	public void schedule(TimerTask task, long delay) {
81  		register(this);
82  		super.schedule(new OneTimeTimerTaskWrapper(task), delay);
83  	}
84  	
85  	public void schedule(TimerTask task, long delay, long period) {
86  		register(this);
87  		super.schedule(task, delay, period);
88  	}
89  	
90  	public void scheduleAtFixedRate(TimerTask task, Date firstTime, long period) {
91  		register(this);
92  		super.schedule(task, firstTime, period);
93  	}
94  	
95  	public void scheduleAtFixedRate(TimerTask task, long delay, long period) {
96  		register(this);
97  		super.scheduleAtFixedRate(task, delay, period);
98  	}
99  	
100 	public void cancel() {
101     	unregister(this);
102 		super.cancel();
103 	}
104 
105 	private void terminate() {
106 		super.cancel();
107 	}
108 	
109 	private static void register(MIDletTimer timer) {
110 		if (timer.midletContext == null) {
111 			timer.midletContext = MIDletBridge.getMIDletContext();
112 		}
113 		if (timer.midletContext == null) {
114 			Logger.error("Creating Timer with no MIDlet context", new Throwable());
115 			return;
116 		}
117 		Map timers = (Map)midlets.get(timer.midletContext);
118 		if (timers == null) {
119 			// Can't use WeakHashMap Timers are disposed by JVM
120 			timers = new HashMap();
121 			midlets.put(timer.midletContext, timers);
122 		}
123 		//Logger.debug("Register timer created from [" + timer.name + "]");
124 		timers.put(timer, timer.midletContext);
125 	}
126 	
127 	private static void unregister(MIDletTimer timer) {
128 		if (timer.midletContext == null) {
129 			Logger.error("Timer with no MIDlet context", new Throwable());
130 			return;
131 		}
132 		Map timers = (Map)midlets.get(timer.midletContext);
133 		if (timers == null) {
134 			return;
135 		}
136 		//Logger.debug("Unregister timer created from [" + timer.name + "]");
137 		timers.remove(timer);
138 	}
139 	
140 	/**
141 	 * Termnate all Threads created by MIDlet
142 	 */
143 	public static void contextDestroyed(MIDletContext midletContext) {
144 		if (midletContext == null) {
145 			return;
146 		}
147 		Map timers = (Map)midlets.get(midletContext);
148 		if (timers != null) {
149 			terminateTimers(timers);
150 			midlets.remove(midletContext);
151 		}
152 	}
153 	
154 	private static void terminateTimers(Map timers) {
155 		for (Iterator iter = timers.keySet().iterator(); iter.hasNext();) {
156 			Object o = iter.next();
157 			if (o == null) {
158 				continue;
159 			}
160 			if (o instanceof MIDletTimer) {
161 				MIDletTimer tm = (MIDletTimer)o;
162 				Logger.warn("MIDlet timer created from [" + tm.name + "] still running");
163 				tm.terminate();
164 			} else {
165 				Logger.debug("unrecognized Object [" + o.getClass().getName() + "]");
166 			}
167 		};
168 	}
169 
170 }