KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > axis2 > util > tcpmon


1 /*
2  * Copyright 2004,2005 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.axis2.util;
17
18 import javax.swing.*;
19 import javax.swing.border.TitledBorder JavaDoc;
20 import javax.swing.event.ChangeEvent JavaDoc;
21 import javax.swing.event.ListSelectionEvent JavaDoc;
22 import javax.swing.event.ListSelectionListener JavaDoc;
23 import javax.swing.plaf.basic.BasicButtonListener JavaDoc;
24 import javax.swing.table.DefaultTableModel JavaDoc;
25 import javax.swing.table.TableColumn JavaDoc;
26 import javax.swing.table.TableModel JavaDoc;
27 import javax.swing.text.AttributeSet JavaDoc;
28 import javax.swing.text.BadLocationException JavaDoc;
29 import javax.swing.text.Document JavaDoc;
30 import javax.swing.text.PlainDocument JavaDoc;
31 import java.awt.*;
32 import java.awt.event.ActionEvent JavaDoc;
33 import java.awt.event.ActionListener JavaDoc;
34 import java.io.*;
35 import java.net.ServerSocket JavaDoc;
36 import java.net.Socket JavaDoc;
37 import java.net.URL JavaDoc;
38 import java.text.DateFormat JavaDoc;
39 import java.text.SimpleDateFormat JavaDoc;
40 import java.util.Date JavaDoc;
41 import java.util.Iterator JavaDoc;
42 import java.util.ResourceBundle JavaDoc;
43 import java.util.Vector JavaDoc;
44
45 /**
46  * TCP monitor to log http messages and responses, both SOAP and plain HTTP.
47  * If you want to choose a different Swing look and feel, set the property
48  * tcpmon.laf to the classname of the new look and feel
49  *
50  * @author Doug Davis (dug@us.ibm.com)
51  * @author Steve Loughran
52  */

