1482 lines
55 KiB
Java
1482 lines
55 KiB
Java
/*
|
|
* 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.axis.monitor.SOAPMonitorConstants;
|
|
|
|
/**
|
|
* This is a SOAP Mointor Applet class. This class provides
|
|
* the user interface for displaying data from the SOAP
|
|
* monitor service.
|
|
*
|
|
* @author Brian Price (pricebe@us.ibm.com)
|
|
*
|
|
*/
|
|
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);
|
|
}
|
|
}
|
|
}
|