0001: /*
0002: * Copyright 2001,2004 The Apache Software Foundation.
0003: *
0004: * Licensed under the Apache License, Version 2.0 (the "License");
0005: * you may not use this file except in compliance with the License.
0006: * You may obtain a copy of the License at
0007: *
0008: * http://www.apache.org/licenses/LICENSE-2.0
0009: *
0010: * Unless required by applicable law or agreed to in writing, software
0011: * distributed under the License is distributed on an "AS IS" BASIS,
0012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013: * See the License for the specific language governing permissions and
0014: * limitations under the License.
0015: */
0016: package com.nabhinc.portlet.wsadmin;
0017:
0018: import java.awt.*;
0019: import java.awt.event.*;
0020: import java.io.*;
0021: import java.net.*;
0022: import java.text.*;
0023: import java.util.*;
0024: import javax.swing.*;
0025: import javax.swing.border.*;
0026: import javax.swing.event.*;
0027: import javax.swing.table.*;
0028:
0029: /**
0030: * This is a SOAP Mointor Applet class. This class provides
0031: * the user interface for displaying data from the SOAP
0032: * monitor service.
0033: *
0034: * @author Brian Price (pricebe@us.ibm.com)
0035: *
0036: */
0037: public class SOAPMonitorApplet extends JApplet {
0038: /**
0039: * SOAP message types. The constants have been copied from
0040: * SOAPMonitorConstants class distributed in Axis. Technically,
0041: * this is a bad idea, but copying allows us to create applet jar
0042: * without Axis dependency.
0043: */
0044: private static final long serialVersionUID = 1437110599535293414L;
0045: public static final int SOAP_MONITOR_REQUEST = 0;
0046: public static final int SOAP_MONITOR_RESPONSE = 1;
0047:
0048: /**
0049: * Private data
0050: */
0051: private JPanel main_panel = null;
0052: private JTabbedPane tabbed_pane = null;
0053: private int port = 0;
0054: private Vector pages = null;
0055:
0056: /**
0057: * Constructor
0058: */
0059: public SOAPMonitorApplet() {
0060: }
0061:
0062: /**
0063: * Applet initialization
0064: */
0065: public void init() {
0066: // Get the port to be used
0067: String port_str = getParameter("port");
0068: if (port_str != null) {
0069: port = Integer.parseInt(port_str);
0070: }
0071: // Try to use the system look and feel
0072: try {
0073: UIManager.setLookAndFeel(UIManager
0074: .getSystemLookAndFeelClassName());
0075: } catch (Exception e) {
0076: }
0077: // Create main panel to hold notebook
0078: main_panel = new JPanel();
0079: main_panel.setBackground(Color.white);
0080: main_panel.setLayout(new BorderLayout());
0081: setContentPane(main_panel);
0082: // Create the notebook
0083: tabbed_pane = new JTabbedPane(JTabbedPane.TOP);
0084: main_panel.add(tabbed_pane, BorderLayout.CENTER);
0085: // Add notebook page for default host connection
0086: pages = new Vector();
0087: addPage(new SOAPMonitorPage(getCodeBase().getHost()));
0088: }
0089:
0090: /**
0091: * Add a page to the notebook
0092: */
0093: private void addPage(SOAPMonitorPage pg) {
0094: tabbed_pane.addTab(" " + pg.getHost() + " ", pg);
0095: pages.addElement(pg);
0096: }
0097:
0098: /**
0099: * Applet is being displayed
0100: */
0101: public void start() {
0102: // Tell all pages to start talking to the server
0103: Enumeration e = pages.elements();
0104: while (e.hasMoreElements()) {
0105: SOAPMonitorPage pg = (SOAPMonitorPage) e.nextElement();
0106: if (pg != null) {
0107: pg.start();
0108: }
0109: }
0110: }
0111:
0112: /*
0113: * Applet is no longer displayed
0114: */
0115: public void stop() {
0116: // Tell all pages to stop talking to the server
0117: Enumeration e = pages.elements();
0118: while (e.hasMoreElements()) {
0119: SOAPMonitorPage pg = (SOAPMonitorPage) e.nextElement();
0120: if (pg != null) {
0121: pg.stop();
0122: }
0123: }
0124: }
0125:
0126: /**
0127: * Applet cleanup
0128: */
0129: public void destroy() {
0130: tabbed_pane = null;
0131: main_panel = null;
0132: }
0133:
0134: /**
0135: * This class provides the contents of a notebook page
0136: * representing a server connection.
0137: */
0138: class SOAPMonitorPage extends JPanel implements Runnable,
0139: ListSelectionListener, ActionListener {
0140:
0141: /**
0142: * Status Strings
0143: */
0144: private final String STATUS_ACTIVE = "The SOAP Monitor is started.";
0145: private final String STATUS_STOPPED = "The SOAP Monitor is stopped.";
0146: private final String STATUS_CLOSED = "The server communication has been terminated.";
0147: private final String STATUS_NOCONNECT = "The SOAP Monitor is unable to communcate with the server.";
0148:
0149: /**
0150: * Private data
0151: */
0152: private String host = null;
0153: private Socket socket = null;
0154: private ObjectInputStream in = null;
0155: private ObjectOutputStream out = null;
0156: private SOAPMonitorTableModel model = null;
0157: private JTable table = null;
0158: private JScrollPane scroll = null;
0159: private JPanel list_panel = null;
0160: private JPanel list_buttons = null;
0161: private JButton remove_button = null;
0162: private JButton remove_all_button = null;
0163: private JButton filter_button = null;
0164: private JPanel details_panel = null;
0165: private JPanel details_header = null;
0166: private JSplitPane details_soap = null;
0167: private JPanel details_buttons = null;
0168: private JLabel details_time = null;
0169: private JLabel details_target = null;
0170: private JLabel details_status = null;
0171: private JLabel details_time_value = null;
0172: private JLabel details_target_value = null;
0173: private JLabel details_status_value = null;
0174: private EmptyBorder empty_border = null;
0175: private EtchedBorder etched_border = null;
0176: private JPanel request_panel = null;
0177: private JPanel response_panel = null;
0178: private JLabel request_label = null;
0179: private JLabel response_label = null;
0180: private SOAPMonitorTextArea request_text = null;
0181: private SOAPMonitorTextArea response_text = null;
0182: private JScrollPane request_scroll = null;
0183: private JScrollPane response_scroll = null;
0184: private JButton layout_button = null;
0185: private JSplitPane split = null;
0186: private JPanel status_area = null;
0187: private JPanel status_buttons = null;
0188: private JButton start_button = null;
0189: private JButton stop_button = null;
0190: private JLabel status_text = null;
0191: private JPanel status_text_panel = null;
0192: private SOAPMonitorFilter filter = null;
0193: private GridBagLayout details_header_layout = null;
0194: private GridBagConstraints details_header_constraints = null;
0195: private JCheckBox reflow_xml = null;
0196:
0197: /**
0198: * Constructor (create and layout page)
0199: */
0200: public SOAPMonitorPage(String host_name) {
0201: host = host_name;
0202: // Set up default filter (show all messages)
0203: filter = new SOAPMonitorFilter();
0204: // Use borders to help improve appearance
0205: etched_border = new EtchedBorder();
0206: // Build top portion of split (list panel)
0207: model = new SOAPMonitorTableModel();
0208: table = new JTable(model);
0209: table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
0210: table.setRowSelectionInterval(0, 0);
0211: table.setPreferredScrollableViewportSize(new Dimension(600,
0212: 96));
0213: table.getSelectionModel().addListSelectionListener(this );
0214: scroll = new JScrollPane(table);
0215: remove_button = new JButton("Remove");
0216: remove_button.addActionListener(this );
0217: remove_button.setEnabled(false);
0218: remove_all_button = new JButton("Remove All");
0219: remove_all_button.addActionListener(this );
0220: filter_button = new JButton("Filter ...");
0221: filter_button.addActionListener(this );
0222: list_buttons = new JPanel();
0223: list_buttons.setLayout(new FlowLayout());
0224: list_buttons.add(remove_button);
0225: list_buttons.add(remove_all_button);
0226: list_buttons.add(filter_button);
0227: list_panel = new JPanel();
0228: list_panel.setLayout(new BorderLayout());
0229: list_panel.add(scroll, BorderLayout.CENTER);
0230: list_panel.add(list_buttons, BorderLayout.SOUTH);
0231: list_panel.setBorder(empty_border);
0232: // Build bottom portion of split (message details)
0233: details_time = new JLabel("Time: ", SwingConstants.RIGHT);
0234: details_target = new JLabel("Target Service: ",
0235: SwingConstants.RIGHT);
0236: details_status = new JLabel("Status: ",
0237: SwingConstants.RIGHT);
0238: details_time_value = new JLabel();
0239: details_target_value = new JLabel();
0240: details_status_value = new JLabel();
0241: Dimension preferred_size = details_time.getPreferredSize();
0242: preferred_size.width = 1;
0243: details_time.setPreferredSize(preferred_size);
0244: details_target.setPreferredSize(preferred_size);
0245: details_status.setPreferredSize(preferred_size);
0246: details_time_value.setPreferredSize(preferred_size);
0247: details_target_value.setPreferredSize(preferred_size);
0248: details_status_value.setPreferredSize(preferred_size);
0249: details_header = new JPanel();
0250: details_header_layout = new GridBagLayout();
0251: details_header.setLayout(details_header_layout);
0252: details_header_constraints = new GridBagConstraints();
0253: details_header_constraints.fill = GridBagConstraints.BOTH;
0254: details_header_constraints.weightx = 0.5;
0255: details_header_layout.setConstraints(details_time,
0256: details_header_constraints);
0257: details_header.add(details_time);
0258: details_header_layout.setConstraints(details_time_value,
0259: details_header_constraints);
0260: details_header.add(details_time_value);
0261: details_header_layout.setConstraints(details_target,
0262: details_header_constraints);
0263: details_header.add(details_target);
0264: details_header_constraints.weightx = 1.0;
0265: details_header_layout.setConstraints(details_target_value,
0266: details_header_constraints);
0267: details_header.add(details_target_value);
0268: details_header_constraints.weightx = .5;
0269: details_header_layout.setConstraints(details_status,
0270: details_header_constraints);
0271: details_header.add(details_status);
0272: details_header_layout.setConstraints(details_status_value,
0273: details_header_constraints);
0274: details_header.add(details_status_value);
0275: details_header.setBorder(etched_border);
0276: request_label = new JLabel("SOAP Request",
0277: SwingConstants.CENTER);
0278: request_text = new SOAPMonitorTextArea();
0279: request_text.setEditable(false);
0280: request_scroll = new JScrollPane(request_text);
0281: request_panel = new JPanel();
0282: request_panel.setLayout(new BorderLayout());
0283: request_panel.add(request_label, BorderLayout.NORTH);
0284: request_panel.add(request_scroll, BorderLayout.CENTER);
0285: response_label = new JLabel("SOAP Response",
0286: SwingConstants.CENTER);
0287: response_text = new SOAPMonitorTextArea();
0288: response_text.setEditable(false);
0289: response_scroll = new JScrollPane(response_text);
0290: response_panel = new JPanel();
0291: response_panel.setLayout(new BorderLayout());
0292: response_panel.add(response_label, BorderLayout.NORTH);
0293: response_panel.add(response_scroll, BorderLayout.CENTER);
0294: details_soap = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
0295: details_soap.setTopComponent(request_panel);
0296: details_soap.setRightComponent(response_panel);
0297: details_soap.setResizeWeight(.5);
0298: details_panel = new JPanel();
0299: layout_button = new JButton("Switch Layout");
0300: layout_button.addActionListener(this );
0301: reflow_xml = new JCheckBox("Reflow XML text");
0302: reflow_xml.addActionListener(this );
0303: details_buttons = new JPanel();
0304: details_buttons.setLayout(new FlowLayout());
0305: details_buttons.add(reflow_xml);
0306: details_buttons.add(layout_button);
0307: details_panel.setLayout(new BorderLayout());
0308: details_panel.add(details_header, BorderLayout.NORTH);
0309: details_panel.add(details_soap, BorderLayout.CENTER);
0310: details_panel.add(details_buttons, BorderLayout.SOUTH);
0311: details_panel.setBorder(empty_border);
0312: // Add the two parts to the age split pane
0313: split = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
0314: split.setTopComponent(list_panel);
0315: split.setRightComponent(details_panel);
0316: // Build status area
0317: start_button = new JButton("Start");
0318: start_button.addActionListener(this );
0319: stop_button = new JButton("Stop");
0320: stop_button.addActionListener(this );
0321: status_buttons = new JPanel();
0322: status_buttons.setLayout(new FlowLayout());
0323: status_buttons.add(start_button);
0324: status_buttons.add(stop_button);
0325: status_text = new JLabel();
0326: status_text.setBorder(new BevelBorder(BevelBorder.LOWERED));
0327: status_text_panel = new JPanel();
0328: status_text_panel.setLayout(new BorderLayout());
0329: status_text_panel.add(status_text, BorderLayout.CENTER);
0330: status_text_panel.setBorder(empty_border);
0331: status_area = new JPanel();
0332: status_area.setLayout(new BorderLayout());
0333: status_area.add(status_buttons, BorderLayout.WEST);
0334: status_area.add(status_text_panel, BorderLayout.CENTER);
0335: status_area.setBorder(etched_border);
0336: // Add the split and status area to page
0337: setLayout(new BorderLayout());
0338: add(split, BorderLayout.CENTER);
0339: add(status_area, BorderLayout.SOUTH);
0340: }
0341:
0342: /**
0343: * Get the name of the host we are displaying
0344: */
0345: public String getHost() {
0346: return host;
0347: }
0348:
0349: /**
0350: * Set the status text
0351: */
0352: public void setStatus(String txt) {
0353: status_text.setForeground(Color.black);
0354: status_text.setText(" " + txt);
0355: }
0356:
0357: /**
0358: * Set the status text to an error
0359: */
0360: public void setErrorStatus(String txt) {
0361: status_text.setForeground(Color.red);
0362: status_text.setText(" " + txt);
0363: }
0364:
0365: /**
0366: * Start talking to the server
0367: */
0368: public void start() {
0369: String codehost = getCodeBase().getHost();
0370: if (socket == null) {
0371: try {
0372: // Open the socket to the server
0373: socket = new Socket(codehost, port);
0374: // Create output stream
0375: out = new ObjectOutputStream(socket
0376: .getOutputStream());
0377: out.flush();
0378: // Create input stream and start background
0379: // thread to read data from the server
0380: in = new ObjectInputStream(socket.getInputStream());
0381: new Thread(this ).start();
0382: } catch (Exception e) {
0383: // Exceptions here are unexpected, but we can't
0384: // really do anything (so just write it to stdout
0385: // in case someone cares and then ignore it)
0386: System.out.println("Exception! " + e.toString());
0387: e.printStackTrace();
0388: setErrorStatus(STATUS_NOCONNECT);
0389: socket = null;
0390: }
0391: } else {
0392: // Already started
0393: }
0394: if (socket != null) {
0395: // Make sure the right buttons are enabled
0396: start_button.setEnabled(false);
0397: stop_button.setEnabled(true);
0398: setStatus(STATUS_ACTIVE);
0399: }
0400: }
0401:
0402: /**
0403: * Stop talking to the server
0404: */
0405: public void stop() {
0406: if (socket != null) {
0407: // Close all the streams and socket
0408: if (out != null) {
0409: try {
0410: out.close();
0411: } catch (IOException ioe) {
0412: }
0413: out = null;
0414: }
0415: if (in != null) {
0416: try {
0417: in.close();
0418: } catch (IOException ioe) {
0419: }
0420: in = null;
0421: }
0422: if (socket != null) {
0423: try {
0424: socket.close();
0425: } catch (IOException ioe) {
0426: }
0427: socket = null;
0428: }
0429: } else {
0430: // Already stopped
0431: }
0432: // Make sure the right buttons are enabled
0433: start_button.setEnabled(true);
0434: stop_button.setEnabled(false);
0435: setStatus(STATUS_STOPPED);
0436: }
0437:
0438: /**
0439: * Background thread used to receive data from
0440: * the server.
0441: */
0442: public void run() {
0443: Long id;
0444: Integer message_type;
0445: String target;
0446: String soap;
0447: SOAPMonitorData data;
0448: int selected;
0449: int row;
0450: boolean update_needed;
0451: while (socket != null) {
0452: try {
0453: // Get the data from the server
0454: message_type = (Integer) in.readObject();
0455: // Process the data depending on its type
0456: switch (message_type.intValue()) {
0457: case SOAP_MONITOR_REQUEST:
0458: // Get the id, target and soap info
0459: id = (Long) in.readObject();
0460: target = (String) in.readObject();
0461: soap = (String) in.readObject();
0462: // Add new request data to the table
0463: data = new SOAPMonitorData(id, target, soap);
0464: model.addData(data);
0465: // If "most recent" selected then update
0466: // the details area if needed
0467: selected = table.getSelectedRow();
0468: if ((selected == 0) && model.filterMatch(data)) {
0469: valueChanged(null);
0470: }
0471: break;
0472: case SOAP_MONITOR_RESPONSE:
0473: // Get the id and soap info
0474: id = (Long) in.readObject();
0475: soap = (String) in.readObject();
0476: data = model.findData(id);
0477: if (data != null) {
0478: update_needed = false;
0479: // Get the selected row
0480: selected = table.getSelectedRow();
0481: // If "most recent", then always
0482: // update details area
0483: if (selected == 0) {
0484: update_needed = true;
0485: }
0486: // If the data being updated is
0487: // selected then update details
0488: row = model.findRow(data);
0489: if ((row != -1) && (row == selected)) {
0490: update_needed = true;
0491: }
0492: // Set the response and update table
0493: data.setSOAPResponse(soap);
0494: model.updateData(data);
0495: // Refresh details area (if needed)
0496: if (update_needed) {
0497: valueChanged(null);
0498: }
0499: }
0500: break;
0501: }
0502:
0503: } catch (Exception e) {
0504: // Exceptions are expected here when the
0505: // server communication has been terminated.
0506: if (stop_button.isEnabled()) {
0507: stop();
0508: setErrorStatus(STATUS_CLOSED);
0509: }
0510: }
0511: }
0512: }
0513:
0514: /**
0515: * Listener to handle table selection changes
0516: */
0517: public void valueChanged(ListSelectionEvent e) {
0518: int row = table.getSelectedRow();
0519: // Check if they selected a specific row
0520: if (row > 0) {
0521: remove_button.setEnabled(true);
0522: } else {
0523: remove_button.setEnabled(false);
0524: }
0525: // Check for "most recent" selection
0526: if (row == 0) {
0527: row = model.getRowCount() - 1;
0528: if (row == 0) {
0529: row = -1;
0530: }
0531: }
0532: if (row == -1) {
0533: // Clear the details panel
0534: details_time_value.setText("");
0535: details_target_value.setText("");
0536: details_status_value.setText("");
0537: request_text.setText("");
0538: response_text.setText("");
0539: } else {
0540: // Show the details for the row
0541: SOAPMonitorData soap = model.getData(row);
0542: details_time_value.setText(soap.getTime());
0543: details_target_value.setText(soap.getTargetService());
0544: details_status_value.setText(soap.getStatus());
0545: if (soap.getSOAPRequest() == null) {
0546: request_text.setText("");
0547: } else {
0548: request_text.setText(soap.getSOAPRequest());
0549: request_text.setCaretPosition(0);
0550: }
0551: if (soap.getSOAPResponse() == null) {
0552: response_text.setText("");
0553: } else {
0554: response_text.setText(soap.getSOAPResponse());
0555: response_text.setCaretPosition(0);
0556: }
0557: }
0558: }
0559:
0560: /**
0561: * Listener to handle button actions
0562: */
0563: public void actionPerformed(ActionEvent e) {
0564: // Check if the user pressed the remove button
0565: if (e.getSource() == remove_button) {
0566: int row = table.getSelectedRow();
0567: model.removeRow(row);
0568: table.clearSelection();
0569: table.repaint();
0570: valueChanged(null);
0571: }
0572: // Check if the user pressed the remove all button
0573: if (e.getSource() == remove_all_button) {
0574: model.clearAll();
0575: table.setRowSelectionInterval(0, 0);
0576: table.repaint();
0577: valueChanged(null);
0578: }
0579: // Check if the user pressed the filter button
0580: if (e.getSource() == filter_button) {
0581: filter.showDialog();
0582: if (filter.okPressed()) {
0583: // Update the display with new filter
0584: model.setFilter(filter);
0585: table.repaint();
0586: }
0587: }
0588: // Check if the user pressed the start button
0589: if (e.getSource() == start_button) {
0590: start();
0591: }
0592: // Check if the user pressed the stop button
0593: if (e.getSource() == stop_button) {
0594: stop();
0595: }
0596: // Check if the user wants to switch layout
0597: if (e.getSource() == layout_button) {
0598: details_panel.remove(details_soap);
0599: details_soap.removeAll();
0600: if (details_soap.getOrientation() == JSplitPane.HORIZONTAL_SPLIT) {
0601: details_soap = new JSplitPane(
0602: JSplitPane.VERTICAL_SPLIT);
0603: } else {
0604: details_soap = new JSplitPane(
0605: JSplitPane.HORIZONTAL_SPLIT);
0606: }
0607: details_soap.setTopComponent(request_panel);
0608: details_soap.setRightComponent(response_panel);
0609: details_soap.setResizeWeight(.5);
0610: details_panel.add(details_soap, BorderLayout.CENTER);
0611: details_panel.validate();
0612: details_panel.repaint();
0613: }
0614: // Check if the user is changing the reflow option
0615: if (e.getSource() == reflow_xml) {
0616: request_text.setReflowXML(reflow_xml.isSelected());
0617: response_text.setReflowXML(reflow_xml.isSelected());
0618: }
0619: }
0620: }
0621:
0622: /**
0623: * This class represend the data for a SOAP request/response pair
0624: */
0625: class SOAPMonitorData {
0626:
0627: /**
0628: * Private data
0629: */
0630: private Long id;
0631: private String time;
0632: private String target;
0633: private String soap_request;
0634: private String soap_response;
0635:
0636: /**
0637: * Constructor
0638: */
0639: public SOAPMonitorData(Long id, String target,
0640: String soap_request) {
0641: this .id = id;
0642: // A null id is used to signal that the "most recent" entry
0643: // is being created.
0644: if (id == null) {
0645: this .time = "Most Recent";
0646: this .target = "---";
0647: this .soap_request = null;
0648: this .soap_response = null;
0649: } else {
0650: this .time = DateFormat.getTimeInstance().format(
0651: new Date());
0652: this .target = target;
0653: this .soap_request = soap_request;
0654: this .soap_response = null;
0655: }
0656: }
0657:
0658: /**
0659: * Get the id for the SOAP message
0660: */
0661: public Long getId() {
0662: return id;
0663: }
0664:
0665: /**
0666: * Get the time the SOAP request was received by the applet
0667: */
0668: public String getTime() {
0669: return time;
0670: }
0671:
0672: /**
0673: * Get the SOAP request target service name
0674: */
0675: public String getTargetService() {
0676: return target;
0677: }
0678:
0679: /**
0680: * Get the status of the request
0681: */
0682: public String getStatus() {
0683: String status = "---";
0684: if (id != null) {
0685: status = "Complete";
0686: if (soap_response == null) {
0687: status = "Active";
0688: }
0689: }
0690: return status;
0691: }
0692:
0693: /**
0694: * Get the request SOAP contents
0695: */
0696: public String getSOAPRequest() {
0697: return soap_request;
0698: }
0699:
0700: /**
0701: * Set the resposne SOAP contents
0702: */
0703: public void setSOAPResponse(String response) {
0704: soap_response = response;
0705: }
0706:
0707: /**
0708: * Get the response SOAP contents
0709: */
0710: public String getSOAPResponse() {
0711: return soap_response;
0712: }
0713: }
0714:
0715: /**
0716: * This table model is used to manage the table displayed
0717: * at the top of the page to show all the SOAP messages
0718: * we have received and to control which message details are
0719: * to be displayed on the bottom of the page.
0720: */
0721: class SOAPMonitorTableModel extends AbstractTableModel {
0722:
0723: /**
0724: * Column titles
0725: */
0726: private final String[] column_names = { "Time",
0727: "Target Service", "Status" };
0728: /**
0729: * Private data
0730: */
0731: private Vector data;
0732: private Vector filter_include;
0733: private Vector filter_exclude;
0734: private boolean filter_active;
0735: private boolean filter_complete;
0736: private Vector filter_data;
0737:
0738: /**
0739: * Constructor
0740: */
0741: public SOAPMonitorTableModel() {
0742: data = new Vector();
0743: // Add "most recent" entry to top of table
0744: SOAPMonitorData soap = new SOAPMonitorData(null, null, null);
0745: data.addElement(soap);
0746: filter_include = null;
0747: filter_exclude = null;
0748: filter_active = false;
0749: filter_complete = false;
0750: filter_data = null;
0751: // By default, exclude NotificationService and
0752: // EventViewerService messages
0753: filter_exclude = new Vector();
0754: filter_exclude.addElement("NotificationService");
0755: filter_exclude.addElement("EventViewerService");
0756: filter_data = new Vector();
0757: filter_data.addElement(soap);
0758: }
0759:
0760: /**
0761: * Get column count (part of table model interface)
0762: */
0763: public int getColumnCount() {
0764: return column_names.length;
0765: }
0766:
0767: /**
0768: * Get row count (part of table model interface)
0769: */
0770: public int getRowCount() {
0771: int count = data.size();
0772: if (filter_data != null) {
0773: count = filter_data.size();
0774: }
0775: return count;
0776: }
0777:
0778: /**
0779: * Get column name (part of table model interface)
0780: */
0781: public String getColumnName(int col) {
0782: return column_names[col];
0783: }
0784:
0785: /**
0786: * Get value at (part of table model interface)
0787: */
0788: public Object getValueAt(int row, int col) {
0789: SOAPMonitorData soap;
0790: String value = null;
0791: soap = (SOAPMonitorData) data.elementAt(row);
0792: if (filter_data != null) {
0793: soap = (SOAPMonitorData) filter_data.elementAt(row);
0794: }
0795: switch (col) {
0796: case 0:
0797: value = soap.getTime();
0798: break;
0799: case 1:
0800: value = soap.getTargetService();
0801: break;
0802: case 2:
0803: value = soap.getStatus();
0804: break;
0805: }
0806: return value;
0807: }
0808:
0809: /**
0810: * Check if soap data matches filter
0811: */
0812: public boolean filterMatch(SOAPMonitorData soap) {
0813: boolean match = true;
0814: if (filter_include != null) {
0815: // Check for service match
0816: Enumeration e = filter_include.elements();
0817: match = false;
0818: while (e.hasMoreElements() && !match) {
0819: String service = (String) e.nextElement();
0820: if (service.equals(soap.getTargetService())) {
0821: match = true;
0822: }
0823: }
0824: }
0825: if (filter_exclude != null) {
0826: // Check for service match
0827: Enumeration e = filter_exclude.elements();
0828: while (e.hasMoreElements() && match) {
0829: String service = (String) e.nextElement();
0830: if (service.equals(soap.getTargetService())) {
0831: match = false;
0832: }
0833: }
0834: }
0835: if (filter_active) {
0836: // Check for active status match
0837: if (soap.getSOAPResponse() != null) {
0838: match = false;
0839: }
0840: }
0841: if (filter_complete) {
0842: // Check for complete status match
0843: if (soap.getSOAPResponse() == null) {
0844: match = false;
0845: }
0846: }
0847: // The "most recent" is always a match
0848: if (soap.getId() == null) {
0849: match = true;
0850: }
0851: return match;
0852: }
0853:
0854: /**
0855: * Add data to the table as a new row
0856: */
0857: public void addData(SOAPMonitorData soap) {
0858: int row = data.size();
0859: data.addElement(soap);
0860: if (filter_data != null) {
0861: if (filterMatch(soap)) {
0862: row = filter_data.size();
0863: filter_data.addElement(soap);
0864: fireTableRowsInserted(row, row);
0865: }
0866: } else {
0867: fireTableRowsInserted(row, row);
0868: }
0869: }
0870:
0871: /**
0872: * Find the data for a given id
0873: */
0874: public SOAPMonitorData findData(Long id) {
0875: SOAPMonitorData soap = null;
0876: for (int row = data.size(); (row > 0) && (soap == null); row--) {
0877: soap = (SOAPMonitorData) data.elementAt(row - 1);
0878: if (soap.getId().longValue() != id.longValue()) {
0879: soap = null;
0880: }
0881: }
0882: return soap;
0883: }
0884:
0885: /**
0886: * Find the row in the table for a given message id
0887: */
0888: public int findRow(SOAPMonitorData soap) {
0889: int row = -1;
0890: if (filter_data != null) {
0891: row = filter_data.indexOf(soap);
0892: } else {
0893: row = data.indexOf(soap);
0894: }
0895: return row;
0896: }
0897:
0898: /**
0899: * Remove all messages from the table (but leave "most recent")
0900: */
0901: public void clearAll() {
0902: int last_row = data.size() - 1;
0903: if (last_row > 0) {
0904: data.removeAllElements();
0905: SOAPMonitorData soap = new SOAPMonitorData(null, null,
0906: null);
0907: data.addElement(soap);
0908: if (filter_data != null) {
0909: filter_data.removeAllElements();
0910: filter_data.addElement(soap);
0911: }
0912: fireTableDataChanged();
0913: }
0914: }
0915:
0916: /**
0917: * Remove a message from the table
0918: */
0919: public void removeRow(int row) {
0920: SOAPMonitorData soap = null;
0921: if (filter_data == null) {
0922: soap = (SOAPMonitorData) data.elementAt(row);
0923: data.remove(soap);
0924: } else {
0925: soap = (SOAPMonitorData) filter_data.elementAt(row);
0926: filter_data.remove(soap);
0927: data.remove(soap);
0928: }
0929: fireTableRowsDeleted(row, row);
0930: }
0931:
0932: /**
0933: * Set a new filter
0934: */
0935: public void setFilter(SOAPMonitorFilter filter) {
0936: // Save new filter criteria
0937: filter_include = filter.getFilterIncludeList();
0938: filter_exclude = filter.getFilterExcludeList();
0939: filter_active = filter.getFilterActive();
0940: filter_complete = filter.getFilterComplete();
0941: applyFilter();
0942: }
0943:
0944: /**
0945: * Refilter the list of messages
0946: */
0947: public void applyFilter() {
0948: // Re-filter using new criteria
0949: filter_data = null;
0950: if ((filter_include != null) || (filter_exclude != null)
0951: || filter_active || filter_complete) {
0952: filter_data = new Vector();
0953: Enumeration e = data.elements();
0954: SOAPMonitorData soap;
0955: while (e.hasMoreElements()) {
0956: soap = (SOAPMonitorData) e.nextElement();
0957: if (filterMatch(soap)) {
0958: filter_data.addElement(soap);
0959: }
0960: }
0961: }
0962: fireTableDataChanged();
0963: }
0964:
0965: /**
0966: * Get the data for a row
0967: */
0968: public SOAPMonitorData getData(int row) {
0969: SOAPMonitorData soap = null;
0970: if (filter_data == null) {
0971: soap = (SOAPMonitorData) data.elementAt(row);
0972: } else {
0973: soap = (SOAPMonitorData) filter_data.elementAt(row);
0974: }
0975: return soap;
0976: }
0977:
0978: /**
0979: * Update a message
0980: */
0981: public void updateData(SOAPMonitorData soap) {
0982: int row;
0983: if (filter_data == null) {
0984: // No filter, so just fire table updated
0985: row = data.indexOf(soap);
0986: if (row != -1) {
0987: fireTableRowsUpdated(row, row);
0988: }
0989: } else {
0990: // Check if the row was being displayed
0991: row = filter_data.indexOf(soap);
0992: if (row == -1) {
0993: // Row was not displayed, so check for if it
0994: // now needs to be displayed
0995: if (filterMatch(soap)) {
0996: int index = -1;
0997: row = data.indexOf(soap) + 1;
0998: while ((row < data.size()) && (index == -1)) {
0999: index = filter_data.indexOf(data
1000: .elementAt(row));
1001: if (index != -1) {
1002: // Insert at this location
1003: filter_data.add(index, soap);
1004: }
1005: row++;
1006: }
1007: if (index == -1) {
1008: // Insert at end
1009: index = filter_data.size();
1010: filter_data.addElement(soap);
1011: }
1012: fireTableRowsInserted(index, index);
1013: }
1014: } else {
1015: // Row was displayed, so check if it needs to
1016: // be updated or removed
1017: if (filterMatch(soap)) {
1018: fireTableRowsUpdated(row, row);
1019: } else {
1020: filter_data.remove(soap);
1021: fireTableRowsDeleted(row, row);
1022: }
1023: }
1024: }
1025: }
1026:
1027: }
1028:
1029: /**
1030: * Panel with checkbox and list
1031: */
1032: class ServiceFilterPanel extends JPanel implements ActionListener,
1033: ListSelectionListener, DocumentListener {
1034:
1035: private JCheckBox service_box = null;
1036: private Vector filter_list = null;
1037: private Vector service_data = null;
1038: private JList service_list = null;
1039: private JScrollPane service_scroll = null;
1040: private JButton remove_service_button = null;
1041: private JPanel remove_service_panel = null;
1042: private EmptyBorder indent_border = null;
1043: private EmptyBorder empty_border = null;
1044: private JPanel service_area = null;
1045: private JPanel add_service_area = null;
1046: private JTextField add_service_field = null;
1047: private JButton add_service_button = null;
1048: private JPanel add_service_panel = null;
1049:
1050: /**
1051: * Constructor
1052: */
1053: public ServiceFilterPanel(String text, Vector list) {
1054: empty_border = new EmptyBorder(5, 5, 0, 5);
1055: indent_border = new EmptyBorder(5, 25, 5, 5);
1056: service_box = new JCheckBox(text);
1057: service_box.addActionListener(this );
1058: service_data = new Vector();
1059: if (list != null) {
1060: service_box.setSelected(true);
1061: service_data = (Vector) list.clone();
1062: }
1063: service_list = new JList(service_data);
1064: service_list.setBorder(new EtchedBorder());
1065: service_list.setVisibleRowCount(5);
1066: service_list.addListSelectionListener(this );
1067: service_list.setEnabled(service_box.isSelected());
1068: service_scroll = new JScrollPane(service_list);
1069: service_scroll.setBorder(new EtchedBorder());
1070: remove_service_button = new JButton("Remove");
1071: remove_service_button.addActionListener(this );
1072: remove_service_button.setEnabled(false);
1073: remove_service_panel = new JPanel();
1074: remove_service_panel.setLayout(new FlowLayout());
1075: remove_service_panel.add(remove_service_button);
1076: service_area = new JPanel();
1077: service_area.setLayout(new BorderLayout());
1078: service_area.add(service_scroll, BorderLayout.CENTER);
1079: service_area.add(remove_service_panel, BorderLayout.EAST);
1080: service_area.setBorder(indent_border);
1081: add_service_field = new JTextField();
1082: add_service_field.addActionListener(this );
1083: add_service_field.getDocument().addDocumentListener(this );
1084: add_service_field.setEnabled(service_box.isSelected());
1085: add_service_button = new JButton("Add");
1086: add_service_button.addActionListener(this );
1087: add_service_button.setEnabled(false);
1088: add_service_panel = new JPanel();
1089: add_service_panel.setLayout(new BorderLayout());
1090: JPanel dummy = new JPanel();
1091: dummy.setBorder(empty_border);
1092: add_service_panel.add(dummy, BorderLayout.WEST);
1093: add_service_panel
1094: .add(add_service_button, BorderLayout.EAST);
1095: add_service_area = new JPanel();
1096: add_service_area.setLayout(new BorderLayout());
1097: add_service_area
1098: .add(add_service_field, BorderLayout.CENTER);
1099: add_service_area.add(add_service_panel, BorderLayout.EAST);
1100: add_service_area.setBorder(indent_border);
1101: setLayout(new BorderLayout());
1102: add(service_box, BorderLayout.NORTH);
1103: add(service_area, BorderLayout.CENTER);
1104: add(add_service_area, BorderLayout.SOUTH);
1105: setBorder(empty_border);
1106: }
1107:
1108: /**
1109: * Get the current list of services
1110: */
1111: public Vector getServiceList() {
1112: Vector list = null;
1113: if (service_box.isSelected()) {
1114: list = service_data;
1115: }
1116: return list;
1117: }
1118:
1119: /**
1120: * Listener to handle button actions
1121: */
1122: public void actionPerformed(ActionEvent e) {
1123: // Check if the user changed the service filter option
1124: if (e.getSource() == service_box) {
1125: service_list.setEnabled(service_box.isSelected());
1126: service_list.clearSelection();
1127: remove_service_button.setEnabled(false);
1128: add_service_field.setEnabled(service_box.isSelected());
1129: add_service_field.setText("");
1130: add_service_button.setEnabled(false);
1131: }
1132: // Check if the user pressed the add service button
1133: if ((e.getSource() == add_service_button)
1134: || (e.getSource() == add_service_field)) {
1135: String text = add_service_field.getText();
1136: if ((text != null) && (text.length() > 0)) {
1137: service_data.addElement(text);
1138: service_list.setListData(service_data);
1139: }
1140: add_service_field.setText("");
1141: add_service_field.requestFocus();
1142: }
1143: // Check if the user pressed the remove service button
1144: if (e.getSource() == remove_service_button) {
1145: Object[] sels = service_list.getSelectedValues();
1146: for (int i = 0; i < sels.length; i++) {
1147: service_data.removeElement(sels[i]);
1148: }
1149: service_list.setListData(service_data);
1150: service_list.clearSelection();
1151: }
1152: }
1153:
1154: /**
1155: * Handle changes to the text field
1156: */
1157: public void changedUpdate(DocumentEvent e) {
1158: String text = add_service_field.getText();
1159: if ((text != null) && (text.length() > 0)) {
1160: add_service_button.setEnabled(true);
1161: } else {
1162: add_service_button.setEnabled(false);
1163: }
1164: }
1165:
1166: /**
1167: * Handle changes to the text field
1168: */
1169: public void insertUpdate(DocumentEvent e) {
1170: changedUpdate(e);
1171: }
1172:
1173: /**
1174: * Handle changes to the text field
1175: */
1176: public void removeUpdate(DocumentEvent e) {
1177: changedUpdate(e);
1178: }
1179:
1180: /**
1181: * Listener to handle service list selection changes
1182: */
1183: public void valueChanged(ListSelectionEvent e) {
1184: if (service_list.getSelectedIndex() == -1) {
1185: remove_service_button.setEnabled(false);
1186: } else {
1187: remove_service_button.setEnabled(true);
1188: }
1189: }
1190: }
1191:
1192: /**
1193: * Class for showing the filter dialog
1194: */
1195: class SOAPMonitorFilter implements ActionListener {
1196:
1197: /**
1198: * Private data
1199: */
1200: private JDialog dialog = null;
1201: private JPanel panel = null;
1202: private JPanel buttons = null;
1203: private JButton ok_button = null;
1204: private JButton cancel_button = null;
1205: private ServiceFilterPanel include_panel = null;
1206: private ServiceFilterPanel exclude_panel = null;
1207: private JPanel status_panel = null;
1208: private JCheckBox status_box = null;
1209: private EmptyBorder empty_border = null;
1210: private EmptyBorder indent_border = null;
1211: private JPanel status_options = null;
1212: private ButtonGroup status_group = null;
1213: private JRadioButton status_active = null;
1214: private JRadioButton status_complete = null;
1215: private Vector filter_include_list = null;
1216: private Vector filter_exclude_list = null;
1217: private boolean filter_active = false;
1218: private boolean filter_complete = false;
1219: private boolean ok_pressed = false;
1220:
1221: /**
1222: * Constructor
1223: */
1224: public SOAPMonitorFilter() {
1225: // By default, exclude NotificationService and
1226: // EventViewerService messages
1227: filter_exclude_list = new Vector();
1228: filter_exclude_list.addElement("NotificationService");
1229: filter_exclude_list.addElement("EventViewerService");
1230: }
1231:
1232: /**
1233: * Get list of services to be included
1234: */
1235: public Vector getFilterIncludeList() {
1236: return filter_include_list;
1237: }
1238:
1239: /**
1240: * Get list of services to be excluded
1241: */
1242: public Vector getFilterExcludeList() {
1243: return filter_exclude_list;
1244: }
1245:
1246: /**
1247: * Check if filter active messages
1248: */
1249: public boolean getFilterActive() {
1250: return filter_active;
1251: }
1252:
1253: /**
1254: * Check if filter complete messages
1255: */
1256: public boolean getFilterComplete() {
1257: return filter_complete;
1258: }
1259:
1260: /**
1261: * Show the filter dialog
1262: */
1263: public void showDialog() {
1264: empty_border = new EmptyBorder(5, 5, 0, 5);
1265: indent_border = new EmptyBorder(5, 25, 5, 5);
1266: include_panel = new ServiceFilterPanel(
1267: "Include messages based on target service:",
1268: filter_include_list);
1269: exclude_panel = new ServiceFilterPanel(
1270: "Exclude messages based on target service:",
1271: filter_exclude_list);
1272: status_box = new JCheckBox(
1273: "Filter messages based on status:");
1274: status_box.addActionListener(this );
1275: status_active = new JRadioButton("Active messages only");
1276: status_active.setSelected(true);
1277: status_active.setEnabled(false);
1278: status_complete = new JRadioButton("Complete messages only");
1279: status_complete.setEnabled(false);
1280: status_group = new ButtonGroup();
1281: status_group.add(status_active);
1282: status_group.add(status_complete);
1283: if (filter_active || filter_complete) {
1284: status_box.setSelected(true);
1285: status_active.setEnabled(true);
1286: status_complete.setEnabled(true);
1287: if (filter_complete) {
1288: status_complete.setSelected(true);
1289: }
1290: }
1291: status_options = new JPanel();
1292: status_options.setLayout(new BoxLayout(status_options,
1293: BoxLayout.Y_AXIS));
1294: status_options.add(status_active);
1295: status_options.add(status_complete);
1296: status_options.setBorder(indent_border);
1297: status_panel = new JPanel();
1298: status_panel.setLayout(new BorderLayout());
1299: status_panel.add(status_box, BorderLayout.NORTH);
1300: status_panel.add(status_options, BorderLayout.CENTER);
1301: status_panel.setBorder(empty_border);
1302: ok_button = new JButton("Ok");
1303: ok_button.addActionListener(this );
1304: cancel_button = new JButton("Cancel");
1305: cancel_button.addActionListener(this );
1306: buttons = new JPanel();
1307: buttons.setLayout(new FlowLayout());
1308: buttons.add(ok_button);
1309: buttons.add(cancel_button);
1310: panel = new JPanel();
1311: panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
1312: panel.add(include_panel);
1313: panel.add(exclude_panel);
1314: panel.add(status_panel);
1315: panel.add(buttons);
1316: dialog = new JDialog();
1317: dialog.setTitle("SOAP Monitor Filter");
1318: dialog.setContentPane(panel);
1319: dialog
1320: .setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
1321: dialog.setModal(true);
1322: dialog.pack();
1323: Dimension d = dialog.getToolkit().getScreenSize();
1324: dialog.setLocation((d.width - dialog.getWidth()) / 2,
1325: (d.height - dialog.getHeight()) / 2);
1326: ok_pressed = false;
1327: dialog.show();
1328: }
1329:
1330: /**
1331: * Listener to handle button actions
1332: */
1333: public void actionPerformed(ActionEvent e) {
1334: // Check if the user pressed the ok button
1335: if (e.getSource() == ok_button) {
1336: filter_include_list = include_panel.getServiceList();
1337: filter_exclude_list = exclude_panel.getServiceList();
1338: if (status_box.isSelected()) {
1339: filter_active = status_active.isSelected();
1340: filter_complete = status_complete.isSelected();
1341: } else {
1342: filter_active = false;
1343: filter_complete = false;
1344: }
1345: ok_pressed = true;
1346: dialog.dispose();
1347: }
1348: // Check if the user pressed the cancel button
1349: if (e.getSource() == cancel_button) {
1350: dialog.dispose();
1351: }
1352: // Check if the user changed the status filter option
1353: if (e.getSource() == status_box) {
1354: status_active.setEnabled(status_box.isSelected());
1355: status_complete.setEnabled(status_box.isSelected());
1356: }
1357: }
1358:
1359: /**
1360: * Check if the user pressed the ok button
1361: */
1362: public boolean okPressed() {
1363: return ok_pressed;
1364: }
1365: }
1366:
1367: /**
1368: * Text panel class that supports XML reflow
1369: */
1370: class SOAPMonitorTextArea extends JTextArea {
1371:
1372: /**
1373: * Private data
1374: */
1375: private boolean format = false;
1376: private String original = "";
1377: private String formatted = null;
1378:
1379: /**
1380: * Constructor
1381: */
1382: public SOAPMonitorTextArea() {
1383: }
1384:
1385: /**
1386: * Override setText to do formatting
1387: */
1388: public void setText(String text) {
1389: original = text;
1390: formatted = null;
1391: if (format) {
1392: doFormat();
1393: super .setText(formatted);
1394: } else {
1395: super .setText(original);
1396: }
1397: }
1398:
1399: /**
1400: * Turn reflow on or off
1401: */
1402: public void setReflowXML(boolean reflow) {
1403: format = reflow;
1404: if (format) {
1405: if (formatted == null) {
1406: doFormat();
1407: }
1408: super .setText(formatted);
1409: } else {
1410: super .setText(original);
1411: }
1412: }
1413:
1414: /**
1415: * Reflow XML
1416: */
1417: public void doFormat() {
1418: Vector parts = new Vector();
1419: char[] chars = original.toCharArray();
1420: int index = 0;
1421: int first = 0;
1422: String part = null;
1423: while (index < chars.length) {
1424: // Check for start of tag
1425: if (chars[index] == '<') {
1426: // Did we have data before this tag?
1427: if (first < index) {
1428: part = new String(chars, first, index - first);
1429: part = part.trim();
1430: // Save non-whitespace data
1431: if (part.length() > 0) {
1432: parts.addElement(part);
1433: }
1434: }
1435: // Save the start of tag
1436: first = index;
1437: }
1438: // Check for end of tag
1439: if (chars[index] == '>') {
1440: // Save the tag
1441: part = new String(chars, first, index - first + 1);
1442: parts.addElement(part);
1443: first = index + 1;
1444: }
1445: // Check for end of line
1446: if ((chars[index] == '\n') || (chars[index] == '\r')) {
1447: // Was there data on this line?
1448: if (first < index) {
1449: part = new String(chars, first, index - first);
1450: part = part.trim();
1451: // Save non-whitespace data
1452: if (part.length() > 0) {
1453: parts.addElement(part);
1454: }
1455: }
1456: first = index + 1;
1457: }
1458: index++;
1459: }
1460: // Reflow as XML
1461: StringBuffer buf = new StringBuffer();
1462: Object[] list = parts.toArray();
1463: int indent = 0;
1464: int pad = 0;
1465: index = 0;
1466: while (index < list.length) {
1467: part = (String) list[index];
1468: if (buf.length() == 0) {
1469: // Just add first tag (should be XML header)
1470: buf.append(part);
1471: } else {
1472: // All other parts need to start on a new line
1473: buf.append('\n');
1474: // If we're at an end tag then decrease indent
1475: if (part.startsWith("</")) {
1476: indent--;
1477: }
1478: // Add any indent
1479: for (pad = 0; pad < indent; pad++) {
1480: buf.append(" ");
1481: }
1482: // Add the tag or data
1483: buf.append(part);
1484: // If this is a start tag then increase indent
1485: if (part.startsWith("<") && !part.startsWith("</")
1486: && !part.endsWith("/>")) {
1487: indent++;
1488: // Check for special <tag>data</tag> case
1489: if ((index + 2) < list.length) {
1490: part = (String) list[index + 2];
1491: if (part.startsWith("</")) {
1492: part = (String) list[index + 1];
1493: if (!part.startsWith("<")) {
1494: buf.append(part);
1495: part = (String) list[index + 2];
1496: buf.append(part);
1497: index = index + 2;
1498: indent--;
1499: }
1500: }
1501: }
1502: }
1503: }
1504: index++;
1505: }
1506: formatted = new String(buf);
1507: }
1508: }
1509: }
|