This is an automated email from the ASF dual-hosted git repository. nfilotto pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push: new 96226cb CAMEL-16628: Add applicableFor to Metadata to filter header by scheme (#7224) 96226cb is described below commit 96226cb3548e14fdf242f38590180811b1d25f42 Author: Nicolas Filotto <essob...@users.noreply.github.com> AuthorDate: Fri Mar 18 12:10:51 2022 +0100 CAMEL-16628: Add applicableFor to Metadata to filter header by scheme (#7224) ## Motivation Some Constants class are shared with several endpoints, we need a mechanism allowing to filter the message headers by endpoint's scheme. ## Modifications * Add the new element `applicableFor` to `@Metadata` to provide the list of schemes for which the metadata is applicable. * Enable the IT as the plugin updates have been published (not related to this need) --- .../java/org/apache/camel/spi/Metadata.java | 17 +++++++++++ tooling/maven/camel-package-maven-plugin/pom.xml | 4 --- .../packaging/EndpointSchemaGeneratorMojo.java | 35 +++++++++++++++------- .../packaging/EndpointSchemaGeneratorMojoTest.java | 19 ++++++++++-- .../packaging/endpoint/SomeEndpointWithFilter.java | 34 +++++++++++++++++++++ .../main/java/org/apache/camel/spi/Metadata.java | 17 +++++++++++ 6 files changed, 109 insertions(+), 17 deletions(-) diff --git a/core/camel-api/src/generated/java/org/apache/camel/spi/Metadata.java b/core/camel-api/src/generated/java/org/apache/camel/spi/Metadata.java index f37ea43..57f5a47 100644 --- a/core/camel-api/src/generated/java/org/apache/camel/spi/Metadata.java +++ b/core/camel-api/src/generated/java/org/apache/camel/spi/Metadata.java @@ -132,4 +132,21 @@ public @interface Metadata { * specify which options each implementation only supports. */ String includeProperties() default ""; + + /** + * Indicates the list of schemes for which this metadata is applicable. This is used to filter out message headers + * that are shared with several endpoints but only applicable for some of them. + * <p/> + * In the next example, the header {@code SOME_HEADER} is only applicable for endpoints whose scheme is "foo" or + * "bar". + * + * <pre> + * <code> + * + * @Metadata(description = "some description", javaType = "String", applicableFor = {"foo", "bar"}) + * public static final String SOME_HEADER = "someHeaderName"; + * </code> + * </pre> + */ + String[] applicableFor() default {}; } diff --git a/tooling/maven/camel-package-maven-plugin/pom.xml b/tooling/maven/camel-package-maven-plugin/pom.xml index 82041b4..39c6839 100644 --- a/tooling/maven/camel-package-maven-plugin/pom.xml +++ b/tooling/maven/camel-package-maven-plugin/pom.xml @@ -188,8 +188,6 @@ </mojoDependencies> </configuration> </plugin> - -<!-- <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-invoker-plugin</artifactId> @@ -230,8 +228,6 @@ </dependency> </dependencies> </plugin> ---> - </plugins> </build> diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/EndpointSchemaGeneratorMojo.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/EndpointSchemaGeneratorMojo.java index 1bc68d8..58b3ddf 100644 --- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/EndpointSchemaGeneratorMojo.java +++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/EndpointSchemaGeneratorMojo.java @@ -261,7 +261,7 @@ public class EndpointSchemaGeneratorMojo extends AbstractGeneratorMojo { } // component headers - addEndpointHeaders(componentModel, uriEndpoint); + addEndpointHeaders(componentModel, uriEndpoint, scheme); // endpoint options findClassProperties(componentModel, classElement, new HashSet<>(), "", null, null, false); @@ -301,11 +301,14 @@ public class EndpointSchemaGeneratorMojo extends AbstractGeneratorMojo { * {@code headersClass} of the annotation {@code UriEndpoint}, convert the metadata found into instances of * {@link EndpointHeaderModel} and finally add the instances of {@link EndpointHeaderModel} to the given component * model. - * + * <p/> + * Only headers applicable for the given scheme are added. + * * @param componentModel the component model to which the headers should be added. * @param uriEndpoint the annotation from which the headers class is retrieved. + * @param scheme the scheme for which we want to add the headers. */ - void addEndpointHeaders(ComponentModel componentModel, UriEndpoint uriEndpoint) { + void addEndpointHeaders(ComponentModel componentModel, UriEndpoint uriEndpoint, String scheme) { final Class<?> headersClass = uriEndpoint.headersClass(); if (headersClass == void.class) { getLog().debug(String.format("The endpoint %s has not defined any headers class", uriEndpoint.scheme())); @@ -319,9 +322,10 @@ public class EndpointSchemaGeneratorMojo extends AbstractGeneratorMojo { getLog().debug( String.format("Trying to add the constant %s in the class %s as header.", field.getName(), headersClass.getName())); - addEndpointHeader(componentModel, field); - foundHeader = true; - continue; + if (addEndpointHeader(componentModel, field, scheme)) { + foundHeader = true; + continue; + } } getLog().debug( String.format("The field %s of the class %s is not considered as a name of a header, thus it is skipped", @@ -336,16 +340,26 @@ public class EndpointSchemaGeneratorMojo extends AbstractGeneratorMojo { * Retrieve the metadata added to the given field, convert the metadata found into an instance of * {@link EndpointHeaderModel} and finally add the instance of {@link EndpointHeaderModel} to the given component * model. + * <p/> + * The header is only added if it is applicable for the given scheme. * - * @param componentModel the component to which the header should be added. - * @param field the field corresponding to the constant from which the metadata should be extracted. + * @param componentModel the component to which the header should be added. + * @param field the field corresponding to the constant from which the metadata should be extracted. + * @param scheme the scheme for which we want to add the header. + * @return {@code true} if the header has been added, {@code false} otherwise. */ - private void addEndpointHeader(ComponentModel componentModel, Field field) { + private boolean addEndpointHeader(ComponentModel componentModel, Field field, String scheme) { final Metadata metadata = field.getAnnotation(Metadata.class); if (metadata == null) { getLog().debug(String.format("The field %s in class %s has no Metadata", field.getName(), field.getDeclaringClass().getName())); - return; + return false; + } + final String[] applicableFor = metadata.applicableFor(); + if (applicableFor.length > 0 && !Arrays.stream(applicableFor).anyMatch(s -> s.equals(scheme))) { + getLog().debug(String.format("The field %s in class %s is not applicable for %s", field.getName(), + field.getDeclaringClass().getName(), scheme)); + return false; } final EndpointHeaderModel header = new EndpointHeaderModel(); header.setDescription(metadata.description().trim()); @@ -373,6 +387,7 @@ public class EndpointSchemaGeneratorMojo extends AbstractGeneratorMojo { getLog().debug(String.format("The field %s in class %s cannot be accessed", field.getName(), field.getDeclaringClass().getName())); } + return true; } private String getExcludedEnd(Metadata classElement) { diff --git a/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/EndpointSchemaGeneratorMojoTest.java b/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/EndpointSchemaGeneratorMojoTest.java index 8e65a7d..d64649b 100644 --- a/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/EndpointSchemaGeneratorMojoTest.java +++ b/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/EndpointSchemaGeneratorMojoTest.java @@ -21,6 +21,7 @@ import java.util.List; import org.apache.camel.maven.packaging.endpoint.SomeEndpoint; import org.apache.camel.maven.packaging.endpoint.SomeEndpointWithBadHeaders; +import org.apache.camel.maven.packaging.endpoint.SomeEndpointWithFilter; import org.apache.camel.maven.packaging.endpoint.SomeEndpointWithoutHeaders; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.tooling.model.ComponentModel; @@ -53,7 +54,7 @@ class EndpointSchemaGeneratorMojoTest { @Test void testCanRetrieveMetadataOfHeaders() { - mojo.addEndpointHeaders(model, SomeEndpoint.class.getAnnotation(UriEndpoint.class)); + mojo.addEndpointHeaders(model, SomeEndpoint.class.getAnnotation(UriEndpoint.class), "some"); List<EndpointHeaderModel> endpointHeaders = model.getEndpointHeaders(); assertEquals(2, endpointHeaders.size()); // Full @@ -91,13 +92,25 @@ class EndpointSchemaGeneratorMojoTest { @Test void testHeadersNotProperlyDefinedAreIgnored() { - mojo.addEndpointHeaders(model, SomeEndpointWithBadHeaders.class.getAnnotation(UriEndpoint.class)); + mojo.addEndpointHeaders(model, SomeEndpointWithBadHeaders.class.getAnnotation(UriEndpoint.class), "some"); assertEquals(0, model.getEndpointHeaders().size()); } @Test void testEndpointWithoutHeadersAreIgnored() { - mojo.addEndpointHeaders(model, SomeEndpointWithoutHeaders.class.getAnnotation(UriEndpoint.class)); + mojo.addEndpointHeaders(model, SomeEndpointWithoutHeaders.class.getAnnotation(UriEndpoint.class), "some"); assertEquals(0, model.getEndpointHeaders().size()); } + + @Test + void testEndpointWithFilterKeepOnlyApplicableHeaders() { + mojo.addEndpointHeaders(model, SomeEndpointWithFilter.class.getAnnotation(UriEndpoint.class), "some"); + List<EndpointHeaderModel> endpointHeaders = model.getEndpointHeaders(); + assertEquals(2, endpointHeaders.size()); + for (int i = 0; i < endpointHeaders.size(); i++) { + EndpointHeaderModel headerEmpty = endpointHeaders.get(i); + assertEquals("header", headerEmpty.getKind()); + assertEquals(String.format("keep-%d", i + 1), headerEmpty.getName()); + } + } } diff --git a/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithFilter.java b/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithFilter.java new file mode 100644 index 0000000..e406eb3 --- /dev/null +++ b/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithFilter.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.maven.packaging.endpoint; + +import org.apache.camel.spi.Metadata; +import org.apache.camel.spi.UriEndpoint; + +@UriEndpoint(scheme = "some", syntax = "some", title = "some", headersClass = SomeEndpointWithFilter.class) +public final class SomeEndpointWithFilter { + + @Metadata(description = "some description") + static final String KEEP_1 = "keep-1"; + @Metadata(description = "some description", applicableFor = "some") + static final String KEEP_2 = "keep-2"; + @Metadata(description = "some description", applicableFor = "other") + static final String IGNORE = "ignore"; + + private SomeEndpointWithFilter() { + } +} diff --git a/tooling/spi-annotations/src/main/java/org/apache/camel/spi/Metadata.java b/tooling/spi-annotations/src/main/java/org/apache/camel/spi/Metadata.java index f37ea43..57f5a47 100644 --- a/tooling/spi-annotations/src/main/java/org/apache/camel/spi/Metadata.java +++ b/tooling/spi-annotations/src/main/java/org/apache/camel/spi/Metadata.java @@ -132,4 +132,21 @@ public @interface Metadata { * specify which options each implementation only supports. */ String includeProperties() default ""; + + /** + * Indicates the list of schemes for which this metadata is applicable. This is used to filter out message headers + * that are shared with several endpoints but only applicable for some of them. + * <p/> + * In the next example, the header {@code SOME_HEADER} is only applicable for endpoints whose scheme is "foo" or + * "bar". + * + * <pre> + * <code> + * + * @Metadata(description = "some description", javaType = "String", applicableFor = {"foo", "bar"}) + * public static final String SOME_HEADER = "someHeaderName"; + * </code> + * </pre> + */ + String[] applicableFor() default {}; }