53 public class tcpmon extends JFrame {
54     /**
55      * Field notebook
56      */

57     private JTabbedPane notebook = null;
58
59     /**
60      * Field STATE_COLUMN
61      */

62     private static final int STATE_COLUMN = 0;
63
64     /**
65      * Field OUTHOST_COLUMN
66      */

67     private static final int OUTHOST_COLUMN = 3;
68
69     /**
70      * Field REQ_COLUMN
71      */

72     private static final int REQ_COLUMN = 4;
73
74     /**
75      * Field DEFAULT_HOST
76      */

77     private static final String JavaDoc DEFAULT_HOST = "127.0.0.1";
78
79     /**
80      * Field DEFAULT_PORT
81      */

82     private static final int DEFAULT_PORT = 8080;
83
84     /**
85      * this is the admin page
86      */

87     class AdminPage extends JPanel {
88         /**
89          * Field listenerButton, proxyButton
90          */

91         public JRadioButton listenerButton, proxyButton;
92
93         /**
94          * Field hostLabel, tportLabel
95          */

96         public JLabel hostLabel, tportLabel;
97
98         /**
99          * Field port
100          */

101         public NumberField port;
102
103         /**
104          * Field host
105          */

106         public HostnameField host;
107
108         /**
109          * Field tport
110          */

111         public NumberField tport;
112
113         /**
114          * Field noteb
115          */

116         public JTabbedPane noteb;
117
118         /**
119          * Field HTTPProxyBox
120          */

121         public JCheckBox HTTPProxyBox;
122
123         /**
124          * Field HTTPProxyHost
125          */

126         public HostnameField HTTPProxyHost;
127
128         /**
129          * Field HTTPProxyPort
130          */

131         public NumberField HTTPProxyPort;
132
133         /**
134          * Field HTTPProxyHostLabel, HTTPProxyPortLabel
135          */

136         public JLabel HTTPProxyHostLabel, HTTPProxyPortLabel;
137
138         /**
139          * Field delayTimeLabel, delayBytesLabel
140          */

141         public JLabel delayTimeLabel, delayBytesLabel;
142
143         /**
144          * Field delayTime, delayBytes
145          */

146         public NumberField delayTime, delayBytes;
147
148         /**
149          * Field delayBox
150          */

151         public JCheckBox delayBox;
152
153         /**
154          * Constructor AdminPage
155          *
156          * @param notebook
157          * @param name
158          */

159         public AdminPage(JTabbedPane notebook, String JavaDoc name) {
160             JPanel mainPane = null;
161             JButton addButton = null;
162             this.setLayout(new BorderLayout());
163             noteb = notebook;
164             GridBagLayout layout = new GridBagLayout();
165             GridBagConstraints c = new GridBagConstraints();
166             mainPane = new JPanel(layout);
167             c.anchor = GridBagConstraints.WEST;
168             c.gridwidth = GridBagConstraints.REMAINDER;
169             mainPane.add(
170                     new JLabel(
171                             getMessage("newTCP00", "Create a new TCP/IP Monitor...")
172                                     + " "), c);
173
174             // Add some blank space
175
mainPane.add(Box.createRigidArea(new Dimension(1, 5)), c);
176
177             // The listener info
178
// /////////////////////////////////////////////////////////////////
179
JPanel tmpPanel = new JPanel(new GridBagLayout());
180             c.anchor = GridBagConstraints.WEST;
181             c.gridwidth = 1;
182             tmpPanel.add(new JLabel(getMessage("listenPort00", "Listen Port #")
183                                     + " "), c);
184             c.anchor = GridBagConstraints.WEST;
185             c.gridwidth = GridBagConstraints.REMAINDER;
186             tmpPanel.add(port = new NumberField(4), c);
187             mainPane.add(tmpPanel, c);
188             mainPane.add(Box.createRigidArea(new Dimension(1, 5)), c);
189
190             // Group for the radio buttons
191
ButtonGroup btns = new ButtonGroup();
192             c.anchor = GridBagConstraints.WEST;
193             c.gridwidth = GridBagConstraints.REMAINDER;
194             mainPane.add(new JLabel(getMessage("actAs00", "Act as a...")), c);
195
196             // Target Host/Port section
197
// /////////////////////////////////////////////////////////////////
198
c.anchor = GridBagConstraints.WEST;
199             c.gridwidth = GridBagConstraints.REMAINDER;
200             final String JavaDoc listener = getMessage("listener00", "Listener");
201             mainPane.add(listenerButton = new JRadioButton(listener), c);
202             btns.add(listenerButton);
203             listenerButton.setSelected(true);
204             listenerButton.addActionListener(new ActionListener JavaDoc() {
205                 public void actionPerformed(ActionEvent JavaDoc event) {
206                     if (listener.equals(event.getActionCommand())) {
207                         boolean state = listenerButton.isSelected();
208                         tport.setEnabled(state);
209                         host.setEnabled(state);
210                         hostLabel.setForeground(state
211                                         ? Color.black
212                                         : Color.gray);
213                         tportLabel.setForeground(state
214                                         ? Color.black
215                                         : Color.gray);
216                     }
217                 }
218             });
219             c.anchor = GridBagConstraints.WEST;
220             c.gridwidth = 1;
221             mainPane.add(Box.createRigidArea(new Dimension(25, 0)));
222             mainPane.add(hostLabel =
223                     new JLabel(getMessage("targetHostname00", "Target Hostname")
224                                     + " "), c);
225             c.anchor = GridBagConstraints.WEST;
226             c.gridwidth = GridBagConstraints.REMAINDER;
227             host = new HostnameField(30);
228             mainPane.add(host, c);
229             host.setText(DEFAULT_HOST);
230             c.anchor = GridBagConstraints.WEST;
231             c.gridwidth = 1;
232             mainPane.add(Box.createRigidArea(new Dimension(25, 0)));
233             mainPane.add(tportLabel =
234                     new JLabel(getMessage("targetPort00", "Target Port #")
235                                     + " "), c);
236             c.anchor = GridBagConstraints.WEST;
237             c.gridwidth = GridBagConstraints.REMAINDER;
238             tport = new NumberField(4);
239             mainPane.add(tport, c);
240             tport.setValue(DEFAULT_PORT);
241
242             // Act as proxy section
243
// /////////////////////////////////////////////////////////////////
244
c.anchor = GridBagConstraints.WEST;
245             c.gridwidth = GridBagConstraints.REMAINDER;
246             final String JavaDoc proxy = getMessage("proxy00", "Proxy");
247             mainPane.add(proxyButton = new JRadioButton(proxy), c);
248             btns.add(proxyButton);
249             proxyButton.addActionListener(new ActionListener JavaDoc() {
250                 public void actionPerformed(ActionEvent JavaDoc event) {
251                     if (proxy.equals(event.getActionCommand())) {
252                         boolean state = proxyButton.isSelected();
253                         tport.setEnabled(!state);
254                         host.setEnabled(!state);
255                         hostLabel.setForeground(state
256                                         ? Color.gray
257                                         : Color.black);
258                         tportLabel.setForeground(state
259                                         ? Color.gray
260                                         : Color.black);
261                     }
262                 }
263             });
264
265             // Spacer
266
// ///////////////////////////////////////////////////////////////
267
c.anchor = GridBagConstraints.WEST;
268             c.gridwidth = GridBagConstraints.REMAINDER;
269             mainPane.add(Box.createRigidArea(new Dimension(1, 10)), c);
270
271             // Options section
272
// /////////////////////////////////////////////////////////////////
273
JPanel opts = new JPanel(new GridBagLayout());
274             opts.setBorder(new TitledBorder JavaDoc(getMessage("options00",
275                                     "Options")));
276             c.anchor = GridBagConstraints.WEST;
277             c.gridwidth = GridBagConstraints.REMAINDER;
278             mainPane.add(opts, c);
279
280             // HTTP Proxy Support section
281
// /////////////////////////////////////////////////////////////////
282
c.anchor = GridBagConstraints.WEST;
283             c.gridwidth = GridBagConstraints.REMAINDER;
284             final String JavaDoc proxySupport = getMessage("proxySupport00",
285                     "HTTP Proxy Support");
286             opts.add(HTTPProxyBox = new JCheckBox(proxySupport), c);
287             c.anchor = GridBagConstraints.WEST;
288             c.gridwidth = 1;
289             opts.add(HTTPProxyHostLabel =
290                     new JLabel(getMessage("hostname00", "Hostname") + " "), c);
291             HTTPProxyHostLabel.setForeground(Color.gray);
292             c.anchor = GridBagConstraints.WEST;
293             c.gridwidth = GridBagConstraints.REMAINDER;
294             opts.add(HTTPProxyHost = new HostnameField(30), c);
295             HTTPProxyHost.setEnabled(false);
296             c.anchor = GridBagConstraints.WEST;
297             c.gridwidth = 1;
298             opts.add(HTTPProxyPortLabel =
299                     new JLabel(getMessage("port00", "Port #") + " "), c);
300             HTTPProxyPortLabel.setForeground(Color.gray);
301             c.anchor = GridBagConstraints.WEST;
302             c.gridwidth = GridBagConstraints.REMAINDER;
303             opts.add(HTTPProxyPort = new NumberField(4), c);
304             HTTPProxyPort.setEnabled(false);
305             HTTPProxyBox.addActionListener(new ActionListener JavaDoc() {
306                 public void actionPerformed(ActionEvent JavaDoc event) {
307                     if (proxySupport.equals(event.getActionCommand())) {
308                         boolean b = HTTPProxyBox.isSelected();
309                         Color color = b
310                                 ? Color.black
311                                 : Color.gray;
312                         HTTPProxyHost.setEnabled(b);
313                         HTTPProxyPort.setEnabled(b);
314                         HTTPProxyHostLabel.setForeground(color);
315                         HTTPProxyPortLabel.setForeground(color);
316                     }
317                 }
318             });
319
320             // Set default proxy values...
321
String JavaDoc tmp = System.getProperty("http.proxyHost");
322             if ((tmp != null) && tmp.equals("")) {
323                 tmp = null;
324             }
325             HTTPProxyBox.setSelected(tmp != null);
326             HTTPProxyHost.setEnabled(tmp != null);
327             HTTPProxyPort.setEnabled(tmp != null);
328             HTTPProxyHostLabel.setForeground((tmp != null)
329                             ? Color.black
330                             : Color.gray);
331             HTTPProxyPortLabel.setForeground((tmp != null)
332                             ? Color.black
333                             : Color.gray);
334             if (tmp != null) {
335                 HTTPProxyBox.setSelected(true);
336                 HTTPProxyHost.setText(tmp);
337                 tmp = System.getProperty("http.proxyPort");
338                 if ((tmp != null) && tmp.equals("")) {
339                     tmp = null;
340                 }
341                 if (tmp == null) {
342                     tmp = "80";
343                 }
344                 HTTPProxyPort.setText(tmp);
345             }
346
347             // add byte delay fields
348
opts.add(Box.createRigidArea(new Dimension(1, 10)), c);
349             c.anchor = GridBagConstraints.WEST;
350             c.gridwidth = GridBagConstraints.REMAINDER;
351             final String JavaDoc delaySupport = getMessage("delay00",
352                     "Simulate Slow Connection");
353             opts.add(delayBox = new JCheckBox(delaySupport), c);
354
355             // bytes per pause
356
c.anchor = GridBagConstraints.WEST;
357             c.gridwidth = 1;
358             delayBytesLabel = new JLabel(getMessage("delay01",
359                             "Bytes per Pause"));
360             opts.add(delayBytesLabel, c);
361             delayBytesLabel.setForeground(Color.gray);
362             c.anchor = GridBagConstraints.WEST;
363             c.gridwidth = GridBagConstraints.REMAINDER;
364             opts.add(delayBytes = new NumberField(6), c);
365             delayBytes.setEnabled(false);
366
367             // delay interval
368
c.anchor = GridBagConstraints.WEST;
369             c.gridwidth = 1;
370             delayTimeLabel = new JLabel(getMessage("delay02",
371                             "Delay in Milliseconds"));
372             opts.add(delayTimeLabel, c);
373             delayTimeLabel.setForeground(Color.gray);
374             c.anchor = GridBagConstraints.WEST;
375             c.gridwidth = GridBagConstraints.REMAINDER;
376             opts.add(delayTime = new NumberField(6), c);
377             delayTime.setEnabled(false);
378
379             // enabler callback
380
delayBox.addActionListener(new ActionListener JavaDoc() {
381                 public void actionPerformed(ActionEvent JavaDoc event) {
382                     if (delaySupport.equals(event.getActionCommand())) {
383                         boolean b = delayBox.isSelected();
384                         Color color = b
385                                 ? Color.black
386                                 : Color.gray;
387                         delayBytes.setEnabled(b);
388                         delayTime.setEnabled(b);
389                         delayBytesLabel.setForeground(color);
390                         delayTimeLabel.setForeground(color);
391                     }
392                 }
393             });
394
395             // Spacer
396
// ////////////////////////////////////////////////////////////////
397
mainPane.add(Box.createRigidArea(new Dimension(1, 10)), c);
398
399             // ADD Button
400
// /////////////////////////////////////////////////////////////////
401
c.anchor = GridBagConstraints.WEST;
402             c.gridwidth = GridBagConstraints.REMAINDER;
403             final String JavaDoc add = getMessage("add00", "Add");
404             mainPane.add(addButton = new JButton(add), c);
405             this.add(new JScrollPane(mainPane), BorderLayout.CENTER);
406
407             // addButton.setEnabled( false );
408
addButton.addActionListener(new ActionListener JavaDoc() {
409                 public void actionPerformed(ActionEvent JavaDoc event) {
410                     if (add.equals(event.getActionCommand())) {
411                         String JavaDoc text;
412                         Listener JavaDoc l = null;
413                         int lPort;
414                         lPort = port.getValue(0);
415                         if (lPort == 0) {
416
417                             // no port, button does nothing
418
return;
419                         }
420                         String JavaDoc tHost = host.getText();
421                         int tPort = 0;
422                         tPort = tport.getValue(0);
423                         SlowLinkSimulator slowLink = null;
424                         if (delayBox.isSelected()) {
425                             int bytes = delayBytes.getValue(0);
426                             int time = delayTime.getValue(0);
427                             slowLink = new SlowLinkSimulator(bytes, time);
428                         }
429                         try {
430                             l = new Listener JavaDoc(noteb, null, lPort, tHost, tPort,
431                                     proxyButton.isSelected(),
432                                     slowLink);
433                         } catch (Exception JavaDoc e) {
434                             e.printStackTrace();
435                         }
436
437                         // Pick-up the HTTP Proxy settings
438
// /////////////////////////////////////////////////
439
text = HTTPProxyHost.getText();
440                         if ("".equals(text)) {
441                             text = null;
442                         }
443                         l.HTTPProxyHost = text;
444                         text = HTTPProxyPort.getText();
445                         int proxyPort = HTTPProxyPort.getValue(-1);
446                         if (proxyPort != -1) {
447                             l.HTTPProxyPort = Integer.parseInt(text);
448                         }
449
450                         // reset the port
451
port.setText(null);
452                     }
453                 }
454             });
455             notebook.addTab(name, this);
456             notebook.repaint();
457             notebook.setSelectedIndex(notebook.getTabCount() - 1);
458         }
459     }
460
461     /**
462      * wait for incoming connections, spawn a connection thread when
463      * stuff comes in.
464      */

465     class SocketWaiter extends Thread JavaDoc {
466         /**
467          * Field sSocket
468          */

469         ServerSocket JavaDoc sSocket = null;
470
471         /**
472          * Field listener
473          */

474         Listener JavaDoc listener;
475
476         /**
477          * Field port
478          */

479         int port;
480
481         /**
482          * Field pleaseStop
483          */

484         boolean pleaseStop = false;
485
486         /**
487          * Constructor SocketWaiter
488          *
489          * @param l
490          * @param p
491          */

492         public SocketWaiter(Listener JavaDoc l, int p) {
493             listener = l;
494             port = p;
495             start();
496         }
497
498         /**
499          * Method run
500          */

501         public void run() {
502             try {
503                 listener.setLeft(
504                         new JLabel(
505                                 getMessage("wait00", " Waiting for Connection...")));
506                 listener.repaint();
507                 sSocket = new ServerSocket JavaDoc(port);
508                 for (; ;) {
509                     Socket JavaDoc inSocket = sSocket.accept();
510                     if (pleaseStop) {
511                         break;
512                     }
513                     new Connection(listener, inSocket);
514                     inSocket = null;
515                 }
516             } catch (Exception JavaDoc exp) {
517                 if (!"socket closed".equals(exp.getMessage())) {
518                     JLabel tmp = new JLabel(exp.toString());
519                     tmp.setForeground(Color.red);
520                     listener.setLeft(tmp);
521                     listener.setRight(new JLabel(""));
522                     listener.stop();
523                 }
524             }
525         }
526
527         /**
528          * force a halt by connecting to self and then closing the server socket
529          */

530         public void halt() {
531             try {
532                 pleaseStop = true;
533                 new Socket JavaDoc("127.0.0.1", port);
534                 if (sSocket != null) {
535                     sSocket.close();
536                 }
537             } catch (Exception JavaDoc e) {
538                 e.printStackTrace();
539             }
540         }
541     }
542
543     /**
544      * class to simulate slow connections by slowing down the system
545      */

546     static class SlowLinkSimulator {
547         /**
548          * Field delayBytes
549          */

550         private int delayBytes;
551
552         /**
553          * Field delayTime
554          */

555         private int delayTime;
556
557         /**
558          * Field currentBytes
559          */

560         private int currentBytes;
561
562         /**
563          * Field totalBytes
564          */

565         private int totalBytes;
566
567         /**
568          * construct
569          *
570          * @param delayBytes bytes per delay; set to 0 for no delay
571          * @param delayTime delay time per delay in milliseconds
572          */

573         public SlowLinkSimulator(int delayBytes, int delayTime) {
574             this.delayBytes = delayBytes;
575             this.delayTime = delayTime;
576         }
577
578         /**
579          * construct by copying delay bytes and time, but not current
580          * count of bytes
581          *
582          * @param that source of data
583          */

584         public SlowLinkSimulator(SlowLinkSimulator that) {
585             this.delayBytes = that.delayBytes;
586             this.delayTime = that.delayTime;
587         }
588
589         /**
590          * how many bytes have gone past?
591          *
592          * @return
593          */

594         public int getTotalBytes() {
595             return totalBytes;
596         }
597
598         /**
599          * log #of bytes pumped. Will pause when necessary. This method is not
600          * synchronized
601          *
602          * @param bytes
603          */

604         public void pump(int bytes) {
605             totalBytes += bytes;
606             if (delayBytes == 0) {
607
608                 // when not delaying, we are just a byte counter
609
return;
610             }
611             currentBytes += bytes;
612             if (currentBytes > delayBytes) {
613
614                 // we have overshot. lets find out how far
615
int delaysize = currentBytes / delayBytes;
616                 long delay = delaysize * (long) delayTime;
617
618                 // move byte counter down to the remainder of bytes
619
currentBytes = currentBytes % delayBytes;
620
621                 // now wait
622
try {
623                     Thread.sleep(delay);
624                 } catch (InterruptedException JavaDoc e) {
625                 ; // ignore the exception
626
}
627             }
628         }
629
630         /**
631          * get the current byte count
632          *
633          * @return
634          */

635         public int getCurrentBytes() {
636             return currentBytes;
637         }
638
639         /**
640          * set the current byte count
641          *
642          * @param currentBytes
643          */

644         public void setCurrentBytes(int currentBytes) {
645             this.currentBytes = currentBytes;
646         }
647     }
648
649     /**
650      * this class handles the pumping of data from the incoming socket to the
651      * outgoing socket
652      */

653     class SocketRR extends Thread JavaDoc {
654         /**
655          * Field inSocket
656          */

657         Socket JavaDoc inSocket = null;
658
659         /**
660          * Field outSocket
661          */

662         Socket JavaDoc outSocket = null;
663
664         /**
665          * Field textArea
666          */

667         JTextArea textArea;
668
669         /**
670          * Field in
671          */

672         InputStream in = null;
673
674         /**
675          * Field out
676          */

677         OutputStream out = null;
678
679         /**
680          * Field xmlFormat
681          */

682         boolean xmlFormat;
683
684         /**
685          * Field done
686          */

687         volatile boolean done = false;
688
689         /**
690          * Field tmodel
691          */

692         TableModel JavaDoc tmodel = null;
693
694         /**
695          * Field tableIndex
696          */

697         int tableIndex = 0;
698
699         /**
700          * Field type
701          */

702         String JavaDoc type = null;
703
704         /**
705          * Field myConnection
706          */

707         Connection myConnection = null;
708
709         /**
710          * Field slowLink
711          */

712         SlowLinkSimulator slowLink;
713
714         /**
715          * Constructor SocketRR
716          *
717          * @param c
718          * @param inputSocket
719          * @param inputStream
720          * @param outputSocket
721          * @param outputStream
722          * @param _textArea
723          * @param format
724          * @param tModel
725          * @param index
726          * @param type
727          * @param slowLink
728          */

729         public SocketRR(Connection c, Socket JavaDoc inputSocket,
730                         InputStream inputStream, Socket JavaDoc outputSocket,
731                         OutputStream outputStream, JTextArea _textArea,
732                         boolean format, TableModel JavaDoc tModel, int index,
733                         final String JavaDoc type, SlowLinkSimulator slowLink) {
734             inSocket = inputSocket;
735             in = inputStream;
736             outSocket = outputSocket;
737             out = outputStream;
738             textArea = _textArea;
739             xmlFormat = format;
740             tmodel = tModel;
741             tableIndex = index;
742             this.type = type;
743             myConnection = c;
744             this.slowLink = slowLink;
745             start();
746         }
747
748         /**
749          * Method isDone
750          *
751          * @return
752          */

753         public boolean isDone() {
754             return (done);
755         }
756
757         /**
758          * Method run
759          */

760         public void run() {
761             try {
762                 byte[] buffer = new byte[4096];
763                 byte[] tmpbuffer = new byte[8192];
764                 int saved = 0;
765                 int len;
766                 int i1, i2;
767                 int i;
768                 int reqSaved = 0;
769                 int tabWidth = 3;
770                 boolean atMargin = true;
771                 int thisIndent = -1, nextIndent = -1, previousIndent = -1;
772                 if (tmodel != null) {
773                     String JavaDoc tmpStr = (String JavaDoc) tmodel.getValueAt(tableIndex,
774                             REQ_COLUMN);
775                     if (!"".equals(tmpStr)) {
776                         reqSaved = tmpStr.length();
777                     }
778                 }
779                 a:
780                 for (; ;) {
781