1 /* 2 * Hunt - A refined core library for D programming language. 3 * 4 * Copyright (C) 2018-2019 HuntLabs 5 * 6 * Website: https://www.huntlabs.net/ 7 * 8 * Licensed under the Apache-2.0 License. 9 * 10 */ 11 12 module hunt.io.Common; 13 14 import hunt.collection.ByteBuffer; 15 import hunt.Exceptions; 16 import hunt.util.Common; 17 import hunt.logging; 18 import hunt.concurrency.CountingCallback; 19 20 import std.algorithm; 21 22 23 /** 24 * Serializability of a class is enabled by the class implementing the 25 * java.io.Serializable interface. 26 * 27 * <p><strong>Warning: Deserialization of untrusted data is inherently dangerous 28 * and should be avoided. Untrusted data should be carefully validated according to the 29 * "Serialization and Deserialization" section of the 30 * {@extLink secure_coding_guidelines_javase Secure Coding Guidelines for Java SE}. 31 * {@extLink serialization_filter_guide Serialization Filtering} describes best 32 * practices for defensive use of serial filters. 33 * </strong></p> 34 * 35 * Classes that do not implement this 36 * interface will not have any of their state serialized or 37 * deserialized. All subtypes of a serializable class are themselves 38 * serializable. The serialization interface has no methods or fields 39 * and serves only to identify the semantics of being serializable. <p> 40 * 41 * To allow subtypes of non-serializable classes to be serialized, the 42 * subtype may assume responsibility for saving and restoring the 43 * state of the supertype's public, protected, and (if accessible) 44 * package fields. The subtype may assume this responsibility only if 45 * the class it extends has an accessible no-arg constructor to 46 * initialize the class's state. It is an error to declare a class 47 * Serializable if this is not the case. The error will be detected at 48 * runtime. <p> 49 * 50 * During deserialization, the fields of non-serializable classes will 51 * be initialized using the public or protected no-arg constructor of 52 * the class. A no-arg constructor must be accessible to the subclass 53 * that is serializable. The fields of serializable subclasses will 54 * be restored from the stream. <p> 55 * 56 * When traversing a graph, an object may be encountered that does not 57 * support the Serializable interface. In this case the 58 * NotSerializableException will be thrown and will identify the class 59 * of the non-serializable object. <p> 60 * 61 * Classes that require special handling during the serialization and 62 * deserialization process must implement special methods with these exact 63 * signatures: 64 * 65 * <PRE> 66 * private void writeObject(java.io.ObjectOutputStream out) 67 * throws IOException 68 * private void readObject(java.io.ObjectInputStream in) 69 * throws IOException, ClassNotFoundException; 70 * private void readObjectNoData() 71 * throws ObjectStreamException; 72 * </PRE> 73 * 74 * <p>The writeObject method is responsible for writing the state of the 75 * object for its particular class so that the corresponding 76 * readObject method can restore it. The default mechanism for saving 77 * the Object's fields can be invoked by calling 78 * out.defaultWriteObject. The method does not need to concern 79 * itself with the state belonging to its superclasses or subclasses. 80 * State is saved by writing the individual fields to the 81 * ObjectOutputStream using the writeObject method or by using the 82 * methods for primitive data types supported by DataOutput. 83 * 84 * <p>The readObject method is responsible for reading from the stream and 85 * restoring the classes fields. It may call in.defaultReadObject to invoke 86 * the default mechanism for restoring the object's non-static and 87 * non-transient fields. The defaultReadObject method uses information in 88 * the stream to assign the fields of the object saved in the stream with the 89 * correspondingly named fields in the current object. This handles the case 90 * when the class has evolved to add new fields. The method does not need to 91 * concern itself with the state belonging to its superclasses or subclasses. 92 * State is restored by reading data from the ObjectInputStream for 93 * the individual fields and making assignments to the appropriate fields 94 * of the object. Reading primitive data types is supported by DataInput. 95 * 96 * <p>The readObjectNoData method is responsible for initializing the state of 97 * the object for its particular class in the event that the serialization 98 * stream does not list the given class as a superclass of the object being 99 * deserialized. This may occur in cases where the receiving party uses a 100 * different version of the deserialized instance's class than the sending 101 * party, and the receiver's version extends classes that are not extended by 102 * the sender's version. This may also occur if the serialization stream has 103 * been tampered; hence, readObjectNoData is useful for initializing 104 * deserialized objects properly despite a "hostile" or incomplete source 105 * stream. 106 * 107 * <p>Serializable classes that need to designate an alternative object to be 108 * used when writing an object to the stream should implement this 109 * special method with the exact signature: 110 * 111 * <PRE> 112 * ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException; 113 * </PRE><p> 114 * 115 * This writeReplace method is invoked by serialization if the method 116 * exists and it would be accessible from a method defined within the 117 * class of the object being serialized. Thus, the method can have private, 118 * protected and package-private access. Subclass access to this method 119 * follows java accessibility rules. <p> 120 * 121 * Classes that need to designate a replacement when an instance of it 122 * is read from the stream should implement this special method with the 123 * exact signature. 124 * 125 * <PRE> 126 * ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException; 127 * </PRE><p> 128 * 129 * This readResolve method follows the same invocation rules and 130 * accessibility rules as writeReplace.<p> 131 * 132 * The serialization runtime associates with each serializable class a version 133 * number, called a serialVersionUID, which is used during deserialization to 134 * verify that the sender and receiver of a serialized object have loaded 135 * classes for that object that are compatible with respect to serialization. 136 * If the receiver has loaded a class for the object that has a different 137 * serialVersionUID than that of the corresponding sender's class, then 138 * deserialization will result in an {@link InvalidClassException}. A 139 * serializable class can declare its own serialVersionUID explicitly by 140 * declaring a field named <code>"serialVersionUID"</code> that must be static, 141 * final, and of type <code>long</code>: 142 * 143 * <PRE> 144 * ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L; 145 * </PRE> 146 * 147 * If a serializable class does not explicitly declare a serialVersionUID, then 148 * the serialization runtime will calculate a default serialVersionUID value 149 * for that class based on various aspects of the class, as described in the 150 * Java(TM) Object Serialization Specification. However, it is <em>strongly 151 * recommended</em> that all serializable classes explicitly declare 152 * serialVersionUID values, since the default serialVersionUID computation is 153 * highly sensitive to class details that may vary depending on compiler 154 * implementations, and can thus result in unexpected 155 * <code>InvalidClassException</code>s during deserialization. Therefore, to 156 * guarantee a consistent serialVersionUID value across different java compiler 157 * implementations, a serializable class must declare an explicit 158 * serialVersionUID value. It is also strongly advised that explicit 159 * serialVersionUID declarations use the <code>private</code> modifier where 160 * possible, since such declarations apply only to the immediately declaring 161 * class--serialVersionUID fields are not useful as inherited members. Array 162 * classes cannot declare an explicit serialVersionUID, so they always have 163 * the default computed value, but the requirement for matching 164 * serialVersionUID values is waived for array classes. 165 * 166 */ 167 interface Serializable { 168 169 } 170 171 /** 172 * This abstract class is the superclass of all classes representing 173 * an input stream of bytes. 174 * 175 * <p> Applications that need to define a subclass of <code>InputStream</code> 176 * must always provide a method that returns the next byte of input. 177 * 178 * @author Arthur van Hoff 179 * @see java.io.BufferedInputStream 180 * @see java.io.ByteArrayInputStream 181 * @see java.io.DataInputStream 182 * @see java.io.FilterInputStream 183 * @see java.io.InputStream#read() 184 * @see java.io.OutputStream 185 * @see java.io.PushbackInputStream 186 * @since JDK1.0 187 */ 188 abstract class InputStream : Closeable { 189 190 // MAX_SKIP_BUFFER_SIZE is used to determine the maximum buffer size to 191 // use when skipping. 192 private enum int MAX_SKIP_BUFFER_SIZE = 2048; 193 194 /** 195 * Reads the next byte of data from the input stream. The value byte is 196 * returned as an <code>int</code> in the range <code>0</code> to 197 * <code>255</code>. If no byte is available because the end of the stream 198 * has been reached, the value <code>-1</code> is returned. This method 199 * blocks until input data is available, the end of the stream is detected, 200 * or an exception is thrown. 201 * 202 * <p> A subclass must provide an implementation of this method. 203 * 204 * @return the next byte of data, or <code>-1</code> if the end of the 205 * stream is reached. 206 * @exception IOException if an I/O error occurs. 207 */ 208 abstract int read(); 209 210 /** 211 * Reads some number of bytes from the input stream and stores them into 212 * the buffer array <code>b</code>. The number of bytes actually read is 213 * returned as an integer. This method blocks until input data is 214 * available, end of file is detected, or an exception is thrown. 215 * 216 * <p> If the length of <code>b</code> is zero, then no bytes are read and 217 * <code>0</code> is returned; otherwise, there is an attempt to read at 218 * least one byte. If no byte is available because the stream is at the 219 * end of the file, the value <code>-1</code> is returned; otherwise, at 220 * least one byte is read and stored into <code>b</code>. 221 * 222 * <p> The first byte read is stored into element <code>b[0]</code>, the 223 * next one into <code>b[1]</code>, and so on. The number of bytes read is, 224 * at most, equal to the length of <code>b</code>. Let <i>k</i> be the 225 * number of bytes actually read; these bytes will be stored in elements 226 * <code>b[0]</code> through <code>b[</code><i>k</i><code>-1]</code>, 227 * leaving elements <code>b[</code><i>k</i><code>]</code> through 228 * <code>b[b.length-1]</code> unaffected. 229 * 230 * <p> The <code>read(b)</code> method for class <code>InputStream</code> 231 * has the same effect as: <pre><code> read(b, 0, b.length) </code></pre> 232 * 233 * @param b the buffer into which the data is read. 234 * @return the total number of bytes read into the buffer, or 235 * <code>-1</code> if there is no more data because the end of 236 * the stream has been reached. 237 * @exception IOException If the first byte cannot be read for any reason 238 * other than the end of the file, if the input stream has been closed, or 239 * if some other I/O error occurs. 240 * @exception NullPointerException if <code>b</code> is <code>null</code>. 241 * @see java.io.InputStream#read(byte[], int, int) 242 */ 243 int read(byte[] b) { 244 return read(b, 0, cast(int)b.length); 245 } 246 247 /** 248 * Reads up to <code>len</code> bytes of data from the input stream into 249 * an array of bytes. An attempt is made to read as many as 250 * <code>len</code> bytes, but a smaller number may be read. 251 * The number of bytes actually read is returned as an integer. 252 * 253 * <p> This method blocks until input data is available, end of file is 254 * detected, or an exception is thrown. 255 * 256 * <p> If <code>len</code> is zero, then no bytes are read and 257 * <code>0</code> is returned; otherwise, there is an attempt to read at 258 * least one byte. If no byte is available because the stream is at end of 259 * file, the value <code>-1</code> is returned; otherwise, at least one 260 * byte is read and stored into <code>b</code>. 261 * 262 * <p> The first byte read is stored into element <code>b[off]</code>, the 263 * next one into <code>b[off+1]</code>, and so on. The number of bytes read 264 * is, at most, equal to <code>len</code>. Let <i>k</i> be the number of 265 * bytes actually read; these bytes will be stored in elements 266 * <code>b[off]</code> through <code>b[off+</code><i>k</i><code>-1]</code>, 267 * leaving elements <code>b[off+</code><i>k</i><code>]</code> through 268 * <code>b[off+len-1]</code> unaffected. 269 * 270 * <p> In every case, elements <code>b[0]</code> through 271 * <code>b[off]</code> and elements <code>b[off+len]</code> through 272 * <code>b[b.length-1]</code> are unaffected. 273 * 274 * <p> The <code>read(b,</code> <code>off,</code> <code>len)</code> method 275 * for class <code>InputStream</code> simply calls the method 276 * <code>read()</code> repeatedly. If the first such call results in an 277 * <code>IOException</code>, that exception is returned from the call to 278 * the <code>read(b,</code> <code>off,</code> <code>len)</code> method. If 279 * any subsequent call to <code>read()</code> results in a 280 * <code>IOException</code>, the exception is caught and treated as if it 281 * were end of file; the bytes read up to that point are stored into 282 * <code>b</code> and the number of bytes read before the exception 283 * occurred is returned. The default implementation of this method blocks 284 * until the requested amount of input data <code>len</code> has been read, 285 * end of file is detected, or an exception is thrown. Subclasses are encouraged 286 * to provide a more efficient implementation of this method. 287 * 288 * @param b the buffer into which the data is read. 289 * @param off the start offset in array <code>b</code> 290 * at which the data is written. 291 * @param len the maximum number of bytes to read. 292 * @return the total number of bytes read into the buffer, or 293 * <code>-1</code> if there is no more data because the end of 294 * the stream has been reached. 295 * @exception IOException If the first byte cannot be read for any reason 296 * other than end of file, or if the input stream has been closed, or if 297 * some other I/O error occurs. 298 * @exception NullPointerException If <code>b</code> is <code>null</code>. 299 * @exception IndexOutOfBoundsException If <code>off</code> is negative, 300 * <code>len</code> is negative, or <code>len</code> is greater than 301 * <code>b.length - off</code> 302 * @see java.io.InputStream#read() 303 */ 304 int read(byte[] b, int off, int len) { 305 if (b is null) { 306 throw new NullPointerException(""); 307 } else if (off < 0 || len < 0 || len > b.length - off) { 308 throw new IndexOutOfBoundsException(""); 309 } else if (len == 0) { 310 return 0; 311 } 312 313 int c = read(); 314 if (c == -1) { 315 return -1; 316 } 317 b[off] = cast(byte)c; 318 319 int i = 1; 320 try { 321 for (; i < len ; i++) { 322 c = read(); 323 if (c == -1) { 324 break; 325 } 326 b[off + i] = cast(byte)c; 327 } 328 } catch (IOException ee) { 329 } 330 return i; 331 } 332 333 /** 334 * Skips over and discards <code>n</code> bytes of data from this input 335 * stream. The <code>skip</code> method may, for a variety of reasons, end 336 * up skipping over some smaller number of bytes, possibly <code>0</code>. 337 * This may result from any of a number of conditions; reaching end of file 338 * before <code>n</code> bytes have been skipped is only one possibility. 339 * The actual number of bytes skipped is returned. If {@code n} is 340 * negative, the {@code skip} method for class {@code InputStream} always 341 * returns 0, and no bytes are skipped. Subclasses may handle the negative 342 * value differently. 343 * 344 * <p> The <code>skip</code> method of this class creates a 345 * byte array and then repeatedly reads into it until <code>n</code> bytes 346 * have been read or the end of the stream has been reached. Subclasses are 347 * encouraged to provide a more efficient implementation of this method. 348 * For instance, the implementation may depend on the ability to seek. 349 * 350 * @param n the number of bytes to be skipped. 351 * @return the actual number of bytes skipped. 352 * @exception IOException if the stream does not support seek, 353 * or if some other I/O error occurs. 354 */ 355 long skip(long n) { 356 long remaining = n; 357 int nr; 358 359 if (n <= 0) { 360 return 0; 361 } 362 363 int size = cast(int)min(MAX_SKIP_BUFFER_SIZE, remaining); 364 byte[] skipBuffer = new byte[size]; 365 while (remaining > 0) { 366 nr = read(skipBuffer, 0, cast(int)min(size, remaining)); 367 if (nr < 0) { 368 break; 369 } 370 remaining -= nr; 371 } 372 373 return n - remaining; 374 } 375 376 /** 377 * Returns an estimate of the number of bytes that can be read (or 378 * skipped over) from this input stream without blocking by the next 379 * invocation of a method for this input stream. The next invocation 380 * might be the same thread or another thread. A single read or skip of this 381 * many bytes will not block, but may read or skip fewer bytes. 382 * 383 * <p> Note that while some implementations of {@code InputStream} will return 384 * the total number of bytes in the stream, many will not. It is 385 * never correct to use the return value of this method to allocate 386 * a buffer intended to hold all data in this stream. 387 * 388 * <p> A subclass' implementation of this method may choose to throw an 389 * {@link IOException} if this input stream has been closed by 390 * invoking the {@link #close()} method. 391 * 392 * <p> The {@code available} method for class {@code InputStream} always 393 * returns {@code 0}. 394 * 395 * <p> This method should be overridden by subclasses. 396 * 397 * @return an estimate of the number of bytes that can be read (or skipped 398 * over) from this input stream without blocking or {@code 0} when 399 * it reaches the end of the input stream. 400 * @exception IOException if an I/O error occurs. 401 */ 402 int available() { // @trusted nothrow 403 return 0; 404 } 405 406 /** 407 * Closes this input stream and releases any system resources associated 408 * with the stream. 409 * 410 * <p> The <code>close</code> method of <code>InputStream</code> does 411 * nothing. 412 * 413 * @exception IOException if an I/O error occurs. 414 */ 415 void close() {} 416 417 /** 418 * Marks the current position in this input stream. A subsequent call to 419 * the <code>reset</code> method repositions this stream at the last marked 420 * position so that subsequent reads re-read the same bytes. 421 * 422 * <p> The <code>readlimit</code> arguments tells this input stream to 423 * allow that many bytes to be read before the mark position gets 424 * invalidated. 425 * 426 * <p> The general contract of <code>mark</code> is that, if the method 427 * <code>markSupported</code> returns <code>true</code>, the stream somehow 428 * remembers all the bytes read after the call to <code>mark</code> and 429 * stands ready to supply those same bytes again if and whenever the method 430 * <code>reset</code> is called. However, the stream is not required to 431 * remember any data at all if more than <code>readlimit</code> bytes are 432 * read from the stream before <code>reset</code> is called. 433 * 434 * <p> Marking a closed stream should not have any effect on the stream. 435 * 436 * <p> The <code>mark</code> method of <code>InputStream</code> does 437 * nothing. 438 * 439 * @param readlimit the maximum limit of bytes that can be read before 440 * the mark position becomes invalid. 441 * @see java.io.InputStream#reset() 442 */ 443 void mark(int readlimit) {} 444 445 /** 446 * Repositions this stream to the position at the time the 447 * <code>mark</code> method was last called on this input stream. 448 * 449 * <p> The general contract of <code>reset</code> is: 450 * 451 * <ul> 452 * <li> If the method <code>markSupported</code> returns 453 * <code>true</code>, then: 454 * 455 * <ul><li> If the method <code>mark</code> has not been called since 456 * the stream was created, or the number of bytes read from the stream 457 * since <code>mark</code> was last called is larger than the argument 458 * to <code>mark</code> at that last call, then an 459 * <code>IOException</code> might be thrown. 460 * 461 * <li> If such an <code>IOException</code> is not thrown, then the 462 * stream is reset to a state such that all the bytes read since the 463 * most recent call to <code>mark</code> (or since the start of the 464 * file, if <code>mark</code> has not been called) will be resupplied 465 * to subsequent callers of the <code>read</code> method, followed by 466 * any bytes that otherwise would have been the next input data as of 467 * the time of the call to <code>reset</code>. </ul> 468 * 469 * <li> If the method <code>markSupported</code> returns 470 * <code>false</code>, then: 471 * 472 * <ul><li> The call to <code>reset</code> may throw an 473 * <code>IOException</code>. 474 * 475 * <li> If an <code>IOException</code> is not thrown, then the stream 476 * is reset to a fixed state that depends on the particular type of the 477 * input stream and how it was created. The bytes that will be supplied 478 * to subsequent callers of the <code>read</code> method depend on the 479 * particular type of the input stream. </ul></ul> 480 * 481 * <p>The method <code>reset</code> for class <code>InputStream</code> 482 * does nothing except throw an <code>IOException</code>. 483 * 484 * @exception IOException if this stream has not been marked or if the 485 * mark has been invalidated. 486 * @see java.io.InputStream#mark(int) 487 * @see java.io.IOException 488 */ 489 void reset() { 490 throw new IOException("mark/reset not supported"); 491 } 492 493 /** 494 * Tests if this input stream supports the <code>mark</code> and 495 * <code>reset</code> methods. Whether or not <code>mark</code> and 496 * <code>reset</code> are supported is an invariant property of a 497 * particular input stream instance. The <code>markSupported</code> method 498 * of <code>InputStream</code> returns <code>false</code>. 499 * 500 * @return <code>true</code> if this stream instance supports the mark 501 * and reset methods; <code>false</code> otherwise. 502 * @see java.io.InputStream#mark(int) 503 * @see java.io.InputStream#reset() 504 */ 505 bool markSupported() { 506 return false; 507 } 508 509 } 510 511 512 /** 513 * This abstract class is the superclass of all classes representing 514 * an output stream of bytes. An output stream accepts output bytes 515 * and sends them to some sink. 516 * <p> 517 * Applications that need to define a subclass of 518 * <code>OutputStream</code> must always provide at least a method 519 * that writes one byte of output. 520 * 521 * @author Arthur van Hoff 522 * @see java.io.BufferedOutputStream 523 * @see java.io.ByteArrayOutputStream 524 * @see java.io.DataOutputStream 525 * @see java.io.FilterOutputStream 526 * @see java.io.InputStream 527 * @see java.io.OutputStream#write(int) 528 * @since JDK1.0 529 */ 530 abstract class OutputStream : Closeable { // implements Flushable 531 /** 532 * Writes the specified byte to this output stream. The general 533 * contract for <code>write</code> is that one byte is written 534 * to the output stream. The byte to be written is the eight 535 * low-order bits of the argument <code>b</code>. The 24 536 * high-order bits of <code>b</code> are ignored. 537 * <p> 538 * Subclasses of <code>OutputStream</code> must provide an 539 * implementation for this method. 540 * 541 * @param b the <code>byte</code>. 542 * @exception IOException if an I/O error occurs. In particular, 543 * an <code>IOException</code> may be thrown if the 544 * output stream has been closed. 545 */ 546 abstract void write(int b) ; 547 548 void write(string b) { 549 write(cast(byte[])b, 0, cast(int)b.length); 550 } 551 552 /** 553 * Writes <code>b.length</code> bytes from the specified byte array 554 * to this output stream. The general contract for <code>write(b)</code> 555 * is that it should have exactly the same effect as the call 556 * <code>write(b, 0, b.length)</code>. 557 * 558 * @param b the data. 559 * @exception IOException if an I/O error occurs. 560 * @see java.io.OutputStream#write(byte[], int, int) 561 */ 562 void write(byte[] b) { 563 write(b, 0, cast(int)b.length); 564 } 565 566 /** 567 * Writes <code>len</code> bytes from the specified byte array 568 * starting at offset <code>off</code> to this output stream. 569 * The general contract for <code>write(b, off, len)</code> is that 570 * some of the bytes in the array <code>b</code> are written to the 571 * output stream in order; element <code>b[off]</code> is the first 572 * byte written and <code>b[off+len-1]</code> is the last byte written 573 * by this operation. 574 * <p> 575 * The <code>write</code> method of <code>OutputStream</code> calls 576 * the write method of one argument on each of the bytes to be 577 * written out. Subclasses are encouraged to override this method and 578 * provide a more efficient implementation. 579 * <p> 580 * If <code>b</code> is <code>null</code>, a 581 * <code>NullPointerException</code> is thrown. 582 * <p> 583 * If <code>off</code> is negative, or <code>len</code> is negative, or 584 * <code>off+len</code> is greater than the length of the array 585 * <code>b</code>, then an <tt>IndexOutOfBoundsException</tt> is thrown. 586 * 587 * @param b the data. 588 * @param off the start offset in the data. 589 * @param len the number of bytes to write. 590 * @exception IOException if an I/O error occurs. In particular, 591 * an <code>IOException</code> is thrown if the output 592 * stream is closed. 593 */ 594 void write(byte[] b, int off, int len) { 595 int bufferSize = cast(int)b.length; 596 if (b is null) { 597 throw new NullPointerException(""); 598 } else if ((off < 0) || (off > bufferSize) || (len < 0) || 599 ((off + len) > bufferSize) || ((off + len) < 0)) { 600 import std.format; 601 string msg = format("buffer error, size: %d, offset: %d, length: %d", 602 bufferSize, off, len); 603 throw new IndexOutOfBoundsException(msg); 604 } else if (len == 0) { 605 return; 606 } 607 for (int i = 0 ; i < len ; i++) { 608 write(b[off + i]); 609 } 610 } 611 612 /** 613 * Flushes this output stream and forces any buffered output bytes 614 * to be written out. The general contract of <code>flush</code> is 615 * that calling it is an indication that, if any bytes previously 616 * written have been buffered by the implementation of the output 617 * stream, such bytes should immediately be written to their 618 * intended destination. 619 * <p> 620 * If the intended destination of this stream is an abstraction provided by 621 * the underlying operating system, for example a file, then flushing the 622 * stream guarantees only that bytes previously written to the stream are 623 * passed to the operating system for writing; it does not guarantee that 624 * they are actually written to a physical device such as a disk drive. 625 * <p> 626 * The <code>flush</code> method of <code>OutputStream</code> does nothing. 627 * 628 * @exception IOException if an I/O error occurs. 629 */ 630 void flush() { 631 } 632 633 /** 634 * Closes this output stream and releases any system resources 635 * associated with this stream. The general contract of <code>close</code> 636 * is that it closes the output stream. A closed stream cannot perform 637 * output operations and cannot be reopened. 638 * <p> 639 * The <code>close</code> method of <code>OutputStream</code> does nothing. 640 * 641 * @exception IOException if an I/O error occurs. 642 */ 643 void close() { 644 } 645 646 } 647 648 /** 649 * IO Utilities. Provides stream handling utilities in singleton Threadpool 650 * implementation accessed by static members. 651 */ 652 // class IO { 653 654 // enum string CRLF = "\015\012"; 655 656 // enum byte[] CRLF_BYTES = [ '\015', '\012' ]; 657 658 // enum int bufferSize = 64 * 1024; 659 660 // /** 661 // * Closes an arbitrary closable, and logs exceptions at ignore level 662 // * 663 // * @param closeable 664 // * the closeable to close 665 // */ 666 // static void close(Closeable closeable) { 667 // try { 668 // if (closeable !is null) 669 // closeable.close(); 670 // } catch (IOException ignore) { 671 // } 672 // } 673 // } 674 675 676 interface BufferReaderHandler { 677 void readBuffer(ByteBuffer buf, CountingCallback countingCallback, long count); 678 }