1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.opencastproject.util;
23
24 import static org.opencastproject.util.PathSupport.path;
25 import static org.opencastproject.util.data.Either.left;
26 import static org.opencastproject.util.data.Either.right;
27 import static org.opencastproject.util.data.functions.Misc.chuck;
28
29 import org.opencastproject.security.api.TrustedHttpClient;
30 import org.opencastproject.security.api.TrustedHttpClientException;
31 import org.opencastproject.util.data.Either;
32
33 import com.google.common.io.Resources;
34
35 import org.apache.commons.io.IOUtils;
36 import org.apache.http.HttpResponse;
37 import org.apache.http.client.methods.HttpGet;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 import java.io.ByteArrayInputStream;
42 import java.io.ByteArrayOutputStream;
43 import java.io.Closeable;
44 import java.io.DataInputStream;
45 import java.io.File;
46 import java.io.FileInputStream;
47 import java.io.FileNotFoundException;
48 import java.io.IOException;
49 import java.io.InputStream;
50 import java.io.ObjectInputStream;
51 import java.io.ObjectOutputStream;
52 import java.io.RandomAccessFile;
53 import java.io.Serializable;
54 import java.net.URISyntaxException;
55 import java.net.URL;
56 import java.nio.channels.FileLock;
57 import java.nio.charset.Charset;
58 import java.util.Optional;
59 import java.util.Properties;
60 import java.util.function.BiFunction;
61 import java.util.function.Function;
62 import java.util.function.Supplier;
63
64 import de.schlichtherle.io.FileWriter;
65
66
67
68
69 public final class IoSupport {
70
71
72
73
74 private static Logger logger = LoggerFactory.getLogger(IoSupport.class.getName());
75
76 public static String getSystemTmpDir() {
77 String tmpdir = System.getProperty("java.io.tmpdir");
78 if (tmpdir == null) {
79 tmpdir = File.separator + "tmp" + File.separator;
80 } else {
81 if (!tmpdir.endsWith(File.separator)) {
82 tmpdir += File.separator;
83 }
84 }
85 return tmpdir;
86 }
87
88 private IoSupport() {
89 }
90
91
92
93
94
95
96
97 public static boolean closeQuietly(final Closeable s) {
98 if (s == null) {
99 return false;
100 }
101 try {
102 s.close();
103 return true;
104 } catch (IOException e) {
105 return false;
106 }
107 }
108
109
110
111
112
113
114
115
116 public static boolean closeQuietly(final Process process) {
117 if (process != null) {
118 closeQuietly(process.getInputStream());
119 closeQuietly(process.getErrorStream());
120 closeQuietly(process.getOutputStream());
121 return true;
122 }
123 return false;
124 }
125
126
127
128
129
130
131
132
133
134
135 public static void writeUTF8File(URL file, String contents) throws IOException {
136 try {
137 writeUTF8File(new File(file.toURI()), contents);
138 } catch (URISyntaxException e) {
139 throw new IOException("Couldn't parse the URL", e);
140 }
141 }
142
143
144
145
146
147
148
149
150
151 public static void writeUTF8File(File file, String contents) throws IOException {
152 writeUTF8File(file.getAbsolutePath(), contents);
153 }
154
155
156
157
158
159
160
161
162
163 public static void writeUTF8File(String filename, String contents) throws IOException {
164 FileWriter out = new FileWriter(filename);
165 try {
166 out.write(contents);
167 } finally {
168 closeQuietly(out);
169 }
170 }
171
172
173
174
175
176
177
178
179
180 @Deprecated
181 public static String readFileFromURL(URL url) {
182 return readFileFromURL(url, null);
183 }
184
185
186
187
188
189
190
191
192
193
194
195
196 @Deprecated
197 public static String readFileFromURL(URL url, TrustedHttpClient trustedClient) {
198 StringBuilder sb = new StringBuilder();
199 DataInputStream in = null;
200 HttpResponse response = null;
201 try {
202
203 if ("file".equals(url.getProtocol())) {
204 in = new DataInputStream(url.openStream());
205 } else {
206 if (trustedClient == null) {
207 logger.error("Unable to read from remote source {} because trusted client is null!", url.getFile());
208 return null;
209 }
210 HttpGet get = new HttpGet(url.toURI());
211 try {
212 response = trustedClient.execute(get);
213 } catch (TrustedHttpClientException e) {
214 logger.warn("Unable to fetch file from {}.", url, e);
215 trustedClient.close(response);
216 return null;
217 }
218 in = new DataInputStream(response.getEntity().getContent());
219 }
220 int c = 0;
221 while ((c = in.read()) != -1) {
222 sb.append((char) c);
223 }
224 } catch (IOException e) {
225 logger.warn("IOException attempting to get file from {}.", url);
226 return null;
227 } catch (URISyntaxException e) {
228 logger.warn("URI error attempting to get file from {}.", url);
229 return null;
230 } catch (NullPointerException e) {
231 logger.warn("Nullpointer attempting to get file from {}.", url);
232 return null;
233 } finally {
234 IOUtils.closeQuietly(in);
235
236 if (response != null) {
237 try {
238 trustedClient.close(response);
239 } catch (IOException e) {
240 }
241 }
242 }
243
244 return sb.toString();
245 }
246
247 public static Properties loadPropertiesFromUrl(final URL url) {
248 try {
249 return loadPropertiesFromStream(url.openStream());
250 } catch (IOException e) {
251 return chuck(e);
252 }
253 }
254
255
256 public static Properties loadPropertiesFromStream(final InputStream stream) {
257 return withResource(stream, (InputStream in) -> {
258 try {
259 Properties p = new Properties();
260 p.load(in);
261 return p;
262 } catch (Exception e) {
263 return chuck(e);
264 }
265 });
266 }
267
268
269
270
271 public static <A, B extends Closeable> A withResource(B b, Function<B, A> f) {
272 try {
273 return f.apply(b);
274 } finally {
275 IoSupport.closeQuietly(b);
276 }
277 }
278
279
280
281
282
283
284 public static Optional<InputStream> openClassPathResource(String resource, Class<?> clazz) {
285 return Optional.ofNullable(clazz.getResourceAsStream(resource));
286 }
287
288
289
290
291
292
293 public static Optional<InputStream> openClassPathResource(String resource) {
294 return openClassPathResource(resource, IoSupport.class);
295 }
296
297
298 public static Optional<File> classPathResourceAsFile(String resource) {
299 try {
300 final URL res = IoSupport.class.getResource(resource);
301 if (res != null) {
302 return Optional.of(new File(res.toURI()));
303 } else {
304 return Optional.empty();
305 }
306 } catch (URISyntaxException e) {
307 return Optional.empty();
308 }
309 }
310
311
312
313
314
315
316 public static Optional<String> loadFileFromClassPathAsString(String resource, Class<?> clazz) {
317 try {
318 final URL url = clazz.getResource(resource);
319 return url != null ? Optional.of(Resources.toString(clazz.getResource(resource), Charset.forName("UTF-8")))
320 : Optional.empty();
321 } catch (IOException e) {
322 return Optional.empty();
323 }
324 }
325
326
327
328
329
330
331 public static Optional<String> loadFileFromClassPathAsString(String resource) {
332 return loadFileFromClassPathAsString(resource, IoSupport.class);
333 }
334
335
336
337
338
339
340
341
342
343
344 public static <A> Optional<A> withFile(File file, BiFunction<InputStream, File, A> f) {
345 try (InputStream s = new FileInputStream(file)) {
346 return Optional.of(f.apply(s, file));
347 } catch (FileNotFoundException e) {
348 return Optional.empty();
349 } catch (IOException e) {
350 return chuck(e);
351 }
352 }
353
354
355
356
357
358
359
360
361
362
363
364 public static <A, Err, B extends Closeable> Either<Err, A> withResource(
365 Supplier<B> resourceSupplier,
366 Function<Exception, Err> toErr,
367 Function<B, A> f) {
368 B resource = null;
369 try {
370 resource = resourceSupplier.get();
371 return right(f.apply(resource));
372 } catch (Exception e) {
373 return left(toErr.apply(e));
374 } finally {
375 IoSupport.closeQuietly(resource);
376 }
377 }
378
379
380 public static final Function<InputStream, String> readToString = in -> {
381 try {
382 return IOUtils.toString(in, "utf-8");
383 } catch (Exception e) {
384 return chuck(e);
385 }
386 };
387
388
389 public static InputStream fileInputStream(File file) {
390 try {
391 return new FileInputStream(file);
392 } catch (FileNotFoundException e) {
393 return chuck(e);
394 }
395 }
396
397
398 public static File file(String... pathElems) {
399 return new File(path(pathElems));
400 }
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415 public static synchronized <A> A locked(File file, Function<File, A> action) throws NotFoundException, IOException {
416 Runnable unlock = acquireLock(file);
417 try {
418 return action.apply(file);
419 } finally {
420 unlock.run();
421 }
422 }
423
424
425
426
427
428
429
430
431
432
433
434 private static Runnable acquireLock(File file) throws NotFoundException, IOException {
435 final RandomAccessFile raf;
436 try {
437 raf = new RandomAccessFile(file, "rw");
438 } catch (FileNotFoundException e) {
439
440
441 throw new NotFoundException("Error acquiring lock for " + file.getAbsolutePath(), e);
442 }
443 final FileLock lock = raf.getChannel().lock();
444 return () -> {
445 try {
446 lock.release();
447 } catch (IOException ignore) {
448 }
449 IoSupport.closeQuietly(raf);
450 };
451 }
452
453
454
455
456 public static <A extends Serializable> A serializeDeserialize(final A a) {
457 final ByteArrayOutputStream out = new ByteArrayOutputStream();
458 try {
459 withResource(
460 new ObjectOutputStream(out),
461 new Function<ObjectOutputStream, Void>() {
462 @Override
463 public Void apply(ObjectOutputStream outStream) {
464 try {
465 outStream.writeObject(a);
466 } catch (IOException e) {
467 throw new RuntimeException(e);
468 }
469 return null;
470 }
471 }
472 );
473
474 return withResource(
475 new ObjectInputStream(new ByteArrayInputStream(out.toByteArray())),
476 new Function<ObjectInputStream, A>() {
477 @Override
478 public A apply(ObjectInputStream inStream) {
479 try {
480 @SuppressWarnings("unchecked")
481 A obj = (A) inStream.readObject();
482 return obj;
483 } catch (IOException | ClassNotFoundException e) {
484 throw new RuntimeException(e);
485 }
486 }
487 }
488 );
489
490 } catch (IOException e) {
491 throw new RuntimeException(e);
492 }
493 }
494 }