001    /******************************************************************************
002     * Copyright (C) MActor Developers. All rights reserved.                        *
003     * ---------------------------------------------------------------------------*
004     * This file is part of MActor.                                               *
005     *                                                                            *
006     * MActor is free software; you can redistribute it and/or modify             *
007     * it under the terms of the GNU General Public License as published by       *
008     * the Free Software Foundation; either version 2 of the License, or          *
009     * (at your option) any later version.                                        *
010     *                                                                            *
011     * MActor is distributed in the hope that it will be useful,                  *
012     * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
013     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
014     * GNU General Public License for more details.                               *
015     *                                                                            *
016     * You should have received a copy of the GNU General Public License          *
017     * along with MActor; if not, write to the Free Software                      *
018     * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA *
019     ******************************************************************************/
020    package org.mactor.ui.gui.testrunner;
021    
022    import java.awt.BorderLayout;
023    import java.awt.Color;
024    import java.awt.FlowLayout;
025    import java.awt.event.ActionEvent;
026    import java.awt.event.ActionListener;
027    import java.io.File;
028    
029    import javax.swing.AbstractAction;
030    import javax.swing.JButton;
031    import javax.swing.JLabel;
032    import javax.swing.JPanel;
033    import javax.swing.JScrollPane;
034    import javax.swing.JSplitPane;
035    import javax.swing.JTextArea;
036    import javax.swing.SwingUtilities;
037    import javax.swing.Timer;
038    
039    import org.mactor.brokers.Message;
040    import org.mactor.brokers.MessageBrokerManager;
041    import org.mactor.brokers.MessageSubscriber;
042    import org.mactor.extensions.GreedyMessageSelector;
043    import org.mactor.framework.MactorException;
044    import org.mactor.ui.gui.GuiUtil;
045    import org.mactor.ui.gui.ResourceUtil;
046    import org.mactor.ui.gui.Stoppable;
047    
048    public class ChannelRuntimePanel extends JPanel implements Stoppable {
049            String channel;
050            Object lock = new Object();
051            Object pendingMessageLock = new Object();
052            boolean requiresResponse;
053            boolean pendingResponse = false;
054            Message pendingResponseMessage;
055            JTextArea messageText = new JTextArea(20, 40);
056            ChannelMessageLogPanel cmlPanel;
057            Timer timer = new Timer(1000, new ActionListener() {
058                    public void actionPerformed(ActionEvent e) {
059                            if (sendButton.getBackground().equals(Color.RED))
060                                    sendButton.setBackground(subscribeButton.getBackground());
061                            else
062                                    sendButton.setBackground(Color.RED);
063                    }
064            });
065            private boolean busy = false;
066            private Object busyLock = new Object();
067            MessageSubscriber ms = new MessageSubscriber() {
068                    public org.mactor.brokers.Message onMessage(final Message message) {
069                            if (requiresResponse)
070                                    return handleIncomingWithResponse(message);
071                            return null;
072                    };
073            };
074            JButton subscribeButton = new JButton(new AbstractAction("Start Subscriber") {
075                    public void actionPerformed(java.awt.event.ActionEvent e) {
076                            try {
077                                    MessageBrokerManager.getInstance().subscribe(channel, ms, new GreedyMessageSelector());
078                                    subscribeButton.setEnabled(false);
079                                    unsubscribeButton.setEnabled(true);
080                                    sendButton.setEnabled(false);
081                            } catch (MactorException me) {
082                                    GuiUtil.showGuiError(ChannelRuntimePanel.this, me);
083                            }
084                    };
085            });
086            JButton unsubscribeButton = new JButton(new AbstractAction("Stop Subscriber") {
087                    public void actionPerformed(java.awt.event.ActionEvent e) {
088                            try {
089                                    MessageBrokerManager.getInstance().unsubscribe(channel, ms);
090                                    timer.stop();
091                                    sendButton.setBackground(subscribeButton.getBackground());
092                                    subscribeButton.setEnabled(true);
093                                    unsubscribeButton.setEnabled(false);
094                                    sendButton.setEnabled(true);
095                            } catch (MactorException me) {
096                                    GuiUtil.showGuiError(ChannelRuntimePanel.this, me);
097                            }
098                    };
099            });
100            JButton sendButton = new JButton(new AbstractAction("Publish Message") {
101                    public void actionPerformed(java.awt.event.ActionEvent e) {
102                            try {
103                                    if (pendingResponse) {
104                                            pendingResponseMessage = Message.createMessage(messageText.getText());
105                                            synchronized (pendingMessageLock) {
106                                                    pendingMessageLock.notifyAll();
107                                            }
108                                    } else {
109                                            /*
110                                             * if(!subscribeButton.isEnabled()) {
111                                             * GuiUtil.showInfo(ChannelRuntimePanel.this, "Sorry, it is
112                                             * not possible to subscribe and published to the same
113                                             * channel in the same 'tab' \n(only response messages can
114                                             * be published )"); return; }
115                                             */
116                                            final Message outgoingMessage = Message.createMessage(messageText.getText());
117                                            sendButton.setEnabled(false);
118                                            new Thread(new Runnable() {
119                                                    public void run() {
120                                                            try {
121                                                                    MessageBrokerManager.getInstance().publish(channel, outgoingMessage);
122                                                                    SwingUtilities.invokeLater(new Runnable() {
123                                                                            public void run() {
124                                                                                    sendButton.setEnabled(true);
125                                                                            }
126                                                                    });
127                                                            } catch (final MactorException me) {
128                                                                    SwingUtilities.invokeLater(new Runnable() {
129                                                                            public void run() {
130                                                                                    sendButton.setEnabled(true);
131                                                                                    GuiUtil.showGuiError(ChannelRuntimePanel.this, me);
132                                                                            }
133                                                                    });
134                                                            }
135                                                    };
136                                            }).start();
137                                    }
138                            } catch (MactorException me) {
139                                    GuiUtil.showGuiError(ChannelRuntimePanel.this, me);
140                            }
141                    };
142            });
143            JButton clearButton = new JButton(new AbstractAction("Clear") {
144                    public void actionPerformed(java.awt.event.ActionEvent e) {
145                            messageText.setText("");
146                    };
147            });
148            private Message handleIncomingWithResponse(final Message message) {
149                    try {
150                            synchronized (busyLock) {
151                                    if (busy)
152                                            busyLock.wait();
153                                    busy = true;
154                            }
155                    } catch (InterruptedException ie) {
156                    }
157                    pendingResponse = true;
158                    SwingUtilities.invokeLater(new Runnable() {
159                            public void run() {
160                                    sendButton.setEnabled(true);
161                                    timer.start();
162                            }
163                    });
164                    try {
165                            synchronized (pendingMessageLock) {
166                                    pendingMessageLock.wait();
167                            }
168                    } catch (InterruptedException ie) {
169                    }
170                    pendingResponse = false;
171                    final Message response = pendingResponseMessage;
172                    response.getMessageContextInfo().setResponseToMessage(message);
173                    SwingUtilities.invokeLater(new Runnable() {
174                            public void run() {
175                                    timer.stop();
176                                    sendButton.setBackground(subscribeButton.getBackground());
177                                    synchronized (busyLock) {
178                                            busy = false;
179                                            busyLock.notify();
180                                    }
181                            }
182                    });
183                    return response;
184            }
185            public void stop() {
186                    try {
187                            MessageBrokerManager.getInstance().unsubscribe(channel, ms);
188                    } catch (MactorException me) {
189                            me.printStackTrace();
190                    }
191            }
192            public ChannelRuntimePanel(String channel, boolean requiresResponse) throws MactorException {
193                    super(new BorderLayout());
194                    this.channel = channel;
195                    cmlPanel = new ChannelMessageLogPanel(channel);
196                    this.requiresResponse = requiresResponse;
197                    unsubscribeButton.setEnabled(false);
198                    JPanel topPanel = new JPanel(new FlowLayout());
199                    topPanel.add(subscribeButton);
200                    topPanel.add(unsubscribeButton);
201                    JPanel messagePanel = new JPanel(new BorderLayout());
202                    messagePanel.add(new JLabel("Message:"), BorderLayout.NORTH);
203                    messagePanel.add(new JScrollPane(messageText), BorderLayout.CENTER);
204                    JPanel messageButtonPanel = new JPanel(new FlowLayout());
205                    messageButtonPanel.add(sendButton);
206                    messageButtonPanel.add(clearButton);
207                    messagePanel.add(messageButtonPanel, BorderLayout.SOUTH);
208                    JPanel logPanel = new JPanel(new BorderLayout());
209                    logPanel.add(new JLabel("Message Log:"), BorderLayout.NORTH);
210                    logPanel.add(cmlPanel, BorderLayout.CENTER);
211                    JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, logPanel, messagePanel);
212                    splitPane.setDividerLocation(400);
213                    add(topPanel, BorderLayout.NORTH);
214                    add(splitPane, BorderLayout.CENTER);
215                    cmlPanel.setMessageSelectionChangedListener(new ChannelMessageLogPanel.MessageSelectionChangedListener() {
216                            public void onChange(File archivedFile) {
217                                    try {
218                                            messageText.setText(ResourceUtil.readFileContent(archivedFile));
219                                    } catch (Exception e) {
220                                            e.printStackTrace();
221                                    }
222                            }
223                    });
224            }
225    }