Skip to content

Commit

Permalink
feat: Customizing Cloudevents validation
Browse files Browse the repository at this point in the history
Signed-off-by: vbhat6 <vinayas_bhat@intuit.com>
  • Loading branch information
vbhat6 committed Oct 6, 2023
1 parent eaef3be commit 8389a27
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 1 deletion.
27 changes: 26 additions & 1 deletion core/src/main/java/io/cloudevents/core/v1/CloudEventBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import io.cloudevents.SpecVersion;
import io.cloudevents.core.CloudEventUtils;
import io.cloudevents.core.impl.BaseCloudEventBuilder;
import io.cloudevents.core.validator.CloudEventValidator;
import io.cloudevents.rw.CloudEventContextReader;
import io.cloudevents.rw.CloudEventContextWriter;
import io.cloudevents.rw.CloudEventRWException;
Expand Down Expand Up @@ -119,7 +120,31 @@ public CloudEvent build() {
throw createMissingAttributeException(TYPE);
}

return new CloudEventV1(id, source, type, datacontenttype, dataschema, subject, time, this.data, this.extensions);
CloudEvent cloudEvent = new CloudEventV1(id, source, type, datacontenttype, dataschema, subject, time, this.data, this.extensions);

String name = null;
try{
// check if the header.validator.class is set as a system property,
if ((name = System.getProperty("header.validator.class")) != null){
Class<?> dynamicClass = Class.forName(name);
Object dynamicObject = dynamicClass.newInstance();

if (dynamicObject instanceof CloudEventValidator) {
// pluggable implementation of validation implementation
CloudEventValidator cloudEventValidator = (CloudEventValidator) dynamicObject;

cloudEventValidator.validate(cloudEvent);
}
else {
throw new IllegalArgumentException("Passed class is not an instance of CloudEventValidator");
}
}
}
catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
throw new IllegalArgumentException("Unable to load the header.validator.class passed as vm argument = " + name + ". Please check the classpath", e);
}

return cloudEvent;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package io.cloudevents.core.validator;

import io.cloudevents.CloudEvent;

/**
* Interface which defines validation for CloudEvents attributes and extensions.
*/
public interface CloudEventValidator {

/**
* Validate the attributes of a CloudEvent.
*
* @param cloudEvent the CloudEvent to validate
*/
void validate(CloudEvent cloudEvent);
}
Original file line number Diff line number Diff line change
Expand Up @@ -142,4 +142,48 @@ void testMissingType() {
).hasMessageContaining("Attribute 'type' cannot be null");
}

@Test
void testClassNotFoundExceptionForValidator(){

System.setProperty("header.validator.class", "io.cloudevents.core.v1.CustomCloudEventValidatorTest");
assertThatCode(() -> CloudEventBuilder
.v1()
.withId("000")
.withSource(URI.create("http://localhost"))
.withType("aaa")
.withExtension("astring", 10)
.build()
).hasMessageContaining("Unable to load the header.validator.class passed as vm argument");
}

@Test
void testClassCastExceptionForValidator(){

System.setProperty("header.validator.class", "io.cloudevents.core.v1.CustomCloudEventValidator");
assertThatCode(() -> CloudEventBuilder
.v1()
.withId("000")
.withSource(URI.create("http://localhost"))
.withType("aaa")
.withExtension("astring", 10)
.build()
).hasMessageContaining("Passed class is not an instance of CloudEventValidator");
}

/**
* This test is to check for the mandatory extension 'namespace' as per Organization need
*/
@Test
void testMissingNamespaceExtension(){

System.setProperty("header.validator.class", "io.cloudevents.core.v1.CustomCloudEventValidatorImpl");
assertThatCode(() -> CloudEventBuilder
.v1()
.withId("000")
.withSource(URI.create("http://localhost"))
.withType("aaa")
.build()
).hasMessageContaining("Extension 'namespace' cannot be null");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package io.cloudevents.core.v1;

/**
* Dummy validation class which does not implement CloudEventValidator class.
*/
public class CustomCloudEventValidator {

void validate(){

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package io.cloudevents.core.v1;

import io.cloudevents.CloudEvent;
import io.cloudevents.core.validator.CloudEventValidator;

public class CustomCloudEventValidatorImpl implements CloudEventValidator {
@Override
public void validate(CloudEvent cloudEvent) {

if (cloudEvent.getExtension("namespace") == null){
throw new IllegalStateException("Extension 'namespace' cannot be null");
}

}
}

0 comments on commit 8389a27

Please sign in to comment.