From 168b3e205a6d3a3bacbcd4902a730342f5f29eb8 Mon Sep 17 00:00:00 2001 From: exceptionfactory Date: Fri, 3 Nov 2023 07:24:19 -0500 Subject: [PATCH] NIFI-12311 Removed Custom Module Support from Jolt UI (#7973) - Removed custom ClassLoader creation support from the JoltTransformJSON Advanced user interface to avoid issues with loading external classes This closes #7973 --- .../transformjson/TransformJSONResource.java | 81 +++++++----------- .../TestTransformJSONResource.java | 29 +------ .../TestCustomJoltTransform.jar | Bin 1025 -> 0 bytes 3 files changed, 35 insertions(+), 75 deletions(-) delete mode 100644 nifi-nar-bundles/nifi-standard-bundle/nifi-jolt-transform-json-ui/src/test/resources/TestTransformJSONResource/TestCustomJoltTransform.jar diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-jolt-transform-json-ui/src/main/java/org/apache/nifi/web/standard/api/transformjson/TransformJSONResource.java b/nifi-nar-bundles/nifi-standard-bundle/nifi-jolt-transform-json-ui/src/main/java/org/apache/nifi/web/standard/api/transformjson/TransformJSONResource.java index af34dc143897..9afa5a7809ea 100644 --- a/nifi-nar-bundles/nifi-standard-bundle/nifi-jolt-transform-json-ui/src/main/java/org/apache/nifi/web/standard/api/transformjson/TransformJSONResource.java +++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-jolt-transform-json-ui/src/main/java/org/apache/nifi/web/standard/api/transformjson/TransformJSONResource.java @@ -25,7 +25,6 @@ import org.apache.nifi.attribute.expression.language.StandardEvaluationContext; import org.apache.nifi.processors.standard.util.jolt.TransformFactory; import org.apache.nifi.processors.standard.util.jolt.TransformUtils; -import org.apache.nifi.util.file.classloader.ClassLoaderUtils; import org.apache.nifi.web.standard.api.AbstractStandardResource; import org.apache.nifi.web.standard.api.transformjson.dto.JoltSpecificationDTO; import org.apache.nifi.web.standard.api.transformjson.dto.ValidationDTO; @@ -37,8 +36,6 @@ import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import java.io.File; -import java.io.FilenameFilter; import java.util.Collections; import java.util.Map; @@ -48,22 +45,22 @@ public class TransformJSONResource extends AbstractStandardResource { private static final Logger logger = LoggerFactory.getLogger(TransformJSONResource.class); private final static String DEFAULT_CHARSET = "UTF-8"; - protected Object getSpecificationJsonObject(JoltSpecificationDTO specificationDTO, boolean evaluateAttributes){ - - if (!StringUtils.isEmpty(specificationDTO.getSpecification()) ){ + private static final String CUSTOM_TRANSFORM_NAME = "jolt-transform-custom"; + protected Object getSpecificationJsonObject(JoltSpecificationDTO specificationDTO, boolean evaluateAttributes) { + if (!StringUtils.isEmpty(specificationDTO.getSpecification())) { final String specification; - if(evaluateAttributes) { + if (evaluateAttributes) { PreparedQuery preparedQuery = Query.prepare(specificationDTO.getSpecification()); Map attributes = specificationDTO.getExpressionLanguageAttributes() == null ? Collections.emptyMap() : specificationDTO.getExpressionLanguageAttributes(); specification = preparedQuery.evaluateExpressions(new StandardEvaluationContext(attributes), null); - }else{ + } else { specification = specificationDTO.getSpecification().replaceAll("\\$\\{","\\\\\\\\\\$\\{"); } return JsonUtils.jsonToObject(specification, DEFAULT_CHARSET); - }else{ + } else { return null; } } @@ -72,65 +69,49 @@ protected Object getSpecificationJsonObject(JoltSpecificationDTO specificationDT @Produces({MediaType.APPLICATION_JSON}) @Path("/validate") public Response validateSpec(JoltSpecificationDTO specificationDTO) { + ValidationDTO validation; try { - getTransformation(specificationDTO,false); - }catch(final Exception e){ - logger.error("Validation Failed - " + e.toString()); - return Response.ok(new ValidationDTO(false,"Validation Failed - Please verify the provided specification.")).build(); + getTransformation(specificationDTO, false); + validation = new ValidationDTO(true, null); + } catch (final Exception e) { + logger.warn("Jolt Transform Validation Failed", e); + + final String message; + if (CUSTOM_TRANSFORM_NAME.equals(specificationDTO.getTransform())) { + message = "Custom Transform not supported for advanced validation"; + } else { + message = "Validation Failed: Please review the Jolt Specification formatting"; + } + + validation = new ValidationDTO(false, message); } - return Response.ok(new ValidationDTO(true,null)).build(); + return Response.ok(validation).build(); } @POST @Produces({MediaType.APPLICATION_JSON}) @Path("/execute") public Response executeSpec(JoltSpecificationDTO specificationDTO) { - try { - JoltTransform transform = getTransformation(specificationDTO,true); + JoltTransform transform = getTransformation(specificationDTO, true); Object inputJson = JsonUtils.jsonToObject(specificationDTO.getInput()); - return Response.ok(JsonUtils.toJsonString(TransformUtils.transform(transform,inputJson))).build(); - - }catch(final Exception e){ - logger.error("Execute Specification Failed - " + e.toString()); + return Response.ok(JsonUtils.toJsonString(TransformUtils.transform(transform, inputJson))).build(); + } catch (final Exception e) { + logger.warn("Jolt Transform Execute Failed", e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } - } - protected JoltTransform getTransformation(JoltSpecificationDTO specificationDTO, boolean evaluateAttributes) throws Exception { - - Object specJson = getSpecificationJsonObject(specificationDTO,evaluateAttributes); - String transformName = specificationDTO.getTransform(); - String modules = specificationDTO.getModules(); + private JoltTransform getTransformation(JoltSpecificationDTO specificationDTO, boolean evaluateAttributes) throws Exception { + final String transformName = specificationDTO.getTransform(); - ClassLoader classLoader = null; - JoltTransform transform ; - - if(modules != null && !modules.isEmpty()){ - classLoader = ClassLoaderUtils.getCustomClassLoader(specificationDTO.getModules(),this.getClass().getClassLoader(), getJarFilenameFilter()); - } else{ - classLoader = this.getClass().getClassLoader(); - } - - if(transformName.equals("jolt-transform-custom")) { - transform = TransformFactory.getCustomTransform(classLoader,specificationDTO.getCustomClass(), specJson); - }else{ - transform = TransformFactory.getTransform(classLoader,specificationDTO.getTransform(), specJson); + if (CUSTOM_TRANSFORM_NAME.equals(transformName)) { + throw new IllegalArgumentException("Custom Transform Classes not supported for dynamic evaluation"); } - return transform; + Object specJson = getSpecificationJsonObject(specificationDTO, evaluateAttributes); + return TransformFactory.getTransform(getClass().getClassLoader(), specificationDTO.getTransform(), specJson); } - - protected FilenameFilter getJarFilenameFilter(){ - return new FilenameFilter() { - @Override - public boolean accept(File dir, String name) { - return (name != null && name.endsWith(".jar")); - } - }; - } - } diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-jolt-transform-json-ui/src/test/java/org/apache/nifi/web/standard/api/transformjson/TestTransformJSONResource.java b/nifi-nar-bundles/nifi-standard-bundle/nifi-jolt-transform-json-ui/src/test/java/org/apache/nifi/web/standard/api/transformjson/TestTransformJSONResource.java index 60e2f5cabfe8..1f4bde33f1c4 100644 --- a/nifi-nar-bundles/nifi-standard-bundle/nifi-jolt-transform-json-ui/src/test/java/org/apache/nifi/web/standard/api/transformjson/TestTransformJSONResource.java +++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-jolt-transform-json-ui/src/test/java/org/apache/nifi/web/standard/api/transformjson/TestTransformJSONResource.java @@ -139,7 +139,7 @@ public void testValidateWithInvalidEmptySpec() { .post(Entity.json(joltSpecificationDTO), ValidationDTO.class); assertNotNull(validation); - assertTrue(!validation.isValid()); + assertFalse(validation.isValid()); } @Test @@ -166,14 +166,13 @@ public void testValidateWithCustomSpec() { JoltSpecificationDTO joltSpecificationDTO = new JoltSpecificationDTO("jolt-transform-custom","[{ \"operation\": \"default\", \"spec\":{ \"custom-id\" :4 }}]"); joltSpecificationDTO.setCustomClass("TestCustomJoltTransform"); - joltSpecificationDTO.setModules("src/test/resources/TestTransformJSONResource/TestCustomJoltTransform.jar"); ValidationDTO validate = client().target(getBaseUri()) .path("/standard/transformjson/validate") .request() .post(Entity.json(joltSpecificationDTO), ValidationDTO.class); assertNotNull(validate); - assertTrue(validate.isValid()); + assertFalse(validate.isValid()); } @Test @@ -208,33 +207,13 @@ public void testValidateWithCustomInvalidSpec() { JoltSpecificationDTO joltSpecificationDTO = new JoltSpecificationDTO("jolt-transform-custom","{ \"operation\": \"default\", \"spec\":{ \"custom-id\" :4 }}"); joltSpecificationDTO.setCustomClass("TestCustomJoltTransform"); - joltSpecificationDTO.setModules("src/test/resources/TestTransformJSONResource/TestCustomJoltTransform.jar"); ValidationDTO validate = client().target(getBaseUri()) .path("/standard/transformjson/validate") .request() .post(Entity.json(joltSpecificationDTO), ValidationDTO.class); assertNotNull(validate); - assertTrue(!validate.isValid()); - } - - @Test - public void testExecuteWithValidCustomSpec() { - final Diffy diffy = new Diffy(); - JoltSpecificationDTO joltSpecificationDTO = new JoltSpecificationDTO("jolt-transform-custom","[{ \"operation\": \"default\", \"spec\":{ \"custom-id\" :4 }}]"); - String inputJson = "{\"rating\":{\"quality\":2,\"count\":1}}"; - joltSpecificationDTO.setInput(inputJson); - joltSpecificationDTO.setCustomClass("TestCustomJoltTransform"); - joltSpecificationDTO.setModules("src/test/resources/TestTransformJSONResource/TestCustomJoltTransform.jar"); - String responseString = client().target(getBaseUri()) - .path("/standard/transformjson/execute") - .request() - .post(Entity.json(joltSpecificationDTO), String.class); - - Object transformedJson = JsonUtils.jsonToObject(responseString); - Object compareJson = JsonUtils.jsonToObject("{\"rating\":{\"quality\":2,\"count\":1}, \"custom-id\": 4}"); - assertNotNull(transformedJson); - assertTrue(diffy.diff(compareJson, transformedJson).isEmpty()); + assertFalse(validate.isValid()); } @Test @@ -285,7 +264,7 @@ public void testExecuteWithValidExpressionLanguageSpec() { JoltSpecificationDTO joltSpecificationDTO = new JoltSpecificationDTO("jolt-transform-shift","{ \"rating\" : {\"quality\": \"${qual_var}\"} }"); String inputJson = "{\"rating\":{\"quality\":2,\"count\":1}}"; joltSpecificationDTO.setInput(inputJson); - Map attributes = new HashMap(); + Map attributes = new HashMap<>(); attributes.put("qual_var","qa"); joltSpecificationDTO.setExpressionLanguageAttributes(attributes); String responseString = client().target(getBaseUri()) diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-jolt-transform-json-ui/src/test/resources/TestTransformJSONResource/TestCustomJoltTransform.jar b/nifi-nar-bundles/nifi-standard-bundle/nifi-jolt-transform-json-ui/src/test/resources/TestTransformJSONResource/TestCustomJoltTransform.jar deleted file mode 100644 index b738658f1c90f00223417a02b2c5f226b9c2d5a2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1025 zcmWIWW@Zs#;Nak3c(n1F2LloiVPIkKbq#UU_4ISo_jUC1baM?3(eritcZz}Gv+tSH zKHj=|7kRyPwa%S6zd6X@it&S|pM1}pxmnf6Po7sjeLkf{MD>~I z@~7fYU#T`PsoYtylOe#Ho#T;uVU-imMi(Fs0J?*Vfq{bo!yTMJS-3ku${^0&wE@++ zvOr}asl_GErNt%rxnB7>B_TzLdBth@MY(#(If=!^wUcx6F9nDk|1Un_(xr`@$;ElQ zewj$VcvWI0+_Ue1PGRO1mQCjSc3tV4dg0#FZ4+KB4|@EW+rB~mR7IYmLHhP3neT1? z&c9!|>-+cl^Y=5nd9aaDc3NZhj&+M0q+LY{gOBUxh!os*;GHe?N=i!VUB-^n2JiV6 zN3h7AJp3ZyM8m!+`K!OJ z&bwdy_}Mc?=XI+0s#wbZT&T9>*){LYhj$G+sqQ;!3Jxq?|4leq&+e0Qo9Ob#u7%ns z)8{+Q>xt;-vn{t5TIlpge3D~-I&01n)v3>pupH&v;eTQ2t=Ym|WjcR1n6GO&E%!9c z^XJ)wEk^@(-J7?5RfM(jZ{4REi&}Jfw{=$EFiT82cf?39b4UIo#xjX()>oLjk`Pm6;SK6&vb}GvKimm5k z%PC3$A#HE3yqo{{?jQA!-*#(!3kfk?@?~}MH2pW%uY8&z^}euFMoTk|?QO(cwudW= zE$6Dmb}`-UH3W8t%iWp^*#U=-D1I=RZr%ql+Xi13@uoZBM)_vAcgFOsa8;q+OB>15i5M