Search in sources :

Example 1 with LogLevel

use of org.apache.nifi.logging.LogLevel in project nifi by apache.

the class FetchFile method onTrigger.

@Override
public void onTrigger(final ProcessContext context, final ProcessSession session) throws ProcessException {
    FlowFile flowFile = session.get();
    if (flowFile == null) {
        return;
    }
    final StopWatch stopWatch = new StopWatch(true);
    final String filename = context.getProperty(FILENAME).evaluateAttributeExpressions(flowFile).getValue();
    final LogLevel levelFileNotFound = LogLevel.valueOf(context.getProperty(FILE_NOT_FOUND_LOG_LEVEL).getValue());
    final LogLevel levelPermDenied = LogLevel.valueOf(context.getProperty(PERM_DENIED_LOG_LEVEL).getValue());
    final File file = new File(filename);
    // Verify that file system is reachable and file exists
    Path filePath = file.toPath();
    if (!Files.exists(filePath) && !Files.notExists(filePath)) {
        // see https://docs.oracle.com/javase/tutorial/essential/io/check.html for more details
        getLogger().log(levelFileNotFound, "Could not fetch file {} from file system for {} because the existence of the file cannot be verified; routing to failure", new Object[] { file, flowFile });
        session.transfer(session.penalize(flowFile), REL_FAILURE);
        return;
    } else if (!Files.exists(filePath)) {
        getLogger().log(levelFileNotFound, "Could not fetch file {} from file system for {} because the file does not exist; routing to not.found", new Object[] { file, flowFile });
        session.getProvenanceReporter().route(flowFile, REL_NOT_FOUND);
        session.transfer(session.penalize(flowFile), REL_NOT_FOUND);
        return;
    }
    // Verify read permission on file
    final String user = System.getProperty("user.name");
    if (!isReadable(file)) {
        getLogger().log(levelPermDenied, "Could not fetch file {} from file system for {} due to user {} not having sufficient permissions to read the file; routing to permission.denied", new Object[] { file, flowFile, user });
        session.getProvenanceReporter().route(flowFile, REL_PERMISSION_DENIED);
        session.transfer(session.penalize(flowFile), REL_PERMISSION_DENIED);
        return;
    }
    // If configured to move the file and fail if unable to do so, check that the existing file does not exist and that we have write permissions
    // for the parent file.
    final String completionStrategy = context.getProperty(COMPLETION_STRATEGY).getValue();
    final String targetDirectoryName = context.getProperty(MOVE_DESTINATION_DIR).evaluateAttributeExpressions(flowFile).getValue();
    if (targetDirectoryName != null) {
        final File targetDir = new File(targetDirectoryName);
        if (COMPLETION_MOVE.getValue().equalsIgnoreCase(completionStrategy)) {
            if (targetDir.exists() && (!isWritable(targetDir) || !isDirectory(targetDir))) {
                getLogger().error("Could not fetch file {} from file system for {} because Completion Strategy is configured to move the original file to {}, " + "but that is not a directory or user {} does not have permissions to write to that directory", new Object[] { file, flowFile, targetDir, user });
                session.transfer(flowFile, REL_FAILURE);
                return;
            }
            final String conflictStrategy = context.getProperty(CONFLICT_STRATEGY).getValue();
            if (CONFLICT_FAIL.getValue().equalsIgnoreCase(conflictStrategy)) {
                final File targetFile = new File(targetDir, file.getName());
                if (targetFile.exists()) {
                    getLogger().error("Could not fetch file {} from file system for {} because Completion Strategy is configured to move the original file to {}, " + "but a file with name {} already exists in that directory and the Move Conflict Strategy is configured for failure", new Object[] { file, flowFile, targetDir, file.getName() });
                    session.transfer(flowFile, REL_FAILURE);
                    return;
                }
            }
        }
    }
    // import content from file system
    try (final FileInputStream fis = new FileInputStream(file)) {
        flowFile = session.importFrom(fis, flowFile);
    } catch (final IOException ioe) {
        getLogger().error("Could not fetch file {} from file system for {} due to {}; routing to failure", new Object[] { file, flowFile, ioe.toString() }, ioe);
        session.transfer(session.penalize(flowFile), REL_FAILURE);
        return;
    }
    session.getProvenanceReporter().modifyContent(flowFile, "Replaced content of FlowFile with contents of " + file.toURI(), stopWatch.getElapsed(TimeUnit.MILLISECONDS));
    session.transfer(flowFile, REL_SUCCESS);
    // It is critical that we commit the session before we perform the Completion Strategy. Otherwise, we could have a case where we
    // ingest the file, delete/move the file, and then NiFi is restarted before the session is committed. That would result in data loss.
    // As long as we commit the session right here, before we perform the Completion Strategy, we are safe.
    session.commit();
    // Attempt to perform the Completion Strategy action
    Exception completionFailureException = null;
    if (COMPLETION_DELETE.getValue().equalsIgnoreCase(completionStrategy)) {
        // convert to path and use Files.delete instead of file.delete so that if we fail, we know why
        try {
            delete(file);
        } catch (final IOException ioe) {
            completionFailureException = ioe;
        }
    } else if (COMPLETION_MOVE.getValue().equalsIgnoreCase(completionStrategy)) {
        final File targetDirectory = new File(targetDirectoryName);
        final File targetFile = new File(targetDirectory, file.getName());
        try {
            if (targetFile.exists()) {
                final String conflictStrategy = context.getProperty(CONFLICT_STRATEGY).getValue();
                if (CONFLICT_KEEP_INTACT.getValue().equalsIgnoreCase(conflictStrategy)) {
                    // don't move, just delete the original
                    Files.delete(file.toPath());
                } else if (CONFLICT_RENAME.getValue().equalsIgnoreCase(conflictStrategy)) {
                    // rename to add a random UUID but keep the file extension if it has one.
                    final String simpleFilename = targetFile.getName();
                    final String newName;
                    if (simpleFilename.contains(".")) {
                        newName = StringUtils.substringBeforeLast(simpleFilename, ".") + "-" + UUID.randomUUID().toString() + "." + StringUtils.substringAfterLast(simpleFilename, ".");
                    } else {
                        newName = simpleFilename + "-" + UUID.randomUUID().toString();
                    }
                    move(file, new File(targetDirectory, newName), false);
                } else if (CONFLICT_REPLACE.getValue().equalsIgnoreCase(conflictStrategy)) {
                    move(file, targetFile, true);
                }
            } else {
                move(file, targetFile, false);
            }
        } catch (final IOException ioe) {
            completionFailureException = ioe;
        }
    }
    // Handle completion failures
    if (completionFailureException != null) {
        getLogger().warn("Successfully fetched the content from {} for {} but failed to perform Completion Action due to {}; routing to success", new Object[] { file, flowFile, completionFailureException }, completionFailureException);
    }
}
Also used : Path(java.nio.file.Path) FlowFile(org.apache.nifi.flowfile.FlowFile) IOException(java.io.IOException) FlowFile(org.apache.nifi.flowfile.FlowFile) File(java.io.File) LogLevel(org.apache.nifi.logging.LogLevel) FileInputStream(java.io.FileInputStream) ProcessException(org.apache.nifi.processor.exception.ProcessException) IOException(java.io.IOException) StopWatch(org.apache.nifi.util.StopWatch)

Aggregations

File (java.io.File)1 FileInputStream (java.io.FileInputStream)1 IOException (java.io.IOException)1 Path (java.nio.file.Path)1 FlowFile (org.apache.nifi.flowfile.FlowFile)1 LogLevel (org.apache.nifi.logging.LogLevel)1 ProcessException (org.apache.nifi.processor.exception.ProcessException)1 StopWatch (org.apache.nifi.util.StopWatch)1