/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.nifi.processors.standard; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.File; import java.io.IOException; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.PosixFilePermission; import java.nio.file.attribute.PosixFilePermissions; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Set; import org.apache.nifi.flowfile.attributes.CoreAttributes; import org.apache.nifi.util.MockFlowFile; import org.apache.nifi.util.TestRunner; import org.apache.nifi.util.TestRunners; import org.junit.Test; public class TestGetFile { @Test public void testWithInaccessibleDir() throws IOException { // Some systems don't support POSIX (Windows) and will fail if run. Should ignore the test in that event if (!FileSystems.getDefault().supportedFileAttributeViews().contains("posix")) { return; } File inaccessibleDir = new File("target/inaccessible"); inaccessibleDir.deleteOnExit(); inaccessibleDir.mkdir(); Set<PosixFilePermission> posixFilePermissions = new HashSet<>(); Files.setPosixFilePermissions(inaccessibleDir.toPath(), posixFilePermissions); final TestRunner runner = TestRunners.newTestRunner(new GetFile()); runner.setProperty(GetFile.DIRECTORY, inaccessibleDir.getAbsolutePath()); try { runner.run(); fail(); } catch (AssertionError e) { assertTrue(e.getCause().getMessage() .endsWith("does not have sufficient permissions (i.e., not writable and readable)")); } } @Test public void testWithUnreadableDir() throws IOException { // Some systems don't support POSIX (Windows) and will fail if run. Should ignore the test in that event if (!FileSystems.getDefault().supportedFileAttributeViews().contains("posix")) { return; } File unreadableDir = new File("target/unreadable"); unreadableDir.deleteOnExit(); unreadableDir.mkdir(); Set<PosixFilePermission> posixFilePermissions = new HashSet<>(); posixFilePermissions.add(PosixFilePermission.GROUP_EXECUTE); posixFilePermissions.add(PosixFilePermission.GROUP_WRITE); posixFilePermissions.add(PosixFilePermission.OTHERS_EXECUTE); posixFilePermissions.add(PosixFilePermission.OTHERS_WRITE); posixFilePermissions.add(PosixFilePermission.OWNER_EXECUTE); posixFilePermissions.add(PosixFilePermission.OWNER_WRITE); Files.setPosixFilePermissions(unreadableDir.toPath(), posixFilePermissions); final TestRunner runner = TestRunners.newTestRunner(new GetFile()); runner.setProperty(GetFile.DIRECTORY, unreadableDir.getAbsolutePath()); try { runner.run(); fail(); } catch (AssertionError e) { assertTrue(e.getCause().getMessage() .endsWith("does not have sufficient permissions (i.e., not writable and readable)")); } } @Test public void testWithUnwritableDir() throws IOException { // Some systems don't support POSIX (Windows) and will fail if run. Should ignore the test in that event if (!FileSystems.getDefault().supportedFileAttributeViews().contains("posix")) { return; } File unwritableDir = new File("target/unwritable"); unwritableDir.deleteOnExit(); unwritableDir.mkdir(); Set<PosixFilePermission> posixFilePermissions = new HashSet<>(); posixFilePermissions.add(PosixFilePermission.GROUP_EXECUTE); posixFilePermissions.add(PosixFilePermission.GROUP_READ); posixFilePermissions.add(PosixFilePermission.OTHERS_EXECUTE); posixFilePermissions.add(PosixFilePermission.OTHERS_READ); posixFilePermissions.add(PosixFilePermission.OWNER_EXECUTE); posixFilePermissions.add(PosixFilePermission.OWNER_READ); Files.setPosixFilePermissions(unwritableDir.toPath(), posixFilePermissions); final TestRunner runner = TestRunners.newTestRunner(new GetFile()); runner.setProperty(GetFile.DIRECTORY, unwritableDir.getAbsolutePath()); try { runner.run(); fail(); } catch (AssertionError e) { assertTrue(e.getCause().getMessage() .endsWith("does not have sufficient permissions (i.e., not writable and readable)")); } } @Test public void testFilePickedUp() throws IOException { final File directory = new File("target/test/data/in"); deleteDirectory(directory); assertTrue("Unable to create test data directory " + directory.getAbsolutePath(), directory.exists() || directory.mkdirs()); final File inFile = new File("src/test/resources/hello.txt"); final Path inPath = inFile.toPath(); final File destFile = new File(directory, inFile.getName()); final Path targetPath = destFile.toPath(); final Path absTargetPath = targetPath.toAbsolutePath(); final String absTargetPathStr = absTargetPath.getParent() + "/"; Files.copy(inPath, targetPath); final TestRunner runner = TestRunners.newTestRunner(new GetFile()); runner.setProperty(GetFile.DIRECTORY, directory.getAbsolutePath()); runner.run(); runner.assertAllFlowFilesTransferred(GetFile.REL_SUCCESS, 1); final List<MockFlowFile> successFiles = runner.getFlowFilesForRelationship(GetFile.REL_SUCCESS); successFiles.get(0).assertContentEquals("Hello, World!".getBytes("UTF-8")); final String path = successFiles.get(0).getAttribute("path"); assertEquals("/", path); final String absolutePath = successFiles.get(0).getAttribute(CoreAttributes.ABSOLUTE_PATH.key()); assertEquals(absTargetPathStr, absolutePath); } private void deleteDirectory(final File directory) throws IOException { if (directory != null && directory.exists()) { for (final File file : directory.listFiles()) { if (file.isDirectory()) { deleteDirectory(file); } assertTrue("Could not delete " + file.getAbsolutePath(), file.delete()); } } } @Test public void testTodaysFilesPickedUp() throws IOException { final SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd", Locale.US); final String dirStruc = sdf.format(new Date()); final File directory = new File("target/test/data/in/" + dirStruc); deleteDirectory(directory); assertTrue("Unable to create test data directory " + directory.getAbsolutePath(), directory.exists() || directory.mkdirs()); final File inFile = new File("src/test/resources/hello.txt"); final Path inPath = inFile.toPath(); final File destFile = new File(directory, inFile.getName()); final Path targetPath = destFile.toPath(); Files.copy(inPath, targetPath); final TestRunner runner = TestRunners.newTestRunner(new GetFile()); runner.setProperty(GetFile.DIRECTORY, "target/test/data/in/${now():format('yyyy/MM/dd')}"); runner.run(); runner.assertAllFlowFilesTransferred(GetFile.REL_SUCCESS, 1); final List<MockFlowFile> successFiles = runner.getFlowFilesForRelationship(GetFile.REL_SUCCESS); successFiles.get(0).assertContentEquals("Hello, World!".getBytes("UTF-8")); } @Test public void testPath() throws IOException { final SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd/", Locale.US); final String dirStruc = sdf.format(new Date()); final File directory = new File("target/test/data/in/" + dirStruc); deleteDirectory(new File("target/test/data/in")); assertTrue("Unable to create test data directory " + directory.getAbsolutePath(), directory.exists() || directory.mkdirs()); final File inFile = new File("src/test/resources/hello.txt"); final Path inPath = inFile.toPath(); final File destFile = new File(directory, inFile.getName()); final Path targetPath = destFile.toPath(); final Path absTargetPath = targetPath.toAbsolutePath(); final String absTargetPathStr = absTargetPath.getParent().toString() + "/"; Files.copy(inPath, targetPath); final TestRunner runner = TestRunners.newTestRunner(new GetFile()); runner.setProperty(GetFile.DIRECTORY, "target/test/data/in"); runner.run(); runner.assertAllFlowFilesTransferred(GetFile.REL_SUCCESS, 1); final List<MockFlowFile> successFiles = runner.getFlowFilesForRelationship(GetFile.REL_SUCCESS); successFiles.get(0).assertContentEquals("Hello, World!".getBytes("UTF-8")); final String path = successFiles.get(0).getAttribute("path"); assertEquals(dirStruc, path.replace('\\', '/')); final String absolutePath = successFiles.get(0).getAttribute(CoreAttributes.ABSOLUTE_PATH.key()); assertEquals(absTargetPathStr, absolutePath); } @Test public void testAttributes() throws IOException { final File directory = new File("target/test/data/in/"); deleteDirectory(directory); assertTrue("Unable to create test data directory " + directory.getAbsolutePath(), directory.exists() || directory.mkdirs()); final File inFile = new File("src/test/resources/hello.txt"); final Path inPath = inFile.toPath(); final File destFile = new File(directory, inFile.getName()); final Path targetPath = destFile.toPath(); Files.copy(inPath, targetPath); boolean verifyLastModified = false; try { destFile.setLastModified(1000000000); verifyLastModified = true; } catch (Exception doNothing) { } boolean verifyPermissions = false; try { /* If you mount an NTFS partition in Linux, you are unable to change the permissions of the files, * because every file has the same permissions, controlled by the 'fmask' and 'dmask' mount options. * Executing a chmod command will not fail, but it does not change the file's permissions. * From Java perspective the NTFS mount point, as a FileStore supports the 'unix' and 'posix' file * attribute views, but the setPosixFilePermissions() has no effect. * * If you set verifyPermissions to true without the following extra check, the test case will fail * on a file system, where Nifi source is located on a NTFS mount point in Linux. * The purpose of the extra check is to ensure, that setPosixFilePermissions() changes the file's * permissions, and set verifyPermissions, after we are convinced. */ Set<PosixFilePermission> perms = PosixFilePermissions.fromString("r--r-----"); Files.setPosixFilePermissions(targetPath, perms); Set<PosixFilePermission> permsAfterSet = Files.getPosixFilePermissions(targetPath); if (perms.equals(permsAfterSet)) { verifyPermissions = true; } } catch (Exception doNothing) { } final TestRunner runner = TestRunners.newTestRunner(new GetFile()); runner.setProperty(GetFile.DIRECTORY, "target/test/data/in"); runner.run(); runner.assertAllFlowFilesTransferred(GetFile.REL_SUCCESS, 1); final List<MockFlowFile> successFiles = runner.getFlowFilesForRelationship(GetFile.REL_SUCCESS); if (verifyLastModified) { try { final DateFormat formatter = new SimpleDateFormat(GetFile.FILE_MODIFY_DATE_ATTR_FORMAT, Locale.US); final Date fileModifyTime = formatter.parse(successFiles.get(0).getAttribute("file.lastModifiedTime")); assertEquals(new Date(1000000000), fileModifyTime); } catch (ParseException e) { fail(); } } if (verifyPermissions) { successFiles.get(0).assertAttributeEquals("file.permissions", "r--r-----"); } } }