Home | History | Annotate | Download | only in io
      1 /*
      2  * Copyright (C) 2012 The Guava Authors
      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 
     17 package com.google.common.io;
     18 
     19 import static com.google.common.base.Preconditions.checkNotNull;
     20 import static com.google.common.io.SourceSinkFactory.ByteSinkFactory;
     21 import static com.google.common.io.SourceSinkFactory.ByteSourceFactory;
     22 import static com.google.common.io.SourceSinkFactory.CharSinkFactory;
     23 import static com.google.common.io.SourceSinkFactory.CharSourceFactory;
     24 
     25 import com.google.common.base.Charsets;
     26 
     27 import java.io.ByteArrayOutputStream;
     28 import java.io.File;
     29 import java.io.FileInputStream;
     30 import java.io.FileOutputStream;
     31 import java.io.IOException;
     32 import java.io.InputStream;
     33 import java.io.InputStreamReader;
     34 import java.io.OutputStream;
     35 import java.io.OutputStreamWriter;
     36 import java.io.Reader;
     37 import java.io.Writer;
     38 import java.nio.CharBuffer;
     39 import java.util.Arrays;
     40 import java.util.logging.Logger;
     41 
     42 import javax.annotation.Nullable;
     43 
     44 /**
     45  * {@link SourceSinkFactory} implementations.
     46  *
     47  * @author Colin Decker
     48  */
     49 public class SourceSinkFactories {
     50 
     51   private SourceSinkFactories() {}
     52 
     53   public static CharSourceFactory stringCharSourceFactory() {
     54     return new StringSourceFactory();
     55   }
     56 
     57   public static ByteSourceFactory byteArraySourceFactory() {
     58     return new ByteArraySourceFactory();
     59   }
     60 
     61   public static ByteSourceFactory emptyByteSourceFactory() {
     62     return new EmptyByteSourceFactory();
     63   }
     64 
     65   public static CharSourceFactory emptyCharSourceFactory() {
     66     return new EmptyCharSourceFactory();
     67   }
     68 
     69   public static ByteSourceFactory fileByteSourceFactory() {
     70     return new FileByteSourceFactory();
     71   }
     72 
     73   public static ByteSinkFactory fileByteSinkFactory() {
     74     return new FileByteSinkFactory(null);
     75   }
     76 
     77   public static ByteSinkFactory appendingFileByteSinkFactory() {
     78     String initialString = IoTestCase.ASCII + IoTestCase.I18N;
     79     return new FileByteSinkFactory(initialString.getBytes(Charsets.UTF_8));
     80   }
     81 
     82   public static CharSourceFactory fileCharSourceFactory() {
     83     return new FileCharSourceFactory();
     84   }
     85 
     86   public static CharSinkFactory fileCharSinkFactory() {
     87     return new FileCharSinkFactory(null);
     88   }
     89 
     90   public static CharSinkFactory appendingFileCharSinkFactory() {
     91     String initialString = IoTestCase.ASCII + IoTestCase.I18N;
     92     return new FileCharSinkFactory(initialString);
     93   }
     94 
     95   public static ByteSourceFactory urlByteSourceFactory() {
     96     return new UrlByteSourceFactory();
     97   }
     98 
     99   public static CharSourceFactory urlCharSourceFactory() {
    100     return new UrlCharSourceFactory();
    101   }
    102 
    103   public static CharSourceFactory asCharSourceFactory(final ByteSourceFactory factory) {
    104     checkNotNull(factory);
    105     return new CharSourceFactory() {
    106       @Override
    107       public CharSource createSource(String string) throws IOException {
    108         return factory.createSource(string.getBytes(Charsets.UTF_8))
    109             .asCharSource(Charsets.UTF_8);
    110       }
    111 
    112       @Override
    113       public String getExpected(String data) {
    114         return new String(factory.getExpected(data.getBytes(Charsets.UTF_8)), Charsets.UTF_8);
    115       }
    116 
    117       @Override
    118       public void tearDown() throws IOException {
    119         factory.tearDown();
    120       }
    121     };
    122   }
    123 
    124   public static CharSinkFactory asCharSinkFactory(final ByteSinkFactory factory) {
    125     checkNotNull(factory);
    126     return new CharSinkFactory() {
    127       @Override
    128       public CharSink createSink() throws IOException {
    129         return factory.createSink().asCharSink(Charsets.UTF_8);
    130       }
    131 
    132       @Override
    133       public String getSinkContents() throws IOException {
    134         return new String(factory.getSinkContents(), Charsets.UTF_8);
    135       }
    136 
    137       @Override
    138       public String getExpected(String data) {
    139         /*
    140          * Get what the byte sink factory would expect for no written bytes, then append expected
    141          * string to that.
    142          */
    143         byte[] factoryExpectedForNothing = factory.getExpected(new byte[0]);
    144         return new String(factoryExpectedForNothing, Charsets.UTF_8) + checkNotNull(data);
    145       }
    146 
    147       @Override
    148       public void tearDown() throws IOException {
    149         factory.tearDown();
    150       }
    151     };
    152   }
    153 
    154   public static ByteSourceFactory asSlicedByteSourceFactory(final ByteSourceFactory factory,
    155       final int off, final int len) {
    156     checkNotNull(factory);
    157     return new ByteSourceFactory() {
    158       @Override
    159       public ByteSource createSource(byte[] bytes) throws IOException {
    160         return factory.createSource(bytes).slice(off, len);
    161       }
    162 
    163       @Override
    164       public byte[] getExpected(byte[] bytes) {
    165         byte[] baseExpected = factory.getExpected(bytes);
    166         return Arrays.copyOfRange(baseExpected, off, Math.min(baseExpected.length, off + len));
    167       }
    168 
    169       @Override
    170       public void tearDown() throws IOException {
    171         factory.tearDown();
    172       }
    173     };
    174   }
    175 
    176   private static class StringSourceFactory implements CharSourceFactory {
    177 
    178     @Override
    179     public CharSource createSource(String data) throws IOException {
    180       return CharSource.wrap(data);
    181     }
    182 
    183     @Override
    184     public String getExpected(String data) {
    185       return data;
    186     }
    187 
    188     @Override
    189     public void tearDown() throws IOException {
    190     }
    191   }
    192 
    193   private static class ByteArraySourceFactory implements ByteSourceFactory {
    194 
    195     @Override
    196     public ByteSource createSource(byte[] bytes) throws IOException {
    197       return ByteSource.wrap(bytes);
    198     }
    199 
    200     @Override
    201     public byte[] getExpected(byte[] bytes) {
    202       return bytes;
    203     }
    204 
    205     @Override
    206     public void tearDown() throws IOException {
    207     }
    208   }
    209 
    210   private static class EmptyCharSourceFactory implements CharSourceFactory {
    211 
    212     @Override
    213     public CharSource createSource(String data) throws IOException {
    214       return CharSource.empty();
    215     }
    216 
    217     @Override
    218     public String getExpected(String data) {
    219       return "";
    220     }
    221 
    222     @Override
    223     public void tearDown() throws IOException {
    224     }
    225   }
    226 
    227   private static class EmptyByteSourceFactory implements ByteSourceFactory {
    228 
    229     @Override
    230     public ByteSource createSource(byte[] bytes) throws IOException {
    231       return ByteSource.empty();
    232     }
    233 
    234     @Override
    235     public byte[] getExpected(byte[] bytes) {
    236       return new byte[0];
    237     }
    238 
    239     @Override
    240     public void tearDown() throws IOException {
    241     }
    242   }
    243 
    244   private abstract static class FileFactory {
    245 
    246     private static final Logger logger = Logger.getLogger(FileFactory.class.getName());
    247 
    248     private final ThreadLocal<File> fileThreadLocal = new ThreadLocal<File>();
    249 
    250     protected File createFile() throws IOException {
    251       File file = File.createTempFile("SinkSourceFile", "txt");
    252       fileThreadLocal.set(file);
    253       return file;
    254     }
    255 
    256     protected File getFile() {
    257       return fileThreadLocal.get();
    258     }
    259 
    260     public final void tearDown() throws IOException {
    261       if (!fileThreadLocal.get().delete()) {
    262         logger.warning("Unable to delete file: " + fileThreadLocal.get());
    263       }
    264       fileThreadLocal.remove();
    265     }
    266   }
    267 
    268   private static class FileByteSourceFactory extends FileFactory implements ByteSourceFactory {
    269 
    270     @Override
    271     public ByteSource createSource(byte[] bytes) throws IOException {
    272       checkNotNull(bytes);
    273       File file = createFile();
    274       OutputStream out = new FileOutputStream(file);
    275       try {
    276         out.write(bytes);
    277       } finally {
    278         out.close();
    279       }
    280       return Files.asByteSource(file);
    281     }
    282 
    283     @Override
    284     public byte[] getExpected(byte[] bytes) {
    285       return checkNotNull(bytes);
    286     }
    287   }
    288 
    289   private static class FileByteSinkFactory extends FileFactory implements ByteSinkFactory {
    290 
    291     private final byte[] initialBytes;
    292 
    293     private FileByteSinkFactory(@Nullable byte[] initialBytes) {
    294       this.initialBytes = initialBytes;
    295     }
    296 
    297     @Override
    298     public ByteSink createSink() throws IOException {
    299       File file = createFile();
    300       if (initialBytes != null) {
    301         FileOutputStream out = new FileOutputStream(file);
    302         try {
    303           out.write(initialBytes);
    304         } finally {
    305           out.close();
    306         }
    307         return Files.asByteSink(file, FileWriteMode.APPEND);
    308       }
    309       return Files.asByteSink(file);
    310     }
    311 
    312     @Override
    313     public byte[] getExpected(byte[] bytes) {
    314       if (initialBytes == null) {
    315         return checkNotNull(bytes);
    316       } else {
    317         byte[] result = new byte[initialBytes.length + bytes.length];
    318         System.arraycopy(initialBytes, 0, result, 0, initialBytes.length);
    319         System.arraycopy(bytes, 0, result, initialBytes.length, bytes.length);
    320         return result;
    321       }
    322     }
    323 
    324     @Override
    325     public byte[] getSinkContents() throws IOException {
    326       File file = getFile();
    327       InputStream in = new FileInputStream(file);
    328       ByteArrayOutputStream out = new ByteArrayOutputStream();
    329       byte[] buffer = new byte[100];
    330       int read;
    331       while ((read = in.read(buffer)) != -1) {
    332         out.write(buffer, 0, read);
    333       }
    334       return out.toByteArray();
    335     }
    336   }
    337 
    338   private static class FileCharSourceFactory extends FileFactory implements CharSourceFactory {
    339 
    340     @Override
    341     public CharSource createSource(String string) throws IOException {
    342       checkNotNull(string);
    343       File file = createFile();
    344       Writer writer = new OutputStreamWriter(new FileOutputStream(file), Charsets.UTF_8);
    345       try {
    346         writer.write(string);
    347       } finally {
    348         writer.close();
    349       }
    350       return Files.asCharSource(file, Charsets.UTF_8);
    351     }
    352 
    353     @Override
    354     public String getExpected(String string) {
    355       return checkNotNull(string);
    356     }
    357   }
    358 
    359   private static class FileCharSinkFactory extends FileFactory implements CharSinkFactory {
    360 
    361     private final String initialString;
    362 
    363     private FileCharSinkFactory(@Nullable String initialString) {
    364       this.initialString = initialString;
    365     }
    366 
    367     @Override
    368     public CharSink createSink() throws IOException {
    369       File file = createFile();
    370       if (initialString != null) {
    371         Writer writer = new OutputStreamWriter(new FileOutputStream(file), Charsets.UTF_8);
    372         try {
    373           writer.write(initialString);
    374         } finally {
    375           writer.close();
    376         }
    377         return Files.asCharSink(file, Charsets.UTF_8, FileWriteMode.APPEND);
    378       }
    379       return Files.asCharSink(file, Charsets.UTF_8);
    380     }
    381 
    382     @Override
    383     public String getExpected(String string) {
    384       checkNotNull(string);
    385       return initialString == null
    386           ? string
    387           : initialString + string;
    388     }
    389 
    390     @Override
    391     public String getSinkContents() throws IOException {
    392       File file = getFile();
    393       Reader reader = new InputStreamReader(new FileInputStream(file), Charsets.UTF_8);
    394       StringBuilder builder = new StringBuilder();
    395       CharBuffer buffer = CharBuffer.allocate(100);
    396       while (reader.read(buffer) != -1) {
    397         buffer.flip();
    398         builder.append(buffer);
    399         buffer.clear();
    400       }
    401       return builder.toString();
    402     }
    403   }
    404 
    405   private static class UrlByteSourceFactory extends FileByteSourceFactory {
    406 
    407     @Override
    408     public ByteSource createSource(byte[] bytes) throws IOException {
    409       super.createSource(bytes);
    410       return Resources.asByteSource(getFile().toURI().toURL());
    411     }
    412   }
    413 
    414   private static class UrlCharSourceFactory extends FileCharSourceFactory {
    415 
    416     @Override
    417     public CharSource createSource(String string) throws IOException {
    418       super.createSource(string); // just ignore returned CharSource
    419       return Resources.asCharSource(getFile().toURI().toURL(), Charsets.UTF_8);
    420     }
    421   }
    422 }
    423