camel-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From zregv...@apache.org
Subject [camel] branch master updated: CAMEL-11968: Support literal values in endpoint...
Date Mon, 30 Oct 2017 22:45:31 GMT
This is an automated email from the ASF dual-hosted git repository.

zregvart pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/master by this push:
     new 4c5c93f  CAMEL-11968: Support literal values in endpoint...
4c5c93f is described below

commit 4c5c93f23672b425c86a650b41ab40102581997b
Author: Zoran Regvart <zregvart@apache.org>
AuthorDate: Mon Oct 30 23:40:22 2017 +0100

    CAMEL-11968: Support literal values in endpoint...
    
    ... parameters
    
    Adds support for literal values, i.e. a predefined constant values that
    can be specified directly on the REST Swagger component's endpoint URI
    and passed along to the delegating component in the URI.
---
 .../src/main/docs/rest-swagger-component.adoc      |  7 ++
 .../rest/swagger/RestSwaggerComponent.java         |  2 +-
 .../rest/swagger/RestSwaggerEndpoint.java          | 96 ++++++++++++++++++++--
 .../rest/swagger/RestSwaggerComponentTest.java     | 15 ++++
 .../rest/swagger/RestSwaggerEndpointTest.java      | 58 +++++++++----
 .../swagger/RestSwaggerEndpointUriParsingTest.java |  4 +-
 6 files changed, 157 insertions(+), 25 deletions(-)

diff --git a/components/camel-rest-swagger/src/main/docs/rest-swagger-component.adoc b/components/camel-rest-swagger/src/main/docs/rest-swagger-component.adoc
index d3150dc..cc5e445 100644
--- a/components/camel-rest-swagger/src/main/docs/rest-swagger-component.adoc
+++ b/components/camel-rest-swagger/src/main/docs/rest-swagger-component.adoc
@@ -73,6 +73,13 @@ endpoint level, CLASSPATH is searched for a suitable delegate. There
 should be only one component present on the CLASSPATH that implements 
 the _RestProducerFactory_ interface for this to work.
 
+This component's endpoint URI is lenient which means that in addition
+to message headers you can specify REST operation's parameters as
+endpoint parameters, these will be constant for all subsequent
+invocations so it makes sense to use this feature only for parameters
+that are indeed constant for all invocations -- for example API version
+in path such as `/api/{version}/users/{id}`. 
+
 ### Options
 
 // component options: START
