Skip to content

Commit

Permalink
Implemented fix for some null pointers
Browse files Browse the repository at this point in the history
  • Loading branch information
jgwoolley committed Jan 29, 2025
1 parent e240083 commit 7f4f1b6
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 22 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
*.flowfilev3
*.adoc
.vscode
.classpath
Expand Down
10 changes: 10 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@
</properties>

<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>2.0.16</version>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-expression-language</artifactId>
<version>1.23.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
Expand Down
38 changes: 28 additions & 10 deletions src/main/java/com/yelloowstone/nf2t/cli/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.stream.Stream;
Expand All @@ -22,6 +23,9 @@
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
import org.apache.nifi.attribute.expression.language.PreparedQuery;
import org.apache.nifi.attribute.expression.language.Query;
import org.apache.nifi.attribute.expression.language.StandardEvaluationContext;
import org.apache.nifi.flowfile.attributes.CoreAttributes;
import org.apache.nifi.util.FlowFilePackager;
import org.apache.nifi.util.FlowFileUnpackager;
Expand Down Expand Up @@ -76,7 +80,7 @@ private void unpackageFlowFileInputStream(final FlowFileStreamResult result, fin
}

if (contentPath != null && result.isUuidFilenames() && flowFileResult != null) {
String filename = flowFileResult.getAttributes().get(CoreAttributes.FILENAME.key());
String filename = flowFileResult.getRawAttributeExpressions().get(CoreAttributes.FILENAME.key());
if (filename != null) {
Path newContentPath = contentPath.getParent().resolve(filename);
Files.move(contentPath, newContentPath);
Expand Down Expand Up @@ -180,10 +184,8 @@ public Integer unpackageFlowFileStream(
+ FlowFileStreamResult.OUTPUTPATH_UNPACKAGE_DESCRIPTION, required = false) final String outputOption,
@Option(names = { "-u",
"--uuid" }, description = FlowFileStreamResult.UUID_DESCRIPTION, defaultValue = "true") final boolean uuidFilenames,
@Option(names = {"-r", "--results"}, description=FlowFileStreamResult.RESULTS_PATH_DESCRIPTION) final String resultsPath,
@Option(names = {"-a", "--attribute"}, description=FlowFileStreamResult.DEFAULT_ATTRIBUTES_DESCRIPTION, required=false) final Map<String,String> attributes,
@Option(names = {"-k", "--keep-attributes"}, description=FlowFileStreamResult.KEEP_ATTRIBUTES_DESCRIPTION, defaultValue="true", required=false) final boolean keepAttributes) {
final FlowFileStreamResult result = createResult(version, extension, uuidFilenames, inputOption, outputOption, resultsPath, attributes, keepAttributes);
@Option(names = {"-r", "--results"}, description=FlowFileStreamResult.RESULTS_PATH_DESCRIPTION) final String resultsPath) {
final FlowFileStreamResult result = createResult(version, extension, uuidFilenames, inputOption, outputOption, resultsPath, new HashMap<>(), true);

// Unpack Frequently Used Variables
final Path inputPath = result.getInputPath();
Expand Down Expand Up @@ -249,8 +251,10 @@ public Integer packageFlowFileStream(
+ FlowFileStreamResult.INPUTPATH_PACKAGE_DESCRIPTION, required = true) final String inputOption,
@Option(names = { "-o", "--out" }, description = "The output path."
+ FlowFileStreamResult.OUTPUTPATH_PACKAGE_DESCRIPTION, required = true) final String outputOption,
@Option(names = {"-r", "--results"}, description=FlowFileStreamResult.RESULTS_PATH_DESCRIPTION) final String resultsPath) {
final FlowFileStreamResult result = createResult(version, extension, true, inputOption, outputOption, resultsPath, new HashMap<>(), true);
@Option(names = {"-r", "--results"}, description=FlowFileStreamResult.RESULTS_PATH_DESCRIPTION) final String resultsPath,
@Option(names = {"-a", "--attribute"}, description=FlowFileStreamResult.DEFAULT_ATTRIBUTES_DESCRIPTION, required=false) final Map<String,String> rawAttributeExpressions,
@Option(names = {"-k", "--keep-attributes"}, description=FlowFileStreamResult.KEEP_ATTRIBUTES_DESCRIPTION, defaultValue="true", required=false) final boolean keepAttributes) {
final FlowFileStreamResult result = createResult(version, extension, true, inputOption, outputOption, resultsPath, rawAttributeExpressions == null ? new HashMap<>(): rawAttributeExpressions, keepAttributes);

// Unpack Frequently Used Variables
final Path inputPath = result.getInputPath();
Expand Down Expand Up @@ -302,19 +306,31 @@ public Integer packageFlowFileStream(

final FlowFilePackager packager = packageVersion.getPackager();

final Map<String, PreparedQuery> attributeExpressions = new HashMap<>();

for(final Entry<String, String> attribute: result.getDefaultAttributes().entrySet()) {
attributeExpressions.put(attribute.getKey(), Query.prepare(attribute.getValue()));
}

try (OutputStream outputStream = Files.newOutputStream(outputPath)) {
for (Path contentPath : contentPaths) {
final SourceFile content = SourceFile.fromPath(null, outputPath);

try {
final long contentSize = Files.size(contentPath);
final Map<String, String> defaultAttributes = generateDefaultAttributes(contentPath, contentSize);
defaultAttributes.putAll(result.getDefaultAttributes());
final Map<String, String> attributes = new HashMap<>();

if(result.keepAttributes) {
attributes.putAll(defaultAttributes);
}

final StandardEvaluationContext evaluationContext = new StandardEvaluationContext(defaultAttributes);
for(final Entry<String,PreparedQuery> attribute: attributeExpressions.entrySet()) {
attributes.put(attribute.getKey(), attribute.getValue().evaluateExpressions(evaluationContext, null));
}

try (InputStream inputStream = Files.newInputStream(contentPath)) {
packager.packageFlowFile(inputStream, outputStream, attributes, contentSize);

Expand Down Expand Up @@ -378,7 +394,7 @@ public boolean printResult(final FlowFileStreamResult result) {
}

public FlowFileStreamResult createResult(final int version, String extension, final boolean uuidFilenames,
final String inputOption, String outputOption, final String resultsOption, final Map<String, String> defaultAttributes, boolean keepAttributes) {
final String inputOption, String outputOption, final String resultsOption, final Map<String, String> attributeExpressions, boolean keepAttributes) {
final Path inputPath = Paths.get(inputOption == null ? "." : inputOption);
final Path outputPath = outputOption == null || outputOption.length() <= 0 ? null : Paths.get(outputOption);
Path resultsPath = resultsOption == null ? null : Paths.get(resultsOption);
Expand All @@ -392,14 +408,16 @@ public FlowFileStreamResult createResult(final int version, String extension, fi
}

long unixTime = System.currentTimeMillis() / 1000L;
return new FlowFileStreamResult(version, extension, uuidFilenames, inputPath, outputPath, resultsPath, unixTime, defaultAttributes, keepAttributes);
return new FlowFileStreamResult(version, extension, uuidFilenames, inputPath, outputPath, resultsPath, unixTime, attributeExpressions, keepAttributes);
}

public static Map<String, String> generateDefaultAttributes(final Path path, final long contentSize) throws IOException {
final Map<String, String> attributes = new HashMap<>();

attributes.put(CoreAttributes.FILENAME.key(), path.getFileName().toString());
attributes.put(CoreAttributes.PATH.key(), path.getParent().toString());
if(path.getParent() != null) {
attributes.put(CoreAttributes.PATH.key(), path.getParent().toString());
}
attributes.put(CoreAttributes.ABSOLUTE_PATH.key(), path.toString());
attributes.put(FILE_SIZE_ATTRIBUTE, Long.toString(contentSize));

Expand Down
12 changes: 6 additions & 6 deletions src/main/java/com/yelloowstone/nf2t/cli/FlowFileResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,19 @@ public class FlowFileResult {
@JsonProperty("contentPath")
private SourceFile contentPath;

@JsonPropertyDescription("Represents the FlowFile Attributes.")
@JsonPropertyDescription("Represents the FlowFile attribute key, and value. The value is an FlowFile Attribute Expression, and can resolve variables from other attributes. Expressions should not reference other attributes that also contain expressions.")
@JsonProperty("attributes")
private final Map<String,String> attributes;
private final Map<String,String> rawAttributeExpressions;

@JsonPropertyDescription("Represents the size of the FlowFile Content.")
@JsonProperty("contentSize")
private final long contentSize;

@JsonCreator
public FlowFileResult(@JsonProperty("flowFilePath") final SourceFile flowFilePath, @JsonProperty("contentPath") final SourceFile contentPath, @JsonProperty("attributes") final Map<String,String> attributes, @JsonProperty("contentSize") final long size) {
public FlowFileResult(@JsonProperty("flowFilePath") final SourceFile flowFilePath, @JsonProperty("contentPath") final SourceFile contentPath, @JsonProperty("attributes") final Map<String,String> rawAttributeExpressions, @JsonProperty("contentSize") final long size) {
this.flowFilePath = flowFilePath;
this.contentPath = contentPath;
this.attributes = attributes;
this.rawAttributeExpressions = rawAttributeExpressions;
this.contentSize = size;
}

Expand All @@ -40,8 +40,8 @@ public SourceFile getContentPath() {
return contentPath;
}

public Map<String,String> getAttributes() {
return attributes;
public Map<String,String> getRawAttributeExpressions() {
return rawAttributeExpressions;
}

public long getContentSize() {
Expand Down
17 changes: 13 additions & 4 deletions src/main/java/com/yelloowstone/nf2t/cli/FlowFileStreamResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,9 @@ public class FlowFileStreamResult {

@JsonPropertyDescription(DEFAULT_ATTRIBUTES_DESCRIPTION)
@JsonProperty("defaultAttributes")
final Map<String, String> defaultAttributes;
final Map<String, String> rawAttributeExpressions;

protected static final String KEEP_ATTRIBUTES_DESCRIPTION = "Keep default attributes generated by nf2t-cli.";
protected static final String KEEP_ATTRIBUTES_DESCRIPTION = "Keep default FlowFile attributes generated by nf2t-cli.";

@JsonPropertyDescription(KEEP_ATTRIBUTES_DESCRIPTION)
@JsonProperty("keepAttributes")
Expand All @@ -87,15 +87,15 @@ public class FlowFileStreamResult {
public FlowFileStreamResult(@JsonProperty("version") final int version, @JsonProperty("extension") String extension,
@JsonProperty("uuidFilenames") final boolean uuidFilenames, @JsonProperty("inputPath") final Path inputPath,
@JsonProperty("outputPath") final Path outputPath, @JsonProperty("resultsPath") Path resultsPath,
@JsonProperty("unixTime") final long unixTime, @JsonProperty("defaultAttributes") Map<String, String> defaultAttributes, @JsonProperty("keepAttributes") boolean keepAttributes) {
@JsonProperty("unixTime") final long unixTime, @JsonProperty("defaultAttributes") Map<String, String> rawAttributeExpressions, @JsonProperty("keepAttributes") boolean keepAttributes) {
this.version = version;
this.extension = extension;
this.uuidFilenames = uuidFilenames;
this.inputPath = inputPath;
this.outputPath = outputPath;
this.resultsPath = resultsPath;
this.unixTime = unixTime;
this.defaultAttributes = defaultAttributes;
this.rawAttributeExpressions = rawAttributeExpressions;
this.keepAttributes = keepAttributes;
}

Expand Down Expand Up @@ -142,4 +142,13 @@ public List<FlowFileErrorResult> getErrors() {
public List<FlowFileResult> getOutputFiles() {
return outputFiles;
}

public Map<String, String> getDefaultAttributes() {
return rawAttributeExpressions;
}

public boolean isKeepAttributes() {
return keepAttributes;
}

}
4 changes: 2 additions & 2 deletions src/test/java/com/yelloowstone/nf2t/cli/AppTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public void testPackageFiles() throws Exception {
final Path contentPath = environment.getContentPath();
final Path packagedPath = environment.getPackagedPath();

final String sw = environment.execute(x -> new String[] {"package", "--version", Integer.toString(version), "--in", contentPath.toString(), "--out", packagedPath.toString()});
final String sw = environment.execute(x -> new String[] {"package", "--version", Integer.toString(version), "--in", contentPath.toString(), "--out", packagedPath.toString(), "--attribute", "key=${foo}$${foo}$$${foo}", "--attribute", "key2=${size}"});

final FlowFileStreamResult result = reader.readValue(sw, FlowFileStreamResult.class);

Expand Down Expand Up @@ -129,7 +129,7 @@ public void testUnpackageFiles() throws Exception {
}

final String sw = environment.execute(x -> new String[] {"unpackage", "--version", Integer.toString(version),
"--in", packagedPath.toString(), "--out", unpackagedPath.toString(), "--attribute", "key=value"});
"--in", packagedPath.toString(), "--out", unpackagedPath.toString()});

System.out.println("\tResult:\n\t" + sw.toString());
final FlowFileStreamResult result = reader.readValue(sw.toString(), FlowFileStreamResult.class);
Expand Down

0 comments on commit 7f4f1b6

Please sign in to comment.