CAMEL-8545: camel-swagger-java to run outside servlet - work in progress
Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/f3aed3eb Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/f3aed3eb Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/f3aed3eb Branch: refs/heads/master Commit: f3aed3eb1ea9fce9dff9adf70ba6a5e4fd08986e Parents: d975acd Author: Claus Ibsen <davscl...@apache.org> Authored: Wed Sep 23 11:17:41 2015 +0200 Committer: Claus Ibsen <davscl...@apache.org> Committed: Wed Sep 23 11:17:41 2015 +0200 ---------------------------------------------------------------------- .../camel/component/rest/RestApiEndpoint.java | 17 +++++++-- .../model/rest/RestConfigurationDefinition.java | 37 ++++++++++++++++++++ .../apache/camel/model/rest/RestDefinition.java | 3 ++ .../camel/spi/RestApiProcessorFactory.java | 10 +++--- .../org/apache/camel/spi/RestConfiguration.java | 17 +++++++++ .../rest/DummyRestProcessorFactory.java | 3 +- .../camel/swagger/RestSwaggerProcessor.java | 26 +++++++++++--- .../camel/swagger/RestSwaggerSupport.java | 15 +++++++- .../swagger/SwaggerRestApiProcessorFactory.java | 4 +-- .../swagger/servlet/RestSwaggerServlet.java | 2 +- .../camel/example/cdi/UserRouteBuilder.java | 6 ++-- 11 files changed, 120 insertions(+), 20 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/f3aed3eb/camel-core/src/main/java/org/apache/camel/component/rest/RestApiEndpoint.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/component/rest/RestApiEndpoint.java b/camel-core/src/main/java/org/apache/camel/component/rest/RestApiEndpoint.java index e6df668..a5e7276 100644 --- a/camel-core/src/main/java/org/apache/camel/component/rest/RestApiEndpoint.java +++ b/camel-core/src/main/java/org/apache/camel/component/rest/RestApiEndpoint.java @@ -33,7 +33,7 @@ import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; import org.apache.camel.spi.UriPath; -@UriEndpoint(scheme = "rest-api", title = "REST API", syntax = "rest-api:path", consumerOnly = true, label = "core,rest") +@UriEndpoint(scheme = "rest-api", title = "REST API", syntax = "rest-api:path/contextId", consumerOnly = true, label = "core,rest") public class RestApiEndpoint extends DefaultEndpoint { public static final String DEFAULT_API_COMPONENT_NAME = "swagger"; @@ -41,6 +41,8 @@ public class RestApiEndpoint extends DefaultEndpoint { @UriPath @Metadata(required = "true") private String path; + @UriPath + private String contextIdPattern; @UriParam private String componentName; @UriParam @@ -68,6 +70,17 @@ public class RestApiEndpoint extends DefaultEndpoint { this.path = path; } + public String getContextIdPattern() { + return contextIdPattern; + } + + /** + * Optional CamelContext id pattern to only allow Rest APIs from rest services within CamelContext's which name matches the pattern. + */ + public void setContextIdPattern(String contextIdPattern) { + this.contextIdPattern = contextIdPattern; + } + public String getComponentName() { return componentName; } @@ -134,7 +147,7 @@ public class RestApiEndpoint extends DefaultEndpoint { path = "/" + path; } - Processor processor = factory.createApiProcessor(getCamelContext(), path, config, getParameters()); + Processor processor = factory.createApiProcessor(getCamelContext(), path, getContextIdPattern(), config, getParameters()); return new RestApiProducer(this, processor); } else { throw new IllegalStateException("Cannot find RestApiProcessorFactory in Registry or classpath"); http://git-wip-us.apache.org/repos/asf/camel/blob/f3aed3eb/camel-core/src/main/java/org/apache/camel/model/rest/RestConfigurationDefinition.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/model/rest/RestConfigurationDefinition.java b/camel-core/src/main/java/org/apache/camel/model/rest/RestConfigurationDefinition.java index 90a6138..0467f21 100644 --- a/camel-core/src/main/java/org/apache/camel/model/rest/RestConfigurationDefinition.java +++ b/camel-core/src/main/java/org/apache/camel/model/rest/RestConfigurationDefinition.java @@ -61,6 +61,9 @@ public class RestConfigurationDefinition { private String apiContextPath; @XmlAttribute + private String apiContextIdPattern; + + @XmlAttribute private RestHostNameResolver hostNameResolver; @XmlAttribute @Metadata(defaultValue = "auto") @@ -190,6 +193,22 @@ public class RestConfigurationDefinition { this.apiContextPath = contextPath; } + public String getApiContextIdPattern() { + return apiContextIdPattern; + } + + /** + * Sets an CamelContext id pattern to only allow Rest APIs from rest services within CamelContext's which name matches the pattern. + * <p/> + * The pattern <tt>#name#</tt> refers to the CamelContext name, to match on the current CamelContext only. + * For any other value, the pattern uses the rules from {@link org.apache.camel.util.EndpointHelper#matchPattern(String, String)} + * + * @param apiContextIdPattern the pattern + */ + public void setApiContextIdPattern(String apiContextIdPattern) { + this.apiContextIdPattern = apiContextIdPattern; + } + public RestHostNameResolver getHostNameResolver() { return hostNameResolver; } @@ -406,6 +425,16 @@ public class RestConfigurationDefinition { } /** + * Sets an CamelContext id pattern to only allow Rest APIs from rest services within CamelContext's which name matches the pattern. + * <p/> + * The pattern uses the rules from {@link org.apache.camel.util.EndpointHelper#matchPattern(String, String)} + */ + public RestConfigurationDefinition apiContextIdPattern(String pattern) { + setApiContextIdPattern(pattern); + return this; + } + + /** * Sets a leading context-path the REST services will be using. * <p/> * This can be used when using components such as <tt>camel-servlet</tt> where the deployed web application @@ -568,6 +597,14 @@ public class RestConfigurationDefinition { if (apiContextPath != null) { answer.setApiContextPath(CamelContextHelper.parseText(context, apiContextPath)); } + if (apiContextIdPattern != null) { + // special to allow #name# to refer to itself + if ("#name#".equals(apiComponent)) { + answer.setApiContextIdPattern(context.getName()); + } else { + answer.setApiContextIdPattern(CamelContextHelper.parseText(context, apiContextIdPattern)); + } + } if (contextPath != null) { answer.setContextPath(CamelContextHelper.parseText(context, contextPath)); } http://git-wip-us.apache.org/repos/asf/camel/blob/f3aed3eb/camel-core/src/main/java/org/apache/camel/model/rest/RestDefinition.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/model/rest/RestDefinition.java b/camel-core/src/main/java/org/apache/camel/model/rest/RestDefinition.java index c004af7..e2b1895 100644 --- a/camel-core/src/main/java/org/apache/camel/model/rest/RestDefinition.java +++ b/camel-core/src/main/java/org/apache/camel/model/rest/RestDefinition.java @@ -554,6 +554,9 @@ public class RestDefinition extends OptionalIdentifiedDefinition<RestDefinition> if (configuration.getComponent() != null && !configuration.getComponent().isEmpty()) { options.put("componentName", configuration.getComponent()); } + if (configuration.getApiContextIdPattern() != null) { + options.put("contextIdPattern", configuration.getApiContextIdPattern()); + } if (!options.isEmpty()) { String query; http://git-wip-us.apache.org/repos/asf/camel/blob/f3aed3eb/camel-core/src/main/java/org/apache/camel/spi/RestApiProcessorFactory.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/spi/RestApiProcessorFactory.java b/camel-core/src/main/java/org/apache/camel/spi/RestApiProcessorFactory.java index a721ec5..8f5210d 100644 --- a/camel-core/src/main/java/org/apache/camel/spi/RestApiProcessorFactory.java +++ b/camel-core/src/main/java/org/apache/camel/spi/RestApiProcessorFactory.java @@ -28,14 +28,14 @@ public interface RestApiProcessorFactory { * href="http://camel.apache.org/processor.html">Processor * </a>, which provides API listing of the REST services * - * @param camelContext the camel context - * @param contextPath the context-path - * @param parameters additional parameters - * + * @param camelContext the camel context + * @param contextPath the context-path + * @param contextIdPattern id pattern to only allow Rest APIs from rest services within CamelContext's which name matches the pattern. + * @param parameters additional parameters * @return a newly created REST API provider * @throws Exception can be thrown */ - Processor createApiProcessor(CamelContext camelContext, String contextPath, + Processor createApiProcessor(CamelContext camelContext, String contextPath, String contextIdPattern, RestConfiguration configuration, Map<String, Object> parameters) throws Exception; } http://git-wip-us.apache.org/repos/asf/camel/blob/f3aed3eb/camel-core/src/main/java/org/apache/camel/spi/RestConfiguration.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/spi/RestConfiguration.java b/camel-core/src/main/java/org/apache/camel/spi/RestConfiguration.java index 55a45d6..c8cbcff 100644 --- a/camel-core/src/main/java/org/apache/camel/spi/RestConfiguration.java +++ b/camel-core/src/main/java/org/apache/camel/spi/RestConfiguration.java @@ -44,6 +44,7 @@ public class RestConfiguration { private int port; private String contextPath; private String apiContextPath; + private String apiContextIdPattern; private RestHostNameResolver restHostNameResolver = RestHostNameResolver.localHostName; private RestBindingMode bindingMode = RestBindingMode.off; private boolean skipBindingOnErrorCode = true; @@ -184,6 +185,22 @@ public class RestConfiguration { this.apiContextPath = contextPath; } + public String getApiContextIdPattern() { + return apiContextIdPattern; + } + + /** + * Optional CamelContext id pattern to only allow Rest APIs from rest services within CamelContext's which name matches the pattern. + * <p/> + * The pattern <tt>#name#</tt> refers to the CamelContext name, to match on the current CamelContext only. + * For any other value, the pattern uses the rules from {@link org.apache.camel.util.EndpointHelper#matchPattern(String, String)} + * + * @param apiContextIdPattern the pattern + */ + public void setApiContextIdPattern(String apiContextIdPattern) { + this.apiContextIdPattern = apiContextIdPattern; + } + /** * Gets the resolver to use for resolving hostname * http://git-wip-us.apache.org/repos/asf/camel/blob/f3aed3eb/camel-core/src/test/java/org/apache/camel/component/rest/DummyRestProcessorFactory.java ---------------------------------------------------------------------- diff --git a/camel-core/src/test/java/org/apache/camel/component/rest/DummyRestProcessorFactory.java b/camel-core/src/test/java/org/apache/camel/component/rest/DummyRestProcessorFactory.java index 1fbe87f..f2d2948 100644 --- a/camel-core/src/test/java/org/apache/camel/component/rest/DummyRestProcessorFactory.java +++ b/camel-core/src/test/java/org/apache/camel/component/rest/DummyRestProcessorFactory.java @@ -27,7 +27,8 @@ import org.apache.camel.spi.RestConfiguration; public class DummyRestProcessorFactory implements RestApiProcessorFactory { @Override - public Processor createApiProcessor(CamelContext camelContext, String contextPath, RestConfiguration configuration, Map<String, Object> parameters) throws Exception { + public Processor createApiProcessor(CamelContext camelContext, String contextPath, String contextIdPattern, + RestConfiguration configuration, Map<String, Object> parameters) throws Exception { return new Processor() { @Override public void process(Exchange exchange) throws Exception { http://git-wip-us.apache.org/repos/asf/camel/blob/f3aed3eb/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/RestSwaggerProcessor.java ---------------------------------------------------------------------- diff --git a/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/RestSwaggerProcessor.java b/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/RestSwaggerProcessor.java index f2752a6..58d3205 100644 --- a/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/RestSwaggerProcessor.java +++ b/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/RestSwaggerProcessor.java @@ -22,6 +22,7 @@ import java.util.Map; import io.swagger.jaxrs.config.BeanConfig; import org.apache.camel.Exchange; import org.apache.camel.Processor; +import org.apache.camel.util.EndpointHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -30,11 +31,14 @@ public class RestSwaggerProcessor implements Processor { private static final Logger LOG = LoggerFactory.getLogger(RestSwaggerProcessor.class); private final BeanConfig swaggerConfig; private final RestSwaggerSupport support; + private final String contextIdPattern; @SuppressWarnings("unchecked") - public RestSwaggerProcessor(Map<String, Object> parameters) { - support = new RestSwaggerSupport(); - swaggerConfig = new BeanConfig(); + public RestSwaggerProcessor(String contextIdPattern, Map<String, Object> parameters) { + this.contextIdPattern = contextIdPattern; + this.support = new RestSwaggerSupport(); + this.swaggerConfig = new BeanConfig(); + if (parameters == null) { parameters = Collections.EMPTY_MAP; } @@ -52,7 +56,7 @@ public class RestSwaggerProcessor implements Processor { try { // render list of camel contexts as root if (route == null || route.equals("") || route.equals("/")) { - support.renderCamelContexts(adapter); + support.renderCamelContexts(adapter, contextIdPattern); } else { // first part is the camel context if (route.startsWith("/")) { @@ -64,7 +68,19 @@ public class RestSwaggerProcessor implements Processor { route = route.substring(contextId.length()); } - support.renderResourceListing(adapter, swaggerConfig, contextId, route); + boolean match = true; + if (contextIdPattern != null) { + match = EndpointHelper.matchPattern(contextId, contextIdPattern); + if (LOG.isDebugEnabled()) { + LOG.debug("Match contextId: {} with pattern: {} -> {}", new Object[]{contextId, contextIdPattern, match}); + } + } + + if (!match) { + adapter.noContent(); + } else { + support.renderResourceListing(adapter, swaggerConfig, contextId, route); + } } } catch (Exception e) { LOG.warn("Error rendering Swagger API due " + e.getMessage(), e); http://git-wip-us.apache.org/repos/asf/camel/blob/f3aed3eb/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/RestSwaggerSupport.java ---------------------------------------------------------------------- diff --git a/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/RestSwaggerSupport.java b/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/RestSwaggerSupport.java index 4e228a8..5e9513d 100644 --- a/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/RestSwaggerSupport.java +++ b/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/RestSwaggerSupport.java @@ -18,6 +18,7 @@ package org.apache.camel.swagger; import java.lang.management.ManagementFactory; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -38,6 +39,7 @@ import org.apache.camel.model.ModelHelper; import org.apache.camel.model.rest.RestDefinition; import org.apache.camel.model.rest.RestsDefinition; import org.apache.camel.util.CamelVersionHelper; +import org.apache.camel.util.EndpointHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -196,7 +198,7 @@ public class RestSwaggerSupport { /** * Renders a list of available CamelContexts in the JVM */ - public void renderCamelContexts(RestApiResponseAdapter response) throws Exception { + public void renderCamelContexts(RestApiResponseAdapter response, String contextIdPattern) throws Exception { LOG.trace("renderCamelContexts"); if (cors) { @@ -210,6 +212,17 @@ public class RestSwaggerSupport { StringBuffer sb = new StringBuffer(); List<String> contexts = findCamelContexts(); + + // filter non matched CamelContext's + Iterator<String> it = contexts.iterator(); + while (it.hasNext()) { + String name = it.next(); + boolean match = EndpointHelper.matchPattern(name, contextIdPattern); + if (!match) { + it.remove(); + } + } + sb.append("[\n"); for (int i = 0; i < contexts.size(); i++) { String name = contexts.get(i); http://git-wip-us.apache.org/repos/asf/camel/blob/f3aed3eb/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/SwaggerRestApiProcessorFactory.java ---------------------------------------------------------------------- diff --git a/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/SwaggerRestApiProcessorFactory.java b/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/SwaggerRestApiProcessorFactory.java index faba694..be70c60 100644 --- a/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/SwaggerRestApiProcessorFactory.java +++ b/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/SwaggerRestApiProcessorFactory.java @@ -26,8 +26,8 @@ import org.apache.camel.spi.RestConfiguration; public class SwaggerRestApiProcessorFactory implements RestApiProcessorFactory { @Override - public Processor createApiProcessor(CamelContext camelContext, String contextPath, + public Processor createApiProcessor(CamelContext camelContext, String contextPath, String contextIdPattern, RestConfiguration configuration, Map<String, Object> parameters) throws Exception { - return new RestSwaggerProcessor(configuration.getApiProperties()); + return new RestSwaggerProcessor(contextIdPattern, configuration.getApiProperties()); } } http://git-wip-us.apache.org/repos/asf/camel/blob/f3aed3eb/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/servlet/RestSwaggerServlet.java ---------------------------------------------------------------------- diff --git a/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/servlet/RestSwaggerServlet.java b/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/servlet/RestSwaggerServlet.java index a5ca00a..a1381ce 100644 --- a/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/servlet/RestSwaggerServlet.java +++ b/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/servlet/RestSwaggerServlet.java @@ -77,7 +77,7 @@ public class RestSwaggerServlet extends HttpServlet { // render list of camel contexts as root if (route == null || route.equals("") || route.equals("/")) { - swagger.renderCamelContexts(adapter); + swagger.renderCamelContexts(adapter, null); } else { // first part is the camel context if (route.startsWith("/")) { http://git-wip-us.apache.org/repos/asf/camel/blob/f3aed3eb/examples/camel-example-swagger-cdi/src/main/java/org/apache/camel/example/cdi/UserRouteBuilder.java ---------------------------------------------------------------------- diff --git a/examples/camel-example-swagger-cdi/src/main/java/org/apache/camel/example/cdi/UserRouteBuilder.java b/examples/camel-example-swagger-cdi/src/main/java/org/apache/camel/example/cdi/UserRouteBuilder.java index 6061ad0..c7657d9 100644 --- a/examples/camel-example-swagger-cdi/src/main/java/org/apache/camel/example/cdi/UserRouteBuilder.java +++ b/examples/camel-example-swagger-cdi/src/main/java/org/apache/camel/example/cdi/UserRouteBuilder.java @@ -26,7 +26,7 @@ import static org.apache.camel.model.rest.RestParamType.path; /** * Define REST services using the Camel REST DSL */ -@ContextName +@ContextName("myCamel") public class UserRouteBuilder extends RouteBuilder { @Override @@ -39,8 +39,8 @@ public class UserRouteBuilder extends RouteBuilder { .dataFormatProperty("prettyPrint", "true") // setup context path and port number that netty will use .contextPath("/rest").port(8080) - // add swagger api-doc out of the box - .apiContextPath("/api-doc") + // add swagger api-doc out of the box, and only allow to docs for this CamelContext + .apiContextPath("/api-doc").apiContextIdPattern("#name#") .apiProperty("api.title", "User API").apiProperty("api.version", "1.2.3") // and enable CORS .apiProperty("cors", "true");