diff --git a/components/camel-rest-swagger/src/main/java/org/apache/camel/component/rest/swagger/RestSwaggerComponent.java
b/components/camel-rest-swagger/src/main/java/org/apache/camel/component/rest/swagger/RestSwaggerComponent.java
index 943f834..9442fd2 100644
--- a/components/camel-rest-swagger/src/main/java/org/apache/camel/component/rest/swagger/RestSwaggerComponent.java
+++ b/components/camel-rest-swagger/src/main/java/org/apache/camel/component/rest/swagger/RestSwaggerComponent.java
@@ -181,7 +181,7 @@ public final class RestSwaggerComponent extends DefaultComponent {
     @Override
     protected Endpoint createEndpoint(final String uri, final String remaining, final Map<String,
Object> parameters)
         throws Exception {
-        final Endpoint endpoint = new RestSwaggerEndpoint(uri, remaining, this);
+        final Endpoint endpoint = new RestSwaggerEndpoint(uri, remaining, this, parameters);
 
         setProperties(endpoint, parameters);
 
diff --git a/components/camel-rest-swagger/src/main/java/org/apache/camel/component/rest/swagger/RestSwaggerEndpoint.java
b/components/camel-rest-swagger/src/main/java/org/apache/camel/component/rest/swagger/RestSwaggerEndpoint.java
index bfc9261..20b3df0 100644
--- a/components/camel-rest-swagger/src/main/java/org/apache/camel/component/rest/swagger/RestSwaggerEndpoint.java
+++ b/components/camel-rest-swagger/src/main/java/org/apache/camel/component/rest/swagger/RestSwaggerEndpoint.java
@@ -20,11 +20,13 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.net.URI;
 import java.net.URISyntaxException;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Optional;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 
 import static java.util.Optional.ofNullable;
@@ -56,6 +58,7 @@ import org.apache.camel.spi.UriPath;
 import org.apache.camel.util.ObjectHelper;
 import org.apache.camel.util.ResourceHelper;
 import org.apache.camel.util.StringHelper;
+import org.apache.camel.util.UnsafeUriCharactersEncoder;
 
 import static org.apache.camel.component.rest.swagger.RestSwaggerHelper.isHostParam;
 import static org.apache.camel.component.rest.swagger.RestSwaggerHelper.isMediaRange;
@@ -72,6 +75,11 @@ import static org.apache.camel.util.StringHelper.notEmpty;
     syntax = "rest-swagger:specificationUri#operationId", label = "rest,swagger,http", producerOnly
= true)
 public final class RestSwaggerEndpoint extends DefaultEndpoint {
 
+    /**
+     * Remaining parameters specified in the Endpoint URI.
+     */
+    Map<String, Object> parameters = Collections.emptyMap();
+
     /** The name of the Camel component, be it `rest-swagger` or `petstore` */
     private String assignedComponentName;
 
@@ -128,8 +136,10 @@ public final class RestSwaggerEndpoint extends DefaultEndpoint {
         // help tooling instantiate endpoint
     }
 
-    public RestSwaggerEndpoint(final String uri, final String remaining, final RestSwaggerComponent
component) {
+    public RestSwaggerEndpoint(final String uri, final String remaining, final RestSwaggerComponent
component,
+        final Map<String, Object> parameters) {
         super(notEmpty(uri, "uri"), notNull(component, "component"));
+        this.parameters = parameters;
 
         assignedComponentName = before(uri, ":");
 
@@ -165,13 +175,15 @@ public final class RestSwaggerEndpoint extends DefaultEndpoint {
             if (maybeOperationEntry.isPresent()) {
                 final Entry<HttpMethod, Operation> operationEntry = maybeOperationEntry.get();
 
-                final String uriTemplate = pathEntry.getKey();
+                final Operation operation = operationEntry.getValue();
+                final Map<String, Parameter> pathParameters = operation.getParameters().stream()
+                    .filter(p -> "path".equals(p.getIn()))
+                    .collect(Collectors.toMap(Parameter::getName, Function.identity()));
+                final String uriTemplate = resolveUri(pathEntry.getKey(), pathParameters);
 
                 final HttpMethod httpMethod = operationEntry.getKey();
                 final String method = httpMethod.name();
 
-                final Operation operation = operationEntry.getValue();
-
                 return createProducerFor(swagger, operation, method, uriTemplate);
             }
         }
@@ -213,6 +225,11 @@ public final class RestSwaggerEndpoint extends DefaultEndpoint {
     }
 
     @Override
+    public boolean isLenientProperties() {
+        return true;
+    }
+
+    @Override
     public boolean isSingleton() {
         return true;
     }
@@ -331,7 +348,7 @@ public final class RestSwaggerEndpoint extends DefaultEndpoint {
         }
 
         final String queryParameters = operation.getParameters().stream().filter(p ->
"query".equals(p.getIn()))
-            .map(RestSwaggerEndpoint::queryParameterExpression).collect(Collectors.joining("&"));
+            .map(this::queryParameter).collect(Collectors.joining("&"));
         if (isNotEmpty(queryParameters)) {
             parameters.put("queryParameters", queryParameters);
         }
@@ -396,6 +413,72 @@ public final class RestSwaggerEndpoint extends DefaultEndpoint {
             + " and there is no global RestConfiguration with those properties");
     }
 
+    String literalPathParameterValue(final Parameter parameter) {
+        final String name = parameter.getName();
+
+        final String valueStr = String.valueOf(parameters.get(name));
+        final String encoded = UnsafeUriCharactersEncoder.encode(valueStr);
+
+        return encoded;
+    }
+
+    String literalQueryParameterValue(final Parameter parameter) {
+        final String name = parameter.getName();
+
+        final String valueStr = String.valueOf(parameters.get(name));
+        final String encoded = UnsafeUriCharactersEncoder.encode(valueStr);
+
+        return name + "=" + encoded;
+    }
+
+    String queryParameter(final Parameter parameter) {
+        final String name = parameter.getName();
+        if (ObjectHelper.isEmpty(name)) {
+            return "";
+        }
+
+        if (parameters.containsKey(name)) {
+            return literalQueryParameterValue(parameter);
+        }
+
+        return queryParameterExpression(parameter);
+    }
+
+    String resolveUri(final String uriTemplate, final Map<String, Parameter> pathParameters)
{
+        if (pathParameters.isEmpty()) {
+            return uriTemplate;
+        }
+
+        int start = uriTemplate.indexOf('{');
+
+        if (start == -1) {
+            return uriTemplate;
+        }
+
+        int pos = 0;
+        final StringBuilder resolved = new StringBuilder(uriTemplate.length() * 2);
+        while (start != -1) {
+            resolved.append(uriTemplate.substring(pos, start));
+
+            final int end = uriTemplate.indexOf('}', start);
+
+            final String name = uriTemplate.substring(start + 1, end);
+
+            if (parameters.containsKey(name)) {
+                final Parameter parameter = pathParameters.get(name);
+                final Object value = literalPathParameterValue(parameter);
+                resolved.append(value);
+            } else {
+                resolved.append('{').append(name).append('}');
+            }
+
+            pos = end;
+            start = uriTemplate.indexOf('{', pos);
+        }
+
+        return resolved.toString();
+    }
+
     static String determineOption(final List<String> specificationLevel, final List<String>
operationLevel,
         final String componentLevel, final String endpointLevel) {
         if (isNotEmpty(endpointLevel)) {
@@ -498,9 +581,6 @@ public final class RestSwaggerEndpoint extends DefaultEndpoint {
 
     static String queryParameterExpression(final Parameter parameter) {
         final String name = parameter.getName();
-        if (ObjectHelper.isEmpty(name)) {
-            return "";
-        }
 
         final StringBuilder expression = new StringBuilder(name).append("={").append(name);
         if (!parameter.getRequired()) {
diff --git a/components/camel-rest-swagger/src/test/java/org/apache/camel/component/rest/swagger/RestSwaggerComponentTest.java
b/components/camel-rest-swagger/src/test/java/org/apache/camel/component/rest/swagger/RestSwaggerComponentTest.java
index f8f002d..dfe5c6f 100644
--- a/components/camel-rest-swagger/src/test/java/org/apache/camel/component/rest/swagger/RestSwaggerComponentTest.java
+++ b/components/camel-rest-swagger/src/test/java/org/apache/camel/component/rest/swagger/RestSwaggerComponentTest.java
@@ -100,6 +100,19 @@ public class RestSwaggerComponentTest extends CamelTestSupport {
     }
 
     @Test
+    public void shouldBeGettingPetsByIdSpecifiedInEndpointParameters() {
+        final Pet pet = template.requestBody("direct:getPetByIdWithEndpointParams", NO_BODY,
Pet.class);
+
+        assertNotNull(pet);
+
+        assertEquals(Integer.valueOf(14), pet.id);
+        assertEquals("Olafur Eliason Arnalds", pet.name);
+
+        petstore.verify(getRequestedFor(urlEqualTo("/v2/pet/14")).withHeader("Accept",
+            equalTo("application/xml, application/json")));
+    }
+
+    @Test
     public void shouldBeGettingPetsByStatus() {
         final Pets pets = template.requestBodyAndHeader("direct:findPetsByStatus", NO_BODY,
"status", "available",
             Pets.class);
@@ -139,6 +152,8 @@ public class RestSwaggerComponentTest extends CamelTestSupport {
 
                 from("direct:getPetById").to("petStore:getPetById").unmarshal(jaxb);
 
+                from("direct:getPetByIdWithEndpointParams").to("petStore:getPetById?petId=14").unmarshal(jaxb);
+
                 from("direct:addPet").marshal(jaxb).to("petStore:addPet").unmarshal(jaxb);
 
                 from("direct:findPetsByStatus").to("petStore:findPetsByStatus").unmarshal(jaxb);
diff --git a/components/camel-rest-swagger/src/test/java/org/apache/camel/component/rest/swagger/RestSwaggerEndpointTest.java
b/components/camel-rest-swagger/src/test/java/org/apache/camel/component/rest/swagger/RestSwaggerEndpointTest.java
index d16cbee..cb88a8c 100644
--- a/components/camel-rest-swagger/src/test/java/org/apache/camel/component/rest/swagger/RestSwaggerEndpointTest.java
+++ b/components/camel-rest-swagger/src/test/java/org/apache/camel/component/rest/swagger/RestSwaggerEndpointTest.java
@@ -20,10 +20,12 @@ import java.io.IOException;
 import java.net.URI;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashMap;
 
 import io.swagger.models.Operation;
 import io.swagger.models.Scheme;
 import io.swagger.models.Swagger;
+import io.swagger.models.parameters.PathParameter;
 import io.swagger.models.parameters.QueryParameter;
 
 import org.apache.camel.CamelContext;
@@ -51,12 +53,24 @@ public class RestSwaggerEndpointTest {
 
         final RestSwaggerComponent component = new RestSwaggerComponent(camelContext);
 
-        final RestSwaggerEndpoint endpoint = new RestSwaggerEndpoint("rest-swagger:unknown",
"unknown", component);
+        final RestSwaggerEndpoint endpoint = new RestSwaggerEndpoint("rest-swagger:unknown",
"unknown", component,
+            Collections.emptyMap());
 
         endpoint.createProducer();
     }
 
     @Test
+    public void shouldComputeQueryParameters() {
+        final RestSwaggerEndpoint endpoint = new RestSwaggerEndpoint();
+        endpoint.parameters = new HashMap<>();
+        endpoint.parameters.put("literal", "value");
+
+        assertThat(endpoint.queryParameter(new QueryParameter())).isEqualTo("");
+        assertThat(endpoint.queryParameter(new QueryParameter().name("param"))).isEqualTo("param={param?}");
+        assertThat(endpoint.queryParameter(new QueryParameter().name("literal"))).isEqualTo("literal=value");
+    }
+
+    @Test
     public void shouldCreateProducers() throws Exception {
         final CamelContext camelContext = mock(CamelContext.class);
         when(camelContext.getClassResolver()).thenReturn(new DefaultClassResolver());
@@ -68,8 +82,8 @@ public class RestSwaggerEndpointTest {
         final RestSwaggerComponent component = new RestSwaggerComponent(camelContext);
         component.setHost("http://petstore.swagger.io");
 
-        final RestSwaggerEndpoint endpoint = new RestSwaggerEndpoint("rest-swagger:getPetById",
"getPetById",
-            component);
+        final RestSwaggerEndpoint endpoint = new RestSwaggerEndpoint("rest-swagger:getPetById",
"getPetById", component,
+            Collections.emptyMap());
 
         final Producer producer = endpoint.createProducer();
 
@@ -78,7 +92,6 @@ public class RestSwaggerEndpointTest {
 
     @Test
     public void shouldCreateQueryParameterExpressions() {
-        assertThat(RestSwaggerEndpoint.queryParameterExpression(new QueryParameter())).isEmpty();
         assertThat(RestSwaggerEndpoint.queryParameterExpression(new QueryParameter().name("q").required(true)))
             .isEqualTo("q={q}");
         assertThat(RestSwaggerEndpoint.queryParameterExpression(new QueryParameter().name("q").required(false)))
@@ -96,8 +109,8 @@ public class RestSwaggerEndpointTest {
 
         final RestSwaggerComponent component = new RestSwaggerComponent();
         component.setCamelContext(camelContext);
-        final RestSwaggerEndpoint endpoint = new RestSwaggerEndpoint("rest-swagger:getPetById",
"getPetById",
-            component);
+        final RestSwaggerEndpoint endpoint = new RestSwaggerEndpoint("rest-swagger:getPetById",
"getPetById", component,
+            Collections.emptyMap());
 
         assertThat(endpoint.determineBasePath(swagger))
             .as("When no base path is specified on component, endpoint or rest configuration
it should default to `/`")
@@ -131,7 +144,8 @@ public class RestSwaggerEndpointTest {
         final RestSwaggerComponent component = new RestSwaggerComponent();
         component.setCamelContext(camelContext);
 
-        final RestSwaggerEndpoint endpoint = new RestSwaggerEndpoint("uri", "remaining",
component);
+        final RestSwaggerEndpoint endpoint = new RestSwaggerEndpoint("uri", "remaining",
component,
+            Collections.emptyMap());
         endpoint.setHost("http://petstore.swagger.io");
 
         final Swagger swagger = new Swagger();
@@ -214,7 +228,7 @@ public class RestSwaggerEndpointTest {
         final RestSwaggerComponent component = new RestSwaggerComponent();
 
         final RestSwaggerEndpoint endpoint = new RestSwaggerEndpoint("rest-swagger:http://some-uri#getPetById",
-            "http://some-uri#getPetById", component);
+            "http://some-uri#getPetById", component, Collections.emptyMap());
 
         final Swagger swagger = new Swagger();
         swagger.host("petstore.swagger.io");
@@ -251,8 +265,8 @@ public class RestSwaggerEndpointTest {
         final RestSwaggerComponent component = new RestSwaggerComponent();
         component.setSpecificationUri(componentJsonUri);
 
-        final RestSwaggerEndpoint endpoint = new RestSwaggerEndpoint("rest-swagger:getPetById",
"getPetById",
-            component);
+        final RestSwaggerEndpoint endpoint = new RestSwaggerEndpoint("rest-swagger:getPetById",
"getPetById", component,
+            Collections.emptyMap());
 
         assertThat(endpoint.getSpecificationUri()).isEqualTo(componentJsonUri);
     }
@@ -263,7 +277,7 @@ public class RestSwaggerEndpointTest {
         component.setSpecificationUri(componentJsonUri);
 
         final RestSwaggerEndpoint endpoint = new RestSwaggerEndpoint("rest-swagger:endpoint.json#getPetById",
-            "endpoint.json#getPetById", component);
+            "endpoint.json#getPetById", component, Collections.emptyMap());
 
         assertThat(endpoint.getSpecificationUri()).isEqualTo(endpointUri);
     }
@@ -284,7 +298,7 @@ public class RestSwaggerEndpointTest {
         component.setCamelContext(camelContext);
 
         final RestSwaggerEndpoint endpoint = new RestSwaggerEndpoint("petstore:http://specification-uri#getPetById",
-            "http://specification-uri#getPetById", component);
+            "http://specification-uri#getPetById", component, Collections.emptyMap());
 
         final Swagger swagger = new Swagger();
         assertThat(endpoint.determineHost(swagger)).isEqualTo("http://specification-uri");
@@ -346,11 +360,25 @@ public class RestSwaggerEndpointTest {
     }
 
     @Test
+    public void shouldSerializeGivenLiteralValues() {
+        final RestSwaggerEndpoint endpoint = new RestSwaggerEndpoint();
+        endpoint.parameters = new HashMap<>();
+        endpoint.parameters.put("param", "va lue");
+
+        final QueryParameter queryParameter = new QueryParameter().name("param");
+
+        assertThat(endpoint.literalQueryParameterValue(queryParameter)).isEqualTo("param=va%20lue");
+
+        final PathParameter pathParameter = new PathParameter().name("param");
+        assertThat(endpoint.literalPathParameterValue(pathParameter)).isEqualTo("va%20lue");
+    }
+
+    @Test
     public void shouldUseDefaultSpecificationUri() throws Exception {
         final RestSwaggerComponent component = new RestSwaggerComponent();
 
-        final RestSwaggerEndpoint endpoint = new RestSwaggerEndpoint("rest-swagger:getPetById",
"getPetById",
-            component);
+        final RestSwaggerEndpoint endpoint = new RestSwaggerEndpoint("rest-swagger:getPetById",
"getPetById", component,
+            Collections.emptyMap());
 
         assertThat(endpoint.getSpecificationUri()).isEqualTo(RestSwaggerComponent.DEFAULT_SPECIFICATION_URI);
     }
@@ -360,7 +388,7 @@ public class RestSwaggerEndpointTest {
         final RestSwaggerComponent component = new RestSwaggerComponent();
 
         final RestSwaggerEndpoint endpoint = new RestSwaggerEndpoint("rest-swagger:#getPetById",
"#getPetById",
-            component);
+            component, Collections.emptyMap());
 
         assertThat(endpoint.getSpecificationUri()).isEqualTo(RestSwaggerComponent.DEFAULT_SPECIFICATION_URI);
     }
diff --git a/components/camel-rest-swagger/src/test/java/org/apache/camel/component/rest/swagger/RestSwaggerEndpointUriParsingTest.java
b/components/camel-rest-swagger/src/test/java/org/apache/camel/component/rest/swagger/RestSwaggerEndpointUriParsingTest.java
index ee90a36..7f73d76 100644
--- a/components/camel-rest-swagger/src/test/java/org/apache/camel/component/rest/swagger/RestSwaggerEndpointUriParsingTest.java
+++ b/components/camel-rest-swagger/src/test/java/org/apache/camel/component/rest/swagger/RestSwaggerEndpointUriParsingTest.java
@@ -17,6 +17,7 @@
 package org.apache.camel.component.rest.swagger;
 
 import java.util.Arrays;
+import java.util.Collections;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -45,7 +46,8 @@ public class RestSwaggerEndpointUriParsingTest {
     public void shouldParseEndpointUri() {
         final RestSwaggerComponent component = new RestSwaggerComponent();
 
-        final RestSwaggerEndpoint endpoint = new RestSwaggerEndpoint(specificationUri, remaining,
component);
+        final RestSwaggerEndpoint endpoint = new RestSwaggerEndpoint(specificationUri, remaining,
component,
+            Collections.emptyMap());
 
         assertThat(endpoint.getSpecificationUri().toString()).isEqualTo(specificationUri);
         assertThat(endpoint.getOperationId()).isEqualTo(operationId);

-- 
To stop receiving notification emails like this one, please contact
['"commits@camel.apache.org" <commits@camel.apache.org>'].

Mime
View raw message