From f8c69c89e6fee93076241e031f9ea98c375e725e Mon Sep 17 00:00:00 2001 From: Russell Bolles Date: Mon, 15 Feb 2016 12:31:45 -0800 Subject: [PATCH] refactor ApiListingResource to not use greedy @Path("/") annotation --- modules/swagger-jaxrs/pom.xml | 2 +- .../AcceptHeaderApiListingResource.java | 42 ++++ .../jaxrs/listing/ApiListingResource.java | 196 +----------------- .../jaxrs/listing/BaseApiListingResource.java | 190 +++++++++++++++++ 4 files changed, 238 insertions(+), 192 deletions(-) create mode 100644 modules/swagger-jaxrs/src/main/java/io/swagger/jaxrs/listing/AcceptHeaderApiListingResource.java create mode 100644 modules/swagger-jaxrs/src/main/java/io/swagger/jaxrs/listing/BaseApiListingResource.java diff --git a/modules/swagger-jaxrs/pom.xml b/modules/swagger-jaxrs/pom.xml index 2b90ae1a29..4f22a519af 100644 --- a/modules/swagger-jaxrs/pom.xml +++ b/modules/swagger-jaxrs/pom.xml @@ -139,6 +139,6 @@ 0.50 0.00 - 3 + 4 diff --git a/modules/swagger-jaxrs/src/main/java/io/swagger/jaxrs/listing/AcceptHeaderApiListingResource.java b/modules/swagger-jaxrs/src/main/java/io/swagger/jaxrs/listing/AcceptHeaderApiListingResource.java new file mode 100644 index 0000000000..6a591fb49b --- /dev/null +++ b/modules/swagger-jaxrs/src/main/java/io/swagger/jaxrs/listing/AcceptHeaderApiListingResource.java @@ -0,0 +1,42 @@ +package io.swagger.jaxrs.listing; + +import io.swagger.annotations.ApiOperation; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.*; + +/** + * Created by rbolles on 2/15/16. + */ +@Path("/swagger") +public class AcceptHeaderApiListingResource extends BaseApiListingResource { + + @Context + ServletContext context; + + @GET + @Produces({MediaType.APPLICATION_JSON}) + @ApiOperation(value = "The swagger definition in JSON", hidden = true) + public Response getListingJson( + @Context Application app, + @Context ServletConfig sc, + @Context HttpHeaders headers, + @Context UriInfo uriInfo) { + return getListingJsonResponse(app, context, sc, headers, uriInfo); + } + + @GET + @Produces("application/yaml") + @ApiOperation(value = "The swagger definition in YAML", hidden = true) + public Response getListingYaml( + @Context Application app, + @Context ServletConfig sc, + @Context HttpHeaders headers, + @Context UriInfo uriInfo) { + return getListingYamlResponse(app, context, sc, headers, uriInfo); + } +} diff --git a/modules/swagger-jaxrs/src/main/java/io/swagger/jaxrs/listing/ApiListingResource.java b/modules/swagger-jaxrs/src/main/java/io/swagger/jaxrs/listing/ApiListingResource.java index bbce130e2e..93623c10d7 100644 --- a/modules/swagger-jaxrs/src/main/java/io/swagger/jaxrs/listing/ApiListingResource.java +++ b/modules/swagger-jaxrs/src/main/java/io/swagger/jaxrs/listing/ApiListingResource.java @@ -1,20 +1,7 @@ package io.swagger.jaxrs.listing; import io.swagger.annotations.ApiOperation; -import io.swagger.config.FilterFactory; -import io.swagger.config.Scanner; -import io.swagger.config.SwaggerConfig; -import io.swagger.core.filter.SpecFilter; -import io.swagger.core.filter.SwaggerSpecFilter; -import io.swagger.jaxrs.Reader; -import io.swagger.jaxrs.config.JaxrsScanner; -import io.swagger.jaxrs.config.ReaderConfigUtils; -import io.swagger.jaxrs.config.SwaggerContextService; -import io.swagger.models.Swagger; -import io.swagger.util.Yaml; import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; @@ -22,113 +9,17 @@ import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; -import javax.ws.rs.core.Application; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.Cookie; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.MultivaluedMap; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriInfo; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; +import javax.ws.rs.core.*; -@Path("/") -public class ApiListingResource { - private static volatile boolean initialized = false; - - private static volatile ConcurrentMap initializedScanner = new ConcurrentHashMap(); - private static volatile ConcurrentMap initializedConfig = new ConcurrentHashMap(); - - Logger LOGGER = LoggerFactory.getLogger(ApiListingResource.class); +@Path("/swagger.{type:json|yaml}") +public class ApiListingResource extends BaseApiListingResource { @Context ServletContext context; - protected synchronized Swagger scan(Application app, ServletConfig sc) { - Swagger swagger = null; - SwaggerContextService ctxService = new SwaggerContextService().withServletConfig(sc); - Scanner scanner = ctxService.getScanner(); - if (scanner != null) { - SwaggerSerializers.setPrettyPrint(scanner.getPrettyPrint()); - swagger = new SwaggerContextService().withServletConfig(sc).getSwagger(); - Set> classes; - if (scanner instanceof JaxrsScanner) { - JaxrsScanner jaxrsScanner = (JaxrsScanner) scanner; - classes = jaxrsScanner.classesFromContext(app, sc); - } else { - classes = scanner.classes(); - } - if (classes != null) { - Reader reader = new Reader(swagger, ReaderConfigUtils.getReaderConfig(context)); - swagger = reader.read(classes); - if (scanner instanceof SwaggerConfig) { - swagger = ((SwaggerConfig) scanner).configure(swagger); - } else { - SwaggerConfig swaggerConfig = ctxService.getConfig(); - if (swaggerConfig != null) { - LOGGER.debug("configuring swagger with " + swaggerConfig); - swaggerConfig.configure(swagger); - } else { - LOGGER.debug("no configurator"); - } - } - new SwaggerContextService().withServletConfig(sc).updateSwagger(swagger); - } - } - if (SwaggerContextService.isScannerIdInitParamDefined(sc)) { - initializedScanner.put(sc.getServletName() + "_" + SwaggerContextService.getScannerIdFromInitParam(sc), true); - } else if (SwaggerContextService.isConfigIdInitParamDefined(sc)) { - initializedConfig.put(sc.getServletName() + "_" + SwaggerContextService.getConfigIdFromInitParam(sc), true); - } else { - initialized = true; - } - - return swagger; - } - - private Swagger process( - Application app, - ServletConfig sc, - HttpHeaders headers, - UriInfo uriInfo) { - Swagger swagger = new SwaggerContextService().withServletConfig(sc).getSwagger(); - synchronized (ApiListingResource.class) { - if (SwaggerContextService.isScannerIdInitParamDefined(sc)) { - if (!initializedScanner.containsKey(sc.getServletName() + "_" + SwaggerContextService.getScannerIdFromInitParam(sc))) { - swagger = scan(app, sc); - } - } else { - if (SwaggerContextService.isConfigIdInitParamDefined(sc)) { - if (!initializedConfig.containsKey(sc.getServletName() + "_" + SwaggerContextService.getConfigIdFromInitParam(sc))) { - swagger = scan(app, sc); - } - } else { - if (!initialized) { - swagger = scan(app, sc); - } - } - } - } - if (swagger != null) { - SwaggerSpecFilter filterImpl = FilterFactory.getFilter(); - if (filterImpl != null) { - SpecFilter f = new SpecFilter(); - swagger = f.filter(swagger, filterImpl, getQueryParams(uriInfo.getQueryParameters()), getCookies(headers), - getHeaders(headers)); - } - } - return swagger; - } - @GET @Produces({MediaType.APPLICATION_JSON, "application/yaml"}) @ApiOperation(value = "The swagger definition in either JSON or YAML", hidden = true) - @Path("/swagger.{type:json|yaml}") public Response getListing( @Context Application app, @Context ServletConfig sc, @@ -136,87 +27,10 @@ public Response getListing( @Context UriInfo uriInfo, @PathParam("type") String type) { if (StringUtils.isNotBlank(type) && type.trim().equalsIgnoreCase("yaml")) { - return getListingYaml(app, sc, headers, uriInfo); - } else { - return getListingJson(app, sc, headers, uriInfo); - } - } - - @GET - @Produces({MediaType.APPLICATION_JSON}) - @Path("/swagger") - @ApiOperation(value = "The swagger definition in JSON", hidden = true) - public Response getListingJson( - @Context Application app, - @Context ServletConfig sc, - @Context HttpHeaders headers, - @Context UriInfo uriInfo) { - Swagger swagger = process(app, sc, headers, uriInfo); - - if (swagger != null) { - return Response.ok().entity(swagger).build(); + return getListingYamlResponse(app, context, sc, headers, uriInfo); } else { - return Response.status(404).build(); - } - } - - @GET - @Produces("application/yaml") - @Path("/swagger") - @ApiOperation(value = "The swagger definition in YAML", hidden = true) - public Response getListingYaml( - @Context Application app, - @Context ServletConfig sc, - @Context HttpHeaders headers, - @Context UriInfo uriInfo) { - Swagger swagger = process(app, sc, headers, uriInfo); - try { - if (swagger != null) { - String yaml = Yaml.mapper().writeValueAsString(swagger); - StringBuilder b = new StringBuilder(); - String[] parts = yaml.split("\n"); - for (String part : parts) { - b.append(part); - b.append("\n"); - } - return Response.ok().entity(b.toString()).type("application/yaml").build(); - } - } catch (Exception e) { - e.printStackTrace(); + return getListingJsonResponse(app, context, sc, headers, uriInfo); } - return Response.status(404).build(); } - protected Map> getQueryParams(MultivaluedMap params) { - Map> output = new HashMap>(); - if (params != null) { - for (String key : params.keySet()) { - List values = params.get(key); - output.put(key, values); - } - } - return output; - } - - protected Map getCookies(HttpHeaders headers) { - Map output = new HashMap(); - if (headers != null) { - for (String key : headers.getCookies().keySet()) { - Cookie cookie = headers.getCookies().get(key); - output.put(key, cookie.getValue()); - } - } - return output; - } - - protected Map> getHeaders(HttpHeaders headers) { - Map> output = new HashMap>(); - if (headers != null) { - for (String key : headers.getRequestHeaders().keySet()) { - List values = headers.getRequestHeaders().get(key); - output.put(key, values); - } - } - return output; - } } diff --git a/modules/swagger-jaxrs/src/main/java/io/swagger/jaxrs/listing/BaseApiListingResource.java b/modules/swagger-jaxrs/src/main/java/io/swagger/jaxrs/listing/BaseApiListingResource.java new file mode 100644 index 0000000000..4a7c97a2ac --- /dev/null +++ b/modules/swagger-jaxrs/src/main/java/io/swagger/jaxrs/listing/BaseApiListingResource.java @@ -0,0 +1,190 @@ +package io.swagger.jaxrs.listing; + +import io.swagger.config.FilterFactory; +import io.swagger.config.Scanner; +import io.swagger.config.SwaggerConfig; +import io.swagger.core.filter.SpecFilter; +import io.swagger.core.filter.SwaggerSpecFilter; +import io.swagger.jaxrs.Reader; +import io.swagger.jaxrs.config.JaxrsScanner; +import io.swagger.jaxrs.config.ReaderConfigUtils; +import io.swagger.jaxrs.config.SwaggerContextService; +import io.swagger.models.Swagger; +import io.swagger.util.Yaml; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.ws.rs.core.*; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + * Created by rbolles on 2/15/16. + */ +public abstract class BaseApiListingResource { + + private static volatile boolean initialized = false; + + private static volatile ConcurrentMap initializedScanner = new ConcurrentHashMap(); + private static volatile ConcurrentMap initializedConfig = new ConcurrentHashMap(); + + private static Logger LOGGER = LoggerFactory.getLogger(BaseApiListingResource.class); + + + protected static synchronized Swagger scan(Application app, ServletContext context, ServletConfig sc) { + Swagger swagger = null; + SwaggerContextService ctxService = new SwaggerContextService().withServletConfig(sc); + Scanner scanner = ctxService.getScanner(); + if (scanner != null) { + SwaggerSerializers.setPrettyPrint(scanner.getPrettyPrint()); + swagger = new SwaggerContextService().withServletConfig(sc).getSwagger(); + Set> classes; + if (scanner instanceof JaxrsScanner) { + JaxrsScanner jaxrsScanner = (JaxrsScanner) scanner; + classes = jaxrsScanner.classesFromContext(app, sc); + } else { + classes = scanner.classes(); + } + if (classes != null) { + Reader reader = new Reader(swagger, ReaderConfigUtils.getReaderConfig(context)); + swagger = reader.read(classes); + if (scanner instanceof SwaggerConfig) { + swagger = ((SwaggerConfig) scanner).configure(swagger); + } else { + SwaggerConfig swaggerConfig = ctxService.getConfig(); + if (swaggerConfig != null) { + LOGGER.debug("configuring swagger with " + swaggerConfig); + swaggerConfig.configure(swagger); + } else { + LOGGER.debug("no configurator"); + } + } + new SwaggerContextService().withServletConfig(sc).updateSwagger(swagger); + } + } + if (SwaggerContextService.isScannerIdInitParamDefined(sc)) { + initializedScanner.put(sc.getServletName() + "_" + SwaggerContextService.getScannerIdFromInitParam(sc), true); + } else if (SwaggerContextService.isConfigIdInitParamDefined(sc)) { + initializedConfig.put(sc.getServletName() + "_" + SwaggerContextService.getConfigIdFromInitParam(sc), true); + } else { + initialized = true; + } + + return swagger; + } + + private Swagger process( + Application app, + ServletContext servletContext, + ServletConfig sc, + HttpHeaders headers, + UriInfo uriInfo) { + Swagger swagger = new SwaggerContextService().withServletConfig(sc).getSwagger(); + synchronized (ApiListingResource.class) { + if (SwaggerContextService.isScannerIdInitParamDefined(sc)) { + if (!initializedScanner.containsKey(sc.getServletName() + "_" + SwaggerContextService.getScannerIdFromInitParam(sc))) { + swagger = scan(app, servletContext, sc); + } + } else { + if (SwaggerContextService.isConfigIdInitParamDefined(sc)) { + if (!initializedConfig.containsKey(sc.getServletName() + "_" + SwaggerContextService.getConfigIdFromInitParam(sc))) { + swagger = scan(app, servletContext, sc); + } + } else { + if (!initialized) { + swagger = scan(app, servletContext, sc); + } + } + } + } + if (swagger != null) { + SwaggerSpecFilter filterImpl = FilterFactory.getFilter(); + if (filterImpl != null) { + SpecFilter f = new SpecFilter(); + swagger = f.filter(swagger, filterImpl, getQueryParams(uriInfo.getQueryParameters()), getCookies(headers), + getHeaders(headers)); + } + } + return swagger; + } + + protected Response getListingYamlResponse( + Application app, + ServletContext servletContext, + ServletConfig servletConfig, + HttpHeaders headers, + UriInfo uriInfo) { + Swagger swagger = process(app, servletContext, servletConfig, headers, uriInfo); + try { + if (swagger != null) { + String yaml = Yaml.mapper().writeValueAsString(swagger); + StringBuilder b = new StringBuilder(); + String[] parts = yaml.split("\n"); + for (String part : parts) { + b.append(part); + b.append("\n"); + } + return Response.ok().entity(b.toString()).type("application/yaml").build(); + } + } catch (Exception e) { + e.printStackTrace(); + } + return Response.status(404).build(); + } + + protected Response getListingJsonResponse( + Application app, + ServletContext servletContext, + ServletConfig servletConfig, + HttpHeaders headers, + UriInfo uriInfo) { + Swagger swagger = process(app, servletContext, servletConfig, headers, uriInfo); + + if (swagger != null) { + return Response.ok().entity(swagger).build(); + } else { + return Response.status(404).build(); + } + } + + protected static Map> getQueryParams(MultivaluedMap params) { + Map> output = new HashMap>(); + if (params != null) { + for (String key : params.keySet()) { + List values = params.get(key); + output.put(key, values); + } + } + return output; + } + + protected static Map getCookies(HttpHeaders headers) { + Map output = new HashMap(); + if (headers != null) { + for (String key : headers.getCookies().keySet()) { + Cookie cookie = headers.getCookies().get(key); + output.put(key, cookie.getValue()); + } + } + return output; + } + + protected static Map> getHeaders(HttpHeaders headers) { + Map> output = new HashMap>(); + if (headers != null) { + for (String key : headers.getRequestHeaders().keySet()) { + List values = headers.getRequestHeaders().get(key); + output.put(key, values); + } + } + return output; + } + + +}