### Question:
IOUtils { public static synchronized File exportResourceToDirectory(String resource, String parentDirectory, String tempFileNamePrefix, String tempFileNameExtension) { try (InputStream resourceStream = IOUtils.class.getResourceAsStream("/" + resource)) { if (resourceStream == null) { throw new IllegalStateException(resource + " not found"); } String hash = md5Hash(IOUtils.class.getResourceAsStream("/" + resource)); File tempFile = new File(parentDirectory, tempFileNamePrefix + "-" + hash + tempFileNameExtension); if (!tempFile.exists()) { try (FileOutputStream out = new FileOutputStream(tempFile)) { FileChannel channel = out.getChannel(); try (FileLock ignored = channel.lock()) { if (tempFile.length() == 0) { byte[] buffer = new byte[1024]; for (int length; (length = resourceStream.read(buffer)) != -1; ) { out.write(buffer, 0, length); } } } } } else if (!md5Hash(new FileInputStream(tempFile)).equals(hash)) { throw new IllegalStateException("Invalid MD5 checksum of " + tempFile + ". Please delete this file."); } return tempFile; } catch (NoSuchAlgorithmException | IOException e) { throw new IllegalStateException(e); } }  @VisibleForAdvice static boolean readUtf8Stream(final InputStream is, final CharBuffer charBuffer); @VisibleForAdvice static CoderResult decodeUtf8Bytes(final byte[] bytes, final CharBuffer charBuffer); @VisibleForAdvice static CoderResult decodeUtf8Bytes(final byte[] bytes, final int offset, final int length, final CharBuffer charBuffer); @VisibleForAdvice static CoderResult decodeUtf8Byte(final byte b, final CharBuffer charBuffer); static synchronized File exportResourceToDirectory(String resource, String parentDirectory, String tempFileNamePrefix,
                                                              String tempFileNameExtension); static String md5Hash(InputStream resourceAsStream);  }### Answer:
@Test void exportResourceToDirectory() throws UnsupportedEncodingException, URISyntaxException { File tmp = IOUtils.exportResourceToDirectory("test.elasticapm.properties", tempDirectory, UUID.randomUUID().toString(), "tmp"); tmp.deleteOnExit(); Path referenceFile = Paths.get(IOUtilsTest.class.getResource("/test.elasticapm.properties").toURI()); assertThat(tmp) .hasSameContentAs(referenceFile.toFile()); }
@Test void exportResourceToDirectoryIdempotence() throws InterruptedException { String destination = UUID.randomUUID().toString(); File tmp = IOUtils.exportResourceToDirectory("test.elasticapm.properties", tempDirectory, destination, "tmp"); tmp.deleteOnExit(); long actual = tmp.lastModified(); Thread.sleep(1000); File after = IOUtils.exportResourceToDirectory("test.elasticapm.properties", tempDirectory, destination, "tmp"); assertThat(actual).isEqualTo(after.lastModified()); }
@Test void exportResourceToDirectory_throwExceptionIfNotFound() { assertThatThrownBy(() -> IOUtils.exportResourceToDirectory("nonexist", tempDirectory, UUID.randomUUID().toString(), "tmp")).hasMessage("nonexist not found"); }
@Test void exportResourceToDirectoryInMultipleThreads() throws InterruptedException, ExecutionException, IOException { final int nbThreads = 10; final ExecutorService executorService = Executors.newFixedThreadPool(nbThreads); final CountDownLatch countDownLatch = new CountDownLatch(nbThreads); final List<Future<File>> futureList = new ArrayList<>(nbThreads); final String tempFileNamePrefix = UUID.randomUUID().toString(); for (int i = 0; i < nbThreads; i++) { futureList.add(executorService.submit(() -> { countDownLatch.countDown(); countDownLatch.await(); File file = IOUtils.exportResourceToDirectory("test.elasticapm.properties", tempDirectory, tempFileNamePrefix, "tmp"); file.deleteOnExit(); return file; })); } executorService.shutdown(); executorService.awaitTermination(1, TimeUnit.SECONDS); for (Future<File> future : futureList) { assertThat(future.get()).isNotNull(); assertThat(future.get()).exists(); } }