• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SourceSinkFactories()51   private SourceSinkFactories() {}
52 
stringCharSourceFactory()53   public static CharSourceFactory stringCharSourceFactory() {
54     return new StringSourceFactory();
55   }
56 
byteArraySourceFactory()57   public static ByteSourceFactory byteArraySourceFactory() {
58     return new ByteArraySourceFactory();
59   }
60 
emptyByteSourceFactory()61   public static ByteSourceFactory emptyByteSourceFactory() {
62     return new EmptyByteSourceFactory();
63   }
64 
emptyCharSourceFactory()65   public static CharSourceFactory emptyCharSourceFactory() {
66     return new EmptyCharSourceFactory();
67   }
68 
fileByteSourceFactory()69   public static ByteSourceFactory fileByteSourceFactory() {
70     return new FileByteSourceFactory();
71   }
72 
fileByteSinkFactory()73   public static ByteSinkFactory fileByteSinkFactory() {
74     return new FileByteSinkFactory(null);
75   }
76 
appendingFileByteSinkFactory()77   public static ByteSinkFactory appendingFileByteSinkFactory() {
78     String initialString = IoTestCase.ASCII + IoTestCase.I18N;
79     return new FileByteSinkFactory(initialString.getBytes(Charsets.UTF_8));
80   }
81 
fileCharSourceFactory()82   public static CharSourceFactory fileCharSourceFactory() {
83     return new FileCharSourceFactory();
84   }
85 
fileCharSinkFactory()86   public static CharSinkFactory fileCharSinkFactory() {
87     return new FileCharSinkFactory(null);
88   }
89 
appendingFileCharSinkFactory()90   public static CharSinkFactory appendingFileCharSinkFactory() {
91     String initialString = IoTestCase.ASCII + IoTestCase.I18N;
92     return new FileCharSinkFactory(initialString);
93   }
94 
urlByteSourceFactory()95   public static ByteSourceFactory urlByteSourceFactory() {
96     return new UrlByteSourceFactory();
97   }
98 
urlCharSourceFactory()99   public static CharSourceFactory urlCharSourceFactory() {
100     return new UrlCharSourceFactory();
101   }
102 
asCharSourceFactory(final ByteSourceFactory factory)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