package com.bao.lc.site.s3.gui; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.*; import javax.swing.border.TitledBorder; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.bao.lc.ResMgr; import com.bao.lc.proxy.HttpProxyServer; import com.bao.lc.proxy.IEProxy; import com.bao.lc.proxy.IEProxy.ProxySettings; import com.bao.lc.site.s3.TdClient; import com.bao.lc.site.s3.TdUtils; import com.bao.lc.site.s3.params.InputParameter; import com.bao.lc.util.AppUtils; @SuppressWarnings("serial") public class MainPanel extends JPanel { private static Log log = LogFactory.getLog(MainPanel.class); private JMenuBar menuBar = null; private JMenuItem addPassengerMenuItem = null; private JMenuItem loginMenuItem = null; private JMenuItem bookMenuItem = null; private JMenuItem logoutMenuItem = null; private JMenuItem oneClickBookMenuItem = null; private JMenuItem stopMenuItem = null; private JMenuItem saveParamMenuItem = null; private JMenuItem helpMenuItem = null; private JToolBar toolBar = null; private JButton addPassengerBtn = null; private JButton loginBtn = null; private JButton bookBtn = null; private JButton logoutBtn = null; private JButton oneClickBookBtn = null; private JButton stopBtn = null; private JCheckBox enableIEBtn = null; private InputInfoPanel inputInfoPanel = new InputInfoPanel(); private JScrollPane msgWindowScrollPane = new JScrollPane(); private JTextArea msgWindow = new JTextArea(); private Log uiLog = null; private WorkerThread worker = null; private TdClient client = null; private HttpProxyServer proxyServer = null; private ProxySettings origProxySettings = null; private StateChange workerState = new StateChange(StateChange.THREAD_NOT_RUNNING); public MainPanel() { initGUI(); addListeners(); setButtonStatus(false); uiLog = new TextAreaLog(msgWindow); client = new TdClient(); WatchDog dog = new WatchDog(); dog.start(); startProxyServer(); } public JMenuBar getMainMenuBar() { return this.menuBar; } public Thread getAppShutdownHook() { return new SysCleanUpThread(); } public void resoreProxySetting() { if(this.origProxySettings != null) { IEProxy.setProxySettings(this.origProxySettings); this.origProxySettings = null; } } private void startProxyServer() { if(!TdOptions.enableOpenIE) { log.debug("Didn't start proxy server because 'enableLoginByIE' is disabled"); return; } String parameter = "-localport " + String.valueOf(TdOptions.proxyPort); proxyServer = new HttpProxyServer(parameter); proxyServer.start(); } private void initGUI() { initMenuBar(); initToolBar(); initMessageWindow(); initMainPanel(); } private void initMenuBar() { menuBar = new JMenuBar(); // ***** create File menu JMenu fileMenu = menuBar.add(new JMenu(ResMgr.getString("td.menu.file"))); addPassengerMenuItem = createMenuItem(fileMenu, ResMgr.getString("td.menu.file.add_passenger")); oneClickBookMenuItem = createMenuItem(fileMenu, ResMgr.getString("td.main.toolbar.one_click_book")); stopMenuItem = createMenuItem(fileMenu, ResMgr.getString("td.main.toolbar.stop")); fileMenu.addSeparator(); loginMenuItem = createMenuItem(fileMenu, ResMgr.getString("td.menu.file.start_login")); bookMenuItem = createMenuItem(fileMenu, ResMgr.getString("td.menu.file.start_book")); logoutMenuItem = createMenuItem(fileMenu, ResMgr.getString("td.logout")); fileMenu.addSeparator(); saveParamMenuItem = createMenuItem(fileMenu, ResMgr.getString("td.menu.file.save_param")); // ***** create Tools menu JMenu toolsMenu = menuBar.add(new JMenu(ResMgr.getString("td.menu.tools"))); createMenuItem(toolsMenu, ResMgr.getString("td.menu.tools.options")); // ***** create Help menu JMenu helpMenu = menuBar.add(new JMenu(ResMgr.getString("td.menu.help"))); helpMenuItem = createMenuItem(helpMenu, ResMgr.getString("td.menu.help.about")); } private JMenuItem createMenuItem(JMenu menu, String text) { JMenuItem mi = menu.add(new JMenuItem(text)); return mi; } private void initToolBar() { toolBar = new JToolBar(); addPassengerBtn = new JButton(ResMgr.getString("td.main.toolbar.add_passenger")); loginBtn = new JButton(ResMgr.getString("td.main.toolbar.start_login")); bookBtn = new JButton(ResMgr.getString("td.main.toolbar.start_book")); logoutBtn = new JButton(ResMgr.getString("td.logout")); oneClickBookBtn = new JButton(ResMgr.getString("td.main.toolbar.one_click_book")); stopBtn = new JButton(ResMgr.getString("td.main.toolbar.stop")); enableIEBtn = new JCheckBox(ResMgr.getString("td.main.toolbar.enable_ie")); toolBar.add(addPassengerBtn); toolBar.add(oneClickBookBtn); toolBar.add(stopBtn); toolBar.addSeparator(); toolBar.add(loginBtn); toolBar.add(bookBtn); toolBar.add(logoutBtn); if(TdOptions.enableOpenIE) { toolBar.addSeparator(); toolBar.add(enableIEBtn); } } private void initMessageWindow() { msgWindow.setEditable(false); msgWindow.setLineWrap(true); msgWindowScrollPane.setViewportBorder(new TitledBorder(ResMgr .getString("td.message.window.title"))); msgWindowScrollPane.getViewport().add(msgWindow); } private void initMainPanel() { // Prepare the main split panel JSplitPane mainSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, inputInfoPanel, msgWindowScrollPane); mainSplitPane.setContinuousLayout(true); mainSplitPane.setOneTouchExpandable(true); Dimension minSize = inputInfoPanel.getMinimumSize(); minSize.height += 80; inputInfoPanel.setMinimumSize(minSize); mainSplitPane.setDividerLocation(minSize.height + mainSplitPane.getDividerSize()); // set the layout setLayout(new BorderLayout()); add(toolBar, BorderLayout.PAGE_START); add(mainSplitPane, BorderLayout.CENTER); } private void addListeners() { addPassengerBtn.addActionListener(new AddPassengerListener()); loginBtn.addActionListener(new LoginListener()); bookBtn.addActionListener(new BookListener()); logoutBtn.addActionListener(new LogoutListener()); oneClickBookBtn.addActionListener(new OneClickBookListener()); stopBtn.addActionListener(new StopListener()); addPassengerMenuItem.addActionListener(new AddPassengerListener()); loginMenuItem.addActionListener(new LoginListener()); bookMenuItem.addActionListener(new BookListener()); logoutMenuItem.addActionListener(new LogoutListener()); oneClickBookMenuItem.addActionListener(new OneClickBookListener()); stopMenuItem.addActionListener(new StopListener()); saveParamMenuItem.addActionListener(new SaveParameterListener()); helpMenuItem.addActionListener(new AboutListener()); if(TdOptions.enableOpenIE) { enableIEBtn.addActionListener(new EnableIEListener()); } } private void addPassenger() { this.inputInfoPanel.addPassenger(); } private boolean saveParameter() { InputParameter parameter = inputInfoPanel.getInputParam(); return inputInfoPanel.saveData(parameter, AppUtils.getUserFilePath("auto_input.xml")); } private void setButtonStatus(boolean isRunning) { // boolean isRunning = (worker != null && worker.isAlive()); boolean isLogin = (client != null && client.isLogin()); addPassengerBtn.setEnabled(!isRunning); addPassengerMenuItem.setEnabled(!isRunning); loginBtn.setEnabled(!isRunning && !isLogin); loginMenuItem.setEnabled(!isRunning && !isLogin); bookBtn.setEnabled(!isRunning && isLogin); bookMenuItem.setEnabled(!isRunning && isLogin); logoutBtn.setEnabled(!isRunning && isLogin); logoutMenuItem.setEnabled(!isRunning && isLogin); oneClickBookBtn.setEnabled(!isRunning && !isLogin); oneClickBookMenuItem.setEnabled(!isRunning && !isLogin); stopBtn.setEnabled(isRunning); stopMenuItem.setEnabled(isRunning); enableIEBtn.setEnabled(!isRunning && isLogin); saveParamMenuItem.setEnabled(!isRunning); } private void login() { if(client != null) { client.login(); System.setProperty("RequestCookieFilter.host", TdOptions.tdHost); System.setProperty("RequestCookieFilter.port", String.valueOf(TdOptions.tdPort)); System.setProperty("RequestCookieFilter.cookie", client.getCookie()); } } private class AddPassengerListener implements ActionListener { public void actionPerformed(ActionEvent e) { if(worker != null && worker.isAlive()) { log.error("Assert failure: worker is alive."); return; } addPassenger(); } } private class LoginListener implements ActionListener { public void actionPerformed(ActionEvent e) { if(worker != null && worker.isAlive()) { log.error("Assert failure: worker is alive."); return; } if(client.isLogin()) { JOptionPane.showMessageDialog(GUIUtils.getMainFrame(), ResMgr.getString("td.msg.user.already_login")); return; } InputParameter param = inputInfoPanel.getInputParam(); if(!inputInfoPanel.checkParameter(param, true)) { return; } saveParameter(); client.initContext(param, uiLog); Runnable target = new Runnable() { public void run() { login(); } }; worker = new WorkerThread(target); worker.start(); } } private class BookListener implements ActionListener { public void actionPerformed(ActionEvent e) { if(worker != null && worker.isAlive()) { log.error("Assert failure: worker is alive."); return; } if(!client.isLogin()) { JOptionPane.showMessageDialog(GUIUtils.getMainFrame(), ResMgr.getString("td.msg.user.not_login")); return; } Runnable target = new Runnable() { public void run() { InputParameter parameter = inputInfoPanel.getInputParam(); client.updateParameter(parameter, false); client.bookTicket(); } }; worker = new WorkerThread(target); worker.start(); } } private class LogoutListener implements ActionListener { public void actionPerformed(ActionEvent e) { if(worker != null && worker.isAlive()) { log.error("Assert failure: worker is alive."); return; } if(!client.isLogin()) { JOptionPane.showMessageDialog(GUIUtils.getMainFrame(), ResMgr.getString("td.msg.user.not_login")); return; } Runnable target = new Runnable() { public void run() { resoreProxySetting(); enableIEBtn.setSelected(false); client.logout(); } }; worker = new WorkerThread(target); worker.start(); } } private class OneClickBookListener implements ActionListener { public void actionPerformed(ActionEvent e) { if(worker != null && worker.isAlive()) { log.error("Assert failure: worker is alive."); return; } if(client.isLogin()) { JOptionPane.showMessageDialog(GUIUtils.getMainFrame(), ResMgr.getString("td.msg.user.already_login")); return; } InputParameter param = inputInfoPanel.getInputParam(); if(!inputInfoPanel.checkParameter(param, true)) { return; } saveParameter(); client.initContext(param, uiLog); Runnable target = new Runnable() { public void run() { login(); client.bookTicket(); } }; worker = new WorkerThread(target); worker.start(); } } private class StopListener implements ActionListener { public void actionPerformed(ActionEvent e) { synchronized(workerState) { workerState.setState(StateChange.THREAD_NOT_RUNNING); workerState.notifyAll(); } if(worker != null && !worker.isAlive()) { log.error("Assert failure: worker is not alive."); return; } worker.end(); worker = null; } } private class SaveParameterListener implements ActionListener { public void actionPerformed(ActionEvent e) { boolean result = saveParameter(); String message = ResMgr.getString("td.save.parameter") + (result ? ResMgr.getString("td.success") : ResMgr.getString("td.failed")); JOptionPane .showMessageDialog(GUIUtils.getMainFrame(), message, ResMgr.getString("td.save.parameter.result.title"), JOptionPane.INFORMATION_MESSAGE); } } private class EnableIEListener implements ActionListener { public void actionPerformed(ActionEvent e) { //Enabled if(enableIEBtn.isSelected()) { if(origProxySettings != null) { JOptionPane.showMessageDialog(GUIUtils.getMainFrame(), ResMgr.getString("td.msg.warning.already_enable_ie"), ResMgr.getString("td.main.window.title"), JOptionPane.WARNING_MESSAGE); return; } //Save original proxy setting origProxySettings = IEProxy.getProxySettings(); //Set the new setting ProxySettings currSetting = new ProxySettings(); currSetting.proxyServer = "127.0.0.1:" + TdOptions.proxyPort; currSetting.proxyBypass = TdOptions.proxyByPass; currSetting.setProxy(true); currSetting.setDirect(true); IEProxy.setProxySettings(currSetting); EnableIEPanel enableIEPanel = new EnableIEPanel(); DialogValueBuilder<String> builder = new DialogValueBuilder<String>(); builder.content(enableIEPanel).valueBean(enableIEPanel).owner(GUIUtils.getMainFrame()); builder.title(ResMgr.getString("td.main.window.title")); builder.preferredSize(new Dimension(360, 200)); builder.parent(GUIUtils.getMainFrame()); builder.build(); } //Disabled else { if(origProxySettings == null) { JOptionPane.showMessageDialog(GUIUtils.getMainFrame(), ResMgr.getString("td.msg.warning.not_enable_ie"), ResMgr.getString("td.main.window.title"), JOptionPane.WARNING_MESSAGE); return; } resoreProxySetting(); JOptionPane.showMessageDialog(GUIUtils.getMainFrame(), ResMgr.getString("td.msg.ie_login_disabled"), ResMgr.getString("td.main.window.title"), JOptionPane.PLAIN_MESSAGE); } } } private class AboutListener implements ActionListener { public void actionPerformed(ActionEvent e) { String message = ResMgr.getString("td.main.window.title") + " " + TdUtils.getVersion(); JOptionPane.showMessageDialog(GUIUtils.getMainFrame(), message, ResMgr.getString("td.main.window.title"), JOptionPane.PLAIN_MESSAGE); } } private class WorkerThread extends Thread { public WorkerThread(Runnable target) { super(target, "BookWorker"); } public void run() { synchronized(workerState) { workerState.setState(StateChange.THREAD_RUNNING); workerState.notifyAll(); } super.run(); synchronized(workerState) { workerState.setState(StateChange.THREAD_NOT_RUNNING); workerState.notifyAll(); } } public void end() { if(!this.isAlive()) { return; } this.interrupt(); synchronized(workerState) { workerState.setState(StateChange.THREAD_NOT_RUNNING); workerState.notifyAll(); } uiLog.info(ResMgr.getString("td.msg.user_kill_book_thread")); } } private class SysCleanUpThread extends Thread { public SysCleanUpThread() { super("SysCleanUpThread"); } public void run() { if(client != null) { // client.logout(); client.shutdown(); } } } private class WatchDog extends Thread { public WatchDog() { super("WatchDog"); setDaemon(true); } public void run() { while(true) { synchronized(workerState) { while(workerState.changed()) { final boolean running = (workerState.getNewState() == StateChange.THREAD_RUNNING); SwingUtilities.invokeLater((new Runnable() { public void run() { setButtonStatus(running); } })); workerState.reset(); } try { workerState.wait(); } catch(InterruptedException e) { log.warn("The thread is interrupted.", e); Thread.currentThread().interrupt(); // very important } } } } } } class StateChange { public static final int THREAD_NOT_RUNNING = 0; public static final int THREAD_RUNNING = 1; private int oldState = THREAD_NOT_RUNNING; private int newState = THREAD_NOT_RUNNING; public StateChange() { this(THREAD_NOT_RUNNING); } public StateChange(int initState) { this.oldState = initState; this.newState = initState; } public int getNewState() { return newState; } public boolean changed() { return oldState != newState; } public void reset() { this.oldState = this.newState; } public void setState(int state) { this.oldState = newState; this.newState = state; } }