/* | |
* Copyright 2001,2004 The Apache Software Foundation. | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
import java.awt.*; | |
import java.awt.event.*; | |
import java.io.*; | |
import java.net.*; | |
import java.text.*; | |
import java.util.*; | |
import javax.swing.*; | |
import javax.swing.border.*; | |
import javax.swing.event.*; | |
import javax.swing.table.*; | |
import org.apache.axis2.soapmonitor.servlet.SOAPMonitorConstants; | |
/** | |
* This is a SOAP Mointor Applet class. This class provides | |
* the user interface for displaying data from the SOAP | |
* monitor service. | |
*/ | |
public class SOAPMonitorApplet extends JApplet { | |
/** | |
* Private data | |
*/ | |
private JPanel main_panel = null; | |
private JTabbedPane tabbed_pane = null; | |
private int port = 0; | |
private Vector pages = null; | |
/** | |
* Constructor | |
*/ | |
public SOAPMonitorApplet() { | |
} | |
/** | |
* Applet initialization | |
*/ | |
public void init() { | |
// Get the port to be used | |
String port_str = getParameter("port"); | |
if (port_str != null) { | |
port = Integer.parseInt(port_str); | |
} | |
// Try to use the system look and feel | |
try { | |
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); | |
} catch (Exception e){ | |
} | |
// Create main panel to hold notebook | |
main_panel = new JPanel(); | |
main_panel.setBackground(Color.white); | |
main_panel.setLayout(new BorderLayout()); | |
setContentPane(main_panel); | |
// Create the notebook | |
tabbed_pane = new JTabbedPane(JTabbedPane.TOP); | |
main_panel.add(tabbed_pane,BorderLayout.CENTER); | |
// Add notebook page for default host connection | |
pages = new Vector(); | |
addPage(new SOAPMonitorPage(getCodeBase().getHost())); | |
} | |
/** | |
* Add a page to the notebook | |
*/ | |
private void addPage(SOAPMonitorPage pg) { | |
tabbed_pane.addTab(" "+pg.getHost()+" ", pg); | |
pages.addElement(pg); | |
} | |
/** | |
* Applet is being displayed | |
*/ | |
public void start() { | |
// Tell all pages to start talking to the server | |
Enumeration e = pages.elements(); | |
while (e.hasMoreElements()) { | |
SOAPMonitorPage pg = (SOAPMonitorPage) e.nextElement(); | |
if (pg != null) { | |
pg.start(); | |
} | |
} | |
} | |
/* | |
* Applet is no longer displayed | |
*/ | |
public void stop() { | |
// Tell all pages to stop talking to the server | |
Enumeration e = pages.elements(); | |
while (e.hasMoreElements()) { | |
SOAPMonitorPage pg = (SOAPMonitorPage) e.nextElement(); | |
if (pg != null) { | |
pg.stop(); | |
} | |
} | |
} | |
/** | |
* Applet cleanup | |
*/ | |
public void destroy() { | |
tabbed_pane = null; | |
main_panel = null; | |
} | |
/** | |
* This class provides the contents of a notebook page | |
* representing a server connection. | |
*/ | |
class SOAPMonitorPage extends JPanel | |
implements Runnable, | |
ListSelectionListener, | |
ActionListener { | |
/** | |
* Status Strings | |
*/ | |
private final String STATUS_ACTIVE = "The SOAP Monitor is started."; | |
private final String STATUS_STOPPED = "The SOAP Monitor is stopped."; | |
private final String STATUS_CLOSED = "The server communication has been terminated."; | |
private final String STATUS_NOCONNECT = "The SOAP Monitor is unable to communcate with the server."; | |
/** | |
* Private data | |
*/ | |
private String host = null; | |
private Socket socket = null; | |
private ObjectInputStream in = null; | |
private ObjectOutputStream out = null; | |
private SOAPMonitorTableModel model = null; | |
private JTable table = null; | |
private JScrollPane scroll = null; | |
private JPanel list_panel = null; | |
private JPanel list_buttons = null; | |
private JButton remove_button = null; | |
private JButton remove_all_button = null; | |
private JButton filter_button = null; | |
private JPanel details_panel = null; | |
private JPanel details_header = null; | |
private JSplitPane details_soap = null; | |
private JPanel details_buttons = null; | |
private JLabel details_time = null; | |
private JLabel details_target = null; | |
private JLabel details_status = null; | |
private JLabel details_time_value = null; | |
private JLabel details_target_value = null; | |
private JLabel details_status_value = null; | |
private EmptyBorder empty_border = null; | |
private EtchedBorder etched_border = null; | |
private JPanel request_panel = null; | |
private JPanel response_panel = null; | |
private JLabel request_label = null; | |
private JLabel response_label = null; | |
private SOAPMonitorTextArea request_text = null; | |
private SOAPMonitorTextArea response_text = null; | |
private JScrollPane request_scroll = null; | |
private JScrollPane response_scroll = null; | |
private JButton layout_button = null; | |
private JSplitPane split = null; | |
private JPanel status_area = null; | |
private JPanel status_buttons = null; | |
private JButton start_button = null; | |
private JButton stop_button = null; | |
private JLabel status_text = null; | |
private JPanel status_text_panel = null; | |
private SOAPMonitorFilter filter = null; | |
private GridBagLayout details_header_layout = null; | |
private GridBagConstraints details_header_constraints = null; | |
private JCheckBox reflow_xml = null; | |
/** | |
* Constructor (create and layout page) | |
*/ | |
public SOAPMonitorPage(String host_name) { | |
host = host_name; | |
// Set up default filter (show all messages) | |
filter = new SOAPMonitorFilter(); | |
// Use borders to help improve appearance | |
etched_border = new EtchedBorder(); | |
// Build top portion of split (list panel) | |
model = new SOAPMonitorTableModel(); | |
table = new JTable(model); | |
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); | |
table.setRowSelectionInterval(0,0); | |
table.setPreferredScrollableViewportSize(new Dimension(600, 96)); | |
table.getSelectionModel().addListSelectionListener(this); | |
scroll = new JScrollPane(table); | |
remove_button = new JButton("Remove"); | |
remove_button.addActionListener(this); | |
remove_button.setEnabled(false); | |
remove_all_button = new JButton("Remove All"); | |
remove_all_button.addActionListener(this); | |
filter_button = new JButton("Filter ..."); | |
filter_button.addActionListener(this); | |
list_buttons = new JPanel(); | |
list_buttons.setLayout(new FlowLayout()); | |
list_buttons.add(remove_button); | |
list_buttons.add(remove_all_button); | |
list_buttons.add(filter_button); | |
list_panel = new JPanel(); | |
list_panel.setLayout(new BorderLayout()); | |
list_panel.add(scroll,BorderLayout.CENTER); | |
list_panel.add(list_buttons, BorderLayout.SOUTH); | |
list_panel.setBorder(empty_border); | |
// Build bottom portion of split (message details) | |
details_time = new JLabel("Time: ", SwingConstants.RIGHT); | |
details_target = new JLabel("Target Service: ", SwingConstants.RIGHT); | |
details_status = new JLabel("Status: ", SwingConstants.RIGHT); | |
details_time_value = new JLabel(); | |
details_target_value = new JLabel(); | |
details_status_value = new JLabel(); | |
Dimension preferred_size = details_time.getPreferredSize(); | |
preferred_size.width = 1; | |
details_time.setPreferredSize(preferred_size); | |
details_target.setPreferredSize(preferred_size); | |
details_status.setPreferredSize(preferred_size); | |
details_time_value.setPreferredSize(preferred_size); | |
details_target_value.setPreferredSize(preferred_size); | |
details_status_value.setPreferredSize(preferred_size); | |
details_header = new JPanel(); | |
details_header_layout = new GridBagLayout(); | |
details_header.setLayout(details_header_layout); | |
details_header_constraints = new GridBagConstraints(); | |
details_header_constraints.fill=GridBagConstraints.BOTH; | |
details_header_constraints.weightx=0.5; | |
details_header_layout.setConstraints(details_time,details_header_constraints); | |
details_header.add(details_time); | |
details_header_layout.setConstraints(details_time_value,details_header_constraints); | |
details_header.add(details_time_value); | |
details_header_layout.setConstraints(details_target,details_header_constraints); | |
details_header.add(details_target); | |
details_header_constraints.weightx=1.0; | |
details_header_layout.setConstraints(details_target_value,details_header_constraints); | |
details_header.add(details_target_value); | |
details_header_constraints.weightx=.5; | |
details_header_layout.setConstraints(details_status,details_header_constraints); | |
details_header.add(details_status); | |
details_header_layout.setConstraints(details_status_value,details_header_constraints); | |
details_header.add(details_status_value); | |
details_header.setBorder(etched_border); | |
request_label = new JLabel("SOAP Request", SwingConstants.CENTER); | |
request_text = new SOAPMonitorTextArea(); | |
request_text.setEditable(false); | |
request_scroll = new JScrollPane(request_text); | |
request_panel = new JPanel(); | |
request_panel.setLayout(new BorderLayout()); | |
request_panel.add(request_label, BorderLayout.NORTH); | |
request_panel.add(request_scroll, BorderLayout.CENTER); | |
response_label = new JLabel("SOAP Response", SwingConstants.CENTER); | |
response_text = new SOAPMonitorTextArea(); | |
response_text.setEditable(false); | |
response_scroll = new JScrollPane(response_text); | |
response_panel = new JPanel(); | |
response_panel.setLayout(new BorderLayout()); | |
response_panel.add(response_label, BorderLayout.NORTH); | |
response_panel.add(response_scroll, BorderLayout.CENTER); | |
details_soap = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); | |
details_soap.setTopComponent(request_panel); | |
details_soap.setRightComponent(response_panel); | |
details_soap.setResizeWeight(.5); | |
details_panel = new JPanel(); | |
layout_button = new JButton("Switch Layout"); | |
layout_button.addActionListener(this); | |
reflow_xml = new JCheckBox("Reflow XML text"); | |
reflow_xml.addActionListener(this); | |
details_buttons = new JPanel(); | |
details_buttons.setLayout(new FlowLayout()); | |
details_buttons.add(reflow_xml); | |
details_buttons.add(layout_button); | |
details_panel.setLayout(new BorderLayout()); | |
details_panel.add(details_header,BorderLayout.NORTH); | |
details_panel.add(details_soap,BorderLayout.CENTER); | |
details_panel.add(details_buttons,BorderLayout.SOUTH); | |
details_panel.setBorder(empty_border); | |
// Add the two parts to the age split pane | |
split = new JSplitPane(JSplitPane.VERTICAL_SPLIT); | |
split.setTopComponent(list_panel); | |
split.setRightComponent(details_panel); | |
// Build status area | |
start_button = new JButton("Start"); | |
start_button.addActionListener(this); | |
stop_button = new JButton("Stop"); | |
stop_button.addActionListener(this); | |
status_buttons = new JPanel(); | |
status_buttons.setLayout(new FlowLayout()); | |
status_buttons.add(start_button); | |
status_buttons.add(stop_button); | |
status_text = new JLabel(); | |
status_text.setBorder(new BevelBorder(BevelBorder.LOWERED)); | |
status_text_panel = new JPanel(); | |
status_text_panel.setLayout(new BorderLayout()); | |
status_text_panel.add(status_text, BorderLayout.CENTER); | |
status_text_panel.setBorder(empty_border); | |
status_area = new JPanel(); | |
status_area.setLayout(new BorderLayout()); | |
status_area.add(status_buttons, BorderLayout.WEST); | |
status_area.add(status_text_panel, BorderLayout.CENTER); | |
status_area.setBorder(etched_border); | |
// Add the split and status area to page | |
setLayout(new BorderLayout()); | |
add(split, BorderLayout.CENTER); | |
add(status_area, BorderLayout.SOUTH); | |
} | |
/** | |
* Get the name of the host we are displaying | |
*/ | |
public String getHost() { | |
return host; | |
} | |
/** | |
* Set the status text | |
*/ | |
public void setStatus(String txt) { | |
status_text.setForeground(Color.black); | |
status_text.setText(" "+txt); | |
} | |
/** | |
* Set the status text to an error | |
*/ | |
public void setErrorStatus(String txt) { | |
status_text.setForeground(Color.red); | |
status_text.setText(" "+txt); | |
} | |
/** | |
* Start talking to the server | |
*/ | |
public void start() { | |
String codehost = getCodeBase().getHost(); | |
if (socket == null) { | |
try { | |
// Open the socket to the server | |
socket = new Socket(codehost, port); | |
// Create output stream | |
out = new ObjectOutputStream(socket.getOutputStream()); | |
out.flush(); | |
// Create input stream and start background | |
// thread to read data from the server | |
in = new ObjectInputStream(socket.getInputStream()); | |
new Thread(this).start(); | |
} catch (Exception e) { | |
// Exceptions here are unexpected, but we can't | |
// really do anything (so just write it to stdout | |
// in case someone cares and then ignore it) | |
System.out.println("Exception! "+e.toString()); | |
e.printStackTrace(); | |
setErrorStatus(STATUS_NOCONNECT); | |
socket = null; | |
} | |
} else { | |
// Already started | |
} | |
if (socket != null) { | |
// Make sure the right buttons are enabled | |
start_button.setEnabled(false); | |
stop_button.setEnabled(true); | |
setStatus(STATUS_ACTIVE); | |
} | |
} | |
/** | |
* Stop talking to the server | |
*/ | |
public void stop() { | |
if (socket != null) { | |
// Close all the streams and socket | |
if (out != null) { | |
try { | |
out.close(); | |
} catch (IOException ioe) { | |
} | |
out = null; | |
} | |
if (in != null) { | |
try { | |
in.close(); | |
} catch (IOException ioe) { | |
} | |
in = null; | |
} | |
if (socket != null) { | |
try { | |
socket.close(); | |
} catch (IOException ioe) { | |
} | |
socket = null; | |
} | |
} else { | |
// Already stopped | |
} | |
// Make sure the right buttons are enabled | |
start_button.setEnabled(true); | |
stop_button.setEnabled(false); | |
setStatus(STATUS_STOPPED); | |
} | |
/** | |
* Background thread used to receive data from | |
* the server. | |
*/ | |
public void run() { | |
Long id; | |
Integer message_type; | |
String target; | |
String soap; | |
SOAPMonitorData data; | |
int selected; | |
int row; | |
boolean update_needed; | |
while (socket != null) { | |
try { | |
// Get the data from the server | |
message_type = (Integer) in.readObject(); | |
// Process the data depending on its type | |
switch (message_type.intValue()) { | |
case SOAPMonitorConstants.SOAP_MONITOR_REQUEST: | |
// Get the id, target and soap info | |
id = (Long) in.readObject(); | |
target = (String) in.readObject(); | |
soap = (String) in.readObject(); | |
// Add new request data to the table | |
data = new SOAPMonitorData(id,target,soap); | |
model.addData(data); | |
// If "most recent" selected then update | |
// the details area if needed | |
selected = table.getSelectedRow(); | |
if ((selected == 0) && model.filterMatch(data)) { | |
valueChanged(null); | |
} | |
break; | |
case SOAPMonitorConstants.SOAP_MONITOR_RESPONSE: | |
// Get the id and soap info | |
id = (Long) in.readObject(); | |
soap = (String) in.readObject(); | |
data = model.findData(id); | |
if (data != null) { | |
update_needed = false; | |
// Get the selected row | |
selected = table.getSelectedRow(); | |
// If "most recent", then always | |
// update details area | |
if (selected == 0) { | |
update_needed = true; | |
} | |
// If the data being updated is | |
// selected then update details | |
row = model.findRow(data); | |
if ((row != -1) && (row == selected)) { | |
update_needed = true; | |
} | |
// Set the response and update table | |
data.setSOAPResponse(soap); | |
model.updateData(data); | |
// Refresh details area (if needed) | |
if (update_needed) { | |
valueChanged(null); | |
} | |
} | |
break; | |
} | |
} catch (Exception e) { | |
// Exceptions are expected here when the | |
// server communication has been terminated. | |
if (stop_button.isEnabled()) { | |
stop(); | |
setErrorStatus(STATUS_CLOSED); | |
} | |
} | |
} | |
} | |
/** | |
* Listener to handle table selection changes | |
*/ | |
public void valueChanged(ListSelectionEvent e) { | |
int row = table.getSelectedRow(); | |
// Check if they selected a specific row | |
if (row > 0) { | |
remove_button.setEnabled(true); | |
} else { | |
remove_button.setEnabled(false); | |
} | |
// Check for "most recent" selection | |
if (row == 0) { | |
row = model.getRowCount() - 1; | |
if (row == 0) { | |
row = -1; | |
} | |
} | |
if (row == -1) { | |
// Clear the details panel | |
details_time_value.setText(""); | |
details_target_value.setText(""); | |
details_status_value.setText(""); | |
request_text.setText(""); | |
response_text.setText(""); | |
} else { | |
// Show the details for the row | |
SOAPMonitorData soap = model.getData(row); | |
details_time_value.setText(soap.getTime()); | |
details_target_value.setText(soap.getTargetService()); | |
details_status_value.setText(soap.getStatus()); | |
if (soap.getSOAPRequest() == null) { | |
request_text.setText(""); | |
} else { | |
request_text.setText(soap.getSOAPRequest()); | |
request_text.setCaretPosition(0); | |
} | |
if (soap.getSOAPResponse() == null) { | |
response_text.setText(""); | |
} else { | |
response_text.setText(soap.getSOAPResponse()); | |
response_text.setCaretPosition(0); | |
} | |
} | |
} | |
/** | |
* Listener to handle button actions | |
*/ | |
public void actionPerformed(ActionEvent e) { | |
// Check if the user pressed the remove button | |
if (e.getSource() == remove_button) { | |
int row = table.getSelectedRow(); | |
model.removeRow(row); | |
table.clearSelection(); | |
table.repaint(); | |
valueChanged(null); | |
} | |
// Check if the user pressed the remove all button | |
if (e.getSource() == remove_all_button) { | |
model.clearAll(); | |
table.setRowSelectionInterval(0,0); | |
table.repaint(); | |
valueChanged(null); | |
} | |
// Check if the user pressed the filter button | |
if (e.getSource() == filter_button) { | |
filter.showDialog(); | |
if (filter.okPressed()) { | |
// Update the display with new filter | |
model.setFilter(filter); | |
table.repaint(); | |
} | |
} | |
// Check if the user pressed the start button | |
if (e.getSource() == start_button) { | |
start(); | |
} | |
// Check if the user pressed the stop button | |
if (e.getSource() == stop_button) { | |
stop(); | |
} | |
// Check if the user wants to switch layout | |
if (e.getSource() == layout_button) { | |
details_panel.remove(details_soap); | |
details_soap.removeAll(); | |
if (details_soap.getOrientation() == JSplitPane.HORIZONTAL_SPLIT) { | |
details_soap = new JSplitPane(JSplitPane.VERTICAL_SPLIT); | |
} else { | |
details_soap = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); | |
} | |
details_soap.setTopComponent(request_panel); | |
details_soap.setRightComponent(response_panel); | |
details_soap.setResizeWeight(.5); | |
details_panel.add(details_soap, BorderLayout.CENTER); | |
details_panel.validate(); | |
details_panel.repaint(); | |
} | |
// Check if the user is changing the reflow option | |
if (e.getSource() == reflow_xml) { | |
request_text.setReflowXML(reflow_xml.isSelected()); | |
response_text.setReflowXML(reflow_xml.isSelected()); | |
} | |
} | |
} | |
/** | |
* This class represend the data for a SOAP request/response pair | |
*/ | |
class SOAPMonitorData { | |
/** | |
* Private data | |
*/ | |
private Long id; | |
private String time; | |
private String target; | |
private String soap_request; | |
private String soap_response; | |
/** | |
* Constructor | |
*/ | |
public SOAPMonitorData(Long id, String target, String soap_request) { | |
this.id = id; | |
// A null id is used to signal that the "most recent" entry | |
// is being created. | |
if (id == null) { | |
this.time = "Most Recent"; | |
this.target = "---"; | |
this.soap_request = null; | |
this.soap_response = null; | |
} else { | |
this.time = DateFormat.getTimeInstance().format(new Date()); | |
this.target = target; | |
this.soap_request = soap_request; | |
this.soap_response = null; | |
} | |
} | |
/** | |
* Get the id for the SOAP message | |
*/ | |
public Long getId() { | |
return id; | |
} | |
/** | |
* Get the time the SOAP request was received by the applet | |
*/ | |
public String getTime() { | |
return time; | |
} | |
/** | |
* Get the SOAP request target service name | |
*/ | |
public String getTargetService() { | |
return target; | |
} | |
/** | |
* Get the status of the request | |
*/ | |
public String getStatus() { | |
String status = "---"; | |
if (id != null) { | |
status = "Complete"; | |
if (soap_response == null) { | |
status = "Active"; | |
} | |
} | |
return status; | |
} | |
/** | |
* Get the request SOAP contents | |
*/ | |
public String getSOAPRequest() { | |
return soap_request; | |
} | |
/** | |
* Set the resposne SOAP contents | |
*/ | |
public void setSOAPResponse(String response) { | |
soap_response = response; | |
} | |
/** | |
* Get the response SOAP contents | |
*/ | |
public String getSOAPResponse() { | |
return soap_response; | |
} | |
} | |
/** | |
* This table model is used to manage the table displayed | |
* at the top of the page to show all the SOAP messages | |
* we have received and to control which message details are | |
* to be displayed on the bottom of the page. | |
*/ | |
class SOAPMonitorTableModel extends AbstractTableModel { | |
/** | |
* Column titles | |
*/ | |
private final String[] column_names = { "Time", | |
"Target Service", | |
"Status" }; | |
/** | |
* Private data | |
*/ | |
private Vector data; | |
private Vector filter_include; | |
private Vector filter_exclude; | |
private boolean filter_active; | |
private boolean filter_complete; | |
private Vector filter_data; | |
/** | |
* Constructor | |
*/ | |
public SOAPMonitorTableModel() { | |
data = new Vector(); | |
// Add "most recent" entry to top of table | |
SOAPMonitorData soap = new SOAPMonitorData(null,null,null); | |
data.addElement(soap); | |
filter_include = null; | |
filter_exclude = null; | |
filter_active = false; | |
filter_complete = false; | |
filter_data = null; | |
// By default, exclude NotificationService and | |
// EventViewerService messages | |
filter_exclude = new Vector(); | |
filter_exclude.addElement("NotificationService"); | |
filter_exclude.addElement("EventViewerService"); | |
filter_data = new Vector(); | |
filter_data.addElement(soap); | |
} | |
/** | |
* Get column count (part of table model interface) | |
*/ | |
public int getColumnCount() { | |
return column_names.length; | |
} | |
/** | |
* Get row count (part of table model interface) | |
*/ | |
public int getRowCount() { | |
int count = data.size(); | |
if (filter_data != null) { | |
count = filter_data.size(); | |
} | |
return count; | |
} | |
/** | |
* Get column name (part of table model interface) | |
*/ | |
public String getColumnName(int col) { | |
return column_names[col]; | |
} | |
/** | |
* Get value at (part of table model interface) | |
*/ | |
public Object getValueAt(int row, int col) { | |
SOAPMonitorData soap; | |
String value = null; | |
soap = (SOAPMonitorData) data.elementAt(row); | |
if (filter_data != null) { | |
soap = (SOAPMonitorData) filter_data.elementAt(row); | |
} | |
switch (col) { | |
case 0: | |
value = soap.getTime(); | |
break; | |
case 1: | |
value = soap.getTargetService(); | |
break; | |
case 2: | |
value = soap.getStatus(); | |
break; | |
} | |
return value; | |
} | |
/** | |
* Check if soap data matches filter | |
*/ | |
public boolean filterMatch(SOAPMonitorData soap) { | |
boolean match = true; | |
if (filter_include != null) { | |
// Check for service match | |
Enumeration e = filter_include.elements(); | |
match = false; | |
while (e.hasMoreElements() && !match) { | |
String service = (String) e.nextElement(); | |
if (service.equals(soap.getTargetService())) { | |
match = true; | |
} | |
} | |
} | |
if (filter_exclude != null) { | |
// Check for service match | |
Enumeration e = filter_exclude.elements(); | |
while (e.hasMoreElements() && match) { | |
String service = (String) e.nextElement(); | |
if (service.equals(soap.getTargetService())) { | |
match = false; | |
} | |
} | |
} | |
if (filter_active) { | |
// Check for active status match | |
if (soap.getSOAPResponse() != null) { | |
match = false; | |
} | |
} | |
if (filter_complete) { | |
// Check for complete status match | |
if (soap.getSOAPResponse() == null) { | |
match = false; | |
} | |
} | |
// The "most recent" is always a match | |
if (soap.getId() == null) { | |
match = true; | |
} | |
return match; | |
} | |
/** | |
* Add data to the table as a new row | |
*/ | |
public void addData(SOAPMonitorData soap) { | |
int row = data.size(); | |
data.addElement(soap); | |
if (filter_data != null) { | |
if (filterMatch(soap)) { | |
row = filter_data.size(); | |
filter_data.addElement(soap); | |
fireTableRowsInserted(row,row); | |
} | |
} else { | |
fireTableRowsInserted(row,row); | |
} | |
} | |
/** | |
* Find the data for a given id | |
*/ | |
public SOAPMonitorData findData(Long id) { | |
SOAPMonitorData soap = null; | |
for (int row=data.size(); (row > 0) && (soap == null); row--) { | |
soap = (SOAPMonitorData) data.elementAt(row-1); | |
if (soap.getId().longValue() != id.longValue()) { | |
soap = null; | |
} | |
} | |
return soap; | |
} | |
/** | |
* Find the row in the table for a given message id | |
*/ | |
public int findRow(SOAPMonitorData soap) { | |
int row = -1; | |
if (filter_data != null) { | |
row = filter_data.indexOf(soap); | |
} else { | |
row = data.indexOf(soap); | |
} | |
return row; | |
} | |
/** | |
* Remove all messages from the table (but leave "most recent") | |
*/ | |
public void clearAll() { | |
int last_row = data.size() - 1; | |
if (last_row > 0) { | |
data.removeAllElements(); | |
SOAPMonitorData soap = new SOAPMonitorData(null,null,null); | |
data.addElement(soap); | |
if (filter_data != null) { | |
filter_data.removeAllElements(); | |
filter_data.addElement(soap); | |
} | |
fireTableDataChanged(); | |
} | |
} | |
/** | |
* Remove a message from the table | |
*/ | |
public void removeRow(int row) { | |
SOAPMonitorData soap = null; | |
if (filter_data == null) { | |
soap = (SOAPMonitorData) data.elementAt(row); | |
data.remove(soap); | |
} else { | |
soap = (SOAPMonitorData) filter_data.elementAt(row); | |
filter_data.remove(soap); | |
data.remove(soap); | |
} | |
fireTableRowsDeleted(row,row); | |
} | |
/** | |
* Set a new filter | |
*/ | |
public void setFilter(SOAPMonitorFilter filter) { | |
// Save new filter criteria | |
filter_include = filter.getFilterIncludeList(); | |
filter_exclude = filter.getFilterExcludeList(); | |
filter_active = filter.getFilterActive(); | |
filter_complete = filter.getFilterComplete(); | |
applyFilter(); | |
} | |
/** | |
* Refilter the list of messages | |
*/ | |
public void applyFilter() { | |
// Re-filter using new criteria | |
filter_data = null; | |
if ((filter_include != null) || | |
(filter_exclude != null) || | |
filter_active || filter_complete ) { | |
filter_data = new Vector(); | |
Enumeration e = data.elements(); | |
SOAPMonitorData soap; | |
while (e.hasMoreElements()) { | |
soap = (SOAPMonitorData) e.nextElement(); | |
if (filterMatch(soap)) { | |
filter_data.addElement(soap); | |
} | |
} | |
} | |
fireTableDataChanged(); | |
} | |
/** | |
* Get the data for a row | |
*/ | |
public SOAPMonitorData getData(int row) { | |
SOAPMonitorData soap = null; | |
if (filter_data == null) { | |
soap = (SOAPMonitorData) data.elementAt(row); | |
} else { | |
soap = (SOAPMonitorData) filter_data.elementAt(row); | |
} | |
return soap; | |
} | |
/** | |
* Update a message | |
*/ | |
public void updateData (SOAPMonitorData soap) { | |
int row; | |
if (filter_data == null) { | |
// No filter, so just fire table updated | |
row = data.indexOf(soap); | |
if (row != -1) { | |
fireTableRowsUpdated(row,row); | |
} | |
} else { | |
// Check if the row was being displayed | |
row = filter_data.indexOf(soap); | |
if (row == -1) { | |
// Row was not displayed, so check for if it | |
// now needs to be displayed | |
if (filterMatch(soap)) { | |
int index = -1; | |
row = data.indexOf(soap) + 1; | |
while ((row < data.size()) && (index == -1)) { | |
index = filter_data.indexOf(data.elementAt(row)); | |
if (index != -1) { | |
// Insert at this location | |
filter_data.add(index,soap); | |
} | |
row++; | |
} | |
if (index == -1) { | |
// Insert at end | |
index = filter_data.size(); | |
filter_data.addElement(soap); | |
} | |
fireTableRowsInserted(index,index); | |
} | |
} else { | |
// Row was displayed, so check if it needs to | |
// be updated or removed | |
if (filterMatch(soap)) { | |
fireTableRowsUpdated(row,row); | |
} else { | |
filter_data.remove(soap); | |
fireTableRowsDeleted(row,row); | |
} | |
} | |
} | |
} | |
} | |
/** | |
* Panel with checkbox and list | |
*/ | |
class ServiceFilterPanel extends JPanel | |
implements ActionListener, | |
ListSelectionListener, | |
DocumentListener { | |
private JCheckBox service_box = null; | |
private Vector filter_list = null; | |
private Vector service_data = null; | |
private JList service_list = null; | |
private JScrollPane service_scroll = null; | |
private JButton remove_service_button = null; | |
private JPanel remove_service_panel = null; | |
private EmptyBorder indent_border = null; | |
private EmptyBorder empty_border = null; | |
private JPanel service_area = null; | |
private JPanel add_service_area = null; | |
private JTextField add_service_field = null; | |
private JButton add_service_button = null; | |
private JPanel add_service_panel = null; | |
/** | |
* Constructor | |
*/ | |
public ServiceFilterPanel(String text, Vector list) { | |
empty_border = new EmptyBorder(5,5,0,5); | |
indent_border = new EmptyBorder(5,25,5,5); | |
service_box = new JCheckBox(text); | |
service_box.addActionListener(this); | |
service_data = new Vector(); | |
if (list != null) { | |
service_box.setSelected(true); | |
service_data = (Vector) list.clone(); | |
} | |
service_list = new JList(service_data); | |
service_list.setBorder(new EtchedBorder()); | |
service_list.setVisibleRowCount(5); | |
service_list.addListSelectionListener(this); | |
service_list.setEnabled(service_box.isSelected()); | |
service_scroll = new JScrollPane(service_list); | |
service_scroll.setBorder(new EtchedBorder()); | |
remove_service_button = new JButton("Remove"); | |
remove_service_button.addActionListener(this); | |
remove_service_button.setEnabled(false); | |
remove_service_panel = new JPanel(); | |
remove_service_panel.setLayout(new FlowLayout()); | |
remove_service_panel.add(remove_service_button); | |
service_area = new JPanel(); | |
service_area.setLayout(new BorderLayout()); | |
service_area.add(service_scroll, BorderLayout.CENTER); | |
service_area.add(remove_service_panel, BorderLayout.EAST); | |
service_area.setBorder(indent_border); | |
add_service_field = new JTextField(); | |
add_service_field.addActionListener(this); | |
add_service_field.getDocument().addDocumentListener(this); | |
add_service_field.setEnabled(service_box.isSelected()); | |
add_service_button = new JButton("Add"); | |
add_service_button.addActionListener(this); | |
add_service_button.setEnabled(false); | |
add_service_panel = new JPanel(); | |
add_service_panel.setLayout(new BorderLayout()); | |
JPanel dummy = new JPanel(); | |
dummy.setBorder(empty_border); | |
add_service_panel.add(dummy, BorderLayout.WEST); | |
add_service_panel.add(add_service_button, BorderLayout.EAST); | |
add_service_area = new JPanel(); | |
add_service_area.setLayout(new BorderLayout()); | |
add_service_area.add(add_service_field, BorderLayout.CENTER); | |
add_service_area.add(add_service_panel, BorderLayout.EAST); | |
add_service_area.setBorder(indent_border); | |
setLayout(new BorderLayout()); | |
add(service_box, BorderLayout.NORTH); | |
add(service_area, BorderLayout.CENTER); | |
add(add_service_area, BorderLayout.SOUTH); | |
setBorder(empty_border); | |
} | |
/** | |
* Get the current list of services | |
*/ | |
public Vector getServiceList() { | |
Vector list = null; | |
if (service_box.isSelected()) { | |
list = service_data; | |
} | |
return list; | |
} | |
/** | |
* Listener to handle button actions | |
*/ | |
public void actionPerformed(ActionEvent e) { | |
// Check if the user changed the service filter option | |
if (e.getSource() == service_box) { | |
service_list.setEnabled(service_box.isSelected()); | |
service_list.clearSelection(); | |
remove_service_button.setEnabled(false); | |
add_service_field.setEnabled(service_box.isSelected()); | |
add_service_field.setText(""); | |
add_service_button.setEnabled(false); | |
} | |
// Check if the user pressed the add service button | |
if ((e.getSource() == add_service_button) || | |
(e.getSource() == add_service_field)) { | |
String text = add_service_field.getText(); | |
if ((text != null) && (text.length() > 0)) { | |
service_data.addElement(text); | |
service_list.setListData(service_data); | |
} | |
add_service_field.setText(""); | |
add_service_field.requestFocus(); | |
} | |
// Check if the user pressed the remove service button | |
if (e.getSource() == remove_service_button) { | |
Object[] sels = service_list.getSelectedValues(); | |
for (int i=0; i<sels.length; i++) { | |
service_data.removeElement(sels[i]); | |
} | |
service_list.setListData(service_data); | |
service_list.clearSelection(); | |
} | |
} | |
/** | |
* Handle changes to the text field | |
*/ | |
public void changedUpdate(DocumentEvent e) { | |
String text = add_service_field.getText(); | |
if ((text != null) && (text.length() > 0)) { | |
add_service_button.setEnabled(true); | |
} else { | |
add_service_button.setEnabled(false); | |
} | |
} | |
/** | |
* Handle changes to the text field | |
*/ | |
public void insertUpdate(DocumentEvent e) { | |
changedUpdate(e); | |
} | |
/** | |
* Handle changes to the text field | |
*/ | |
public void removeUpdate(DocumentEvent e) { | |
changedUpdate(e); | |
} | |
/** | |
* Listener to handle service list selection changes | |
*/ | |
public void valueChanged(ListSelectionEvent e) { | |
if (service_list.getSelectedIndex() == -1) { | |
remove_service_button.setEnabled(false); | |
} else { | |
remove_service_button.setEnabled(true); | |
} | |
} | |
} | |
/** | |
* Class for showing the filter dialog | |
*/ | |
class SOAPMonitorFilter implements ActionListener { | |
/** | |
* Private data | |
*/ | |
private JDialog dialog = null; | |
private JPanel panel = null; | |
private JPanel buttons = null; | |
private JButton ok_button = null; | |
private JButton cancel_button = null; | |
private ServiceFilterPanel include_panel = null; | |
private ServiceFilterPanel exclude_panel = null; | |
private JPanel status_panel = null; | |
private JCheckBox status_box = null; | |
private EmptyBorder empty_border = null; | |
private EmptyBorder indent_border = null; | |
private JPanel status_options = null; | |
private ButtonGroup status_group = null; | |
private JRadioButton status_active = null; | |
private JRadioButton status_complete = null; | |
private Vector filter_include_list = null; | |
private Vector filter_exclude_list = null; | |
private boolean filter_active = false; | |
private boolean filter_complete = false; | |
private boolean ok_pressed = false; | |
/** | |
* Constructor | |
*/ | |
public SOAPMonitorFilter() { | |
// By default, exclude NotificationService and | |
// EventViewerService messages | |
filter_exclude_list = new Vector(); | |
filter_exclude_list.addElement("NotificationService"); | |
filter_exclude_list.addElement("EventViewerService"); | |
} | |
/** | |
* Get list of services to be included | |
*/ | |
public Vector getFilterIncludeList() { | |
return filter_include_list; | |
} | |
/** | |
* Get list of services to be excluded | |
*/ | |
public Vector getFilterExcludeList() { | |
return filter_exclude_list; | |
} | |
/** | |
* Check if filter active messages | |
*/ | |
public boolean getFilterActive() { | |
return filter_active; | |
} | |
/** | |
* Check if filter complete messages | |
*/ | |
public boolean getFilterComplete() { | |
return filter_complete; | |
} | |
/** | |
* Show the filter dialog | |
*/ | |
public void showDialog() { | |
empty_border = new EmptyBorder(5,5,0,5); | |
indent_border = new EmptyBorder(5,25,5,5); | |
include_panel = new ServiceFilterPanel("Include messages based on target service:", | |
filter_include_list); | |
exclude_panel = new ServiceFilterPanel("Exclude messages based on target service:", | |
filter_exclude_list); | |
status_box = new JCheckBox("Filter messages based on status:"); | |
status_box.addActionListener(this); | |
status_active = new JRadioButton("Active messages only"); | |
status_active.setSelected(true); | |
status_active.setEnabled(false); | |
status_complete = new JRadioButton("Complete messages only"); | |
status_complete.setEnabled(false); | |
status_group = new ButtonGroup(); | |
status_group.add(status_active); | |
status_group.add(status_complete); | |
if (filter_active || filter_complete) { | |
status_box.setSelected(true); | |
status_active.setEnabled(true); | |
status_complete.setEnabled(true); | |
if (filter_complete) { | |
status_complete.setSelected(true); | |
} | |
} | |
status_options = new JPanel(); | |
status_options.setLayout(new BoxLayout(status_options, BoxLayout.Y_AXIS)); | |
status_options.add(status_active); | |
status_options.add(status_complete); | |
status_options.setBorder(indent_border); | |
status_panel = new JPanel(); | |
status_panel.setLayout(new BorderLayout()); | |
status_panel.add(status_box, BorderLayout.NORTH); | |
status_panel.add(status_options, BorderLayout.CENTER); | |
status_panel.setBorder(empty_border); | |
ok_button = new JButton("Ok"); | |
ok_button.addActionListener(this); | |
cancel_button = new JButton("Cancel"); | |
cancel_button.addActionListener(this); | |
buttons = new JPanel(); | |
buttons.setLayout(new FlowLayout()); | |
buttons.add(ok_button); | |
buttons.add(cancel_button); | |
panel = new JPanel(); | |
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); | |
panel.add(include_panel); | |
panel.add(exclude_panel); | |
panel.add(status_panel); | |
panel.add(buttons); | |
dialog = new JDialog(); | |
dialog.setTitle("SOAP Monitor Filter"); | |
dialog.setContentPane(panel); | |
dialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); | |
dialog.setModal(true); | |
dialog.pack(); | |
Dimension d = dialog.getToolkit().getScreenSize(); | |
dialog.setLocation((d.width-dialog.getWidth())/2, | |
(d.height-dialog.getHeight())/2); | |
ok_pressed = false; | |
dialog.show(); | |
} | |
/** | |
* Listener to handle button actions | |
*/ | |
public void actionPerformed(ActionEvent e) { | |
// Check if the user pressed the ok button | |
if (e.getSource() == ok_button) { | |
filter_include_list = include_panel.getServiceList(); | |
filter_exclude_list = exclude_panel.getServiceList(); | |
if (status_box.isSelected()) { | |
filter_active = status_active.isSelected(); | |
filter_complete = status_complete.isSelected(); | |
} else { | |
filter_active = false; | |
filter_complete = false; | |
} | |
ok_pressed = true; | |
dialog.dispose(); | |
} | |
// Check if the user pressed the cancel button | |
if (e.getSource() == cancel_button) { | |
dialog.dispose(); | |
} | |
// Check if the user changed the status filter option | |
if (e.getSource() == status_box) { | |
status_active.setEnabled(status_box.isSelected()); | |
status_complete.setEnabled(status_box.isSelected()); | |
} | |
} | |
/** | |
* Check if the user pressed the ok button | |
*/ | |
public boolean okPressed() { | |
return ok_pressed; | |
} | |
} | |
/** | |
* Text panel class that supports XML reflow | |
*/ | |
class SOAPMonitorTextArea extends JTextArea { | |
/** | |
* Private data | |
*/ | |
private boolean format = false; | |
private String original = ""; | |
private String formatted = null; | |
/** | |
* Constructor | |
*/ | |
public SOAPMonitorTextArea() { | |
} | |
/** | |
* Override setText to do formatting | |
*/ | |
public void setText(String text) { | |
original = text; | |
formatted = null; | |
if (format) { | |
doFormat(); | |
super.setText(formatted); | |
} else { | |
super.setText(original); | |
} | |
} | |
/** | |
* Turn reflow on or off | |
*/ | |
public void setReflowXML(boolean reflow) { | |
format = reflow; | |
if (format) { | |
if (formatted == null) { | |
doFormat(); | |
} | |
super.setText(formatted); | |
} else { | |
super.setText(original); | |
} | |
} | |
/** | |
* Reflow XML | |
*/ | |
public void doFormat() { | |
Vector parts = new Vector(); | |
char[] chars = original.toCharArray(); | |
int index = 0; | |
int first = 0; | |
String part = null; | |
while (index < chars.length) { | |
// Check for start of tag | |
if (chars[index] == '<') { | |
// Did we have data before this tag? | |
if (first < index) { | |
part = new String(chars,first,index-first); | |
part = part.trim(); | |
// Save non-whitespace data | |
if (part.length() > 0) { | |
parts.addElement(part); | |
} | |
} | |
// Save the start of tag | |
first = index; | |
} | |
// Check for end of tag | |
if (chars[index] == '>') { | |
// Save the tag | |
part = new String(chars,first,index-first+1); | |
parts.addElement(part); | |
first = index+1; | |
} | |
// Check for end of line | |
if ((chars[index] == '\n') || (chars[index] == '\r')) { | |
// Was there data on this line? | |
if (first < index) { | |
part = new String(chars,first,index-first); | |
part = part.trim(); | |
// Save non-whitespace data | |
if (part.length() > 0) { | |
parts.addElement(part); | |
} | |
} | |
first = index+1; | |
} | |
index++; | |
} | |
// Reflow as XML | |
StringBuffer buf = new StringBuffer(); | |
Object[] list = parts.toArray(); | |
int indent = 0; | |
int pad = 0; | |
index = 0; | |
while (index < list.length) { | |
part = (String) list[index]; | |
if (buf.length() == 0) { | |
// Just add first tag (should be XML header) | |
buf.append(part); | |
} else { | |
// All other parts need to start on a new line | |
buf.append('\n'); | |
// If we're at an end tag then decrease indent | |
if (part.startsWith("</")) { | |
indent--; | |
} | |
// Add any indent | |
for (pad = 0; pad < indent; pad++) { | |
buf.append(" "); | |
} | |
// Add the tag or data | |
buf.append(part); | |
// If this is a start tag then increase indent | |
if (part.startsWith("<") && | |
!part.startsWith("</") && | |
!part.endsWith("/>")) { | |
indent++; | |
// Check for special <tag>data</tag> case | |
if ((index + 2) < list.length) { | |
part = (String) list[index+2]; | |
if (part.startsWith("</")) { | |
part = (String) list[index+1]; | |
if (!part.startsWith("<")) { | |
buf.append(part); | |
part = (String) list[index+2]; | |
buf.append(part); | |
index = index + 2; | |
indent--; | |
} | |
} | |
} | |
} | |
} | |
index++; | |
} | |
formatted = new String(buf); | |
} | |
} | |
} |