View Javadoc

1   /**
2    *  BlueCove - Java library for Bluetooth
3    *  Copyright (C) 2006-2008 Vlad Skarzhevskyy
4    *
5    *  Licensed to the Apache Software Foundation (ASF) under one
6    *  or more contributor license agreements.  See the NOTICE file
7    *  distributed with this work for additional information
8    *  regarding copyright ownership.  The ASF licenses this file
9    *  to you under the Apache License, Version 2.0 (the
10   *  "License"); you may not use this file except in compliance
11   *  with the License.  You may obtain a copy of the License at
12   *
13   *    http://www.apache.org/licenses/LICENSE-2.0
14   *
15   *  Unless required by applicable law or agreed to in writing,
16   *  software distributed under the License is distributed on an
17   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18   *  KIND, either express or implied.  See the License for the
19   *  specific language governing permissions and limitations
20   *  under the License.
21   *
22   *  @author vlads
23   *  @version $Id: Switcher.java 2654 2008-12-24 15:32:49Z skarzhevskyy $
24   */
25  package net.sf.bluecove;
26  
27  import java.util.Enumeration;
28  import java.util.Random;
29  import java.util.Vector;
30  
31  import javax.bluetooth.BluetoothStateException;
32  import javax.bluetooth.DiscoveryAgent;
33  import javax.bluetooth.LocalDevice;
34  
35  import org.bluecove.tester.log.Logger;
36  import org.bluecove.tester.util.RuntimeDetect;
37  
38  import net.sf.bluecove.util.BluetoothTypesInfo;
39  import net.sf.bluecove.util.CollectionUtils;
40  
41  public class Switcher implements Runnable {
42  
43  	public static TestResponderClient client;
44  
45  	private static Vector runningClients = new Vector();
46  
47  	public static TestResponderServer server;
48  
49  	private static Vector runningServers = new Vector();
50  
51  	public static int clientStartCount = 0;
52  
53  	public static int serverStartCount = 0;
54  
55  	private boolean stoped = false;
56  
57  	public Thread thread;
58  
59  	boolean isRunning = false;
60  
61  	private static Switcher instance;
62  
63  	Random random = new Random();
64  
65  	static Thread tckRFCOMMThread;
66  
67  	static Thread tckL2CALthread;
68  
69  	static Thread tckGOEPThread;
70  
71  	static Thread tckOBEXThread;
72  
73  	public Switcher() {
74  		instance = this;
75  	}
76  
77  	public static synchronized void clear() {
78  		clientStartCount = 0;
79  		serverStartCount = 0;
80  	}
81  
82  	public static void yield(TestResponderClient client) {
83  		if (instance != null) {
84  			clientShutdown();
85  			synchronized (instance) {
86  				instance.notifyAll();
87  			}
88  		}
89  	}
90  
91  	public static void yield(TestResponderServer server) {
92  		if (instance != null) {
93  			while (server.hasRunningConnections()) {
94  				try {
95  					Thread.sleep(2000);
96  				} catch (Exception e) {
97  					break;
98  				}
99  			}
100 			serverShutdown();
101 		}
102 	}
103 
104 	public static boolean isRunning() {
105 		return (instance != null) && instance.isRunning;
106 	}
107 
108 	public static boolean isRunningClient() {
109 		return ((client != null) && client.isRunning) || (!runningClients.isEmpty());
110 	}
111 
112 	public static boolean isRunningServer() {
113 		return isTCKRunning() || ((server != null) && server.isRunning());
114 	}
115 
116 	public static boolean isRunningServerClients() {
117 		return ((server != null) && (server.countClientConnections() > 0));
118 	}
119 
120 	public void run() {
121 		Logger.debug("Switcher started...");
122 		isRunning = true;
123 		try {
124 			if (!isRunningClient()) {
125 				startClient();
126 			}
127 			while (!stoped) {
128 				synchronized (this) {
129 					try {
130 						wait();
131 					} catch (InterruptedException e) {
132 						break;
133 					}
134 				}
135 				if (stoped) {
136 					break;
137 				}
138 				try {
139 					Thread.sleep(2000);
140 				} catch (Exception e) {
141 					break;
142 				}
143 				if (stoped) {
144 					break;
145 				}
146 				startServer();
147 				if (stoped) {
148 					break;
149 				}
150 				try {
151 					int sec = randomTTL(30, Configuration.serverMAXTimeSec);
152 					Logger.info("switch to client in " + sec + " sec");
153 					Thread.sleep(sec * 1000);
154 				} catch (Exception e) {
155 					break;
156 				}
157 
158 				yield(server);
159 				if (stoped) {
160 					break;
161 				}
162 				try {
163 					Thread.sleep(2000);
164 				} catch (Exception e) {
165 					break;
166 				}
167 				if (stoped) {
168 					break;
169 				}
170 				startClient();
171 
172 			}
173 		} finally {
174 			isRunning = false;
175 			Logger.info("Switcher finished!");
176 		}
177 	}
178 
179 	public int randomTTL(int min, int max) {
180 		int d = random.nextInt() % (max - min);
181 		if (d < 0) {
182 			d = -d;
183 		}
184 		return min + d;
185 	}
186 
187 	public void shutdown() {
188 		Logger.info("shutdownSwitcher");
189 		stoped = true;
190 		interruptThread(thread);
191 		synchronized (this) {
192 			notifyAll();
193 		}
194 		instance = null;
195 	}
196 
197 	public static void clientStarted(CanShutdown t) {
198 		runningClients.addElement(t);
199 	}
200 
201 	public static void clientEnds(CanShutdown t) {
202 		runningClients.removeElement(t);
203 	}
204 
205 	public static void interruptThread(Thread thread) {
206 		if (RuntimeDetect.cldcStub != null) {
207 			RuntimeDetect.cldcStub.interruptThread(thread);
208 		}
209 	}
210 
211 	public static Thread createThreadByName(String className) {
212 		try {
213 			Class c = Class.forName(className);
214 			return (Thread) c.newInstance();
215 		} catch (Throwable e) {
216 			Logger.debug(className, e);
217 			return null;
218 		}
219 	}
220 
221 	public static void startTCKAgent() {
222 		try {
223 			LocalDevice localDevice = LocalDevice.getLocalDevice();
224 			Logger.info("address:" + localDevice.getBluetoothAddress());
225 			Logger.info("name:" + localDevice.getFriendlyName());
226 			Logger.info("class:" + BluetoothTypesInfo.toString(localDevice.getDeviceClass()));
227 			localDevice.setDiscoverable(DiscoveryAgent.GIAC);
228 		} catch (BluetoothStateException e) {
229 			Logger.error("start", e);
230 			return;
231 		}
232 
233 		if (Configuration.likedTCKAgent) {
234 		    try {
235                 SwitcherTck.startTCKAgent();
236             } catch (Throwable e) {
237                 Logger.error("Error", e);
238             }
239 		}
240 	}
241 
242 	public static boolean isTCKRunning() {
243 		return (tckRFCOMMThread != null) || (tckL2CALthread != null) || (tckGOEPThread != null)
244 				|| (tckOBEXThread != null);
245 	}
246 
247 	static void stopTCK() {
248 		interruptThread(tckRFCOMMThread);
249 		tckRFCOMMThread = null;
250 
251 		interruptThread(tckL2CALthread);
252 		tckL2CALthread = null;
253 
254 		interruptThread(tckGOEPThread);
255 		tckGOEPThread = null;
256 
257 		interruptThread(tckOBEXThread);
258 		tckOBEXThread = null;
259 	}
260 
261 	public static TestResponderClient createClient() {
262 		return createClient(false);
263 	}
264 
265 	public static TestResponderClient createClient(boolean force) {
266 		try {
267 			TestResponderClient c;
268 			if ((client == null) || (force)) {
269 				c = new TestResponderClient(!force);
270 				client = c;
271 			} else {
272 				c = client;
273 			}
274 			if (!c.isRunning) {
275 				c.config.logID = "";
276 				c.configured = false;
277 				c.config.discoveryOnce = false;
278 				c.config.connectDevice = null;
279 				c.config.searchServiceRetry = true;
280 				c.config.useDiscoveredDevices = false;
281 				c.config.searchOnlyBluecoveUuid = Configuration.searchOnlyBluecoveUuid;
282 				String name = "Client" + clientStartCount++;
283 				c.thread = RuntimeDetect.cldcStub.createNamedThread(c, name);
284 				c.thread.start();
285 				return c;
286 			} else {
287 				if (RuntimeDetect.isJ2ME) {
288 					BlueCoveTestMIDlet.message("Warn", "Client is already Running");
289 				} else {
290 					Logger.warn("Client is already Running");
291 				}
292 				return null;
293 			}
294 		} catch (Throwable e) {
295 			Logger.error("start error ", e);
296 			return null;
297 		}
298 	}
299 
300 	public static void startTwoClients() {
301 		try {
302 			client = new TestResponderClient();
303 			client.configured = false;
304 			client.config.discoveryOnce = false;
305 			client.config.useDiscoveredDevices = false;
306 			client.config.searchOnlyBluecoveUuid = Configuration.searchOnlyBluecoveUuid;
307 			client.thread = new Thread(client);
308 			client.configured();
309 
310 			TestResponderClient client2 = new TestResponderClient();
311 			client2.configured = false;
312 			client2.config.discoveryOnce = false;
313 			client2.config.useDiscoveredDevices = false;
314 			client2.config.searchOnlyBluecoveUuid = Configuration.searchOnlyBluecoveUuid;
315 			client2.thread = new Thread(client2);
316 			client2.configured();
317 
318 			client.thread.start();
319 			client2.thread.start();
320 		} catch (Throwable e) {
321 			Logger.error("start error ", e);
322 		}
323 	}
324 
325 	public static void startDiscovery() {
326 		TestResponderClient client = createClient();
327 		if (client != null) {
328 			client.config.discoveryOnce = true;
329 			client.config.useDiscoveredDevices = false;
330 			client.config.searchOnlyBluecoveUuid = Configuration.discoverySearchOnlyBluecoveUuid;
331 			client.configured();
332 		}
333 	}
334 
335 	public static void startServicesSearch() {
336 		TestResponderClient client = createClient();
337 		if (client != null) {
338 			client.config.discoveryOnce = true;
339 			client.config.useDiscoveredDevices = true;
340 			client.config.searchOnlyBluecoveUuid = Configuration.discoverySearchOnlyBluecoveUuid;
341 			client.configured();
342 		}
343 	}
344 
345 	public static void startClient() {
346 		try {
347 			createClient();
348 			if (client != null) {
349 				client.configured();
350 			}
351 		} catch (Throwable e) {
352 			Logger.error("startClient", e);
353 		}
354 	}
355 
356 	public static int runClient() {
357 		createClient();
358 		if (client != null) {
359 			client.config.connectOnce = true;
360 			client.configured();
361 			try {
362 				client.thread.join();
363 			} catch (InterruptedException e) {
364 				return 2;
365 			}
366 			if (TestResponderClient.failure.countFailure > 0) {
367 				return 2;
368 			} else if (TestResponderClient.countSuccess == 0) {
369 				return 3;
370 			}
371 			return 1;
372 		} else {
373 			return 2;
374 		}
375 	}
376 
377 	public static void startClientStress() {
378 		if ((client != null) && client.isRunning) {
379 			Logger.warn("Client is already Running");
380 			return;
381 		}
382 		createClient();
383 		if (client != null) {
384 			client.runStressTest = true;
385 			client.configured();
386 		}
387 	}
388 
389 	public static void startClientLastURl() {
390 		if (Configuration.storage == null) {
391 			Logger.warn("no storage");
392 			return;
393 		}
394 		if ((client != null) && client.isRunning) {
395 			Logger.warn("Client is already Running");
396 			return;
397 		}
398 		String lastURL = Configuration.getLastServerURL();
399 		if (lastURL != null) {
400 			createClient();
401 			if (client != null) {
402 				client.config.connectURL = lastURL;
403 				client.configured();
404 			}
405 		} else {
406 			Logger.warn("no recent Connections");
407 		}
408 	}
409 
410 	public static void startClientSelectService() {
411 		if ((client != null) && client.isRunning) {
412 			Logger.warn("Client is already Running");
413 			return;
414 		}
415 		createClient();
416 		if (client != null) {
417 			client.config.connectURL = "";
418 			client.configured();
419 		}
420 	}
421 
422 	public static void startClientLastDevice() {
423 		if (Configuration.storage == null) {
424 			Logger.warn("no storage");
425 			return;
426 		}
427 		if ((client != null) && client.isRunning) {
428 			Logger.warn("Client is already Running");
429 			return;
430 		}
431 		String lastURL = Configuration.getLastServerURL();
432 		if (lastURL != null) {
433 			createClient();
434 			if (client != null) {
435 				client.config.connectDevice = BluetoothTypesInfo.extractBluetoothAddress(lastURL);
436 				client.configured();
437 			}
438 		} else {
439 			Logger.warn("no recent Connections");
440 		}
441 	}
442 
443 	public static void clientShutdown() {
444 		if (client != null) {
445 			client.shutdown();
446 			client = null;
447 		}
448 		Vector runningClientsCopy = CollectionUtils.copy(runningClients);
449 		for (Enumeration iter = runningClientsCopy.elements(); iter.hasMoreElements();) {
450 			CanShutdown t = (CanShutdown) iter.nextElement();
451 			t.shutdown();
452 		}
453 	}
454 
455 	public static void startServer() {
456 		try {
457 			if (server == null) {
458 				server = new TestResponderServer();
459 			}
460 			if (!server.isRunning()) {
461 				String name = "Server" + serverStartCount++;
462 				server.thread = RuntimeDetect.cldcStub.createNamedThread(server, name);
463 				server.thread.start();
464 			} else {
465 				if (Configuration.canCloseServer) {
466 					if (RuntimeDetect.isJ2ME) {
467 						BlueCoveTestMIDlet.message("Warn", "Server is already running");
468 					} else {
469 						Logger.warn("Server is already running");
470 					}
471 				} else {
472 					serverStartCount++;
473 					server.updateServiceRecord();
474 					TestResponderServer.setDiscoverable();
475 				}
476 			}
477 		} catch (Throwable e) {
478 			Logger.error("start error ", e);
479 		}
480 	}
481 
482 	public static void serverShutdown() {
483 		if (Configuration.canCloseServer) {
484 			serverShutdownForce();
485 		} else {
486 			TestResponderServer.setNotDiscoverable();
487 		}
488 		stopTCK();
489 	}
490 
491 	public static void serverShutdownOnExit() {
492 		serverShutdownForce();
493 	}
494 
495 	public static void serverShutdownForce() {
496 		if (server != null) {
497 			server.shutdown();
498 			server = null;
499 		}
500 	}
501 
502 	public static void closeServerClientConnections() {
503 		if (server != null) {
504 			server.closeServerClientConnections();
505 		}
506 	}
507 
508 }