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: Main.java 2607 2008-12-17 23:51:33Z skarzhevskyy $
24   */
25  package net.sf.bluecove.swing;
26  
27  import java.awt.Dimension;
28  import java.awt.EventQueue;
29  import java.awt.Font;
30  import java.awt.Rectangle;
31  import java.awt.Toolkit;
32  import java.awt.event.ActionEvent;
33  import java.awt.event.ActionListener;
34  import java.awt.event.KeyEvent;
35  import java.awt.event.WindowAdapter;
36  import java.awt.event.WindowEvent;
37  import java.util.Vector;
38  
39  import javax.swing.JFrame;
40  import javax.swing.JMenu;
41  import javax.swing.JMenuBar;
42  import javax.swing.JMenuItem;
43  import javax.swing.JScrollPane;
44  import javax.swing.JTextArea;
45  
46  import net.sf.bluecove.Configuration;
47  import net.sf.bluecove.Switcher;
48  import net.sf.bluecove.se.BlueCoveSpecific;
49  import net.sf.bluecove.se.FileStorage;
50  import net.sf.bluecove.se.JavaSECommon;
51  import net.sf.bluecove.se.UIHelper;
52  
53  import org.bluecove.tester.log.Logger;
54  import org.bluecove.tester.log.LoggerAppender;
55  import org.bluecove.tester.util.TimeUtils;
56  
57  /**
58   *
59   * 
60   */
61  public class Main extends JFrame implements LoggerAppender {
62  
63  	private static final long serialVersionUID = 1L;
64  
65  	private JTextArea output = null;
66  
67  	private int outputLines = 0;
68  
69  	private Vector logLinesQueue = new Vector();
70  
71  	private boolean logUpdaterRunning = false;
72  
73  	JMenuItem debugOn;
74  
75  	public static void main(String[] args) {
76  		JavaSECommon.initOnce();
77  		Configuration.storage = new FileStorage();
78  
79  		Main app = new Main();
80  		app.setVisible(true);
81  
82  		Logger.debug("Stated app");
83  		Logger.debug("OS:" + System.getProperty("os.name") + "|" + System.getProperty("os.version") + "|"
84  				+ System.getProperty("os.arch"));
85  		Logger.debug("Java:" + System.getProperty("java.vendor") + " " + System.getProperty("java.version"));
86  	}
87  
88  	Main() {
89  		addWindowListener(new WindowAdapter() {
90  			public void windowClosing(WindowEvent w) {
91  				quit();
92  			}
93  		});
94  
95  		Logger.addAppender(this);
96  		BlueCoveSpecific.addAppender(this);
97  
98  		this.setTitle("BlueCove tester");
99  
100 		final JMenuBar menuBar = new JMenuBar();
101 		setJMenuBar(menuBar);
102 		JMenu menuBluetooth = new JMenu("Bluetooth");
103 
104 		final JMenuItem serverStart = addMenu(menuBluetooth, "Server Start", new ActionListener() {
105 			public void actionPerformed(ActionEvent e) {
106 				Switcher.startServer();
107 				updateTitle();
108 			}
109 		}, KeyEvent.VK_5);
110 
111 		final JMenuItem serverStop = addMenu(menuBluetooth, "Server Stop", new ActionListener() {
112 			public void actionPerformed(ActionEvent e) {
113 				Switcher.serverShutdown();
114 			}
115 		}, KeyEvent.VK_6);
116 
117 		final JMenuItem clientStart = addMenu(menuBluetooth, "Client Start", new ActionListener() {
118 			public void actionPerformed(ActionEvent e) {
119 				Switcher.startClient();
120 				updateTitle();
121 			}
122 		}, KeyEvent.VK_2);
123 
124 		final JMenuItem clientStop = addMenu(menuBluetooth, "Client Stop", new ActionListener() {
125 			public void actionPerformed(ActionEvent e) {
126 				Switcher.clientShutdown();
127 			}
128 		}, KeyEvent.VK_3);
129 
130 		final JMenuItem tckStart;
131 		if (Configuration.likedTCKAgent) {
132 			tckStart = addMenu(menuBluetooth, "Start TCK Agent", new ActionListener() {
133 				public void actionPerformed(ActionEvent e) {
134 					Switcher.startTCKAgent();
135 				}
136 			});
137 		} else {
138 			tckStart = null;
139 		}
140 
141 		addMenu(menuBluetooth, "Discovery", new ActionListener() {
142 			public void actionPerformed(ActionEvent e) {
143 				Switcher.startDiscovery();
144 				updateTitle();
145 			}
146 		}, KeyEvent.VK_MULTIPLY);
147 
148 		addMenu(menuBluetooth, "Services Search", new ActionListener() {
149 			public void actionPerformed(ActionEvent e) {
150 				Switcher.startServicesSearch();
151 				updateTitle();
152 			}
153 		}, KeyEvent.VK_7);
154 
155 		addMenu(menuBluetooth, "Client Stress Start", new ActionListener() {
156 			public void actionPerformed(ActionEvent e) {
157 				Switcher.startClientStress();
158 				updateTitle();
159 			}
160 		});
161 
162 		addMenu(menuBluetooth, "Client selectService Start", new ActionListener() {
163 			public void actionPerformed(ActionEvent e) {
164 				Switcher.startClientSelectService();
165 				updateTitle();
166 			}
167 		});
168 
169 		addMenu(menuBluetooth, "Client Last service Start", new ActionListener() {
170 			public void actionPerformed(ActionEvent e) {
171 				Switcher.startClientLastURl();
172 				updateTitle();
173 			}
174 		});
175 
176 		addMenu(menuBluetooth, "Client Last device Start", new ActionListener() {
177 			public void actionPerformed(ActionEvent e) {
178 				Switcher.startClientLastDevice();
179 				updateTitle();
180 			}
181 		});
182 
183 		final JMenuItem stop = addMenu(menuBluetooth, "Stop all work", new ActionListener() {
184 			public void actionPerformed(ActionEvent e) {
185 				Switcher.clientShutdown();
186 				Switcher.serverShutdown();
187 			}
188 		}, KeyEvent.VK_S);
189 
190 		addMenu(menuBluetooth, "Quit", new ActionListener() {
191 			public void actionPerformed(ActionEvent e) {
192 				quit();
193 			}
194 		}, KeyEvent.VK_X);
195 
196 		menuBar.add(menuBluetooth);
197 
198 		JMenu menuLogs = new JMenu("Logs");
199 
200 		debugOn = addMenu(menuLogs, "BlueCove Debug ON", new ActionListener() {
201 			public void actionPerformed(ActionEvent e) {
202 				boolean dbg = BlueCoveSpecific.changeDebug();
203 				if (dbg) {
204 					debugOn.setText("BlueCove Debug OFF");
205 				} else {
206 					debugOn.setText("BlueCove Debug ON");
207 				}
208 			}
209 		});
210 
211 		addMenu(menuLogs, "Clear Log", new ActionListener() {
212 			public void actionPerformed(ActionEvent e) {
213 				clear();
214 			}
215 		}, KeyEvent.VK_Z);
216 
217 		addMenu(menuLogs, "Print FailureLog", new ActionListener() {
218 			public void actionPerformed(ActionEvent e) {
219 				UIHelper.printFailureLog();
220 			}
221 		}, KeyEvent.VK_4);
222 
223 		addMenu(menuLogs, "Clear Stats", new ActionListener() {
224 			public void actionPerformed(ActionEvent e) {
225 				UIHelper.clearStats();
226 			}
227 		});
228 
229 		if (JavaSECommon.isJava5()) {
230 			addMenu(menuLogs, "ThreadDump", new ActionListener() {
231 				public void actionPerformed(ActionEvent e) {
232 					JavaSECommon.threadDump();
233 				}
234 			});
235 		}
236 
237 		menuBar.add(menuLogs);
238 
239 		output = new JTextArea("");
240 		output.setEditable(false);
241 		Font logFont = new Font("Monospaced", Font.PLAIN, 12);
242 		output.setFont(logFont);
243 
244 		JScrollPane scroll = new JScrollPane(output, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
245 				JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
246 		getContentPane().add(scroll);
247 
248 		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
249 		if (screenSize.height < 400) {
250 			Configuration.screenSizeSmall = true;
251 			Font smallLogFont = new Font("Monospaced", Font.PLAIN, 9);
252 			output.setFont(smallLogFont);
253 		}
254 
255 		if (screenSize.width > 600) {
256 			screenSize.setSize(240, 320);
257 		}
258 		if (this.isResizable()) {
259 			Rectangle b = this.getBounds();
260 			b.x = Integer.valueOf(Configuration.getStorageData("main.x", "0")).intValue();
261 			b.y = Integer.valueOf(Configuration.getStorageData("main.y", "0")).intValue();
262 			b.height = Integer.valueOf(Configuration.getStorageData("main.height", String.valueOf(screenSize.height)))
263 					.intValue();
264 			b.width = Integer.valueOf(Configuration.getStorageData("main.width", String.valueOf(screenSize.width)))
265 					.intValue();
266 			this.setBounds(b);
267 		}
268 	}
269 
270 	private JMenuItem addMenu(JMenu menu, String name, ActionListener l) {
271 		return addMenu(menu, name, l, 0);
272 	}
273 
274 	private JMenuItem addMenu(JMenu menu, String name, ActionListener l, int key) {
275 		JMenuItem menuItem = new JMenuItem(name);
276 		menuItem.addActionListener(l);
277 		menu.add(menuItem);
278 		if (key != 0) {
279 			// menuItem.setShortcut(new MenuShortcut(key, false));
280 		}
281 		return menuItem;
282 	}
283 
284 	private void updateTitle() {
285 		this.setTitle(UIHelper.getMainWindowTitle());
286 	}
287 
288 	private void clear() {
289 		if (output == null) {
290 			return;
291 		}
292 		output.setText("");
293 		outputLines = 0;
294 	}
295 
296 	private void quit() {
297 		Logger.debug("quit");
298 		Switcher.clientShutdown();
299 		Switcher.serverShutdownOnExit();
300 
301 		Rectangle b = this.getBounds();
302 		Configuration.storeData("main.x", String.valueOf(b.x));
303 		Configuration.storeData("main.y", String.valueOf(b.y));
304 		Configuration.storeData("main.height", String.valueOf(b.height));
305 		Configuration.storeData("main.width", String.valueOf(b.width));
306 
307 		Logger.removeAppender(this);
308 		BlueCoveSpecific.removeAppender();
309 
310 		// this.dispose();
311 		System.exit(0);
312 	}
313 
314 	public void appendLog(int level, String message, Throwable throwable) {
315 		if (output == null) {
316 			return;
317 		}
318 		final StringBuffer buf = new StringBuffer();
319 
320 		if (Configuration.logTimeStamp) {
321 			String time = TimeUtils.timeNowToString();
322 			buf.append(time).append(" ");
323 		}
324 
325 		switch (level) {
326 		case Logger.ERROR:
327 			// errorCount ++;
328 			buf.append("e.");
329 			break;
330 		case Logger.WARN:
331 			buf.append("w.");
332 			break;
333 		case Logger.INFO:
334 			buf.append("i.");
335 			break;
336 		}
337 		buf.append(message);
338 		if (throwable != null) {
339 			buf.append(' ');
340 			String className = throwable.getClass().getName();
341 			buf.append(className.substring(1 + className.lastIndexOf('.')));
342 			if (throwable.getMessage() != null) {
343 				buf.append(':');
344 				buf.append(throwable.getMessage());
345 			}
346 		}
347 		buf.append("\n");
348 		boolean createUpdater = false;
349 		synchronized (logLinesQueue) {
350 			if (logLinesQueue.isEmpty()) {
351 				createUpdater = true;
352 			} else {
353 				createUpdater = !logUpdaterRunning;
354 			}
355 			logLinesQueue.addElement(buf.toString());
356 		}
357 		if (createUpdater) {
358 			try {
359 				EventQueue.invokeLater(new AwtLogUpdater());
360 			} catch (NoSuchMethodError java1) {
361 				(new AwtLogUpdater()).run();
362 			}
363 		}
364 	}
365 
366 	private class AwtLogUpdater implements Runnable {
367 
368 		private String getNextLine() {
369 			synchronized (logLinesQueue) {
370 				if (logLinesQueue.isEmpty()) {
371 					return null;
372 				}
373 				String line = (String) logLinesQueue.firstElement();
374 				logLinesQueue.removeElementAt(0);
375 				return line;
376 			}
377 		}
378 
379 		public void run() {
380 			int oneCallCount = 0;
381 			synchronized (logLinesQueue) {
382 				logUpdaterRunning = true;
383 			}
384 			String line;
385 			try {
386 				while ((line = getNextLine()) != null) {
387 					output.append(line);
388 					outputLines++;
389 					if (outputLines > 5000) {
390 						clear();
391 					}
392 					oneCallCount++;
393 					if (oneCallCount > 40) {
394 						break;
395 					}
396 				}
397 			} finally {
398 				synchronized (logLinesQueue) {
399 					logUpdaterRunning = false;
400 				}
401 			}
402 		}
403 	}
404 }