File Source: DCCSendWindow.java

         /* 
    P/P   *  Method: com.dmdirc.addons.dcc.DCCSendWindow__static_init
          */
     1  /*
     2   * Copyright (c) 2006-2009 Chris Smith, Shane Mc Cormack, Gregory Holmes
     3   *
     4   * Permission is hereby granted, free of charge, to any person obtaining a copy
     5   * of this software and associated documentation files (the "Software"), to deal
     6   * in the Software without restriction, including without limitation the rights
     7   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     8   * copies of the Software, and to permit persons to whom the Software is
     9   * furnished to do so, subject to the following conditions:
    10   *
    11   * The above copyright notice and this permission notice shall be included in
    12   * all copies or substantial portions of the Software.
    13   *
    14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    20   * SOFTWARE.
    21   */
    22  
    23  package com.dmdirc.addons.dcc;
    24  
    25  import com.dmdirc.actions.ActionManager;
    26  import com.dmdirc.addons.dcc.actions.DCCActions;
    27  import com.dmdirc.config.IdentityManager;
    28  import com.dmdirc.parser.irc.IRCParser;
    29  import com.dmdirc.parser.irc.SocketState;
    30  import com.dmdirc.parser.irc.callbacks.interfaces.ISocketClosed;
    31  
    32  import java.awt.event.ActionEvent;
    33  import java.awt.event.ActionListener;
    34  import java.io.File;
    35  
    36  import javax.swing.JButton;
    37  import javax.swing.JLabel;
    38  import javax.swing.JOptionPane;
    39  import javax.swing.JProgressBar;
    40  
    41  import net.miginfocom.swing.MigLayout;
    42  
    43  /**
    44   * This class links DCC Send objects to a window.
    45   *
    46   * @author Shane 'Dataforce' McCormack
    47   */
    48  public class DCCSendWindow extends DCCFrame implements DCCSendInterface, ActionListener, ISocketClosed {
    49  	/** The DCCSend object we are a window for */
    50  	private final DCCSend dcc;
    51  	
    52  	/** Other Nickname */
    53  	private final String otherNickname;
    54  	
    55  	/** Total data transfered */
    56  	private volatile long transferCount = 0;
    57  	
    58  	/** Time Started */
    59  	private long timeStarted = 0;
    60  	
    61  	/** Progress Bar */
    62  	private final JProgressBar progress = new JProgressBar();
    63  	
    64  	/** Status Label */
    65  	private final JLabel status = new JLabel("Status: Waiting");
    66  	
    67  	/** Speed Label */
    68  	private final JLabel speed = new JLabel("Speed: Unknown");
    69  	
    70  	/** Time Label */
    71  	private final JLabel remaining = new JLabel("Time Remaining: Unknown");
    72  	
    73  	/** Time Taken */
    74  	private final JLabel taken = new JLabel("Time Taken: 00:00");
    75  	
    76  	/** Button */
    77  	private final JButton button = new JButton("Cancel");
    78  
    79      /** Plugin that this send belongs to. */
    80      private final DCCPlugin myPlugin;
    81  	
    82  	/** IRC Parser that caused this send */
    83  	private IRCParser parser = null;
    84  	
    85  	/**
    86  	 * Creates a new instance of DCCSendWindow with a given DCCSend object.
    87  	 *
    88  	 * @param plugin the DCC Plugin responsible for this window
    89  	 * @param dcc The DCCSend object this window wraps around
    90  	 * @param title The title of this window
    91  	 * @param targetNick Nickname of target
    92  	 * @param parser The IRC parser that initiated this send
    93  	 */
    94  	public DCCSendWindow(final DCCPlugin plugin, final DCCSend dcc, final String title, final String targetNick, final IRCParser parser) {
        		 /* 
    P/P 		  *  Method: void com.dmdirc.addons.dcc.DCCSendWindow(DCCPlugin, DCCSend, String, String, IRCParser)
        		  * 
        		  *  Preconditions:
        		  *    dcc != null
        		  *    init'ed(dcc.filename)
        		  *    init'ed(dcc.transferType)
        		  *    init'ed(plugin.container)
        		  *    plugin != null
        		  *    (soft) plugin.childFrames != null
        		  * 
        		  *  Presumptions:
        		  *    com.dmdirc.addons.ui_swing.components.frames.TextFrame:getContentPane(...)@192 != null
        		  *    com.dmdirc.config.IdentityManager:getGlobalConfig(...)@138 init'ed
        		  *    com.dmdirc.parser.irc.IRCParser:getCallbackManager(...)@101 != null
        		  *    (soft) init'ed(com/dmdirc/FrameContainer.java.awt.Color.BLACK)
        		  * 
        		  *  Postconditions:
        		  *    dcc.handler == this
        		  *    dcc.handler != null
        		  *    plugin.container == One-of{old plugin.container, &new DCCPlugin$3(createContainer#1)}
        		  *    plugin.container != null
        		  *    this.button == &new JButton(DCCSendWindow#6)
        		  *    this.changer == &new FrameContainer$IconChanger(FrameContainer#2)
        		  *    this.config != null
        		  *    this.dcc == dcc
        		  *    this.dcc != null
        		  *    this.icon in Addr_Set{&"dcc-receive-inactive",&"dcc-send-inactive"}
        		  *    ...
        		  * 
        		  *  Test Vectors:
        		  *    parser: Addr_Set{null}, Inverse{null}
        		  */
    95  		super(plugin, title, dcc.getType() == DCCSend.TransferType.SEND ? "dcc-send-inactive" : "dcc-receive-inactive");
    96  		this.dcc = dcc;
    97  		this.parser = parser;
    98          this.myPlugin = plugin;
    99          
   100  		if (parser != null) {
   101  			parser.getCallbackManager().addNonCriticalCallback("onSocketClosed", this);
   102  		}
   103  		dcc.setHandler(this);
   104  
   105  		otherNickname = targetNick;
   106  		
   107  		getContentPane().setLayout(new MigLayout());
   108  		
   109  		progress.setMinimum(0);
   110  		progress.setMaximum(100);
   111  		progress.setStringPainted(true);
   112  		progress.setValue(0);
   113  		
   114  		if (dcc.getType() == DCCSend.TransferType.SEND) {
   115  			getContentPane().add(new JLabel("Sending: "+dcc.getShortFileName()), "wrap");
   116  			getContentPane().add(new JLabel("To: "+targetNick), "wrap");
   117  		} else {
   118  			getContentPane().add(new JLabel("Recieving: "+dcc.getShortFileName()), "wrap");
   119  			getContentPane().add(new JLabel("From: "+targetNick), "wrap");
   120  		}
   121  		getContentPane().add(status, "wrap");
   122  		getContentPane().add(speed, "wrap");
   123  		getContentPane().add(remaining, "wrap");
   124  		getContentPane().add(taken, "wrap");
   125  		getContentPane().add(progress, "growx, wrap");
   126  		
   127  		button.addActionListener(this);
   128  		getContentPane().add(button, "wrap, align right");
   129  		
   130  		plugin.addWindow(this);
   131  	}
   132  	
   133  	/** {@inheritDoc} */
   134      @Override
   135  	public void onSocketClosed(final IRCParser tParser) {
   136  		// Remove our reference to the parser (and its reference to us)
        		 /* 
    P/P 		  *  Method: void onSocketClosed(IRCParser)
        		  * 
        		  *  Preconditions:
        		  *    this.parser != null
        		  *    this.button != null
        		  * 
        		  *  Presumptions:
        		  *    com.dmdirc.parser.irc.IRCParser:getCallbackManager(...)@137 != null
        		  * 
        		  *  Postconditions:
        		  *    this.parser == null
        		  * 
        		  *  Test Vectors:
        		  *    java.lang.String:equals(...)@140: {0}, {1}
        		  */
   137  		parser.getCallbackManager().delAllCallback(this);
   138  		parser = null;
   139  		// Can't resend without the parser.
   140  		if ("Resend".equals(button.getText())) {
   141  			button.setText("Close Window");
   142  		}
   143  	}
   144  	
   145  	/**
   146  	 * Get the DCCSend Object associated with this window
   147  	 *
   148  	 * @return The DCCSend Object associated with this window
   149  	 */
   150  	public DCCSend getDCC() {
        		 /* 
    P/P 		  *  Method: DCCSend getDCC()
        		  * 
        		  *  Postconditions:
        		  *    return_value == this.dcc
        		  *    init'ed(return_value)
        		  */
   151  		return dcc;
   152  	}
   153  	
   154  	/** {@inheritDoc} */
   155      @Override
   156  	public void actionPerformed(final ActionEvent e) {
        		 /* 
    P/P 		  *  Method: void actionPerformed(ActionEvent)
        		  * 
        		  *  Preconditions:
        		  *    e != null
        		  *    (soft) init'ed(this.dcc.address)
        		  *    (soft) init'ed(this.dcc.fileIn)
        		  *    (soft) init'ed(this.dcc.filename)
        		  *    (soft) init'ed(this.dcc.port)
        		  *    (soft) init'ed(this.dcc.serverSocket)
        		  *    (soft) init'ed(this.dcc.socket)
        		  *    (soft) init'ed(this.dcc.startpos)
        		  *    (soft) this.button != null
        		  *    (soft) this.dcc != null
        		  *    ...
        		  * 
        		  *  Presumptions:
        		  *    com.dmdirc.config.IdentityManager:getGlobalConfig(...)@187 != null
        		  *    com.dmdirc.parser.irc.IRCParser:getIRCStringConverter(...)@176 != null
        		  *    init'ed(com.dmdirc.parser.irc.SocketState.OPEN)
        		  *    java.awt.event.ActionEvent:getActionCommand(...)@157 != null
        		  *    java.awt.event.ActionEvent:getActionCommand(...)@165 != null
        		  *    ...
        		  * 
        		  *  Postconditions:
        		  *    java.lang.Integer:toString(...)._tainted == 0
        		  *    this.dcc.address == One-of{old this.dcc.address, 0}
        		  *    init'ed(this.dcc.address)
        		  *    this.dcc.fileIn == One-of{old this.dcc.fileIn, &new DataInputStream(setFileName#2), null}
        		  *    init'ed(this.dcc.fileIn)
        		  *    possibly_updated(this.dcc.fileOut)
        		  *    this.dcc.filename == old this.dcc.filename
        		  *    init'ed(this.dcc.filename)
        		  *    this.dcc.handler.timeStarted == old this.dcc.handler.timeStarted
        		  *    possibly_updated(this.dcc.in)
        		  *    ...
        		  * 
        		  *  Test Vectors:
        		  *    this.parser: Addr_Set{null}, Inverse{null}
        		  *    com.dmdirc.config.ConfigManager:getOptionBool(...)@187: {0}, {1}
        		  *    com.dmdirc.parser.irc.IRCStringConverter:equalsIgnoreCase(...)@176: {0}, {1}
        		  *    java.lang.String:equals(...)@157: {0}, {1}
        		  *    java.lang.String:equals(...)@165: {0}, {1}
        		  *    java.lang.String:equals(...)@199: {0}, {1}
        		  */
   157  		if (e.getActionCommand().equals("Cancel")) {
   158  			if (dcc.getType() == DCCSend.TransferType.SEND) {
   159  				button.setText("Resend");
   160  			} else {
   161  				button.setText("Close Window");
   162  			}
   163  			status.setText("Status: Cancelled");
   164  			dcc.close();
   165  		} else if (e.getActionCommand().equals("Resend")) {
   166  			button.setText("Cancel");
   167  			status.setText("Status: Resending...");
   168  			synchronized (this) {
   169  				transferCount = 0;
   170  			}
   171  			dcc.reset();
   172  			if (parser != null && parser.getSocketState() == SocketState.OPEN) {
   173  				final String myNickname = parser.getMyNickname();
   174  				// Check again incase we have changed nickname to the same nickname that
   175  				// this send is for.
   176  				if (parser.getIRCStringConverter().equalsIgnoreCase(otherNickname, myNickname)) {
        					 /* 
    P/P 					  *  Method: void com.dmdirc.addons.dcc.DCCSendWindow$1(DCCSendWindow)
        					  */
   177  					final Thread errorThread = new Thread(new Runnable() {
   178  						/** {@inheritDoc} */
   179  						@Override
   180  						public void run() {
        							 /* 
    P/P 							  *  Method: void run()
        							  */
   181  							JOptionPane.showMessageDialog(null, "You can't DCC yourself.", "DCC Error", JOptionPane.ERROR_MESSAGE);
   182  						}
   183  					});
   184  					errorThread.start();
   185  					return;
   186  				} else {
   187  					if (IdentityManager.getGlobalConfig().getOptionBool(plugin.getDomain(), "send.reverse")) {
   188  						parser.sendCTCP(otherNickname, "DCC", "SEND \""+(new File(dcc.getFileName())).getName()+"\" "+DCC.ipToLong(myPlugin.getListenIP(parser))+" 0 "+dcc.getFileSize()+" "+dcc.makeToken()+((dcc.isTurbo()) ? " T" : ""));
   189  						return;
   190  					} else if (plugin.listen(dcc)) {
   191  						parser.sendCTCP(otherNickname, "DCC", "SEND \""+(new File(dcc.getFileName())).getName()+"\" "+DCC.ipToLong(myPlugin.getListenIP(parser))+" "+dcc.getPort()+" "+dcc.getFileSize()+((dcc.isTurbo()) ? " T" : ""));
   192  						return;
   193  					}
   194  				}
   195  			} else {
   196  				status.setText("Status: Resend failed.");
   197  				button.setText("Close Window");
   198  			}
   199  		} else if (e.getActionCommand().equals("Close Window")) {
   200  			close();
   201  		}
   202  	}
   203  	
   204  	/**
   205  	 * Called when data is sent/recieved
   206  	 *
   207  	 * @param dcc The DCCSend that this message is from
   208  	 * @param bytes The number of new bytes that were transfered
   209  	 */
   210      @Override
   211  	public void dataTransfered(final DCCSend dcc, final int bytes) {
   212  		final double percent;
        		 /* 
    P/P 		  *  Method: void dataTransfered(DCCSend, int)
        		  * 
        		  *  Preconditions:
        		  *    (float) (dcc.size) != +0
        		  *    init'ed(com/dmdirc/actions/ActionManager.killSwitch)
        		  *    dcc != null
        		  *    init'ed(dcc.size)
        		  *    init'ed(dcc.startpos)
        		  *    init'ed(dcc.transferType)
        		  *    this.dcc != null
        		  *    init'ed(this.dcc.size)
        		  *    init'ed(this.dcc.startpos)
        		  *    this.progress != null
        		  *    ...
        		  * 
        		  *  Presumptions:
        		  *    (int) (java.lang.Math:floor(...)@226) in {-231..232-1}
        		  *    bytes + this.transferCount in {-263..264-1}
        		  * 
        		  *  Postconditions:
        		  *    com/dmdirc/ServerManager.me == old com/dmdirc/ServerManager.me
        		  *    init'ed(this.transferCount)
        		  *    new ArrayList(ServerManager#1) num objects == 0, if init'ed
        		  *    new ServerManager(getServerManager#1) num objects == 0, if init'ed
        		  *    new ServerManager(getServerManager#1).servers == null
        		  */
   213  		synchronized (this) {
   214  			transferCount += bytes;
   215  			percent = (100.00 / dcc.getFileSize()) * (transferCount + dcc.getFileStart());
   216  		}
   217  		
   218  		if (dcc.getType() == DCCSend.TransferType.SEND) {
   219  			status.setText("Status: Sending");
   220  		} else {
   221  			status.setText("Status: Recieving");
   222  		}
   223  		
   224  		updateSpeedAndTime();
   225  		
   226  		progress.setValue((int)Math.floor(percent));
   227  		
   228  		ActionManager.processEvent(DCCActions.DCC_SEND_DATATRANSFERED, null, this, bytes);
   229  	}
   230  	
   231  	/**
   232  	 * Update the transfer speed, time remaining and time taken labels.
   233  	 */
   234  	public void updateSpeedAndTime() {
        		 /* 
    P/P 		  *  Method: void updateSpeedAndTime()
        		  * 
        		  *  Preconditions:
        		  *    this.dcc != null
        		  *    init'ed(this.dcc.size)
        		  *    init'ed(this.dcc.startpos)
        		  *    this.remaining != null
        		  *    this.speed != null
        		  *    this.taken != null
        		  *    init'ed(this.timeStarted)
        		  * 
        		  *  Presumptions:
        		  *    (int) (java.lang.Math:floor(...)@255) in {-263..264-1}
        		  *    (this.dcc.startpos - this.dcc.size) + this.transferCount in {-264+1..263}
        		  */
   235  		final long time = (System.currentTimeMillis() - timeStarted) / 1000;
   236  		final double bytesPerSecond;
   237  		synchronized (this) {
   238  			bytesPerSecond = (time > 0) ? (transferCount / time) : transferCount;
   239  		}
   240  			
   241  		if (bytesPerSecond > 1048576) {
   242  			speed.setText(String.format("Speed: %.2f MB/s", (bytesPerSecond/1048576)));
   243  		} else if (bytesPerSecond > 1024) {
   244  			speed.setText(String.format("Speed: %.2f KB/s", (bytesPerSecond/1024)));
   245  		} else {
   246  			speed.setText(String.format("Speed: %f B/s", bytesPerSecond));
   247  		}
   248  		
   249  		final long remaningBytes;
   250  		synchronized (this) {
   251  			remaningBytes = dcc.getFileSize() - dcc.getFileStart() - transferCount;
   252  		}
   253  		final double remainingSeconds = (bytesPerSecond > 0) ? (remaningBytes / bytesPerSecond) : 1;
   254  		
   255  		remaining.setText(String.format("Time Remaining: %s", duration((int) Math.floor(remainingSeconds))));
   256  		taken.setText(String.format("Time Taken: %s", timeStarted == 0 ? "N/A" : duration(time)));
   257  	}
   258  	
   259  	/**
   260  	 * Get the duration in seconds as a string.
   261  	 *
   262  	 * @param secondsInput to get duration for
   263  	 * @return Duration as a string
   264  	 */
   265  	private String duration(final long secondsInput) {
        		 /* 
    P/P 		  *  Method: String duration(long)
        		  * 
        		  *  Postconditions:
        		  *    java.lang.StringBuilder:toString(...)._tainted == 0
        		  *    return_value == &java.lang.StringBuilder:toString(...)
        		  * 
        		  *  Test Vectors:
        		  *    secondsInput: {-263..3_599}, {3_600..264-1}
        		  *    secondsInput/3_600: {-2_562_047_788_015_215..0}, {1..5_124_095_576_030_431}
        		  *    secondsInput/60: {-153_722_867_280_912_930..59}, {60..307_445_734_561_825_860}
        		  */
   266  		final StringBuilder result = new StringBuilder();
   267  		final long hours = (secondsInput / 3600);
   268  		final long minutes = (secondsInput / 60 % 60);
   269  		final long seconds = (secondsInput % 60);
   270  		
   271  		if (hours > 0) { result.append(hours+":"); }
   272  		result.append(String.format("%0,2d:%0,2d",minutes,seconds));
   273  		
   274  		return result.toString();
   275  	}
   276  	
   277  	/**
   278  	 * Called when the socket is closed
   279  	 *
   280  	 * @param dcc The DCCSend that this message is from
   281  	 */
   282  	@Override
   283  	public void socketClosed(final DCCSend dcc) {
        		 /* 
    P/P 		  *  Method: void socketClosed(DCCSend)
        		  * 
        		  *  Preconditions:
        		  *    init'ed(com/dmdirc/actions/ActionManager.killSwitch)
        		  *    init'ed(this.windowClosing)
        		  *    (soft) com.dmdirc.addons.dcc.actions.DCCActions__static_init.new DCCActions(DCCActions__static_init#7).type != null
        		  *    (soft) dcc != null
        		  *    (soft) init'ed(dcc.size)
        		  *    (soft) init'ed(dcc.transferType)
        		  *    (soft) init'ed(com/dmdirc/ServerManager.me)
        		  *    (soft) this.button != null
        		  *    (soft) this.config != null
        		  *    (soft) this.dcc != null
        		  *    ...
        		  * 
        		  *  Postconditions:
        		  *    com/dmdirc/ServerManager.me == old com/dmdirc/ServerManager.me
        		  *    this.icon == One-of{old this.icon, &"dcc-send-done", &"dcc-receive-done", &"dcc-send-failed", &"dcc-receive-failed"}
        		  *    new ArrayList(ServerManager#1) num objects == undefined
        		  *    new ArrayList(ServerManager#1) num objects == 0, if init'ed
        		  *    new ServerManager(getServerManager#1) num objects == new ArrayList(ServerManager#1) num objects
        		  *    new ServerManager(getServerManager#1).servers == undefined
        		  *    new ServerManager(getServerManager#1).servers == null
        		  * 
        		  *  Test Vectors:
        		  *    this.windowClosing: {1}, {0}
        		  */
   284  		ActionManager.processEvent(DCCActions.DCC_SEND_SOCKETCLOSED, null, this);
   285  		if (!isWindowClosing()) {
   286  			synchronized (this) {
   287  				if (transferCount == dcc.getFileSize()) {
   288  					status.setText("Status: Transfer Compelete.");
   289  					progress.setValue(100);
   290  					setIcon(dcc.getType() == DCCSend.TransferType.SEND ? "dcc-send-done" : "dcc-receive-done");
   291  					button.setText("Close Window");
   292  				} else {
   293  					status.setText("Status: Transfer Failed.");
   294  					setIcon(dcc.getType() == DCCSend.TransferType.SEND ? "dcc-send-failed" : "dcc-receive-failed");
   295  					if (dcc.getType() == DCCSend.TransferType.SEND) {
   296  						button.setText("Resend");
   297  					} else {
   298  						button.setText("Close Window");
   299  					}
   300  				}
   301  			}
   302  			updateSpeedAndTime();
   303  		}
   304  	}
   305  	
   306  	/**
   307  	 * Called when the socket is opened
   308  	 *
   309  	 * @param dcc The DCCSend that this message is from
   310  	 */
   311  	@Override
   312  	public void socketOpened(final DCCSend dcc) {
        		 /* 
    P/P 		  *  Method: void socketOpened(DCCSend)
        		  * 
        		  *  Preconditions:
        		  *    init'ed(com/dmdirc/actions/ActionManager.killSwitch)
        		  *    dcc != null
        		  *    init'ed(dcc.transferType)
        		  *    this.config != null
        		  *    this.listeners != null
        		  *    this.status != null
        		  *    (soft) com.dmdirc.addons.dcc.actions.DCCActions__static_init.new DCCActions(DCCActions__static_init#8).type != null
        		  *    (soft) init'ed(com/dmdirc/ServerManager.me)
        		  * 
        		  *  Postconditions:
        		  *    com/dmdirc/ServerManager.me == old com/dmdirc/ServerManager.me
        		  *    this.icon == One-of{&"dcc-send-active", &"dcc-receive-active"}
        		  *    this.icon in Addr_Set{&"dcc-receive-active",&"dcc-send-active"}
        		  *    init'ed(this.timeStarted)
        		  *    new ArrayList(ServerManager#1) num objects == undefined
        		  *    new ArrayList(ServerManager#1) num objects == 0, if init'ed
        		  *    new ServerManager(getServerManager#1) num objects == new ArrayList(ServerManager#1) num objects
        		  *    new ServerManager(getServerManager#1).servers == undefined
        		  *    new ServerManager(getServerManager#1).servers == null
        		  */
   313  		ActionManager.processEvent(DCCActions.DCC_SEND_SOCKETOPENED, null, this);
   314  		status.setText("Status: Socket Opened");
   315  		timeStarted = System.currentTimeMillis();
   316  		setIcon(dcc.getType() == DCCSend.TransferType.SEND ? "dcc-send-active" : "dcc-receive-active");
   317  	}
   318  	
   319  	/**
   320  	 * Closes this container (and it's associated frame).
   321  	 */
   322  	@Override
   323  	public void windowClosing() {
        		 /* 
    P/P 		  *  Method: void windowClosing()
        		  * 
        		  *  Preconditions:
        		  *    this.myWindow != null
        		  *    init'ed(this.plugin.container)
        		  *    this.dcc != null
        		  *    this.dcc.serverSocketSem != null
        		  *    this.plugin != null
        		  *    (soft) init'ed(this.dcc.serverSocket)
        		  *    (soft) init'ed(this.dcc.socket)
        		  *    (soft) this.dcc.serverListeningSem != null
        		  *    (soft) this.plugin.childFrames != null
        		  * 
        		  *  Postconditions:
        		  *    possibly_updated(this.dcc.in)
        		  *    possibly_updated(this.dcc.out)
        		  *    this.dcc.serverSocket == null
        		  *    this.dcc.socket == null
        		  *    this.myWindow == null
        		  *    this.plugin.container == One-of{old this.plugin.container, null}
        		  *    init'ed(this.plugin.container)
        		  *    this.windowClosing == 1
        		  */
   324  		super.windowClosing();
   325  		dcc.removeFromSends();
   326  		dcc.close();
   327  	}
   328  }








SofCheck Inspector Build Version : 2.17854
DCCSendWindow.java 2009-Jun-25 01:54:24
DCCSendWindow.class 2009-Sep-02 17:04:17
DCCSendWindow$1.class 2009-Sep-02 17:04:17