protected void copyFileToLocalDirectory(
      String remoteDirectoryPath, F remoteFile, File localDirectory, Session<F> session)
      throws IOException {
    String remoteFileName = this.getFilename(remoteFile);
    String localFileName = this.generateLocalFileName(remoteFileName);
    String remoteFilePath =
        remoteDirectoryPath != null
            ? (remoteDirectoryPath + this.remoteFileSeparator + remoteFileName)
            : remoteFileName;
    if (!this.isFile(remoteFile)) {
      if (this.logger.isDebugEnabled()) {
        this.logger.debug("cannot copy, not a file: " + remoteFilePath);
      }
      return;
    }

    File localFile = new File(localDirectory, localFileName);
    if (!localFile.exists()) {
      String tempFileName = localFile.getAbsolutePath() + this.temporaryFileSuffix;
      File tempFile = new File(tempFileName);
      OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(tempFile));
      try {
        session.read(remoteFilePath, outputStream);
      } catch (Exception e) {
        if (e instanceof RuntimeException) {
          throw (RuntimeException) e;
        } else {
          throw new MessagingException(
              "Failure occurred while copying from remote to local directory", e);
        }
      } finally {
        try {
          outputStream.close();
        } catch (Exception ignored2) {
        }
      }

      if (tempFile.renameTo(localFile)) {
        if (this.deleteRemoteFiles) {
          session.remove(remoteFilePath);
          if (this.logger.isDebugEnabled()) {
            this.logger.debug("deleted " + remoteFilePath);
          }
        }
      }
      if (this.preserveTimestamp) {
        localFile.setLastModified(getModified(remoteFile));
      }
    }
  }
  @Test
  @SuppressWarnings({"unchecked", "rawtypes"})
  public void testWrite() throws Exception {
    File file = new File(tmpDir, "foo.txt");
    file.delete();

    ByteArrayInputStream data = new ByteArrayInputStream("foobarbaz".getBytes());
    Session session = mock(Session.class);
    SessionFactory factory = mock(SessionFactory.class);
    when(factory.getSession()).thenReturn(session);
    when(session.readRaw("foo.txt")).thenReturn(data);
    when(session.finalizeRaw()).thenReturn(true);

    StepExecution stepExecution = new StepExecution("foo", null);
    ExecutionContext stepExecutionContext = new ExecutionContext();
    stepExecutionContext.putString("filePath", "foo.txt");
    stepExecution.setExecutionContext(stepExecutionContext);
    StepContext stepContext = new StepContext(stepExecution);
    ChunkContext chunkContext = new ChunkContext(stepContext);

    RemoteFileTemplate template = new RemoteFileTemplate(factory);
    template.setBeanFactory(mock(BeanFactory.class));
    template.afterPropertiesSet();

    // clean up from old tests
    FileSystem fs = FileSystem.get(configuration);
    Path p = new Path("/qux/foo.txt");
    fs.delete(p, true);
    assertFalse(fs.exists(p));

    RemoteFileToHadoopTasklet tasklet =
        new RemoteFileToHadoopTasklet(template, configuration, "/qux");

    assertEquals(RepeatStatus.FINISHED, tasklet.execute(null, chunkContext));

    assertTrue(fs.exists(p));

    FSDataInputStream stream = fs.open(p);
    byte[] out = new byte[9];
    stream.readFully(out);
    stream.close();
    assertEquals("foobarbaz", new String(out));

    fs.close();
  }