You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by st...@apache.org on 2003/01/25 20:12:54 UTC
cvs commit: xml-axis/java/src/org/apache/axis/utils tcpmon.properties tcpmon.java
stevel 2003/01/25 11:12:54
Modified: java/src/org/apache/axis/utils tcpmon.properties tcpmon.java
Log:
Changes to tcpmon, a mixture of functionality, usability and code layout
-user specifiable delay of X milliseconds every bytes, lets you simulate restricted bandwidth links for better client testing
-hostname and numeric text edit boxes are charset-restricted; you can't put a char like $ or % in a hostname box, or anything other than 0-9 in a number
-explicit import of classes, bracing around all if statements &c.
Revision Changes Path
1.5 +7 -0 xml-axis/java/src/org/apache/axis/utils/tcpmon.properties
Index: tcpmon.properties
===================================================================
RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/utils/tcpmon.properties,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- tcpmon.properties 30 May 2002 23:46:02 -0000 1.4
+++ tcpmon.properties 25 Jan 2003 19:12:54 -0000 1.5
@@ -51,3 +51,10 @@
# NOTE: in xmlFormat00, do not translate "XML"
xmlFormat00=XML Format
+
+#NOTE: this is a SimpleDateFormat format string to declare the layout of date
+#and time in the message log. It does need i18n, but not 'translation', per se.
+dateformat00=yyyy-MM-dd HH:mm:ss
+delay00=Simulate Slow Connection
+delay01=Bytes per Pause
+delay02=Delay in Milliseconds
\ No newline at end of file
1.46 +680 -149 xml-axis/java/src/org/apache/axis/utils/tcpmon.java
Index: tcpmon.java
===================================================================
RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/utils/tcpmon.java,v
retrieving revision 1.45
retrieving revision 1.46
diff -u -r1.45 -r1.46
--- tcpmon.java 17 Jan 2003 04:40:09 -0000 1.45
+++ tcpmon.java 25 Jan 2003 19:12:54 -0000 1.46
@@ -2,7 +2,7 @@
* The Apache Software License, Version 1.1
*
*
- * Copyright (c) 2001 The Apache Software Foundation. All rights
+ * Copyright (c) 2001-2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -10,7 +10,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
@@ -18,7 +18,7 @@
* distribution.
*
* 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
+ * if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
@@ -26,7 +26,7 @@
*
* 4. The names "Axis" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
- * software without prior written permission. For written
+ * software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
@@ -55,7 +55,26 @@
package org.apache.axis.utils ;
-import javax.swing.*;
+import javax.swing.BorderFactory;
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.ButtonGroup;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JFileChooser;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
+import javax.swing.JTabbedPane;
+import javax.swing.JTable;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+import javax.swing.ListSelectionModel;
+import javax.swing.SwingConstants;
+import javax.swing.UIManager;
import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ListSelectionEvent;
@@ -64,7 +83,16 @@
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
-import java.awt.*;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Document;
+import javax.swing.text.PlainDocument;
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
@@ -87,26 +115,41 @@
/**
+ * TCP monitor to log http messages and responses, both SOAP and plain HTTP.
* @author Doug Davis (dug@us.ibm.com)
+ * @author Steve Loughran
*/
public class tcpmon extends JFrame {
private JTabbedPane notebook = null ;
- private static int STATE_COLUMN = 0 ;
- private static int TIME_COLUMN = 1 ;
- private static int INHOST_COLUMN = 2 ;
- private static int OUTHOST_COLUMN = 3 ;
- private static int REQ_COLUMN = 4 ;
+ private static final int STATE_COLUMN = 0 ;
+ private static final int TIME_COLUMN = 1 ;
+ private static final int INHOST_COLUMN = 2 ;
+ private static final int OUTHOST_COLUMN = 3 ;
+ private static final int REQ_COLUMN = 4 ;
+
+ private static final String DEFAULT_HOST="127.0.0.1";
+ private static final int DEFAULT_PORT=8080;
+
+ /**
+ * this is the admin page
+ */
class AdminPage extends JPanel {
public JRadioButton listenerButton, proxyButton ;
public JLabel hostLabel, tportLabel;
- public JTextField port, host, tport ;
+ public NumberField port;
+ public HostnameField host;
+ public NumberField tport ;
public JTabbedPane noteb ;
public JCheckBox HTTPProxyBox ;
- public JTextField HTTPProxyHost, HTTPProxyPort ;
+ public HostnameField HTTPProxyHost;
+ public NumberField HTTPProxyPort ;
public JLabel HTTPProxyHostLabel, HTTPProxyPortLabel ;
+ public JLabel delayTimeLabel, delayBytesLabel;
+ public NumberField delayTime, delayBytes;
+ public JCheckBox delayBox;
public AdminPage( JTabbedPane notebook, String name ) {
JPanel mainPane = null ;
@@ -137,7 +180,7 @@
c.anchor = GridBagConstraints.WEST ;
c.gridwidth = GridBagConstraints.REMAINDER ;
- tmpPanel.add( port = new JTextField(4), c );
+ tmpPanel.add( port = new NumberField(4), c );
mainPane.add( tmpPanel, c );
@@ -182,7 +225,9 @@
c.anchor = GridBagConstraints.WEST ;
c.gridwidth = GridBagConstraints.REMAINDER ;
- mainPane.add( host = new JTextField(30), c );
+ host = new HostnameField(30);
+ mainPane.add( host, c );
+ host.setText(DEFAULT_HOST);
c.anchor = GridBagConstraints.WEST ;
c.gridwidth = 1 ;
@@ -191,7 +236,9 @@
c.anchor = GridBagConstraints.WEST ;
c.gridwidth = GridBagConstraints.REMAINDER ;
- mainPane.add( tport = new JTextField(4), c );
+ tport = new NumberField(4);
+ mainPane.add( tport, c );
+ tport.setValue(DEFAULT_PORT);
// Act as proxy section
///////////////////////////////////////////////////////////////////
@@ -246,7 +293,7 @@
c.anchor = GridBagConstraints.WEST ;
c.gridwidth = GridBagConstraints.REMAINDER ;
- opts.add( HTTPProxyHost = new JTextField(30), c );
+ opts.add( HTTPProxyHost = new HostnameField(30), c );
HTTPProxyHost.setEnabled( false );
c.anchor = GridBagConstraints.WEST ;
@@ -256,7 +303,7 @@
c.anchor = GridBagConstraints.WEST ;
c.gridwidth = GridBagConstraints.REMAINDER ;
- opts.add( HTTPProxyPort = new JTextField(4), c );
+ opts.add( HTTPProxyPort = new NumberField(4), c );
HTTPProxyPort.setEnabled( false );
HTTPProxyBox.addActionListener( new ActionListener() {
@@ -271,15 +318,15 @@
HTTPProxyPortLabel.setForeground( color );
}
}
- ;
}
);
// Set default proxy values...
String tmp = System.getProperty( "http.proxyHost" );
- if ( tmp != null && tmp.equals("") )
+ if ( tmp != null && tmp.equals("") ) {
tmp = null ;
+ }
HTTPProxyBox.setSelected( tmp != null );
HTTPProxyHost.setEnabled( tmp != null );
@@ -291,11 +338,61 @@
HTTPProxyBox.setSelected( true );
HTTPProxyHost.setText( tmp );
tmp = System.getProperty( "http.proxyPort" );
- if ( tmp != null && tmp.equals("") ) tmp = null ;
- if ( tmp == null ) tmp = "80" ;
+ if ( tmp != null && tmp.equals("") ) {
+ tmp = null ;
+ }
+ if ( tmp == null ) {
+ tmp = "80" ;
+ }
HTTPProxyPort.setText( tmp );
}
+ //add byte delay fields
+ opts.add(Box.createRigidArea(new Dimension(1, 10)), c);
+ c.anchor = GridBagConstraints.WEST;
+ c.gridwidth = GridBagConstraints.REMAINDER;
+ final String delaySupport = getMessage("delay00", "Simulate Slow Connection");
+ opts.add(delayBox = new JCheckBox(delaySupport), c);
+
+ //bytes per pause
+ c.anchor = GridBagConstraints.WEST;
+ c.gridwidth = 1;
+ delayBytesLabel=new JLabel(getMessage("delay01", "Bytes per Pause"));
+ opts.add(delayBytesLabel, c);
+ delayBytesLabel.setForeground(Color.gray);
+ c.anchor = GridBagConstraints.WEST;
+ c.gridwidth = GridBagConstraints.REMAINDER;
+ opts.add(delayBytes = new NumberField(6), c);
+ delayBytes.setEnabled(false);
+
+ //delay interval
+ c.anchor = GridBagConstraints.WEST;
+ c.gridwidth = 1;
+ delayTimeLabel = new JLabel(getMessage("delay02", "Delay in Milliseconds"));
+ opts.add(delayTimeLabel, c);
+ delayTimeLabel.setForeground(Color.gray);
+ c.anchor = GridBagConstraints.WEST;
+ c.gridwidth = GridBagConstraints.REMAINDER;
+ opts.add(delayTime = new NumberField(6), c);
+ delayTime.setEnabled(false);
+
+ //enabler callback
+ delayBox.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent event) {
+ if (delaySupport.equals(event.getActionCommand())) {
+ boolean b = delayBox.isSelected();
+ Color color = b ? Color.black : Color.gray;
+
+ delayBytes.setEnabled(b);
+ delayTime.setEnabled(b);
+ delayBytesLabel.setForeground(color);
+ delayTimeLabel.setForeground(color);
+ }
+ }
+ ;
+ }
+ );
+
// Spacer
//////////////////////////////////////////////////////////////////
mainPane.add( Box.createRigidArea(new Dimension(1, 10)), c );
@@ -317,29 +414,44 @@
if ( add.equals(event.getActionCommand()) ) {
String text ;
Listener l = null ;
- int lPort = Integer.parseInt(port.getText());
+ int lPort;
+ lPort=port.getValue(0);
+ if(lPort==0) {
+ //no port, button does nothing
+ return;
+ }
String tHost = host.getText();
int tPort = 0 ;
-
- text = tport.getText();
- if ( text != null && !text.equals("") )
- tPort = Integer.parseInt(text);
+ tPort=tport.getValue(0);
+ SlowLinkSimulator slowLink=null;
+ if(delayBox.isSelected()) {
+ int bytes= delayBytes.getValue(0);
+ int time = delayTime.getValue(0);
+ slowLink=new SlowLinkSimulator(bytes,time);
+ }
l = new Listener( noteb, null, lPort, tHost, tPort,
- proxyButton.isSelected() );
+ proxyButton.isSelected(), slowLink);
// Pick-up the HTTP Proxy settings
///////////////////////////////////////////////////
text = HTTPProxyHost.getText();
- if ( "".equals(text) ) text = null ;
+ if ( "".equals(text) ) {
+ text = null ;
+ }
l.HTTPProxyHost = text ;
text = HTTPProxyPort.getText();
- if ( "".equals(text) ) text = null ;
- if ( text != null )
+ int proxyPort=HTTPProxyPort.getValue(-1);
+ if(proxyPort!=-1) {
l.HTTPProxyPort = Integer.parseInt(text);
-
+ }
+ //reset the port
port.setText(null);
+
+ /* but not, any more, the target port and host
+ values
host.setText(null);
tport.setText(null);
+ */
}
}
;
@@ -350,8 +462,14 @@
notebook.repaint();
notebook.setSelectedIndex( notebook.getTabCount() - 1 );
}
+
+
}
+ /**
+ * wait for incoming connections, spawn a connection thread when
+ * stuff comes in.
+ */
class SocketWaiter extends Thread {
ServerSocket sSocket = null ;
Listener listener ;
@@ -372,12 +490,13 @@
for (; ; ) {
Socket inSocket = sSocket.accept();
- if ( pleaseStop ) break ;
+ if ( pleaseStop ) {
+ break ;
+ }
new Connection( listener, inSocket );
inSocket = null ;
}
- }
- catch ( Exception exp ) {
+ } catch ( Exception exp ) {
if ( !"socket closed".equals(exp.getMessage()) ) {
JLabel tmp = new JLabel( exp.toString() );
@@ -389,19 +508,109 @@
}
}
+ /**
+ * force a halt by connecting to self and then closing the server socket
+ */
public void halt() {
try {
pleaseStop = true ;
new Socket( "127.0.0.1", port );
- if ( sSocket != null ) sSocket.close();
- }
- catch ( Exception e ) {
+ if ( sSocket != null ) {
+ sSocket.close();
+ }
+ } catch ( Exception e ) {
e.printStackTrace();
}
}
}
+ /**
+ * class to simulate slow connections by slowing down the system
+ */
+ static class SlowLinkSimulator {
+ private int delayBytes;
+ private int delayTime;
+ private int currentBytes;
+ private int totalBytes;
+
+ /**
+ * construct
+ * @param delayBytes bytes per delay; set to 0 for no delay
+ * @param delayTime delay time per delay in milliseconds
+ */
+ public SlowLinkSimulator(int delayBytes, int delayTime) {
+ this.delayBytes = delayBytes;
+ this.delayTime = delayTime;
+ }
+
+ /**
+ * construct by copying delay bytes and time, but not current
+ * count of bytes
+ * @param that source of data
+ */
+ public SlowLinkSimulator(SlowLinkSimulator that) {
+ this.delayBytes=that.delayBytes;
+ this.delayTime=that.delayTime;
+ }
+
+ /**
+ * how many bytes have gone past?
+ * @return
+ */
+ public int getTotalBytes() {
+ return totalBytes;
+ }
+
+ /**
+ * log #of bytes pumped. Will pause when necessary. This method is not
+ * synchronized
+ * @param bytes
+ */
+ public void pump(int bytes) {
+ totalBytes+=bytes;
+ if(delayBytes==0) {
+ //when not delaying, we are just a byte counter
+ return;
+ }
+ currentBytes += bytes;
+ if(currentBytes>delayBytes) {
+ //we have overshot. lets find out how far
+ int delaysize=currentBytes/delayBytes;
+ long delay=delaysize*(long)delayTime;
+ //move byte counter down to the remainder of bytes
+ currentBytes=currentBytes%delayBytes;
+ //now wait
+ try {
+ Thread.sleep(delay);
+ } catch (InterruptedException e) {
+ ; //ignore the exception
+ }
+ }
+ }
+
+ /**
+ * get the current byte count
+ * @return
+ */
+ public int getCurrentBytes() {
+ return currentBytes;
+ }
+
+ /**
+ * set the current byte count
+ * @param currentBytes
+ */
+ public void setCurrentBytes(int currentBytes) {
+ this.currentBytes = currentBytes;
+ }
+
+ }
+
+ /**
+ * this class handles the pumping of data from the incoming socket to the
+ * outgoing socket
+ */
class SocketRR extends Thread {
Socket inSocket = null ;
Socket outSocket = null ;
@@ -414,11 +623,12 @@
int tableIndex = 0 ;
String type = null;
Connection myConnection = null;
+ SlowLinkSimulator slowLink;
public SocketRR(Connection c, Socket inputSocket, InputStream inputStream,
Socket outputSocket, OutputStream outputStream,
JTextArea _textArea, boolean format,
- TableModel tModel, int index, final String type) {
+ TableModel tModel, int index, final String type, SlowLinkSimulator slowLink) {
inSocket = inputSocket ;
in = inputStream ;
outSocket = outputSocket ;
@@ -429,6 +639,7 @@
tableIndex = index ;
this.type = type;
myConnection = c;
+ this.slowLink= slowLink;
start();
}
@@ -458,42 +669,56 @@
String tmpStr = (String) tmodel.getValueAt(tableIndex,
REQ_COLUMN);
- if ( !"".equals(tmpStr) )
+ if ( !"".equals(tmpStr) ) {
reqSaved = tmpStr.length();
+ }
}
- a:
+ a:
for ( ; ; ) {
- if ( done ) break;
+ if ( done ) {
+ break;
+ }
//try{
//len = in.available();
//}catch(Exception e){len=0;}
len = buffer.length ;
- // Used to be 1, but if we block it doesn't matter
+ // Used to be 1, but if we block it doesn't matter
// however 1 will break with some servers, including apache
- if ( len == 0 ) len = buffer.length;
- if ( saved + len > buffer.length) len = buffer.length - saved ;
+ if ( len == 0 ) {
+ len = buffer.length;
+ }
+ if ( saved + len > buffer.length) {
+ len = buffer.length - saved ;
+ }
int len1 = 0;
while ( len1 == 0 ) {
try {
len1 = in.read(buffer, saved, len);
- }
+ }
catch ( Exception ex ) {
- if ( done && saved == 0 ) break a;
+ if ( done && saved == 0 ) {
+ break a;
+ }
len1 = -1;
break;
}
}
len = len1;
- if ( len == -1 && saved == 0 ) break ;
- if ( len == -1) done = true;
+ if ( len == -1 && saved == 0 ) {
+ break ;
+ }
+ if ( len == -1) {
+ done = true;
+ }
// No matter how we may (or may not) format it, send it
// on unformatted - we don't want to mess with how its
// sent to the other side, just how its displayed
if ( out != null && len > 0 ) {
+ slowLink.pump(len);
out.write( buffer, saved, len );
}
@@ -502,8 +727,9 @@
REQ_COLUMN);
old = old + new String(buffer, saved, len);
- if ( old.length() > 50 )
+ if ( old.length() > 50 ) {
old = old.substring(0, 50);
+ }
reqSaved = old.length();
@@ -520,7 +746,9 @@
boolean inXML = false ;
int bufferLen = saved ;
- if ( len != -1 ) bufferLen += len ;
+ if ( len != -1 ) {
+ bufferLen += len ;
+ }
i1 = 0 ;
i2 = 0 ;
saved = 0 ;
@@ -537,8 +765,9 @@
inXML = true ;
}
if ( buffer[i1] == '<' && buffer[i1 + 1] == '/' ) {
- if (previousIndent > nextIndent)
+ if (previousIndent > nextIndent) {
thisIndent = nextIndent;
+ }
previousIndent = nextIndent--;
inXML = true ;
}
@@ -547,9 +776,12 @@
inXML = true ;
}
if ( thisIndent != -1 ) {
- if ( thisIndent > 0 ) tmpbuffer[i2++] = (byte) '\n';
- for ( i = tabWidth * thisIndent; i > 0; i-- )
+ if ( thisIndent > 0 ) {
+ tmpbuffer[i2++] = (byte) '\n';
+ }
+ for ( i = tabWidth * thisIndent; i > 0; i-- ) {
tmpbuffer[i2++] = (byte) ' ';
+ }
}
atMargin = ( buffer[i1] == '\n' || buffer[i1] == '\r');
@@ -561,8 +793,9 @@
textArea.append( new String( tmpbuffer, 0, i2 ) );
// Shift saved bytes to the beginning
- for ( i = 0 ; i < saved ; i++ )
+ for ( i = 0 ; i < saved ; i++ ) {
buffer[i] = buffer[bufferLen - saved + i];
+ }
}
else {
textArea.append( new String( buffer, 0, len ) );
@@ -584,18 +817,24 @@
try {
if (out != null) {
out.flush();
- if (null != outSocket) outSocket.shutdownOutput();
- else out.close();
+ if (null != outSocket) {
+ outSocket.shutdownOutput();
+ } else {
+ out.close();
+ }
out = null;
}
- }
+ }
catch (Exception e) {
;
}
try {
if (in != null) {
- if (inSocket != null) inSocket.shutdownInput();
- else in.close();
+ if (inSocket != null) {
+ inSocket.shutdownInput();
+ } else {
+ in.close();
+ }
in = null;
}
}
@@ -608,16 +847,24 @@
public void halt() {
try {
- if ( inSocket != null ) inSocket.close();
- if ( outSocket != null ) outSocket.close();
+ if ( inSocket != null ) {
+ inSocket.close();
+ }
+ if ( outSocket != null ) {
+ outSocket.close();
+ }
inSocket = null ;
outSocket = null ;
- if ( in != null ) in.close();
- if ( out != null ) out.close();
+ if ( in != null ) {
+ in.close();
+ }
+ if ( out != null ) {
+ out.close();
+ }
in = null ;
out = null ;
done = true;
- }
+ }
catch ( Exception e ) {
e.printStackTrace();
}
@@ -625,6 +872,9 @@
}
+ /**
+ * a connection listens to a single current connection
+ */
class Connection extends Thread {
Listener listener ;
boolean active ;
@@ -644,11 +894,13 @@
String HTTPProxyHost = null ;
int HTTPProxyPort = 80 ;
+ private SlowLinkSimulator slowLink;
public Connection(Listener l) {
listener = l ;
HTTPProxyHost = l.HTTPProxyHost ;
HTTPProxyPort = l.HTTPProxyPort ;
+ slowLink =l.slowLink;
}
public Connection(Listener l, Socket s ) {
@@ -668,33 +920,42 @@
active = true ;
HTTPProxyHost = System.getProperty( "http.proxyHost" );
- if ( HTTPProxyHost != null && HTTPProxyHost.equals("") )
+ if ( HTTPProxyHost != null && HTTPProxyHost.equals("") ) {
HTTPProxyHost = null ;
+ }
if ( HTTPProxyHost != null ) {
String tmp = System.getProperty( "http.proxyPort" );
- if ( tmp != null && tmp.equals("") ) tmp = null ;
- if ( tmp == null ) HTTPProxyPort = 80 ;
- else HTTPProxyPort = Integer.parseInt( tmp );
+ if ( tmp != null && tmp.equals("") ) {
+ tmp = null ;
+ }
+ if ( tmp == null ) {
+ HTTPProxyPort = 80 ;
+ } else {
+ HTTPProxyPort = Integer.parseInt( tmp );
+ }
}
- if ( inSocket != null )
+ if ( inSocket != null ) {
fromHost = (inSocket.getInetAddress()).getHostName();
- else
+ } else {
fromHost = "resend" ;
+ }
+
- DateFormat df = new SimpleDateFormat("MM/dd/yy hh:mm:ss aa");
+ String dateformat=getMessage("dateformat00", "yyyy-MM-dd HH:mm:ss");
+ DateFormat df = new SimpleDateFormat(dateformat);
time = df.format( new Date() );
int count = listener.connections.size();
- listener.tableModel.insertRow(count + 1, new Object[] {
+ listener.tableModel.insertRow(count + 1, new Object[] {
getMessage("active00", "Active"),
time,
fromHost,
- listener.hostField.getText(), ""
+ listener.hostField.getText(), ""
}
);
listener.connections.add( this );
@@ -729,11 +990,13 @@
InputStream tmpIn2 = null ;
OutputStream tmpOut2 = null ;
- if ( tmpIn1 == null )
+ if ( tmpIn1 == null ) {
tmpIn1 = inSocket.getInputStream();
+ }
- if ( inSocket != null )
+ if ( inSocket != null ) {
tmpOut1 = inSocket.getOutputStream();
+ }
String bufferedData = null ;
StringBuffer buf = null ;
@@ -751,10 +1014,14 @@
int len ;
len = tmpIn1.read(b, 0, 1);
- if ( len == -1 ) break ;
+ if ( len == -1 ) {
+ break ;
+ }
s = new String( b );
buf.append( s );
- if ( b[0] != '\n' ) continue ;
+ if ( b[0] != '\n' ) {
+ continue ;
+ }
break ;
}
@@ -767,16 +1034,22 @@
URL url ;
start = bufferedData.indexOf( ' ' ) + 1;
- while ( bufferedData.charAt(start) == ' ' ) start++ ;
+ while ( bufferedData.charAt(start) == ' ' ) {
+ start++ ;
+ }
end = bufferedData.indexOf( ' ', start );
String urlString = bufferedData.substring( start, end );
- if ( urlString.charAt(0) == '/' ) urlString = urlString.substring(1);
+ if ( urlString.charAt(0) == '/' ) {
+ urlString = urlString.substring(1);
+ }
if ( listener.isProxyBox.isSelected() ) {
url = new URL( urlString );
targetHost = url.getHost();
targetPort = url.getPort();
- if ( targetPort == -1 ) targetPort = 80 ;
+ if ( targetPort == -1 ) {
+ targetPort = 80 ;
+ }
listener.tableModel.setValueAt( targetHost, index + 1,
OUTHOST_COLUMN );
@@ -791,15 +1064,15 @@
listener.tableModel.setValueAt( targetHost, index + 1,
OUTHOST_COLUMN );
bufferedData = bufferedData.substring( 0, start) +
- url.toExternalForm() +
- bufferedData.substring( end );
+ url.toExternalForm() +
+ bufferedData.substring( end );
targetHost = HTTPProxyHost ;
targetPort = HTTPProxyPort ;
}
}
- }
+ }
else {
//
// Change Host: header to point to correct host
@@ -814,12 +1087,14 @@
int len ;
len = tmpIn1.read(b1, 0, 1);
- if ( len == -1 )
+ if ( len == -1 ) {
break ;
+ }
s1 = new String( b1 );
buf.append( s1 );
- if ( b1[0] != '\n' )
+ if ( b1[0] != '\n' ) {
continue ;
+ }
// we have a complete line
String line = buf.toString();
@@ -833,14 +1108,19 @@
break ;
}
// add it to our headers so far
- if (bufferedData == null)
+ if (bufferedData == null) {
bufferedData = line;
- else
+ } else {
bufferedData = bufferedData.concat(line);
+ }
// failsafe
- if (line.equals("\r\n")) break;
- if ("\n".equals(lastLine) && line.equals("\n")) break ;
+ if (line.equals("\r\n")) {
+ break;
+ }
+ if ("\n".equals(lastLine) && line.equals("\n")) {
+ break ;
+ }
lastLine = line ;
}
if ( bufferedData != null ) {
@@ -849,16 +1129,20 @@
s1 = bufferedData.substring( 0, idx );
int i = s1.indexOf('\n');
- if ( i > 0 ) s1 = s1.substring(0, i - 1);
+ if ( i > 0 ) {
+ s1 = s1.substring(0, i - 1);
+ }
s1 = s1 + " " +
- " ";
+ " ";
s1 = s1.substring(0, 51);
listener.tableModel.setValueAt( s1, index + 1,
REQ_COLUMN );
}
}
- if ( targetPort == -1 ) targetPort = 80 ;
+ if ( targetPort == -1 ) {
+ targetPort = 80 ;
+ }
outSocket = new Socket(targetHost, targetPort );
tmpIn2 = outSocket.getInputStream();
@@ -866,25 +1150,30 @@
if ( bufferedData != null ) {
byte[] b = bufferedData.getBytes();
-
tmpOut2.write( b );
+ slowLink.pump(b.length);
}
boolean format = listener.xmlFormatBox.isSelected();
+
+ //this is the channel to the endpoint
rr1 = new SocketRR(this, inSocket, tmpIn1, outSocket,
tmpOut2, inputText, format,
- listener.tableModel, index + 1, "request:" );
+ listener.tableModel, index + 1, "request:", slowLink);
+ //create the response slow link from the inbound slow link
+ SlowLinkSimulator responseLink = new SlowLinkSimulator(slowLink);
+ //this is the channel from the endpoint
rr2 = new SocketRR( this, outSocket, tmpIn2, inSocket,
tmpOut1, outputText, format,
- null, 0, "response:" );
+ null, 0, "response:", responseLink);
while ( rr1 != null || rr2 != null ) {
// Only loop as long as the connection to the target
// machine is available - once that's gone we can stop.
// The old way, loop until both are closed, left us
// looping forever since no one closed the 1st one.
- // while( !rr2.isDone() )
+ // while( !rr2.isDone() )
if (null != rr1 && rr1.isDone()) {
if ( index >= 0 && rr2 != null) {
listener.tableModel.setValueAt(getMessage("resp00", "Resp"),
@@ -933,11 +1222,17 @@
PrintWriter wr = new PrintWriter(st);
int index = listener.connections.indexOf( this );
- if ( index >= 0 )
+ if ( index >= 0 ) {
listener.tableModel.setValueAt( getMessage("error00", "Error"), 1 + index, STATE_COLUMN );
+ }
e.printStackTrace(wr);
wr.close();
- outputText.append( st.toString() );
+ if(outputText!=null) {
+ outputText.append( st.toString() );
+ } else {
+ //something went wrong before we had the output area
+ System.out.println(st.toString());
+ }
halt();
}
}
@@ -948,11 +1243,19 @@
public void halt() {
try {
- if ( rr1 != null ) rr1.halt();
- if ( rr2 != null ) rr2.halt();
- if ( inSocket != null ) inSocket.close();
+ if ( rr1 != null ) {
+ rr1.halt();
+ }
+ if ( rr2 != null ) {
+ rr2.halt();
+ }
+ if ( inSocket != null ) {
+ inSocket.close();
+ }
inSocket = null ;
- if ( outSocket != null ) outSocket.close();
+ if ( outSocket != null ) {
+ outSocket.close();
+ }
outSocket = null ;
}
catch ( Exception e ) {
@@ -977,6 +1280,9 @@
}
+ /**
+ * this is one of the tabbed panels that acts as the actual proxy
+ */
class Listener extends JPanel {
public Socket inputSocket = null ;
public Socket outputSocket = null ;
@@ -1002,15 +1308,36 @@
public JTabbedPane notebook = null ;
public String HTTPProxyHost = null ;
public int HTTPProxyPort = 80 ;
-
- final public Vector connections = new Vector();
-
+ public int delayBytes = 0;
+ public int delayTime = 0;
+ public SlowLinkSimulator slowLink;
+
+ public final Vector connections = new Vector();
+
+ /**
+ * create a listener
+ * @param _notebook
+ * @param name
+ * @param listenPort
+ * @param host
+ * @param targetPort
+ * @param isProxy
+ * @param slowLink optional reference to a slow connection
+ */
public Listener(JTabbedPane _notebook, String name,
int listenPort, String host, int targetPort,
- boolean isProxy) {
+ boolean isProxy, SlowLinkSimulator slowLink) {
notebook = _notebook ;
- if ( name == null ) name = getMessage("port01", "Port") + " " + listenPort ;
-
+ if ( name == null ) {
+ name = getMessage("port01", "Port") + " " + listenPort ;
+ }
+ //set the slow link to the passed down link
+ if(slowLink!=null) {
+ this.slowLink=slowLink;
+ } else {
+ //or make up a no-op one.
+ this.slowLink=new SlowLinkSimulator(0,0);
+ }
this.setLayout( new BorderLayout() );
// 1st component is just a row of labels and 1-line entry fields
@@ -1054,8 +1381,12 @@
stopButton.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent event) {
- if ( getMessage("stop00", "Stop").equals(event.getActionCommand()) ) stop();
- if ( start.equals(event.getActionCommand()) ) start();
+ if ( getMessage("stop00", "Stop").equals(event.getActionCommand()) ) {
+ stop();
+ }
+ if ( start.equals(event.getActionCommand()) ) {
+ start();
+ }
}
}
);
@@ -1090,7 +1421,9 @@
sel.addListSelectionListener( new ListSelectionListener() {
public void valueChanged(ListSelectionEvent event) {
- if (event.getValueIsAdjusting()) return ;
+ if (event.getValueIsAdjusting()) {
+ return ;
+ }
ListSelectionModel m = (ListSelectionModel) event.getSource();
int divLoc = outPane.getDividerLocation();
@@ -1138,11 +1471,11 @@
}
outPane.setDividerLocation(divLoc);
}
- }
+ }
);
- tableModel.addRow( new Object[] {
- "---", getMessage("mostRecent00", "Most Recent"), "---", "---", "---"
- }
+ tableModel.addRow( new Object[] {
+ "---", getMessage("mostRecent00", "Most Recent"), "---", "---", "---"
+ }
);
JPanel tablePane = new JPanel();
@@ -1168,7 +1501,9 @@
removeButton.setEnabled( false );
removeButton.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent event) {
- if ( removeSelected.equals(event.getActionCommand()) ) remove();
+ if ( removeSelected.equals(event.getActionCommand()) ) {
+ remove();
+ }
}
}
);
@@ -1176,7 +1511,9 @@
removeAllButton.setEnabled( false );
removeAllButton.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent event) {
- if ( removeAll.equals(event.getActionCommand()) ) removeAll();
+ if ( removeAll.equals(event.getActionCommand()) ) {
+ removeAll();
+ }
}
}
);
@@ -1228,7 +1565,9 @@
saveButton.setEnabled( false );
saveButton.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent event) {
- if ( save.equals(event.getActionCommand()) ) save();
+ if ( save.equals(event.getActionCommand()) ) {
+ save();
+ }
}
}
);
@@ -1236,7 +1575,9 @@
resendButton.setEnabled( false );
resendButton.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent event) {
- if ( resend.equals(event.getActionCommand()) ) resend();
+ if ( resend.equals(event.getActionCommand()) ) {
+ resend();
+ }
}
}
);
@@ -1246,10 +1587,14 @@
if (switchStr.equals(event.getActionCommand()) ) {
int v = outPane.getOrientation();
- if ( v == 0 ) // top/bottom
+ if ( v == 0 ) {
+ // top/bottom
outPane.setOrientation(1);
- else // left/right
+ }
+ else {
+ // left/right
outPane.setOrientation(0);
+ }
outPane.setDividerLocation(0.5);
}
}
@@ -1258,8 +1603,9 @@
closeButton.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent event) {
- if (close.equals(event.getActionCommand()) )
+ if (close.equals(event.getActionCommand()) ) {
close();
+ }
}
}
);
@@ -1272,7 +1618,7 @@
pane1.setDividerLocation( 150 );
this.add( pane1, BorderLayout.CENTER );
- //
+ //
////////////////////////////////////////////////////////////////////
sel.setSelectionInterval(0, 0);
outPane.setDividerLocation( 150 );
@@ -1343,15 +1689,18 @@
for ( int i = top ; i >= bot ; i-- ) {
((Connection) connections.get(i - 1)).remove();
}
- if ( bot > connections.size() ) bot = connections.size();
+ if ( bot > connections.size() ) {
+ bot = connections.size();
+ }
lsm.setSelectionInterval(bot, bot);
}
public void removeAll() {
ListSelectionModel lsm = connectionTable.getSelectionModel();
lsm.clearSelection();
- while ( connections.size() > 0 )
+ while ( connections.size() > 0 ) {
((Connection) connections.get(0)).remove();
+ }
lsm.setSelectionInterval(0, 0);
}
@@ -1369,7 +1718,7 @@
rc = lsm.getLeadSelectionIndex();
- int n = 0;
+ int n = 0;
for (Iterator i = connections.iterator();i.hasNext();n++) {
Connection conn = (Connection)i.next();
if (lsm.isSelectedIndex(n + 1) ||
@@ -1381,16 +1730,16 @@
"\n" )).getBytes() );
rc = Integer.parseInt( tPortField.getText() );
out.write( (new String(getMessage("targetPort01", "Target Port:") + " " + rc + "\n" )).getBytes() );
-
+
out.write( (new String("==== " + getMessage("request01", "Request") + " ====\n" )).getBytes() );
out.write( conn.inputText.getText().getBytes() );
-
+
out.write( (new String("==== " + getMessage("response00", "Response") + " ====\n" )).getBytes() );
out.write( conn.outputText.getText().getBytes() );
out.write("\n==============\n".getBytes());
}
}
-
+
out.close();
}
catch ( Exception e ) {
@@ -1406,7 +1755,9 @@
ListSelectionModel lsm = connectionTable.getSelectionModel();
rc = lsm.getLeadSelectionIndex();
- if ( rc == 0 ) rc = connections.size();
+ if ( rc == 0 ) {
+ rc = connections.size();
+ }
Connection conn = (Connection) connections.get( rc - 1 );
if ( rc > 0 ) {
@@ -1426,10 +1777,13 @@
pos3 = text.indexOf( "\n\n" );
if ( pos3 == -1 ) {
pos3 = text.indexOf( "\r\n\r\n" );
- if ( pos3 != -1 ) pos3 = pos3 + 4 ;
+ if ( pos3 != -1 ) {
+ pos3 = pos3 + 4 ;
+ }
}
- else
+ else {
pos3 += 2 ;
+ }
headers = text.substring( 0, pos3 );
@@ -1474,24 +1828,31 @@
if ( listenPort != 0 ) {
Listener l = null ;
- if ( targetHost == null )
+ if ( targetHost == null ) {
l = new Listener( notebook, null, listenPort,
- targetHost, targetPort, true );
- else
+ targetHost, targetPort, true, null);
+ } else {
l = new Listener( notebook, null, listenPort,
- targetHost, targetPort, false );
+ targetHost, targetPort, false, null);
+ }
notebook.setSelectedIndex( 1 );
l.HTTPProxyHost = System.getProperty( "http.proxyHost" );
- if ( l.HTTPProxyHost != null && l.HTTPProxyHost.equals("") )
+ if ( l.HTTPProxyHost != null && l.HTTPProxyHost.equals("") ) {
l.HTTPProxyHost = null ;
+ }
if ( l.HTTPProxyHost != null ) {
String tmp = System.getProperty( "http.proxyPort" );
- if ( tmp != null && tmp.equals("") ) tmp = null ;
- if ( tmp == null ) l.HTTPProxyPort = 80 ;
- else l.HTTPProxyPort = Integer.parseInt( tmp );
+ if ( tmp != null && tmp.equals("") ) {
+ tmp = null ;
+ }
+ if ( tmp == null ) {
+ l.HTTPProxyPort = 80 ;
+ } else {
+ l.HTTPProxyPort = Integer.parseInt( tmp );
+ }
}
}
@@ -1502,11 +1863,11 @@
protected void processWindowEvent(WindowEvent event) {
switch ( event.getID() ) {
- case WindowEvent.WINDOW_CLOSING:
+ case WindowEvent.WINDOW_CLOSING:
exit();
break ;
- default:
+ default:
super.processWindowEvent(event);
break ;
}
@@ -1522,26 +1883,39 @@
public void setOutputHostPort(char hostName, int port) {
}
+ /**
+ * set up the L&F
+ */
+ private static void setupLookAndFeel(boolean nativeLookAndFeel) throws Exception {
+ UIManager.setLookAndFeel(
+ nativeLookAndFeel ? UIManager.getSystemLookAndFeelClassName()
+ : UIManager.getCrossPlatformLookAndFeelClassName());
+ JFrame.setDefaultLookAndFeelDecorated(true);
+ }
+ /**
+ * this is our main method
+ * @param args
+ */
public static void main(String[] args) {
try {
+ //switch between swing L&F here
+ setupLookAndFeel(true);
if ( args.length == 3 ) {
int p1 = Integer.parseInt( args[0] );
int p2 = Integer.parseInt( args[2] );
- UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
new tcpmon( p1, args[1], p2 );
}
else if ( args.length == 1 ) {
int p1 = Integer.parseInt( args[0] );
- UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
new tcpmon( p1, null, 0 );
}
else if ( args.length != 0 ) {
- System.err.println( getMessage("usage00", "Usage:") + " tcpmon [listenPort targetHost targetPort]\n");
+ System.err.println( getMessage("usage00", "Usage:")
+ + " tcpmon [listenPort targetHost targetPort]\n");
}
else {
- UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
new tcpmon(0, null, 0);
}
}
@@ -1562,8 +1936,7 @@
initializeMessages();
}
return messages.getString(key);
- }
- catch (Throwable t) {
+ } catch (Throwable t) {
// If there is any problem whatsoever getting the internationalized
// message, return the default.
return defaultMsg;
@@ -1578,5 +1951,163 @@
private static void initializeMessages() {
messages = ResourceBundle.getBundle("org.apache.axis.utils.tcpmon");
} // initializeMessages
+
+ /**
+ * a text field with a restricted set of characters
+ */
+ static class RestrictedTextField extends JTextField {
+ protected String validText;
+
+ public RestrictedTextField(String validText) {
+ setValidText(validText);
+ }
+
+ public RestrictedTextField(int columns, String validText) {
+ super(columns);
+ setValidText(validText);
+ }
+
+ public RestrictedTextField(String text, String validText) {
+ super(text);
+ setValidText(validText);
+ }
+
+ public RestrictedTextField(String text, int columns, String validText) {
+ super(text, columns);
+ setValidText(validText);
+ }
+
+ private void setValidText(String validText) {
+ this.validText = validText;
+ }
+
+ /**
+ * fascinatingly, this method is called in the super() constructor,
+ * meaning before we are fully initialized. C++ doesnt actually permit
+ * such a situation, but java clearly does...
+ * @return a new document
+ */
+ public Document createDefaultModel() {
+ return new RestrictedDocument();
+ }
+
+ /**
+ * this class strips out invaid chars
+ */
+ class RestrictedDocument extends PlainDocument {
+
+
+ /**
+ * Constructs a plain text document. A default model using
+ * <code>GapContent</code> is constructed and set.
+ */
+ public RestrictedDocument() {
+
+ }
+
+ /**
+ * add a string; only those chars in the valid text list are allowed
+ * @param offset
+ * @param string
+ * @param attributes
+ * @throws BadLocationException
+ */
+ public void insertString(int offset, String string, AttributeSet attributes)
+ throws BadLocationException {
+
+ if (string == null) {
+ return;
+ }
+ int len = string.length();
+ StringBuffer buffer = new StringBuffer(string.length());
+ for (int i = 0; i < len; i++) {
+ char ch = string.charAt(i);
+ if (validText.indexOf(ch) >= 0) {
+ buffer.append(ch);
+ }
+ }
+ super.insertString(offset, new String(buffer), attributes);
+ }
+ } //end class NumericDocument
+ }
+
+ /**
+ * because we cant use Java1.4's JFormattedTextField, here is
+ * a class that accepts numbers only
+ */
+ static class NumberField extends RestrictedTextField {
+
+ private static final String VALID_TEXT = "0123456789";
+
+ /**
+ * Constructs a new <code>TextField</code>. A default model is created,
+ * the initial string is <code>null</code>,
+ * and the number of columns is set to 0.
+ */
+ public NumberField() {
+ super(VALID_TEXT);
+ }
+
+ /**
+ * Constructs a new empty <code>TextField</code> with the specified
+ * number of columns.
+ * A default model is created and the initial string is set to
+ * <code>null</code>.
+ *
+ * @param columns the number of columns to use to calculate
+ * the preferred width; if columns is set to zero, the
+ * preferred width will be whatever naturally results from
+ * the component implementation
+ */
+ public NumberField(int columns) {
+ super(columns, VALID_TEXT);
+ }
+
+
+ /**
+ * get the int value of a field, any invalid (non int) field returns
+ * the default
+ * @param def default value
+ * @return the field contents
+ */
+ public int getValue(int def) {
+ int result = def;
+ String text = getText();
+ if (text != null && text.length() != 0) {
+ try {
+ result = Integer.parseInt(text);
+ } catch (NumberFormatException e) {
+
+ }
+ }
+ return result;
+ }
+
+ /**
+ * set the text to a numeric value
+ * @param value number to assign
+ */
+ public void setValue(int value) {
+ setText(Integer.toString(value));
+ }
+
+ } //end class NumericTextField
+
+ /**
+ * hostname fields
+ */
+ static class HostnameField extends RestrictedTextField {
+ //list of valid chars in a hostname
+ private static final String VALID_TEXT =
+ "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWZYZ-.";
+
+ public HostnameField(int columns) {
+ super(columns, VALID_TEXT);
+ }
+
+ public HostnameField() {
+ super(VALID_TEXT);
+ }
+ }
}