-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #311 from logzio/add-base64-decode-processor
- Loading branch information
Showing
3 changed files
with
181 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
68 changes: 68 additions & 0 deletions
68
sawmill-core/src/main/java/io/logz/sawmill/processors/Base64DecodeProcessor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package io.logz.sawmill.processors; | ||
|
||
import io.logz.sawmill.Doc; | ||
import io.logz.sawmill.ProcessResult; | ||
import io.logz.sawmill.Processor; | ||
import io.logz.sawmill.annotations.ProcessorProvider; | ||
import io.logz.sawmill.exceptions.ProcessorConfigurationException; | ||
import io.logz.sawmill.utilities.JsonUtils; | ||
|
||
import java.util.Base64; | ||
import java.util.Map; | ||
|
||
import static java.util.Objects.requireNonNull; | ||
|
||
@ProcessorProvider(type = "base64Decode", factory = Base64DecodeProcessor.Factory.class) | ||
public class Base64DecodeProcessor implements Processor { | ||
|
||
private final String sourceField; | ||
private final String targetField; | ||
|
||
public Base64DecodeProcessor(String sourceField, String targetField) { | ||
this.sourceField = requireNonNull(sourceField); | ||
this.targetField = requireNonNull(targetField); | ||
} | ||
|
||
@Override | ||
public ProcessResult process(Doc doc) { | ||
if(!doc.hasField(sourceField, String.class)) | ||
return ProcessResult.failure("field is missing from doc"); | ||
|
||
String value = doc.getField(sourceField); | ||
String decodedValue = new String(Base64.getDecoder().decode(value)); | ||
doc.addField(targetField, decodedValue); | ||
return ProcessResult.success(); | ||
} | ||
|
||
public static class Factory implements Processor.Factory { | ||
public Factory() {} | ||
|
||
@Override | ||
public Base64DecodeProcessor create(Map<String,Object> config) { | ||
Base64DecodeProcessor.Configuration configuration = | ||
JsonUtils.fromJsonMap(Base64DecodeProcessor.Configuration.class, config); | ||
validateConfiguration(configuration); | ||
return new Base64DecodeProcessor(configuration.getSourceField(), configuration.getTargetField()); | ||
} | ||
|
||
private void validateConfiguration(Configuration configuration) { | ||
if(configuration.getSourceField() == null || configuration.getSourceField().isEmpty() | ||
|| configuration.getTargetField() == null || configuration.getTargetField().isEmpty()) | ||
throw new ProcessorConfigurationException("sourceField, targetField can not be null or empty"); | ||
} | ||
} | ||
|
||
public static class Configuration implements Processor.Configuration { | ||
private String sourceField; | ||
private String targetField; | ||
|
||
public Configuration() {} | ||
public Configuration(String sourceField, String targetField) { | ||
this.sourceField = sourceField; | ||
this.targetField = targetField; | ||
} | ||
|
||
public String getSourceField() { return sourceField; } | ||
public String getTargetField() { return targetField; } | ||
} | ||
} |
111 changes: 111 additions & 0 deletions
111
sawmill-core/src/test/java/io/logz/sawmill/processors/Base64DecodeProcessorTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
package io.logz.sawmill.processors; | ||
|
||
import io.logz.sawmill.Doc; | ||
import io.logz.sawmill.ProcessResult; | ||
import io.logz.sawmill.Processor; | ||
import io.logz.sawmill.exceptions.ProcessorConfigurationException; | ||
import org.junit.Test; | ||
|
||
import java.util.Base64; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.stream.Stream; | ||
|
||
import static io.logz.sawmill.utils.FactoryUtils.createProcessor; | ||
import static org.assertj.core.api.Assertions.assertThat; | ||
import static org.assertj.core.api.Assertions.assertThatThrownBy; | ||
|
||
public class Base64DecodeProcessorTest { | ||
|
||
@Test | ||
public void testNullOrEmptyConfigurationFieldsShouldFailCreator() { | ||
Stream.of( | ||
createConfig(null, "target"), | ||
createConfig("", "target"), | ||
createConfig("source", null), | ||
createConfig("source", "")) | ||
.forEach((config) -> assertThatThrownBy(() -> createProcessor(Base64DecodeProcessor.class, config)) | ||
.isInstanceOf(ProcessorConfigurationException.class) | ||
.hasMessageContaining("sourceField, targetField can not be null or empty")); | ||
} | ||
|
||
@Test | ||
public void testDecode() { | ||
Map<String, Object> config = new HashMap<>(); | ||
config.put("sourceField", "message"); | ||
config.put("targetField", "message_decoded"); | ||
|
||
Map<String, Object> map = new HashMap<>(); | ||
String encodedMessage = Base64.getEncoder().encodeToString("testEmptyFieldsShouldFail".getBytes()); | ||
map.put("message", encodedMessage); | ||
Doc doc = new Doc(map); | ||
|
||
ProcessResult result; | ||
Processor processor = createProcessor(Base64DecodeProcessor.class, config); | ||
try { | ||
result = processor.process(doc); | ||
} catch (InterruptedException e) { throw new RuntimeException(e); } | ||
|
||
assertThat(result != null && result.isSucceeded()).isTrue(); | ||
assertThat(doc.getField(config.get("sourceField").toString()).toString()).isEqualTo(encodedMessage); | ||
assertThat(doc.getField(config.get("targetField").toString()).toString()) | ||
.isEqualTo("testEmptyFieldsShouldFail"); | ||
} | ||
|
||
@Test | ||
public void testNonStringFieldShouldFail() { | ||
Map<String, Object> config = new HashMap<>(); | ||
config.put("sourceField", "numberField"); | ||
config.put("targetField", "noop"); | ||
|
||
Map<String, Object> map = new HashMap<>(); | ||
map.put("message", "testSingleNonStringFieldShouldFail"); | ||
map.put("numberField", 123); | ||
Doc doc = new Doc(map); | ||
|
||
Processor processor = createProcessor(Base64DecodeProcessor.class, config); | ||
|
||
ProcessResult result; | ||
|
||
try { | ||
result = processor.process(doc); | ||
} catch (InterruptedException e) { throw new RuntimeException(e); } | ||
assertThat(result != null && !result.isSucceeded()).isTrue(); | ||
assertThat(result.getError().isPresent()).isTrue(); | ||
assertThat(result.getError().get().getMessage()) | ||
.isEqualTo("field is missing from doc"); | ||
assertThat(doc.hasField(config.get("targetField").toString())).isFalse(); | ||
assertThat(doc.getField("message").toString()).isEqualTo(map.get("message").toString()); | ||
} | ||
|
||
@Test | ||
public void testMissingFieldShouldFail() { | ||
Map<String, Object> config = new HashMap<>(); | ||
config.put("sourceField", "foo"); | ||
config.put("targetField", "foo_decoded"); | ||
|
||
Map<String, Object> map = new HashMap<>(); | ||
map.put("message", "testAllFieldsMissingShouldFail"); | ||
|
||
Doc doc = new Doc(map); | ||
|
||
ProcessResult result; | ||
Processor processor = createProcessor(Base64DecodeProcessor.class, config); | ||
try { | ||
result = processor.process(doc); | ||
} catch (InterruptedException e) { throw new RuntimeException(e); } | ||
|
||
assertThat(result != null && !result.isSucceeded()).isTrue(); | ||
assertThat(result.getError().get().getMessage()) | ||
.isEqualTo("field is missing from doc"); | ||
assertThat(doc.hasField(config.get("targetField").toString())).isFalse(); | ||
assertThat(doc.getField("message").toString()).isEqualTo(map.get("message").toString()); | ||
} | ||
|
||
private Map<String, Object> createConfig(String sourceField, String targetField) { | ||
Map<String, Object> config = new HashMap<>(); | ||
config.put("sourceField", sourceField); | ||
config.put("targetField", targetField); | ||
return config; | ||
} | ||
} |