View Javadoc
1 /************************************************************ 2 * Copyright * 3 * Portions of this software are Copyright (c) 1993 - 2002, * 4 * Chad Z. Hower (Kudzu) and the Indy Pit Crew * 5 * - http://www.nevrona.com/Indy/ * 6 ************************************************************/ 7 package org.indy; 8 9 import java.io.ByteArrayInputStream; 10 import java.io.ByteArrayOutputStream; 11 import java.io.File; 12 import java.io.FileInputStream; 13 import java.io.FileNotFoundException; 14 import java.io.IOException; 15 import java.io.InputStream; 16 import java.io.UnsupportedEncodingException; 17 18 import org.indy.io.IOHandler; 19 import org.indy.io.IndyIOException; 20 import org.indy.io.MaxLineLengthExceededException; 21 import org.indy.io.NotConnectedException; 22 import org.indy.io.PeerDisconnectedException; 23 import org.indy.io.ReadTimedOutException; 24 25 import org.indy.util.IndyUtilities; 26 import org.indy.util.StringList; 27 28 29 /*** 30 * Provides extended functionality for using {@link org.indy.IOHandler}s, 31 * such as reading and writing primitives, checking response codes and 32 * extracting RFC compliant messages. 33 * 34 *@author Owen Green 35 */ 36 public class Connection extends IndyComponent { 37 /*** 38 * The IOHandler used by this connection 39 */ 40 protected IOHandler ioHandler; 41 42 /*** 43 * Holds the result of the last command for reply checking 44 */ 45 protected RFCReply lastCmdResult = new RFCReply(); 46 47 /*** 48 * Constructs a new instance of <code>TCPConnection</code> 49 * 50 * @param handler The IOHandler for this connection to use 51 */ 52 public Connection(IOHandler handler) { 53 super(); 54 ioHandler = handler; 55 } 56 57 /*** 58 * Sets the maxLineLength attribute of the TCPConnection object 59 * 60 *@param newLen The new maxLineLength value 61 */ 62 public void setMaxLineLength(int newLen) { 63 ioHandler.setMaximumLineLength(newLen); 64 } 65 66 /*** 67 * Sets the timeout for read operations. 68 * 69 *@param timeout The new readTimeOut value 70 */ 71 public void setReadTimeOut(int timeout) throws IndyIOException { 72 ioHandler.setReadTimeOut(timeout); 73 } 74 75 /*** 76 * Sets the iOHandler attribute of the IdTCPConnection object 77 * 78 *@param handler The new iOHandler value 79 */ 80 public void setIOHandler(IOHandler handler) { 81 if (handler == null) { 82 throw new NullPointerException(); 83 } 84 85 ioHandler = handler; 86 } 87 88 /*** 89 * Gets the maxLineLength attribute of the IdTCPConnection object 90 * 91 *@return The maxLineLength value 92 */ 93 public int getMaximumLineLength() { 94 return ioHandler.getMaximumLineLength(); 95 } 96 97 /*** 98 * Returns the timeout for read operations. 99 * 100 *@return The readTimeOut value 101 *@returns The timeout for read operations, in milliseconds. 102 */ 103 public int getReadTimeOut() throws IndyIOException { 104 return ioHandler.getReadTimeOut(); 105 } 106 107 /*** 108 * Checks whether this TCP connection is still connected. 109 * 110 *@return <code>true</code> if the connection is still active, false otherwise. 111 *@throws ConnectionClosedGracefullyException If the connection closes gracefully 112 */ 113 public boolean isConnected() { 114 return (ioHandler == null) ? false : ioHandler.isConnected(); 115 } 116 117 /*** 118 * Gets the iOHandler attribute of the TCPConnection object 119 * 120 *@return The iOHandler value 121 */ 122 public IOHandler getIOHandler() { 123 return ioHandler; 124 } 125 126 /*** 127 * 128 * Reads lines from the connection into <code>dest</code> until <code>delim</code> is hit, 129 * and returns the number of lines read into <code>dest</code> 130 * 131 * @param dest The {@link Captureable} to add lines to 132 * @param delim The delimiter to used demarcate the message 133 * @param isRFCMessage Whether the incoming text should be treated as part of an RFC message 134 * @return The number of lines read 135 * @throws IndyIOException if an IO error occurs 136 * @throws ReadTimedOutException if the read operation times out 137 * @throws PeerDisconnectedException if the remote connection disconnects 138 * @throws MaxLineLengthExceededException if the maximum line lentgh is exceeded 139 * @throws NotConnectedException if not connected 140 */ 141 protected final int performCapture(Capturable dest, String delim, 142 boolean isRFCMessage) 143 throws IndyIOException, ReadTimedOutException, 144 PeerDisconnectedException, 145 MaxLineLengthExceededException, 146 NotConnectedException { 147 if (dest == null) { 148 throw new NullPointerException(); 149 } 150 151 int lineCount = 0; 152 153 doBeginWork(IndyComponent.WorkMode.READ); 154 155 try { 156 while (true) { 157 String s = readLine(); 158 159 if (s.equals(delim)) { 160 break; 161 } 162 163 lineCount++; 164 165 //For RFC 822 retrives 166 if (isRFCMessage && s.startsWith("..")) { 167 s = s.substring(1); 168 } 169 170 dest.addLine(s); 171 } 172 } 173 finally { 174 doEndWork(IndyComponent.WorkMode.WRITE); 175 176 return lineCount; 177 } 178 } 179 180 /*** 181 * Reads lines of text from the connection until into a {@link org.indy.util.StringList} 182 * delim is found and returns the number of lines read. 183 * 184 * @param strings The <code>StringList</code> to fill 185 * @param delim The delimter to read up to 186 * @param isRFC Whether the text should be interpreted as part of an RFC message 187 * @return The number of lines read 188 * @throws IndyIOException if an IO error occurs 189 * @throws ReadTimedOutException if the read operation times out 190 * @throws PeerDisconnectedException if the remote peer disconnects 191 * @throws MaxLineLengthExceededException if the maximum line length is exceeded 192 * @throws NotConnectedException if not connected 193 */ 194 public final int capture(final StringList strings, String delim, 195 boolean isRFC) throws IndyIOException, 196 ReadTimedOutException, 197 PeerDisconnectedException, 198 MaxLineLengthExceededException, 199 NotConnectedException { 200 Capturable c = new Capturable() { 201 public void addLine(String s) { 202 strings.add(s); 203 } 204 }; 205 206 return performCapture(c, delim, isRFC); 207 } 208 209 /*** 210 * Reads lines of text from the connection into a <code>StringBuffer</code> 211 * until <code>delim</code> is found and returns the number of lines read. 212 * 213 * @param strings The <code>StringBuffer</code> to fill 214 * @param delim the delimiter to look for 215 * @param isRFC <code>true</code> if this should be treated as an RFC message 216 * @return the number of lines read 217 * @throws IndyIOException if an IO error occurs 218 * @throws ReadTimedOutException if the read operation times out 219 * @throws PeerDisconnectedException if the remote peer disconnects 220 * @throws MaxLineLengthExceededException if the maximum line length is exceeded 221 * @throws NotConnectedException if not connected 222 */ 223 public final int capture(final StringBuffer strings, String delim, 224 boolean isRFC) throws IndyIOException, 225 ReadTimedOutException, 226 PeerDisconnectedException, 227 MaxLineLengthExceededException, 228 NotConnectedException { 229 Capturable c = new Capturable() { 230 public void addLine(String s) { 231 strings.append(s); 232 strings.append('\n'); 233 } 234 }; 235 236 return performCapture(c, delim, isRFC); 237 } 238 239 /*** 240 * Resets this connection 241 */ 242 protected void resetConnection() { 243 if (ioHandler != null) { 244 ioHandler.clearBuffer(); 245 } 246 } 247 248 /*** 249 * Disconnects this connection. 250 * 251 * @throws IndyIOException If an IO error occurs 252 */ 253 public void disconnect() { 254 doStatus(Status.DISCONNECTING); 255 disconnectSocket(); 256 257 258 // ioHandler = null; 259 doStatus(Status.DISCONNECTED); 260 } 261 262 /*** 263 * 264 */ 265 public void disconnectSocket() { 266 if (ioHandler != null) { 267 ioHandler.close(); 268 } 269 } 270 271 /*** 272 * Checks whether a numeric response code is within a desired 273 * list of responses. If so, the response is returned otherwise 274 * a {@link ProtocolException} is thrown. 275 * 276 * @param response The response being examined 277 * @param allowedResponses The allowed responses 278 * @return The response encountered 279 * @throws ProtocolException if the response is not in the allowed list 280 */ 281 public int checkResponse(int response, int[] allowedResponses) 282 throws ProtocolException { 283 if (allowedResponses == null) { 284 throw new NullPointerException(); 285 } 286 287 if (allowedResponses.length > 0) { 288 for (int i = 0; i < allowedResponses.length; i++) { 289 if (response == allowedResponses[i]) { 290 return response; 291 } 292 } 293 294 throw new ProtocolException(lastCmdResult); 295 } 296 297 return response; 298 } 299 300 /*** 301 * Reads a response from the remote peer, typically 302 * of the form of a response code and some text, 303 * and checks that the code is within <code>allowedResponses</code>. 304 * 305 * If not a {@link ProtocolException} is thrown, otherwise the response 306 * encountered is returned. 307 * 308 * @param allowedResponses The response codes allowed 309 * @return The encountered response 310 * @throws PeerDisconnectedException If the remote host disconnects 311 * @throws ReadTimedOutException If the read operation times out 312 * @throws IndyIOException If an IO error occurs 313 * @throws ProtocolException If the response is not in allowed set 314 * @throws MaxLineLengthExceededException If the maximum line length is exceeded 315 * @throws NotConnectedException If not connected 316 */ 317 public int getResponse(int[] allowedResponses) 318 throws PeerDisconnectedException, ReadTimedOutException, 319 IndyIOException, ProtocolException, 320 MaxLineLengthExceededException, NotConnectedException { 321 getInternalResponse(); 322 323 return checkResponse(lastCmdResult.getNumericCode(), allowedResponses); 324 } 325 326 /*** 327 * Retreives a response from the connection using {@link getInternalResponse} 328 * and checks it for validity. This is an alias for {@link getResponse(int[])} 329 * 330 * @param allowedResponse The expected response 331 * @return The response, if found 332 * @throws PeerDisconnectedException if the remote peer disconnected 333 * @throws ReadTimedOutException if the read operation timed out 334 * @throws IndyIOException if an IO error occured 335 * @throws ProtocolException if the desired response was not returned 336 * @throws MaxLineLengthExceededException if the maximum line length was exceeded 337 * @throws NotConnectedException if not connected 338 */ 339 public int getResponse(int allowedResponse) throws PeerDisconnectedException, 340 ReadTimedOutException, 341 IndyIOException, 342 ProtocolException, 343 MaxLineLengthExceededException, 344 NotConnectedException { 345 return getResponse(new int[] { allowedResponse }); 346 } 347 348 /*** 349 * Used to implement the processing required for {@link getResponse(int[])}. 350 * A response, typically expected to be comptrised of a three digit code and 351 * some text is read and stored using {@link readLineWait()} 352 * 353 * @throws IndyIOException if an IO error occurs 354 * @throws ReadTimedOutException if the read operation times out 355 * @throws PeerDisconnectedException if the remote peer disconnectes 356 * @throws MaxLineLengthExceededException if the maximum line length is exceeded 357 * @throws NotConnectedException if not connected 358 */ 359 protected void getInternalResponse() throws IndyIOException, 360 ReadTimedOutException, 361 PeerDisconnectedException, 362 MaxLineLengthExceededException, 363 NotConnectedException { 364 StringList response = new StringList(); 365 String line = readLineWait(); 366 367 response.add(line); 368 369 if (line.length() > 3) { 370 if (line.charAt(4) == '-') { 371 String term = line.substring(1, 4) + " "; 372 373 while ((line.length() > 4) && !line.substring(1, 5).equals(term)) { 374 line = readLineWait(); 375 response.add(line); 376 } 377 } 378 } 379 380 lastCmdResult.parseResponse(response); 381 } 382 383 /*** 384 * Invokes {@link readLine} and will allow upto 385 * <code>failCount</code> time outs before throwing 386 * {@link ReadTimedOutException}. 387 * 388 * @param failCount The number of time outs to allow before failing 389 * @return A line of text from the connection. 390 * @throws IndyIOException If an IO error occurs. 391 * @throws ReadTimedOutException If the operation times out more than <code>failCount</code> times 392 * @throws PeerDisconnectedException If the remote peer disconnects 393 * @throws MaxLineLengthExceededException If the maximum line length is exceeded 394 * @throws NotConnectedException If not connected 395 */ 396 public String readLineWait(int failCount) throws IndyIOException, 397 ReadTimedOutException, 398 PeerDisconnectedException, 399 MaxLineLengthExceededException, 400 NotConnectedException { 401 StringBuffer sb = new StringBuffer(); 402 int attempts = 0; 403 404 while ((sb.length() == 0) && (attempts < failCount)) { 405 attempts++; 406 407 try { 408 sb.append(readLine()); 409 } 410 catch (ReadTimedOutException ex) { 411 if (attempts >= failCount) { 412 throw ex; 413 } 414 } 415 } 416 417 return sb.toString(); 418 } 419 420 /*** 421 * DOCUMENT ME! 422 * 423 * @return DOCUMENT ME! 424 * 425 * @throws IndyIOException DOCUMENT ME! 426 * @throws ReadTimedOutException DOCUMENT ME! 427 * @throws PeerDisconnectedException DOCUMENT ME! 428 * @throws MaxLineLengthExceededException DOCUMENT ME! 429 * @throws NotConnectedException DOCUMENT ME! 430 */ 431 public String readLineWait() throws IndyIOException, ReadTimedOutException, 432 PeerDisconnectedException, 433 MaxLineLengthExceededException, 434 NotConnectedException { 435 return readLineWait(Integer.MAX_VALUE); 436 } 437 438 /*** 439 * Reads a line of text from the connection. 440 * This wraps {@link org.indy.io.IOHandler#readLine()}/ 441 * 442 * @return A line of text from the connection 443 * @throws PeerDisconnectedException If the remote peer disconnects 444 * @throws ReadTimedOutException If the read operation times out 445 * @throws IndyIOException If an IO error occurs 446 * @throws MaxLineLengthExceededException If the maximum line length is exceeded 447 * @throws NotConnectedException If not connected 448 */ 449 public String readLine() throws PeerDisconnectedException, 450 ReadTimedOutException, IndyIOException, 451 MaxLineLengthExceededException, 452 NotConnectedException { 453 return ioHandler.readLine(); 454 } 455 456 /*** 457 *Reads a line of text from the connection. This wraps 458 * {@link org.indy.io.IOHandler#readLine(int,int)} 459 * 460 * @param timeout The timeout to allow for this read operation 461 * @param maxLineLength The maximum line lentgh to accept 462 * @return A line of text from this connection 463 * @throws IndyIOException If an IO error occurs 464 * @throws ReadTimedOutException If the operation times out 465 * @throws PeerDisconnectedException If the remote peer disonnects 466 * @throws MaxLineLengthExceededException If the maximum line length is exceeded 467 * @throws NotConnectedException If not connected 468 */ 469 public String readLine(int timeout, int maxLineLength) 470 throws IndyIOException, ReadTimedOutException, 471 PeerDisconnectedException, NotConnectedException, 472 MaxLineLengthExceededException { 473 if (!isConnected()) { 474 throw new NotConnectedException(IndyUtilities.getResourceString( 475 "RSNotConnected")); 476 } 477 478 return ioHandler.readLine(timeout, maxLineLength, null); 479 } 480 481 /*** 482 * Fills a buffer, <code>b</code>, with up to <code>len</code> bytes of 483 * data from the connection. 484 * 485 * @param b The buffer to fill 486 * @param len The amount of data to read 487 * @return The actual amount of data read 488 * @throws PeerDisconnectedException If the remote peer disconnects 489 * @throws ReadTimedOutException If the read operation times out 490 * @throws IndyIOException If an IOError occurs 491 * @throws NotConnectedException if not connected 492 */ 493 public final int readBuffer(byte[] b, int len) 494 throws PeerDisconnectedException, ReadTimedOutException, 495 IndyIOException, NotConnectedException { 496 if (b == null) { 497 throw new NullPointerException(IndyUtilities.getResourceString( 498 "RSNullBuffer")); 499 } 500 501 if ((len > b.length) || (len < 1)) { 502 throw new IllegalArgumentException(IndyUtilities.getResourceString( 503 "RSBufferBoundsFail")); 504 } 505 506 return ioHandler.read(b, 0, len); 507 } 508 509 /*** 510 * Reads an <code>int</code> from this connection. 511 * 512 * @return An <code>int</code> 513 * @throws PeerDisconnectedException If the remote peer disconnects 514 * @throws ReadTimedOutException If the read operation timed out 515 * @throws IndyIOException If an IO error occurs. 516 * @throws NotConnectedException If not connected 517 */ 518 public final int readInt() throws PeerDisconnectedException, 519 ReadTimedOutException, IndyIOException, 520 NotConnectedException { 521 byte[] b = new byte[4]; 522 523 ioHandler.read(b, 0, 4); 524 525 return (b[0] << 24) + (b[1] << 16) + (b[2] << 8) + b[3]; 526 } 527 528 /*** 529 * Reads a <code>long</code> from the connection 530 * 531 * @return A <code>long</code> from the connection 532 * @throws PeerDisconnectedException If the remote peer disconnects 533 * @throws ReadTimedOutException If the read operation times out 534 * @throws NotConnectedException If not connected 535 * @throws IndyIOException If an IO error occurs 536 */ 537 public final long readLong() throws PeerDisconnectedException, 538 ReadTimedOutException, IndyIOException, 539 NotConnectedException { 540 byte[] buf = new byte[8]; 541 542 ioHandler.read(buf, 0, 8); 543 544 return ((buf[0] & 0xFFL) << 56) + ((buf[1] & 0xFFL) << 48) + 545 ((buf[2] & 0xFFL) << 40) + ((buf[3] & 0xFFL) << 32) + 546 ((buf[4] & 0xFFL) << 24) + ((buf[5] & 0xFFL) << 16) + 547 ((buf[6] & 0xFFL) << 8) + ((buf[7] & 0xFFL) << 0); 548 } 549 550 /*** 551 * Read a <code>char</code> from the connection 552 * 553 * @return A <code>char</code> from the connection 554 * @throws PeerDisconnectedException If the remote peer disconnects 555 * @throws ReadTimedOutException If the read operation times out 556 * @throws NotConnectedException If not connected 557 * @throws IndyIOException If an IO error occurs 558 */ 559 public final char readChar() throws PeerDisconnectedException, 560 ReadTimedOutException, IndyIOException, 561 NotConnectedException { 562 byte[] b = new byte[2]; 563 564 readBuffer(b, 2); 565 566 return (char) ((b[0] << 8) + (b[1] << 0)); 567 } 568 569 /*** 570 * Reads a short from the connection 571 * 572 * @return A <code>short</code> from the connection 573 * @throws PeerDisconnectedException If the remote peer disconnects 574 * @throws ReadTimedOutException If the read operation times out 575 * @throws NotConnectedException If not connected 576 * @throws IndyIOException If an IO error occurs 577 */ 578 public final short readShort() throws PeerDisconnectedException, 579 ReadTimedOutException, IndyIOException, 580 NotConnectedException { 581 return (short) readChar(); 582 } 583 584 /*** 585 * Reads bytes from the socket and returns them in an InputStream. 586 * If readUntilDisconnect is true, then the method will block and return only when the connection has closed (or if an exception is thrown). 587 * If readUntilDisconnect is false, then byteCount bytes will be read. 588 * If readUntilDisconnect is false and byteCount = -1 then the first 4 bytes read from the socket will be assumed to be an integer representing the stream size, and this number of bytes will be read. 589 * 590 * @param byteCount The number of bytes to read 591 * @param readUntilDisconnect Whether <code>byteCount</code> should be ignored and the read operation should contniue until disconnected 592 * @return An <code>InputStream</code> containing bytes from the connection. 593 * @throws PeerDisconnectedException If the remote peer disconnects 594 * @throws ReadTimedOutException If the read operation times out 595 * @throws NotConnectedException If not connected 596 * @throws IndyIOException If an IO error occurs 597 */ 598 public final InputStream readStream(int byteCount, 599 boolean readUntilDisconnect) 600 throws PeerDisconnectedException, 601 ReadTimedOutException, 602 NotConnectedException, IndyIOException { 603 if ((byteCount == -1) && (!readUntilDisconnect)) { 604 /*** @todo This should probably nuke if the result is negative */ 605 byteCount = readInt(); 606 } 607 608 if (readUntilDisconnect) { 609 return new ByteArrayInputStream(readTillDisconnect()); 610 } 611 else { 612 byte[] bytes = new byte[byteCount]; 613 614 readBuffer(bytes, byteCount); 615 616 return new ByteArrayInputStream(bytes); 617 } 618 } 619 620 /*** 621 * Write the contents of a {@link org.indy.util.StringList} instance 622 * to this connection. 623 * 624 * This method ensures that individual lines in <code>strings</code> beginning 625 * with the response termination character '.' are converted to '..', 626 * and call WriteLn using the updated values. When all lines have been 627 * written, WriteRFCStrings calls WriteLn to send the '.' termination 628 * character to indicate the end of RFC response messages 629 * 630 * @param strings A <code>StringList</code> to write 631 * @throws IndyIOException If an IO error occurs 632 * @throws NotConnectedException If not connected 633 */ 634 public final void writeRFCStrings(StringList strings) 635 throws IndyIOException { 636 for (int i = 0, n = strings.size(); i < n; i++) { 637 if (strings.get(i).equals(".")) { 638 writeLine(".."); 639 } 640 else { 641 writeLine(strings.get(i)); 642 } 643 } 644 645 writeLine("."); 646 } 647 648 /*** 649 * Write an {@link org.indy.RFCReply} to this connection. 650 * 651 * @param reply The <code>RFCReply</code> to write 652 * @throws IndyIOException If an IO error occurs 653 * @throws NotConnectedException If not connected 654 */ 655 public final void writeRFCReply(RFCReply reply) throws IndyIOException { 656 if (reply.replyExists()) { 657 write(reply.generateReply()); 658 } 659 } 660 661 /*** 662 * Write a <code>String</code> to this connection. 663 * 664 * @param s The <code>String</code> to write 665 * @throws IndyIOException If an IO error occurs 666 * @throws NotConnectedException If not connected 667 */ 668 public final void write(String s) throws IndyIOException, 669 NotConnectedException { 670 if ((s != null) && (s.length() > 0)) { 671 writeBuffer(s.getBytes()); 672 } 673 } 674 675 /*** 676 * Write a buffer of bytes to this connection. 677 * 678 * @param buf The bytes to write 679 * @throws IndyIOException If an IO error occurs 680 * @throws NotConnectedException If not connected 681 */ 682 public final void writeBuffer(byte[] buf) throws IndyIOException, 683 NotConnectedException { 684 if (!isConnected()) { 685 throw new NotConnectedException(IndyUtilities.getResourceString( 686 "RSNotConnected")); 687 } 688 689 if ((buf != null) && (buf.length > 0)) { 690 /* 691 * This could possibly do with changing? 692 */ 693 try { 694 for (int i = 0; i < buf.length; i++) { 695 ioHandler.write(buf[i]); 696 doWork(IndyComponent.WorkMode.WRITE, i); 697 } 698 699 ioHandler.flush(); 700 } 701 catch (IndyIOException ioe) { 702 disconnectSocket(); 703 throw ioe; 704 } 705 } 706 } 707 708 /*** 709 * Write a line of text to the connection. 710 * 711 * @param line The text to write as a line 712 * @throws IndyIOException If an IO error occurs 713 * @throws NotConnectedException If not connected 714 */ 715 public final void writeLine(String line) throws IndyIOException { 716 /*** @todo Fix to use prop EOL */ 717 write(line + "\n"); 718 ioHandler.flush(); 719 } 720 721 /*** 722 * Write the contents of a {@link org.indy.util.StringList} 723 * as an RFC header, translating strings of the form 724 * <pre>name=value</pre> 725 * to 726 * <pre>name:value</pre> 727 * 728 * 729 * @todo This seems a silly way of doing it - why not use <code>java.util.Map</code>? 730 * @param header The <code>StringList</code> to write as a header 731 * @throws IndyIOException If an IO error occurs 732 * @throws NotConnectedException If not connected 733 */ 734 public final void writeHeader(StringList header) throws IndyIOException { 735 if (header == null) { 736 throw new NullPointerException(); 737 } 738 739 for (int i = 0, n = header.size(); i < n; i++) { 740 String line = header.get(i); 741 int pos = line.indexOf('='); 742 743 writeLine(line.substring(0, pos) + ": " + line.substring(pos + 1)); 744 } 745 } 746 747 /*** 748 * @throws IndyIOException If an IO error occurs 749 * @throws NotConnectedException If not connected 750 * 751 * @param value The <code>int</code> to write 752 * @throws IndyIOException If an IO error occurs 753 * @throws NotConnectedException If not connected 754 */ 755 public final void writeInt(int value) throws IndyIOException { 756 ioHandler.write((value >>> 24) & 0xFF); 757 ioHandler.write((value >>> 16) & 0xFF); 758 ioHandler.write((value >>> 8) & 0xFF); 759 ioHandler.write((value >>> 0) & 0xFF); 760 } 761 762 /*** 763 * Write a <code>long</code> to the connection 764 * 765 * @param value The <code>long</code> to write 766 * @throws IndyIOException If an IO error occurs 767 * @throws NotConnectedException If not connected 768 */ 769 public final void writeLong(long value) throws IndyIOException { 770 byte[] buf = new byte[8]; 771 int mask = 0xFF; 772 773 for (int i = 0; i < 8; i++) { 774 buf[i] = (byte) ((value & (mask << (8 * i))) >> (8 * i)); 775 } 776 777 writeBuffer(buf); 778 } 779 780 /*** 781 * Write a <code>short</code> to the connection 782 * @param value The <code>short</code> to write 783 * @throws IndyIOException If an IO error occurs 784 * @throws NotConnectedException If not connected 785 */ 786 public final void writeShort(short value) throws IndyIOException { 787 writeBuffer( 788 new byte[] { (byte) ((value & 0xFF00) >> 8), (byte) (value & 0xFF) }); 789 } 790 791 /*** 792 * Write a the contents of a {@link org.indy.util.StringList} instance 793 * to the connection as individual lines. 794 * 795 * @param strings The <code>StringList</code> to write 796 * @param writeLineCount Whether to prepend the text with a int representing the number of lines 797 * @throws IndyIOException If an IO error occurs 798 * @throws NotConnectedException If not connected 799 */ 800 public final void writeStrings(StringList strings, boolean writeLineCount) 801 throws IndyIOException { 802 if (writeLineCount) { 803 writeInt(strings.size()); 804 } 805 806 for (int i = 0, n = strings.size(); i < n; i++) { 807 writeLine(strings.get(i)); 808 } 809 } 810 811 /*** 812 * Writes the contents of an <code>InputStream</code> to the connection 813 * 814 * @param stream The <code>InputStream</code> to write 815 * @param len The number of bytes to write 816 * @param writeByteCount Whether the bytes should be prepended with an int representing the byte count 817 * @throws IndyIOException If an IO error occurs 818 * @throws NotConnectedException If not connected 819 */ 820 public final void writeStream(InputStream stream, int len, 821 boolean writeByteCount) 822 throws IndyIOException { 823 doBeginWork(IndyComponent.WorkMode.WRITE, len); 824 825 try { 826 if (writeByteCount) { 827 writeInt(len); 828 } 829 830 /*** @todo Must do better - this will be horrible for large data sets */ 831 byte[] buf = new byte[len]; 832 833 stream.read(buf); 834 writeBuffer(buf); 835 } 836 catch (IOException ioe) { 837 throw new IndyIOException(ioe); 838 } 839 finally { 840 doEndWork(IndyComponent.WorkMode.WRITE); 841 } 842 } 843 844 /*** 845 * Writes a <code>File</code> object to the stream 846 * 847 * @param f The <code>File</code> to write 848 * @throws FileNotFoundException If the <code>File</code> doesn't exist 849 * @throws IndyIOException If an IO error occurs 850 * @throws NotConnectedException If not connected 851 */ 852 public final void writeFile(File f) throws FileNotFoundException, 853 IndyIOException { 854 if (!f.exists()) { 855 throw new FileNotFoundException(f.getName()); 856 } 857 858 writeStream(new FileInputStream(f), (int) f.length(), true); 859 } 860 861 /*** 862 * Returns the current data that can be read without blocking. 863 * 864 * This wraps {@link org.indy.io.IOHandler#currentReadBuffer()} 865 * 866 * @return The data from the read buffer 867 * @throws PeerDisconnectedException If the remote peer has disconnected 868 * @throws ReadTimedOutException If the read operation times out 869 * @throws IndyIOException If an IO error occurs 870 * @throws NotConnectedException If not connected 871 */ 872 public final byte[] currentReadBuffer() throws PeerDisconnectedException, 873 IndyIOException { 874 return ioHandler.currentReadBuffer(); 875 } 876 877 /*** 878 * DOCUMENT ME! 879 * 880 * @return DOCUMENT ME! 881 * 882 * @throws PeerDisconnectedException DOCUMENT ME! 883 * @throws ReadTimedOutException DOCUMENT ME! 884 * @throws IndyIOException DOCUMENT ME! 885 */ 886 protected byte[] readTillDisconnect() throws PeerDisconnectedException, 887 ReadTimedOutException, 888 IndyIOException { 889 doBeginWork(IndyComponent.WorkMode.READ); 890 891 boolean timeoutChanged = false; 892 final ByteArrayOutputStream bytes = new ByteArrayOutputStream(); 893 894 try { 895 while (true) { 896 try { 897 bytes.write(currentReadBuffer()); 898 } 899 catch (PeerDisconnectedException e) { 900 break; 901 } 902 catch (IOException ex) { 903 throw new IndyIOException(ex); 904 } 905 } 906 907 return bytes.toByteArray(); 908 } 909 finally { 910 doEndWork(IndyComponent.WorkMode.READ); 911 } 912 } 913 914 /*** 915 * Reads all data from the connection until disconnection occurs, 916 * and returns it as a <code>String</code> using the platform character 917 * encoding. 918 * 919 * This is equivalent to <code>allData(null)</code>. 920 * 921 * @return A string representing all read data from the connection 922 * @throws ReadTimedOutException If the read operation times out 923 * @throws IndyIOException If an IO error occurs 924 * @throws NotConnectedException If not connected 925 * @see allData(String) 926 */ 927 public String allData() throws ReadTimedOutException, IndyIOException, 928 NotConnectedException { 929 return allData(null); 930 } 931 932 /*** 933 * Reads all data from the connection until disconnection occurs, 934 * and returns it as a <code>String</code> using the character 935 * encoding specified by <code>encoding</code>, or the platform default 936 * if <code>encoding</code> is <code>null</code>. 937 * 938 * @param encoding The character encoding to use 939 * @return A string representing all read data from the connection 940 * @throws IndyIOException If an IO error occurs 941 * @throws ReadTimedOutException If the read operation times out 942 * @throws NotConnectedException If not connected 943 */ 944 public String allData(String encoding) throws IndyIOException, 945 ReadTimedOutException, 946 NotConnectedException { 947 try { 948 return (encoding == null) 949 ? new String(readTillDisconnect()) 950 : new String(readTillDisconnect(), encoding); 951 } 952 catch (UnsupportedEncodingException ex) { 953 throw new IndyIOException(ex); 954 } 955 } 956 957 /*** 958 * An interface that supports having lines of text input to it. 959 */ 960 protected interface Capturable { 961 void addLine(String s); 962 } 963 }

This page was automatically generated by Maven