View Javadoc

1   /*--------------------------------------------------------------------------
2    *  Copyright 2008 utgenome.org
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   *--------------------------------------------------------------------------*/
16  //--------------------------------------
17  // utgb-shell Project
18  //
19  // UTGBPortableWidget.java
20  // Since: Sep 2, 2008
21  //
22  // $URL$ 
23  // $Author$
24  //--------------------------------------
25  package org.utgenome.shell;
26  
27  import java.awt.Color;
28  import java.awt.Component;
29  import java.awt.Cursor;
30  import java.awt.Dimension;
31  import java.awt.FlowLayout;
32  import java.awt.Insets;
33  import java.awt.Toolkit;
34  import java.awt.event.ActionEvent;
35  import java.awt.event.ActionListener;
36  import java.awt.event.KeyEvent;
37  import java.awt.event.KeyListener;
38  import java.awt.event.MouseEvent;
39  import java.awt.event.MouseListener;
40  
41  import javax.swing.BorderFactory;
42  import javax.swing.BoxLayout;
43  import javax.swing.ImageIcon;
44  import javax.swing.JButton;
45  import javax.swing.JFrame;
46  import javax.swing.JLabel;
47  import javax.swing.JPanel;
48  import javax.swing.JTextField;
49  import javax.swing.UIManager;
50  import javax.swing.border.TitledBorder;
51  
52  import org.xerial.core.XerialException;
53  import org.xerial.util.FileResource;
54  import org.xerial.util.log.Logger;
55  
56  /**
57   * GUI Panel of the UTGB Portable Server
58   * 
59   * @author leo
60   * 
61   */
62  public class UTGBPortableWidget extends JFrame implements ServerListener {
63  
64  	private static Logger _logger = Logger.getLogger(UTGBPortableWidget.class);
65  
66  	/**
67  	 * 
68  	 */
69  	private static final long serialVersionUID = 1L;
70  
71  	static class CustomTitledBorder extends TitledBorder {
72  
73  		/**
74  		 * 
75  		 */
76  		private static final long serialVersionUID = 1L;
77  
78  		public CustomTitledBorder(String title) {
79  			super(title);
80  		}
81  
82  		@Override
83  		public Insets getBorderInsets(Component c) {
84  			return getBorderInsets(c, new Insets(0, 0, 0, 0));
85  		}
86  
87  		@Override
88  		public Insets getBorderInsets(Component c, Insets insets) {
89  			insets.set(12, 7, 5, 7);
90  			return insets;
91  		}
92  	}
93  
94  	static class CustomButton extends JButton {
95  		/**
96  		 * 
97  		 */
98  		private static final long serialVersionUID = 1L;
99  
100 		public CustomButton(String label) {
101 			super(label);
102 			setMargin(new Insets(2, 5, 2, 5));
103 		}
104 	}
105 
106 	class ServerLaunchPanel extends JPanel {
107 		/**
108 		 * 
109 		 */
110 		private static final long serialVersionUID = 1L;
111 		JButton startButton = new CustomButton("start");
112 		JButton stopButton = new CustomButton("stop");
113 		JButton restartButton = new CustomButton("restart");
114 		JButton syncButton = new CustomButton("sync");
115 		JLabel serverURL = new JLabel();
116 		JTextField portNumberField = new JTextField(Integer.toString(config.getPortNumber()));
117 		JTextField contextPathField = new JTextField(config.getContextPath());
118 
119 		public ServerLaunchPanel() {
120 
121 			JPanel buttonPanel = new JPanel();
122 			buttonPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 10));
123 			buttonPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
124 			buttonPanel.add(startButton);
125 			buttonPanel.add(stopButton);
126 			buttonPanel.add(restartButton);
127 			// buttonPanel.add(syncButton);
128 
129 			// URL
130 			serverURL.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
131 			buttonPanel.add(serverURL);
132 
133 			serverURL.addMouseListener(new MouseListener() {
134 
135 				public void mouseClicked(MouseEvent e) {
136 					// open the OS's default browser
137 					WebBrowser.openURL(config.getServerURL());
138 				}
139 
140 				public void mouseEntered(MouseEvent e) {
141 
142 				}
143 
144 				public void mouseExited(MouseEvent e) {
145 
146 				}
147 
148 				public void mousePressed(MouseEvent e) {
149 
150 				}
151 
152 				public void mouseReleased(MouseEvent e) {
153 
154 				}
155 			});
156 
157 			// button listener
158 			startButton.addActionListener(new ActionListener() {
159 				public void actionPerformed(ActionEvent e) {
160 					onPushStart();
161 				}
162 			});
163 
164 			stopButton.addActionListener(new ActionListener() {
165 				public void actionPerformed(ActionEvent e) {
166 					onPushStop();
167 				}
168 			});
169 
170 			restartButton.addActionListener(new ActionListener() {
171 				public void actionPerformed(ActionEvent e) {
172 					onPushRestart();
173 				}
174 			});
175 
176 			syncButton.addActionListener(new ActionListener() {
177 				public void actionPerformed(ActionEvent e) {
178 					onPushSync();
179 				}
180 			});
181 
182 			// server configuration panel (port & context path)
183 			JPanel serverConfigurationPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
184 			// port number
185 			JLabel portNumberLabel = new JLabel("port number:");
186 
187 			portNumberField.setColumns(5);
188 			serverConfigurationPanel.add(portNumberLabel);
189 			serverConfigurationPanel.add(portNumberField);
190 			portNumberField.addKeyListener(new KeyListener() {
191 
192 				public void keyPressed(KeyEvent e) {
193 				}
194 
195 				public void keyReleased(KeyEvent e) {
196 					String inputPort = portNumberField.getText();
197 					try {
198 						config.portNumber = Integer.parseInt(inputPort);
199 						serverLaunchPanel.update();
200 						clearStatus();
201 					}
202 					catch (NumberFormatException ne) {
203 						setStatus(MessageType.ERROR, "invalid port number");
204 					}
205 				}
206 
207 				public void keyTyped(KeyEvent e) {
208 				}
209 			});
210 
211 			// context path
212 			JLabel contextPathLabel = new JLabel("context path:");
213 
214 			contextPathField.setColumns(12);
215 			serverConfigurationPanel.add(contextPathLabel);
216 			serverConfigurationPanel.add(contextPathField);
217 			serverConfigurationPanel.setBorder(createTitledBorder("server configurations"));
218 			contextPathField.addKeyListener(new KeyListener() {
219 
220 				public void keyPressed(KeyEvent e) {
221 				}
222 
223 				public void keyReleased(KeyEvent e) {
224 					String path = contextPathField.getText();
225 					if (!path.startsWith("/")) {
226 						path = "/" + path;
227 						contextPathField.setText(path);
228 					}
229 					config.contextPath = path;
230 					serverLaunchPanel.update();
231 				}
232 
233 				public void keyTyped(KeyEvent e) {
234 				}
235 			});
236 
237 			// layout panels
238 			setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
239 			add(buttonPanel);
240 			add(serverConfigurationPanel);
241 		}
242 
243 		public void onPushStart() {
244 			startButton.setEnabled(false);
245 			stopButton.setEnabled(true);
246 			restartButton.setEnabled(true);
247 			syncButton.setEnabled(true);
248 
249 			portNumberField.setEditable(false);
250 			contextPathField.setEditable(false);
251 
252 			try {
253 				if (launcher != null)
254 					launcher.startTomcatServer(config);
255 			}
256 			catch (XerialException e) {
257 				setStatus(MessageType.ERROR, "failed to start server: " + e.getMessage());
258 				onPushStop();
259 			}
260 		}
261 
262 		public void onPushStop() {
263 			startButton.setEnabled(true);
264 			stopButton.setEnabled(false);
265 			restartButton.setEnabled(false);
266 			syncButton.setEnabled(false);
267 
268 			portNumberField.setEditable(true);
269 			contextPathField.setEditable(true);
270 
271 			setStatus(MessageType.INFO, "stopping the web server...");
272 			if (launcher != null)
273 				launcher.stopTomcatServer(config);
274 		}
275 
276 		public void onPushRestart() {
277 			if (launcher != null) {
278 				onPushStop();
279 				onPushStart();
280 			}
281 		}
282 
283 		public void onPushSync() {
284 
285 		}
286 
287 		public void update() {
288 			serverURL.setText(config.generateServerURLLinkHTML());
289 			UTGBPortableWidget.this.pack();
290 		}
291 
292 	}
293 
294 	private final UTGBPortableConfig config;
295 	private ServerLaunchPanel serverLaunchPanel;
296 	private JLabel status = new JLabel(" ");
297 	private JPanel mainPanel = new JPanel();
298 	private TomcatServerLauncher launcher = null;
299 
300 	static {
301 		// take the menu bar off the jframe
302 		System.setProperty("apple.laf.useScreenMenuBar", "true");
303 
304 		// set the name of the application menu item
305 		System.setProperty("com.apple.mrj.application.apple.menu.about.name", "UTGB Portable");
306 
307 		// set the look and feel
308 		try {
309 			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
310 		}
311 		catch (Exception e) {
312 			_logger.error(e);
313 		}
314 	}
315 
316 	public UTGBPortableWidget() {
317 		this(new UTGBPortableConfig());
318 	}
319 
320 	public UTGBPortableWidget(UTGBPortableConfig config) {
321 		this.config = config;
322 		buildGUI();
323 	}
324 
325 	public void pushStart() {
326 		serverLaunchPanel.onPushStart();
327 	}
328 
329 	public void updateLink() {
330 		serverLaunchPanel.update();
331 	}
332 
333 	protected void buildGUI() {
334 		Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
335 
336 		setTitle("UTGB Portable");
337 
338 		// main panel
339 
340 		// set icon
341 		ImageIcon imageIcon = new ImageIcon(FileResource.find(UTGBPortableWidget.class, "utgb-icon.png"));
342 		setIconImage(imageIcon.getImage());
343 
344 		// add server start/stop/restart buttons
345 		serverLaunchPanel = new ServerLaunchPanel();
346 
347 		// track project folder
348 		JPanel trackProjectPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
349 		trackProjectPanel.setBorder(createTitledBorder("project root"));
350 		JLabel trackProjectFolder = new JLabel(config.getProjectRoot());
351 		trackProjectPanel.add(trackProjectFolder);
352 
353 		// status panel
354 		JPanel statusPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
355 		statusPanel.setBorder(createTitledBorder("status"));
356 		statusPanel.add(status);
357 
358 		// layout panels
359 		mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
360 		mainPanel.add(serverLaunchPanel);
361 		mainPanel.add(trackProjectPanel);
362 		mainPanel.add(statusPanel);
363 		add(mainPanel);
364 		// init the widgets
365 		serverLaunchPanel.onPushStop();
366 		serverLaunchPanel.update();
367 
368 		this.pack();
369 	}
370 
371 	public static enum MessageType {
372 		INFO(new Color(0x50, 0x50, 0x50)), WARN(Color.ORANGE), ERROR(new Color(0xFF, 0x00, 0x00));
373 
374 		private Color color;
375 
376 		MessageType(Color color) {
377 			this.color = color;
378 		}
379 
380 		Color getColor() {
381 			return color;
382 		}
383 	}
384 
385 	public void setStatus(MessageType type, String message) {
386 		status.setForeground(type.getColor());
387 		status.setText(message);
388 		pack();
389 	}
390 
391 	public void clearStatus() {
392 		status.setText(" ");
393 		pack();
394 	}
395 
396 	public static TitledBorder createTitledBorder(String borderTitle) {
397 		return new CustomTitledBorder(borderTitle);
398 	}
399 
400 	public static void setButtonMargin(JButton button) {
401 		button.setMargin(new Insets(2, 5, 2, 5));
402 	}
403 
404 	public void setTomcatServerLauncher(TomcatServerLauncher launcher) {
405 		this.launcher = launcher;
406 		launcher.addServerListener(this);
407 	}
408 
409 	public static void main(String[] args) {
410 		UTGBPortableWidget portableWidget = new UTGBPortableWidget();
411 		Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
412 		portableWidget.setLocation((int) d.getWidth() / 4, (int) d.getHeight() / 4);
413 		portableWidget.setVisible(true);
414 		portableWidget.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
415 	}
416 
417 	public void beforeStart() {
418 		setStatus(MessageType.INFO, "Starting the web server...");
419 	}
420 
421 	public void afterStart() {
422 		setStatus(MessageType.INFO, "The web server started.");
423 	}
424 
425 	public void afterStop() {
426 		setStatus(MessageType.INFO, "The web server terminated.");
427 	}
428 
429 	public void beforeStop() {
430 		setStatus(MessageType.INFO, "Terminating the web server...");
431 	}
432 
433 }
434 
435 /**
436  * Required to launch a Tomcat server instance
437  * 
438  * @author leo
439  * 
440  */
441 interface TomcatServerLauncher {
442 
443 	void startTomcatServer(UTGBPortableConfig config) throws XerialException;
444 
445 	void stopTomcatServer(UTGBPortableConfig config);
446 
447 	void addServerListener(ServerListener listener);
448 
449 }