Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  *
      8  *   - Redistributions of source code must retain the above copyright
      9  *     notice, this list of conditions and the following disclaimer.
     10  *
     11  *   - Redistributions in binary form must reproduce the above copyright
     12  *     notice, this list of conditions and the following disclaimer in the
     13  *     documentation and/or other materials provided with the distribution.
     14  *
     15  *   - Neither the name of Oracle nor the names of its
     16  *     contributors may be used to endorse or promote products derived
     17  *     from this software without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
     20  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 /*
     33  * This source code is provided to illustrate the usage of a given feature
     34  * or technique and has been deliberately simplified. Additional steps
     35  * required for a production-quality application, such as security checks,
     36  * input validation, and proper error handling, might not be present in
     37  * this sample code.
     38  */
     39 
     40 import java.io.BufferedOutputStream;
     41 import java.io.IOException;
     42 import java.io.OutputStream;
     43 import java.io.PrintStream;
     44 import java.nio.file.Files;
     45 import java.nio.file.Path;
     46 import java.nio.file.Paths;
     47 
     48 /**
     49  * This sample demonstrates the ability to create custom resource that
     50  * implements the {@code AutoCloseable} interface. This resource can be used in
     51  * the try-with-resources construct.
     52  */
     53 public class CustomAutoCloseableSample {
     54 
     55     /**
     56      * The main method for the CustomAutoCloseableSample program.
     57      *
     58      * @param args is not used.
     59      */
     60     public static void main(String[] args) {
     61         /*
     62          * TeeStream will be closed automatically after the try block.
     63          */
     64         try (TeeStream teeStream = new TeeStream(System.out, Paths.get("out.txt"));
     65              PrintStream out = new PrintStream(teeStream)) {
     66             out.print("Hello, world");
     67         } catch (Exception e) {
     68             e.printStackTrace();
     69             System.exit(1);
     70         }
     71     }
     72 
     73     /**
     74      * Passes the output through to the specified output stream while copying it into a file.
     75      * The TeeStream functionality is similar to the Unix tee utility.
     76      * TeeStream implements AutoCloseable interface. See OutputStream for details.
     77      */
     78     public static class TeeStream extends OutputStream {
     79 
     80         private final OutputStream fileStream;
     81         private final OutputStream outputStream;
     82 
     83         /**
     84          * Creates a TeeStream.
     85          *
     86          * @param outputStream an output stream.
     87          * @param outputFile   an path to file.
     88          * @throws IOException If an I/O error occurs.
     89          */
     90         public TeeStream(OutputStream outputStream, Path outputFile) throws IOException {
     91             this.fileStream = new BufferedOutputStream(Files.newOutputStream(outputFile));
     92             this.outputStream = outputStream;
     93         }
     94 
     95         /**
     96          * Writes the specified byte to the specified output stream
     97          * and copies it to the file.
     98          *
     99          * @param b the byte to be written.
    100          * @throws IOException If an I/O error occurs.
    101          */
    102         @Override
    103         public void write(int b) throws IOException {
    104             fileStream.write(b);
    105             outputStream.write(b);
    106         }
    107 
    108         /**
    109          * Flushes this output stream and forces any buffered output bytes
    110          * to be written out.
    111          * The <code>flush</code> method of <code>TeeStream</code> flushes
    112          * the specified output stream and the file output stream.
    113          *
    114          * @throws IOException if an I/O error occurs.
    115          */
    116         @Override
    117         public void flush() throws IOException {
    118             outputStream.flush();
    119             fileStream.flush();
    120         }
    121 
    122         /**
    123          * Closes underlying streams and resources.
    124          * The external output stream won't be closed.
    125          * This method is the member of AutoCloseable interface and
    126          * it will be invoked automatically after the try-with-resources block.
    127          *
    128          * @throws IOException If an I/O error occurs.
    129          */
    130         @Override
    131         public void close() throws IOException {
    132             try (OutputStream file = fileStream) {
    133                 flush();
    134             }
    135         }
    136     }
    137 }
    138