diff --git a/.gitignore b/.gitignore index a971ac8..48abf29 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,4 @@ bin .factorypath .idea .idea/* +*.iml diff --git a/.idea/.name b/.idea/.name deleted file mode 100644 index 474ae0e..0000000 --- a/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -proteus-core \ No newline at end of file diff --git a/README.md b/README.md index 2a26757..366c381 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ Controller class methods respect standard Swagger / JAX-RS annotations: ```java @GET @Path("/plaintext") -@Produces((MediaType.TEXT_PLAIN)) +@Produces((MediaType.TEXT_PLAIN)) @Operation(description = "Plaintext endpoint" ) public ServerResponse plaintext(ServerRequest request) { diff --git a/conf/logback.xml b/core/conf/logback.xml similarity index 90% rename from conf/logback.xml rename to core/conf/logback.xml index 196beaa..9addeeb 100644 --- a/conf/logback.xml +++ b/core/conf/logback.xml @@ -12,6 +12,8 @@ + + @@ -20,7 +22,8 @@ - + + @@ -48,7 +51,7 @@ - + diff --git a/core/pom.xml b/core/pom.xml new file mode 100644 index 0000000..e92f85b --- /dev/null +++ b/core/pom.xml @@ -0,0 +1,293 @@ + + + + proteus-project + io.sinistral + 0.4-SNAPSHOT + + 4.0.0 + + proteus-core + + Proteus Core + + jar + + + + + src/main/resources + false + + + + + src/test/resources + + + src/test/java + + **/*.java + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.1.0 + + + + test-jar + + + + **/*.class + + + + + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-javadoc-plugin + + + maven-surefire-plugin + 2.20.1 + + + + org.apache.maven.plugins + maven-gpg-plugin + + + org.sonatype.plugins + nexus-staging-maven-plugin + + + org.apache.maven.plugins + maven-release-plugin + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + + + io.undertow + undertow-core + ${undertow.version} + + + + ch.qos.logback + logback-classic + 1.2.3 + + + org.slf4j + slf4j-api + + + + + + org.slf4j + slf4j-api + 1.7.25 + + + org.slf4j + slf4j-ext + 1.7.25 + + + + jakarta.ws.rs + jakarta.ws.rs-api + 2.1.4 + + + + net.openhft + compiler + 2.3.1 + + + org.slf4j + slf4j-api + + + + + + com.squareup + javapoet + 1.8.0 + + + + com.google.inject + guice + 4.1.0 + + + + com.google.guava + guava + 27.0-jre + + + + com.typesafe + config + 1.3.1 + + + + org.yaml + snakeyaml + 1.23 + + + + commons-io + commons-io + 2.6 + + + + org.apache.httpcomponents + httpcore + 4.4.10 + + + + org.fusesource.jansi + jansi + 1.17.1 + + + + com.fasterxml.woodstox + woodstox-core + 5.1.0 + + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson.version} + + + + com.fasterxml.jackson.core + jackson-core + ${jackson.version} + + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${jackson.version} + + + + com.fasterxml.jackson.dataformat + jackson-dataformat-yaml + ${jackson.version} + + + + com.fasterxml.jackson.module + jackson-module-afterburner + ${jackson.version} + + + com.fasterxml.jackson.datatype + jackson-datatype-jdk8 + ${jackson.version} + + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + org.apache.commons + commons-lang3 + 3.8.1 + + + org.reflections + reflections + 0.9.11 + compile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + https://oss.sonatype.org/content/groups/public/io/sinistral/proteus-core + + \ No newline at end of file diff --git a/src/main/java/io/sinistral/proteus/ProteusApplication.java b/core/src/main/java/io/sinistral/proteus/ProteusApplication.java similarity index 100% rename from src/main/java/io/sinistral/proteus/ProteusApplication.java rename to core/src/main/java/io/sinistral/proteus/ProteusApplication.java diff --git a/src/main/java/io/sinistral/proteus/annotations/Blocking.java b/core/src/main/java/io/sinistral/proteus/annotations/Blocking.java similarity index 100% rename from src/main/java/io/sinistral/proteus/annotations/Blocking.java rename to core/src/main/java/io/sinistral/proteus/annotations/Blocking.java diff --git a/src/main/java/io/sinistral/proteus/annotations/Chain.java b/core/src/main/java/io/sinistral/proteus/annotations/Chain.java similarity index 100% rename from src/main/java/io/sinistral/proteus/annotations/Chain.java rename to core/src/main/java/io/sinistral/proteus/annotations/Chain.java diff --git a/src/main/java/io/sinistral/proteus/annotations/Debug.java b/core/src/main/java/io/sinistral/proteus/annotations/Debug.java similarity index 100% rename from src/main/java/io/sinistral/proteus/annotations/Debug.java rename to core/src/main/java/io/sinistral/proteus/annotations/Debug.java diff --git a/src/main/java/io/sinistral/proteus/modules/ApplicationModule.java b/core/src/main/java/io/sinistral/proteus/modules/ApplicationModule.java similarity index 100% rename from src/main/java/io/sinistral/proteus/modules/ApplicationModule.java rename to core/src/main/java/io/sinistral/proteus/modules/ApplicationModule.java diff --git a/src/main/java/io/sinistral/proteus/modules/ConfigModule.java b/core/src/main/java/io/sinistral/proteus/modules/ConfigModule.java similarity index 100% rename from src/main/java/io/sinistral/proteus/modules/ConfigModule.java rename to core/src/main/java/io/sinistral/proteus/modules/ConfigModule.java diff --git a/src/main/java/io/sinistral/proteus/server/Extractors.java b/core/src/main/java/io/sinistral/proteus/server/Extractors.java similarity index 93% rename from src/main/java/io/sinistral/proteus/server/Extractors.java rename to core/src/main/java/io/sinistral/proteus/server/Extractors.java index d309d9d..9da892e 100644 --- a/src/main/java/io/sinistral/proteus/server/Extractors.java +++ b/core/src/main/java/io/sinistral/proteus/server/Extractors.java @@ -260,7 +260,7 @@ public static java.util.Optional byteBuffer(final HttpServerExchang public static class Header { - public static String string(final HttpServerExchange exchange, final String name) throws java.lang.IllegalArgumentException + public static String string(final HttpServerExchange exchange, final String name) throws IllegalArgumentException { try { @@ -283,19 +283,19 @@ public static java.util.Optional string(final HttpServerExchange exchan } - public static Date date(final HttpServerExchange exchange,final String name) throws java.lang.IllegalArgumentException { + public static Date date(final HttpServerExchange exchange,final String name) throws IllegalArgumentException { return Date.from( OffsetDateTime.parse( string(exchange,name) ).toInstant() ); } - public static ZonedDateTime zonedDateTime(final HttpServerExchange exchange,final String name) throws java.lang.IllegalArgumentException { + public static ZonedDateTime zonedDateTime(final HttpServerExchange exchange,final String name) throws IllegalArgumentException { return ZonedDateTime.parse( string(exchange,name) ); } - public static OffsetDateTime offsetDateTime(final HttpServerExchange exchange,final String name) throws java.lang.IllegalArgumentException { + public static OffsetDateTime offsetDateTime(final HttpServerExchange exchange,final String name) throws IllegalArgumentException { return OffsetDateTime.parse( string(exchange,name) ); @@ -347,7 +347,7 @@ public static JsonNode jsonNode(final HttpServerExchange exchange ) return parseJson(exchange.getAttachment(ServerRequest.BYTE_BUFFER_KEY).array()); } - public static Path filePath(final HttpServerExchange exchange, final String name) throws java.lang.IllegalArgumentException + public static Path filePath(final HttpServerExchange exchange, final String name) throws IllegalArgumentException { try { @@ -358,7 +358,7 @@ public static Path filePath(final HttpServerExchange exchange, final String nam } } - public static File file(final HttpServerExchange exchange, final String name) throws java.lang.IllegalArgumentException + public static File file(final HttpServerExchange exchange, final String name) throws IllegalArgumentException { try { @@ -387,7 +387,7 @@ public static ByteBuffer byteBuffer(final HttpServerExchange exchange, final St } - public static String string(final HttpServerExchange exchange, final String name) throws java.lang.IllegalArgumentException + public static String string(final HttpServerExchange exchange, final String name) throws IllegalArgumentException { try { @@ -398,45 +398,45 @@ public static String string(final HttpServerExchange exchange, final String name } } - public static T extractWithFunction(final HttpServerExchange exchange, final String name, Function function) throws java.lang.IllegalArgumentException + public static T extractWithFunction(final HttpServerExchange exchange, final String name, Function function) throws IllegalArgumentException { return function.apply(string(exchange, name)); } - public static Float floatValue(final HttpServerExchange exchange, final String name) throws java.lang.IllegalArgumentException + public static Float floatValue(final HttpServerExchange exchange, final String name) throws IllegalArgumentException { return Float.parseFloat(string(exchange, name)); } - public static Double doubleValue(final HttpServerExchange exchange, final String name) throws java.lang.IllegalArgumentException + public static Double doubleValue(final HttpServerExchange exchange, final String name) throws IllegalArgumentException { return Double.parseDouble(string(exchange, name)); } - public static Long longValue(final HttpServerExchange exchange, final String name) throws java.lang.IllegalArgumentException + public static Long longValue(final HttpServerExchange exchange, final String name) throws IllegalArgumentException { return Long.parseLong( string(exchange, name) ); } - public static Instant instant(final HttpServerExchange exchange, final String name) throws java.lang.IllegalArgumentException + public static Instant instant(final HttpServerExchange exchange, final String name) throws IllegalArgumentException { return Instant.parse( string(exchange, name) ); } - public static Integer integerValue(final HttpServerExchange exchange, final String name) throws java.lang.IllegalArgumentException + public static Integer integerValue(final HttpServerExchange exchange, final String name) throws IllegalArgumentException { return Integer.parseInt(string(exchange, name)); } - public static Short shortValue(final HttpServerExchange exchange, final String name) throws java.lang.IllegalArgumentException + public static Short shortValue(final HttpServerExchange exchange, final String name) throws IllegalArgumentException { return Short.parseShort(string(exchange, name)); } - public static Boolean booleanValue(final HttpServerExchange exchange, final String name) throws java.lang.IllegalArgumentException + public static Boolean booleanValue(final HttpServerExchange exchange, final String name) throws IllegalArgumentException { return Boolean.parseBoolean(string(exchange, name)); } diff --git a/src/main/java/io/sinistral/proteus/server/MediaType.java b/core/src/main/java/io/sinistral/proteus/server/MediaType.java similarity index 100% rename from src/main/java/io/sinistral/proteus/server/MediaType.java rename to core/src/main/java/io/sinistral/proteus/server/MediaType.java diff --git a/src/main/java/io/sinistral/proteus/server/ServerRequest.java b/core/src/main/java/io/sinistral/proteus/server/ServerRequest.java similarity index 99% rename from src/main/java/io/sinistral/proteus/server/ServerRequest.java rename to core/src/main/java/io/sinistral/proteus/server/ServerRequest.java index bd7bbd0..7c52580 100644 --- a/src/main/java/io/sinistral/proteus/server/ServerRequest.java +++ b/core/src/main/java/io/sinistral/proteus/server/ServerRequest.java @@ -239,7 +239,7 @@ public Map> getQueryParameters() /** * @return the security context - * @see io.undertow.server.security.api#getSecurityContext() + * @see io.undertow.server.HttpServerExchange#getSecurityContext() */ public SecurityContext getSecurityContext() { diff --git a/src/main/java/io/sinistral/proteus/server/ServerResponse.java b/core/src/main/java/io/sinistral/proteus/server/ServerResponse.java similarity index 100% rename from src/main/java/io/sinistral/proteus/server/ServerResponse.java rename to core/src/main/java/io/sinistral/proteus/server/ServerResponse.java diff --git a/src/main/java/io/sinistral/proteus/server/endpoints/EndpointInfo.java b/core/src/main/java/io/sinistral/proteus/server/endpoints/EndpointInfo.java similarity index 100% rename from src/main/java/io/sinistral/proteus/server/endpoints/EndpointInfo.java rename to core/src/main/java/io/sinistral/proteus/server/endpoints/EndpointInfo.java diff --git a/src/main/java/io/sinistral/proteus/server/exceptions/ServerException.java b/core/src/main/java/io/sinistral/proteus/server/exceptions/ServerException.java similarity index 100% rename from src/main/java/io/sinistral/proteus/server/exceptions/ServerException.java rename to core/src/main/java/io/sinistral/proteus/server/exceptions/ServerException.java diff --git a/src/main/java/io/sinistral/proteus/server/handlers/HandlerGenerator.java b/core/src/main/java/io/sinistral/proteus/server/handlers/HandlerGenerator.java similarity index 100% rename from src/main/java/io/sinistral/proteus/server/handlers/HandlerGenerator.java rename to core/src/main/java/io/sinistral/proteus/server/handlers/HandlerGenerator.java diff --git a/src/main/java/io/sinistral/proteus/server/handlers/ProteusHandler.java b/core/src/main/java/io/sinistral/proteus/server/handlers/ProteusHandler.java similarity index 99% rename from src/main/java/io/sinistral/proteus/server/handlers/ProteusHandler.java rename to core/src/main/java/io/sinistral/proteus/server/handlers/ProteusHandler.java index 0ce5cd4..307ecd1 100644 --- a/src/main/java/io/sinistral/proteus/server/handlers/ProteusHandler.java +++ b/core/src/main/java/io/sinistral/proteus/server/handlers/ProteusHandler.java @@ -307,7 +307,7 @@ public void handleRouterRequest(HttpServerExchange exchange) throws Exception exchange.putAttachment(PathTemplateMatch.ATTACHMENT_KEY, match); - for (Map.Entry entry : match.getParameters().entrySet()) + for (Entry entry : match.getParameters().entrySet()) { exchange.addQueryParam(entry.getKey(), entry.getValue()); } diff --git a/src/main/java/io/sinistral/proteus/server/handlers/ServerDefaultHttpHandler.java b/core/src/main/java/io/sinistral/proteus/server/handlers/ServerDefaultHttpHandler.java similarity index 100% rename from src/main/java/io/sinistral/proteus/server/handlers/ServerDefaultHttpHandler.java rename to core/src/main/java/io/sinistral/proteus/server/handlers/ServerDefaultHttpHandler.java diff --git a/src/main/java/io/sinistral/proteus/server/handlers/ServerDefaultResponseListener.java b/core/src/main/java/io/sinistral/proteus/server/handlers/ServerDefaultResponseListener.java similarity index 100% rename from src/main/java/io/sinistral/proteus/server/handlers/ServerDefaultResponseListener.java rename to core/src/main/java/io/sinistral/proteus/server/handlers/ServerDefaultResponseListener.java diff --git a/src/main/java/io/sinistral/proteus/server/handlers/ServerFallbackHandler.java b/core/src/main/java/io/sinistral/proteus/server/handlers/ServerFallbackHandler.java similarity index 100% rename from src/main/java/io/sinistral/proteus/server/handlers/ServerFallbackHandler.java rename to core/src/main/java/io/sinistral/proteus/server/handlers/ServerFallbackHandler.java diff --git a/src/main/java/io/sinistral/proteus/server/handlers/TypeHandler.java b/core/src/main/java/io/sinistral/proteus/server/handlers/TypeHandler.java similarity index 98% rename from src/main/java/io/sinistral/proteus/server/handlers/TypeHandler.java rename to core/src/main/java/io/sinistral/proteus/server/handlers/TypeHandler.java index 8996a9c..426d767 100644 --- a/src/main/java/io/sinistral/proteus/server/handlers/TypeHandler.java +++ b/core/src/main/java/io/sinistral/proteus/server/handlers/TypeHandler.java @@ -74,11 +74,11 @@ public enum TypeHandler HeaderValueOfType("$T $L = $T.valueOf($T.string(exchange,$S))", false, StatementParameterType.TYPE, StatementParameterType.LITERAL, StatementParameterType.TYPE, io.sinistral.proteus.server.Extractors.Header.class, StatementParameterType.STRING), HeaderFromStringType("$T $L = $T.fromString($T.string(exchange,$S))", false, StatementParameterType.TYPE, StatementParameterType.LITERAL, StatementParameterType.TYPE, io.sinistral.proteus.server.Extractors.Header.class, StatementParameterType.STRING), - HeaderStringType("$T $L = $T.string(exchange,$S)", false, java.lang.String.class, StatementParameterType.LITERAL, io.sinistral.proteus.server.Extractors.Header.class, StatementParameterType.STRING), + HeaderStringType("$T $L = $T.string(exchange,$S)", false, String.class, StatementParameterType.LITERAL, io.sinistral.proteus.server.Extractors.Header.class, StatementParameterType.STRING), OptionalHeaderValueOfType("$T<$T> $L = $T.string(exchange,$S).map($T::valueOf)", false, Optional.class, StatementParameterType.RAW, StatementParameterType.LITERAL, io.sinistral.proteus.server.Extractors.Header.Optional.class, StatementParameterType.STRING, StatementParameterType.RAW), OptionalHeaderFromStringType("$T<$T> $L = $T.string(exchange,$S).map($T::fromString)", false, Optional.class, StatementParameterType.RAW, StatementParameterType.LITERAL, io.sinistral.proteus.server.Extractors.Header.Optional.class, StatementParameterType.STRING, StatementParameterType.RAW), - OptionalHeaderStringType("$T<$T> $L = $T.string(exchange,$S)", false, Optional.class, java.lang.String.class, StatementParameterType.LITERAL, io.sinistral.proteus.server.Extractors.Header.Optional.class, StatementParameterType.STRING), + OptionalHeaderStringType("$T<$T> $L = $T.string(exchange,$S)", false, Optional.class, String.class, StatementParameterType.LITERAL, io.sinistral.proteus.server.Extractors.Header.Optional.class, StatementParameterType.STRING), QueryOptionalListValueOfType("$T $L = java.util.Optional.ofNullable(exchange.getQueryParameters().get($S)).map(java.util.Deque::stream).map( p -> p.map($T::valueOf).collect(java.util.stream.Collectors.toList()))", false, StatementParameterType.RAW, StatementParameterType.LITERAL, StatementParameterType.STRING, StatementParameterType.RAW), QueryOptionalListFromStringType("$T $L = java.util.Optional.ofNullable(exchange.getQueryParameters().get($S)).map(java.util.Deque::stream).map( p -> p.map($T::fromString).collect(java.util.stream.Collectors.toList()))", false, StatementParameterType.RAW, StatementParameterType.LITERAL, StatementParameterType.STRING, StatementParameterType.RAW), diff --git a/src/main/java/io/sinistral/proteus/server/predicates/MaxRequestContentLengthPredicate.java b/core/src/main/java/io/sinistral/proteus/server/predicates/MaxRequestContentLengthPredicate.java similarity index 100% rename from src/main/java/io/sinistral/proteus/server/predicates/MaxRequestContentLengthPredicate.java rename to core/src/main/java/io/sinistral/proteus/server/predicates/MaxRequestContentLengthPredicate.java diff --git a/src/main/java/io/sinistral/proteus/server/predicates/ServerPredicates.java b/core/src/main/java/io/sinistral/proteus/server/predicates/ServerPredicates.java similarity index 100% rename from src/main/java/io/sinistral/proteus/server/predicates/ServerPredicates.java rename to core/src/main/java/io/sinistral/proteus/server/predicates/ServerPredicates.java diff --git a/src/main/java/io/sinistral/proteus/server/security/MapIdentityManager.java b/core/src/main/java/io/sinistral/proteus/server/security/MapIdentityManager.java similarity index 100% rename from src/main/java/io/sinistral/proteus/server/security/MapIdentityManager.java rename to core/src/main/java/io/sinistral/proteus/server/security/MapIdentityManager.java diff --git a/src/main/java/io/sinistral/proteus/services/AssetsService.java b/core/src/main/java/io/sinistral/proteus/services/AssetsService.java similarity index 100% rename from src/main/java/io/sinistral/proteus/services/AssetsService.java rename to core/src/main/java/io/sinistral/proteus/services/AssetsService.java diff --git a/src/main/java/io/sinistral/proteus/services/BaseService.java b/core/src/main/java/io/sinistral/proteus/services/BaseService.java similarity index 100% rename from src/main/java/io/sinistral/proteus/services/BaseService.java rename to core/src/main/java/io/sinistral/proteus/services/BaseService.java diff --git a/src/main/java/io/sinistral/proteus/utilities/SecurityOps.java b/core/src/main/java/io/sinistral/proteus/utilities/SecurityOps.java similarity index 100% rename from src/main/java/io/sinistral/proteus/utilities/SecurityOps.java rename to core/src/main/java/io/sinistral/proteus/utilities/SecurityOps.java diff --git a/src/main/java/io/sinistral/proteus/utilities/TablePrinter.java b/core/src/main/java/io/sinistral/proteus/utilities/TablePrinter.java similarity index 100% rename from src/main/java/io/sinistral/proteus/utilities/TablePrinter.java rename to core/src/main/java/io/sinistral/proteus/utilities/TablePrinter.java diff --git a/core/src/main/resources/META-INF/MANIFEST.MF b/core/src/main/resources/META-INF/MANIFEST.MF new file mode 100644 index 0000000..9d885be --- /dev/null +++ b/core/src/main/resources/META-INF/MANIFEST.MF @@ -0,0 +1 @@ +Manifest-Version: 1.0 diff --git a/src/main/resources/META-INF/services/io.undertow.protocols.alpn.ALPNProvider b/core/src/main/resources/META-INF/services/io.undertow.protocols.alpn.ALPNProvider similarity index 100% rename from src/main/resources/META-INF/services/io.undertow.protocols.alpn.ALPNProvider rename to core/src/main/resources/META-INF/services/io.undertow.protocols.alpn.ALPNProvider diff --git a/src/main/resources/development.cer b/core/src/main/resources/development.cer similarity index 100% rename from src/main/resources/development.cer rename to core/src/main/resources/development.cer diff --git a/src/main/resources/development.jks b/core/src/main/resources/development.jks similarity index 100% rename from src/main/resources/development.jks rename to core/src/main/resources/development.jks diff --git a/src/main/resources/development.ts b/core/src/main/resources/development.ts similarity index 100% rename from src/main/resources/development.ts rename to core/src/main/resources/development.ts diff --git a/src/main/resources/io/sinistral/proteus/favicon.ico b/core/src/main/resources/io/sinistral/proteus/favicon.ico similarity index 100% rename from src/main/resources/io/sinistral/proteus/favicon.ico rename to core/src/main/resources/io/sinistral/proteus/favicon.ico diff --git a/src/main/resources/reference.conf b/core/src/main/resources/reference.conf similarity index 97% rename from src/main/resources/reference.conf rename to core/src/main/resources/reference.conf index 9837ec6..3afcb62 100644 --- a/src/main/resources/reference.conf +++ b/core/src/main/resources/reference.conf @@ -40,7 +40,7 @@ globalHeaders } health { - statusPath = "/internal/status" + statusPath = "/health" } @@ -61,7 +61,6 @@ assets { openapi { - resourcePrefix="io/sinistral/proteus/server/tools/openapi" basePath= ${application.path}"/openapi" diff --git a/src/test/java/io/sinistral/proteus/test/controllers/Tests.java b/core/src/test/java/io/sinistral/proteus/swagger/test/controllers/Tests.java similarity index 81% rename from src/test/java/io/sinistral/proteus/test/controllers/Tests.java rename to core/src/test/java/io/sinistral/proteus/swagger/test/controllers/Tests.java index 820466b..ff54aed 100644 --- a/src/test/java/io/sinistral/proteus/test/controllers/Tests.java +++ b/core/src/test/java/io/sinistral/proteus/swagger/test/controllers/Tests.java @@ -1,7 +1,7 @@ /** * */ -package io.sinistral.proteus.test.controllers; +package io.sinistral.proteus.swagger.test.controllers; import static io.sinistral.proteus.server.ServerResponse.response; @@ -39,15 +39,8 @@ import io.sinistral.proteus.annotations.Blocking; import io.sinistral.proteus.server.ServerRequest; import io.sinistral.proteus.server.ServerResponse; -import io.sinistral.proteus.test.models.User; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.security.SecurityRequirement; -import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.tags.Tags; -import io.swagger.v3.oas.models.servers.Server; +import io.sinistral.proteus.swagger.test.models.User; + import io.undertow.server.HttpServerExchange; /** @@ -55,8 +48,7 @@ * */ -@Api(tags="tests") -@Tags({@Tag(name = "tests")}) + @Path("/tests") @Produces((MediaType.APPLICATION_JSON)) @Consumes((MediaType.MEDIA_TYPE_WILDCARD)) @@ -78,9 +70,7 @@ public class Tests @GET @Path("/exchange/json/serialize") - @Operation(description = "Json serialization endpoint" ) - @ApiOperation(value = "Json serialization endpoint" ) - public void exchangeJsonSerialize(HttpServerExchange exchange) + public void exchangeJsonSerialize(HttpServerExchange exchange) { try { @@ -93,9 +83,6 @@ public void exchangeJsonSerialize(HttpServerExchange exchange) @GET @Path("/exchange/json/serializeToBytes") - @Operation(description = "Json serialization with bytes endpoint" ) - @ApiOperation(value = "Json serialization with bytes endpoint" ) - public void exchangeJsonSerializeToBytes(HttpServerExchange exchange) { try @@ -111,7 +98,6 @@ public void exchangeJsonSerializeToBytes(HttpServerExchange exchange) @GET @Path("exchange/user/json") - @Operation(description = "User serialization endpoint" ) public void exchangeUserJson(HttpServerExchange exchange) { response( new User(123L) ).applicationJson().send(exchange); @@ -120,7 +106,6 @@ public void exchangeUserJson(HttpServerExchange exchange) @GET @Path("exchange/user/xml") @Produces((MediaType.APPLICATION_XML)) - @Operation(description = "User serialization endpoint" ) public void exchangeUserXml(HttpServerExchange exchange) { response( new User(123L) ).applicationXml().send(exchange); @@ -128,7 +113,6 @@ public void exchangeUserXml(HttpServerExchange exchange) @GET @Path("response/user/json") - @Operation(description = "User serialization endpoint" ) public ServerResponse responseUserJson(ServerRequest request) { User user = new User(123L); @@ -139,7 +123,6 @@ public ServerResponse responseUserJson(ServerRequest request) @GET @Path("response/user/xml") @Produces((MediaType.APPLICATION_XML)) - @Operation(description = "User serialization endpoint" ) public ServerResponse responseUserXml(ServerRequest request) { User user = new User(123L); @@ -151,7 +134,6 @@ public ServerResponse responseUserXml(ServerRequest request) @GET @Path("exchange/plaintext") @Produces((MediaType.TEXT_PLAIN)) - @Operation(description = "Plaintext endpoint" ) public void exchangePlaintext(HttpServerExchange exchange) { response("Hello, World!").textPlain().send(exchange); @@ -161,7 +143,6 @@ public void exchangePlaintext(HttpServerExchange exchange) @GET @Path("exchange/plaintext2") @Produces((MediaType.TEXT_PLAIN)) - @Operation(description = "Plaintext endpoint 2" ) public void exchangePlaintext2(HttpServerExchange exchange) { exchange.getResponseHeaders().put(io.undertow.util.Headers.CONTENT_TYPE, "text/plain"); @@ -171,7 +152,6 @@ public void exchangePlaintext2(HttpServerExchange exchange) @GET @Path("response/plaintext") @Produces((MediaType.TEXT_PLAIN)) - @Operation(description = "Plaintext endpoint" ) public ServerResponse responsePlaintext(ServerRequest request) { return response("Hello, World!").textPlain(); @@ -180,7 +160,6 @@ public ServerResponse responsePlaintext(ServerRequest request) @GET @Path("response/future/map") - @Operation(description = "Future map endpoint" ) public CompletableFuture>> responseFutureMap( ServerRequest request ) { Map map = ImmutableMap.of("message", "success"); @@ -189,7 +168,6 @@ public CompletableFuture>> responseFutureMap( @GET @Path("response/map") - @Operation(description = "Map endpoint" ) public ServerResponse> futureMap( ServerRequest request ) { Map map = ImmutableMap.of("message", "success"); @@ -200,7 +178,6 @@ public ServerResponse> futureMap( ServerRequest request ) @Path("response/file/path") @Produces(MediaType.APPLICATION_OCTET_STREAM) @Consumes(MediaType.MULTIPART_FORM_DATA) - @Operation(description = "Upload file path endpoint" ) public ServerResponse responseUploadFilePath(ServerRequest request, @FormParam("file") java.nio.file.Path file ) throws Exception { return response(ByteBuffer.wrap(Files.toByteArray(file.toFile()))).applicationOctetStream(); @@ -210,7 +187,6 @@ public ServerResponse responseUploadFilePath(ServerRequest request, @Path("response/file/path/optional") @Produces(MediaType.APPLICATION_OCTET_STREAM) @Consumes(MediaType.MULTIPART_FORM_DATA) - @Operation(description = "Upload optional file path endpoint" ) public ServerResponse responseUploadOptionalFilePath(ServerRequest request, @FormParam("file") Optional file ) throws Exception { if(file.isPresent()) @@ -227,7 +203,6 @@ public ServerResponse responseUploadOptionalFilePath(ServerRequest r @Path("response/json/echo") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.MULTIPART_FORM_DATA) - @Operation(description = "Echo json endpoint" ) public ServerResponse responseEchoJson(ServerRequest request, @FormParam("user") User user ) throws Exception { return response(user).applicationJson(); @@ -237,7 +212,6 @@ public ServerResponse responseEchoJson(ServerRequest request, @FormParam(" @Path("response/json/beanparam") @Produces(MediaType.APPLICATION_OCTET_STREAM) @Consumes(MediaType.APPLICATION_JSON) - @Operation(description = "Echo json inner class endpoint" ) public ServerResponse responseInnerClassTest(ServerRequest request, @BeanParam User user ) throws Exception { return response(user).applicationJson(); @@ -246,8 +220,7 @@ public ServerResponse responseInnerClassTest(ServerRequest request, @BeanP @GET @Path("generic/set") - @Produces((MediaType.APPLICATION_JSON)) - @Operation(description = "Generic set endpoint" ) + @Produces((MediaType.APPLICATION_JSON)) public ServerResponse> genericSet( ServerRequest request, @QueryParam("ids") Set ids ) throws Exception { return response( ids ).applicationJson(); @@ -258,7 +231,6 @@ public ServerResponse> genericSet( ServerRequest request, @QueryParam @Path("generic/set/bean") @Produces((MediaType.APPLICATION_JSON)) @Consumes(MediaType.APPLICATION_JSON) - @Operation(description = "Generic bean set endpoint" ) public ServerResponse> genericBeanSet( ServerRequest request, @BeanParam Set ids ) throws Exception { return response( ids ).applicationJson(); @@ -269,8 +241,6 @@ public ServerResponse> genericBeanSet( ServerRequest request, @BeanPa @Path("generic/list/bean") @Produces((MediaType.APPLICATION_JSON)) @Consumes(MediaType.APPLICATION_JSON) - - @Operation(description = "Generic bean list endpoint" ) public ServerResponse> genericBeanList( ServerRequest request, @BeanParam List ids ) throws Exception { return response( ids ).applicationJson(); @@ -278,8 +248,7 @@ public ServerResponse> genericBeanList( ServerRequest request, @Bean @GET @Path("optional/set") - @Produces((MediaType.APPLICATION_JSON)) - @Operation(description = "Generic optional set endpoint" ) + @Produces((MediaType.APPLICATION_JSON)) public ServerResponse> genericOptionalSet( ServerRequest request, @QueryParam("ids") Optional> ids ) throws Exception { return response( ids.get() ).applicationJson(); @@ -288,7 +257,6 @@ public ServerResponse> genericOptionalSet( ServerRequest request, @Qu @GET @Path("redirect/permanent") - @Operation(description = "Permanent redirect endpoint" ) @Produces(MediaType.WILDCARD) public ServerResponse testPermanentRedirect() { @@ -297,7 +265,6 @@ public ServerResponse testPermanentRedirect() @GET @Path("redirect") - @Operation(description = "Redirect endpoint" ) @Produces(MediaType.WILDCARD) public ServerResponse testRedirect() { @@ -309,7 +276,6 @@ public ServerResponse testRedirect() @Blocking @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) - @Operation(description = "Convert ids") public ServerResponse> listConversion( ServerRequest request, @BeanParam List ids ) throws Exception { @@ -321,8 +287,7 @@ public ServerResponse> listConversion( ServerRequest request, @BeanPa @GET @Path("response/parse/timestamp") @Blocking - @Produces(MediaType.TEXT_PLAIN) - @Operation(description = "Convert timestamp") + @Produces(MediaType.TEXT_PLAIN) public ServerResponse timestampConversion( ServerRequest request, @QueryParam("timestamp") Timestamp timestamp ) throws Exception { @@ -334,8 +299,7 @@ public ServerResponse timestampConversion( ServerRequest request, @Q @GET @Path("response/parse/instant") @Blocking - @Produces(MediaType.TEXT_PLAIN) - @Operation(description = "Convert instant") + @Produces(MediaType.TEXT_PLAIN) public ServerResponse instantConversion( ServerRequest request, @QueryParam("instant") Instant instant ) throws Exception { @@ -348,7 +312,6 @@ public ServerResponse instantConversion( ServerRequest request, @Que @Path("response/bytebuffer") @Produces(MediaType.APPLICATION_OCTET_STREAM) @Consumes("*/*") - @Operation(description = "Upload file path endpoint") public ServerResponse responseUploadByteBuffer(ServerRequest request, @FormParam("file") ByteBuffer file ) throws Exception { @@ -361,7 +324,6 @@ public ServerResponse responseUploadByteBuffer(ServerRequest request @Path("response/file") @Produces(MediaType.APPLICATION_OCTET_STREAM) @Consumes("*/*") - @Operation(description = "Upload file path endpoint") public ServerResponse responseUploadFile(ServerRequest request, @FormParam("file") File file ) throws Exception { @@ -375,7 +337,6 @@ public ServerResponse responseUploadFile(ServerRequest request, @For @GET @Path("response/debug") - @Operation(description = "Debug endpoint") public ServerResponse> debugEndpoint(ServerRequest request) { try @@ -393,7 +354,6 @@ public ServerResponse> debugEndpoint(ServerRequest request) @GET @Path("response/debug/blocking") @Blocking - @Operation(description="Debug blocking endpoint") public ServerResponse> debugBlockingEndpoint(ServerRequest request) { try @@ -409,7 +369,6 @@ public ServerResponse> debugBlockingEndpoint(ServerRequest re @GET @Path("response/future/user") - @Operation(description="Future user endpoint") @Produces((MediaType.APPLICATION_JSON)) public CompletableFuture> responseFutureUser() { @@ -418,14 +377,13 @@ public CompletableFuture> responseFutureUser() @GET @Path("response/parameters/complex/{pathLong}") - @Operation(description = "Complex parameters" ) @Produces((MediaType.APPLICATION_JSON)) public ServerResponse> complexParameters( ServerRequest serverRequest, @PathParam("pathLong") Long pathLong, @QueryParam("optionalQueryString") Optional optionalQueryString, @QueryParam("optionalQueryLong") Optional optionalQueryLong, - @QueryParam("optionalQueryDate") @ApiParam(format="date") Optional optionalQueryDate, + @QueryParam("optionalQueryDate") Optional optionalQueryDate, @QueryParam("optionalQueryUUID") Optional optionalQueryUUID, @HeaderParam("optionalHeaderUUID") Optional optionalHeaderUUID, @QueryParam("optionalQueryEnum") Optional optionalQueryEnum, @@ -458,9 +416,7 @@ public ServerResponse> complexParameters( } @GET - @SecurityRequirement(name = "testRequirement") @Path("secure/resource") - @Operation(description="Secure resource") @Produces(MediaType.APPLICATION_JSON) public ServerResponse> responseSecureContext() { diff --git a/src/test/java/io/sinistral/proteus/test/models/User.java b/core/src/test/java/io/sinistral/proteus/swagger/test/models/User.java similarity index 94% rename from src/test/java/io/sinistral/proteus/test/models/User.java rename to core/src/test/java/io/sinistral/proteus/swagger/test/models/User.java index 04e405e..32d81c2 100644 --- a/src/test/java/io/sinistral/proteus/test/models/User.java +++ b/core/src/test/java/io/sinistral/proteus/swagger/test/models/User.java @@ -1,7 +1,7 @@ /** * */ -package io.sinistral.proteus.test.models; +package io.sinistral.proteus.swagger.test.models; /** diff --git a/core/src/test/java/io/sinistral/proteus/swagger/test/server/DefaultServer.java b/core/src/test/java/io/sinistral/proteus/swagger/test/server/DefaultServer.java new file mode 100644 index 0000000..a65fab2 --- /dev/null +++ b/core/src/test/java/io/sinistral/proteus/swagger/test/server/DefaultServer.java @@ -0,0 +1,128 @@ +/** + * + */ +package io.sinistral.proteus.swagger.test.server; + +import java.util.List; + +import io.sinistral.proteus.swagger.test.controllers.Tests; +import org.junit.runner.Description; +import org.junit.runner.Result; +import org.junit.runner.notification.RunListener; +import org.junit.runner.notification.RunNotifier; +import org.junit.runners.BlockJUnit4ClassRunner; +import org.junit.runners.model.InitializationError; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.restassured.RestAssured; +import io.sinistral.proteus.ProteusApplication; +import io.sinistral.proteus.services.AssetsService; + +/** + * @author jbauer + */ +public class DefaultServer extends BlockJUnit4ClassRunner +{ + private static Logger log = LoggerFactory.getLogger(DefaultServer.class.getCanonicalName()); + + private static boolean first = true; + + /** + * @param clazz + * @throws InitializationError + */ + public DefaultServer(Class clazz) throws InitializationError + { + super(clazz); + } + + @Override + public void run(final RunNotifier notifier) + { + notifier.addListener(new RunListener() + { + @Override + public void testStarted(Description description) throws Exception + { + + super.testStarted(description); + } + + @Override + public void testFinished(Description description) throws Exception + { + + super.testFinished(description); + } + }); + + runInternal(notifier); + + super.run(notifier); + } + + private static void runInternal(final RunNotifier notifier) + { + + if (first) + { + + first = false; + + final ProteusApplication app = new ProteusApplication(); + + app.addService(AssetsService.class); + + app.addController(Tests.class); + + app.start(); + + int port = 0; + + try + { + Thread.sleep(5000); + + System.out.println(app.getPorts()); + + List ports = app.getPorts(); + + port = ports.get(0); + + } catch (Exception e) + { + e.printStackTrace(); + } + + + + RestAssured.baseURI = String.format("http://localhost:%d/v1",port); + + RestAssured.enableLoggingOfRequestAndResponseIfValidationFails(); + + while (!app.isRunning()) + { + try + { + Thread.sleep(100L); + } catch (InterruptedException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + notifier.addListener(new RunListener() + { + @Override + public void testRunFinished(final Result result) throws Exception + { + app.shutdown(); + }; + }); + } + + } + +} diff --git a/src/test/java/io/sinistral/proteus/test/server/TestControllerEndpoints.java b/core/src/test/java/io/sinistral/proteus/swagger/test/server/TestControllerEndpoints.java similarity index 94% rename from src/test/java/io/sinistral/proteus/test/server/TestControllerEndpoints.java rename to core/src/test/java/io/sinistral/proteus/swagger/test/server/TestControllerEndpoints.java index a20b5ea..dfa5079 100644 --- a/src/test/java/io/sinistral/proteus/test/server/TestControllerEndpoints.java +++ b/core/src/test/java/io/sinistral/proteus/swagger/test/server/TestControllerEndpoints.java @@ -1,10 +1,9 @@ /** * */ -package io.sinistral.proteus.test.server; +package io.sinistral.proteus.swagger.test.server; import static io.restassured.RestAssured.given; -import static io.restassured.RestAssured.when; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; @@ -37,8 +36,8 @@ import com.fasterxml.jackson.databind.ObjectMapper; import io.restassured.http.ContentType; -import io.sinistral.proteus.test.models.User; -import io.sinistral.proteus.test.models.User.UserType; +import io.sinistral.proteus.swagger.test.models.User; +import io.sinistral.proteus.swagger.test.models.User.UserType; /* * import static io.restassured.RestAssured.*; import static io.restassured.matcher.RestAssuredMatchers.*; import static org.hamcrest.Matchers.*; @@ -78,23 +77,6 @@ public void setUp() } } - @Test - public void testSwaggerDocs() - { - given().accept(ContentType.JSON).when().get("swagger.json").then().statusCode(200).and().body("basePath", is("/v1")); - } - - @Test - public void testOpenAPIDocs() - { - when().get("openapi.yaml").then().statusCode(200); - } - - @Test - public void testSecurityRequirementEndpoint() - { - when().get("tests/secure/resource").then().statusCode(200); - } @Test public void testDebugEndpoint() @@ -482,9 +464,9 @@ public void responseComplexParameters() .queryParam("optionalQueryDate", "1970-01-01T00:00:00.000+00:00") - .queryParam("queryEnum", User.UserType.ADMIN) + .queryParam("queryEnum", UserType.ADMIN) - .queryParam("optionalQueryEnum", User.UserType.ADMIN) + .queryParam("optionalQueryEnum", UserType.ADMIN) .queryParam("queryIntegerList", integerList) @@ -512,9 +494,9 @@ public void responseComplexParameters() assertThat((map.get("optionalQueryLong").toString()), CoreMatchers.is(longValue.toString())); - assertThat((map.get("optionalQueryEnum").toString()), CoreMatchers.is(User.UserType.ADMIN.name())); + assertThat((map.get("optionalQueryEnum").toString()), CoreMatchers.is(UserType.ADMIN.name())); - assertThat((map.get("queryEnum").toString()), CoreMatchers.is(User.UserType.ADMIN.name())); + assertThat((map.get("queryEnum").toString()), CoreMatchers.is(UserType.ADMIN.name())); assertThat((map.get("headerString").toString()), CoreMatchers.is(stringValue)); diff --git a/core/src/test/resources/application.conf b/core/src/test/resources/application.conf new file mode 100644 index 0000000..9c55400 --- /dev/null +++ b/core/src/test/resources/application.conf @@ -0,0 +1,91 @@ + +application { + + env = dev + + version = "1.0" + + name="proteus" + + path = "/v1" + + host = "localhost" + + ports { + http = 0 + # https = 8443 + } + + charset = UTF-8 + + fallbackHandler = "io.sinistral.proteus.server.handlers.ServerFallbackHandler" + + defaultResponseListener = "io.sinistral.proteus.server.handlers.ServerDefaultResponseListener" + + tmpdir = ${java.io.tmpdir}/${application.name} + + # path to default favicon file + favicon = "/io/sinistral/proteus/favicon.ico" + +} + +api.version="v1" + +globalHeaders +{ +# Access-Control-Allow-Origin: "*" +# Access-Control-Allow-Methods: "*" +# Access-Control-Allow-Headers: "*" + Server = ${application.name} +} + +assets { + # the base path assets will be server from + path = "/public" + # the directory to load the assets from + dir = "./assets" + cache { + # cache timeout for the assets + time = 500 + } + + +} + + + + + +undertow +{ + server { + enableHttp2 = false + alwaysSetDate = true + alwaysSetKeepAlive = false + recordRequestStartTime = false + maxEntitySize = 100M + bufferPipelinedData = false + } + + socket { + backlog = 10000 + } + + + ssl { + enabled=false + keystorePath="development.jks" + truststorePath="development.ts" + keystorePassword="password" + truststorePassword="password" + } + + enableHttp2=false + # x AvailableProcessors + ioThreadsMultiplier = 2 + workerThreadMultiplier = 8 + bufferSize = 16K + directBuffers = true +} + + \ No newline at end of file diff --git a/src/test/resources/development.jks b/core/src/test/resources/development.jks similarity index 100% rename from src/test/resources/development.jks rename to core/src/test/resources/development.jks diff --git a/src/test/resources/development.ts b/core/src/test/resources/development.ts similarity index 100% rename from src/test/resources/development.ts rename to core/src/test/resources/development.ts diff --git a/src/test/resources/logback-test.xml b/core/src/test/resources/logback-test.xml similarity index 83% rename from src/test/resources/logback-test.xml rename to core/src/test/resources/logback-test.xml index 265ca0f..aba346f 100644 --- a/src/test/resources/logback-test.xml +++ b/core/src/test/resources/logback-test.xml @@ -12,14 +12,16 @@ + - - - + + + + @@ -47,7 +49,7 @@ - + diff --git a/openapi/pom.xml b/openapi/pom.xml new file mode 100644 index 0000000..06a3eb5 --- /dev/null +++ b/openapi/pom.xml @@ -0,0 +1,125 @@ + + + + proteus-project + io.sinistral + 0.4-SNAPSHOT + + 4.0.0 + + proteus-openapi + + + Proteus OpenAPI + + jar + + + + + + src/main/resources + false + + + + + src/test/resources + + + src/test/java + + **/*.java + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.1.0 + + + + test-jar + + + + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-javadoc-plugin + + + maven-surefire-plugin + 2.20.1 + + + + org.apache.maven.plugins + maven-gpg-plugin + + + org.sonatype.plugins + nexus-staging-maven-plugin + + + org.apache.maven.plugins + maven-release-plugin + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + + + + + + io.swagger.core.v3 + swagger-annotations + ${openapi.version} + + + + io.swagger.core.v3 + swagger-models + ${openapi.version} + + + + io.swagger.core.v3 + swagger-jaxrs2 + ${openapi.version} + + + + io.swagger.core.v3 + swagger-integration + ${openapi.version} + + + ${project.groupId} + proteus-core + ${project.version} + + + + + + + https://oss.sonatype.org/content/groups/public/io/sinistral/proteus-openapi + + + \ No newline at end of file diff --git a/src/main/java/io/sinistral/proteus/server/tools/openapi/Reader.java b/openapi/src/main/java/io/sinistral/proteus/openapi/jaxrs2/Reader.java similarity index 96% rename from src/main/java/io/sinistral/proteus/server/tools/openapi/Reader.java rename to openapi/src/main/java/io/sinistral/proteus/openapi/jaxrs2/Reader.java index 02ed263..69522a4 100644 --- a/src/main/java/io/sinistral/proteus/server/tools/openapi/Reader.java +++ b/openapi/src/main/java/io/sinistral/proteus/openapi/jaxrs2/Reader.java @@ -1,61 +1,24 @@ /** * */ -package io.sinistral.proteus.server.tools.openapi; +package io.sinistral.proteus.openapi.jaxrs2; /** * @author jbauer */ -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.TreeSet; -import java.util.concurrent.CompletableFuture; -import java.util.stream.Collectors; - -import javax.ws.rs.ApplicationPath; -import javax.ws.rs.Consumes; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.Application; - -import org.apache.commons.lang3.ArrayUtils; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.fasterxml.jackson.annotation.JsonView; import com.fasterxml.jackson.databind.BeanDescription; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.introspect.AnnotatedMethod; import com.fasterxml.jackson.databind.introspect.AnnotatedParameter; import com.fasterxml.jackson.databind.type.TypeFactory; - import io.sinistral.proteus.server.ServerRequest; import io.sinistral.proteus.server.ServerResponse; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.converter.ResolvedSchema; -import io.swagger.v3.core.util.AnnotationsUtils; -import io.swagger.v3.core.util.Json; -import io.swagger.v3.core.util.ParameterProcessor; -import io.swagger.v3.core.util.PathUtils; -import io.swagger.v3.core.util.ReflectionUtils; +import io.swagger.v3.core.util.*; import io.swagger.v3.jaxrs2.OperationParser; import io.swagger.v3.jaxrs2.ReaderListener; import io.swagger.v3.jaxrs2.ResolvedParameter; @@ -67,14 +30,9 @@ import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.servers.Server; -import io.swagger.v3.oas.integration.ContextUtils; import io.swagger.v3.oas.integration.SwaggerConfiguration; import io.swagger.v3.oas.integration.api.OpenAPIConfiguration; -import io.swagger.v3.oas.models.Components; -import io.swagger.v3.oas.models.OpenAPI; -import io.swagger.v3.oas.models.Operation; -import io.swagger.v3.oas.models.PathItem; -import io.swagger.v3.oas.models.Paths; +import io.swagger.v3.oas.models.*; import io.swagger.v3.oas.models.callbacks.Callback; import io.swagger.v3.oas.models.media.Content; import io.swagger.v3.oas.models.media.MediaType; @@ -88,6 +46,23 @@ import io.swagger.v3.oas.models.security.SecurityScheme; import io.swagger.v3.oas.models.tags.Tag; import io.undertow.server.HttpServerExchange; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.ws.rs.ApplicationPath; +import javax.ws.rs.Consumes; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Application; +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; public class Reader extends io.swagger.v3.jaxrs2.Reader { @@ -353,10 +328,10 @@ public OpenAPI read(Class cls, ExternalDocumentation apiExternalDocs = ReflectionUtils.getAnnotation(cls, ExternalDocumentation.class); io.swagger.v3.oas.annotations.tags.Tag[] apiTags = ReflectionUtils.getRepeatableAnnotationsArray(cls, io.swagger.v3.oas.annotations.tags.Tag.class); - io.swagger.v3.oas.annotations.servers.Server[] apiServers = ReflectionUtils.getRepeatableAnnotationsArray(cls, io.swagger.v3.oas.annotations.servers.Server.class); + Server[] apiServers = ReflectionUtils.getRepeatableAnnotationsArray(cls, Server.class); - javax.ws.rs.Consumes classConsumes = ReflectionUtils.getAnnotation(cls, javax.ws.rs.Consumes.class); - javax.ws.rs.Produces classProduces = ReflectionUtils.getAnnotation(cls, javax.ws.rs.Produces.class); + Consumes classConsumes = ReflectionUtils.getAnnotation(cls, Consumes.class); + Produces classProduces = ReflectionUtils.getAnnotation(cls, Produces.class); // OpenApiDefinition OpenAPIDefinition openAPIDefinition = ReflectionUtils.getAnnotation(cls, OpenAPIDefinition.class); @@ -488,8 +463,8 @@ public OpenAPI read(Class cls, AnnotatedMethod annotatedMethod = bd.findMethod(method.getName(), parameterTypes); - javax.ws.rs.Produces methodProduces = ReflectionUtils.getAnnotation(method, javax.ws.rs.Produces.class); - javax.ws.rs.Consumes methodConsumes = ReflectionUtils.getAnnotation(method, javax.ws.rs.Consumes.class); + Produces methodProduces = ReflectionUtils.getAnnotation(method, Produces.class); + Consumes methodConsumes = ReflectionUtils.getAnnotation(method, Consumes.class); if (ReflectionUtils.isOverriddenMethod(method, cls)) { @@ -839,7 +814,7 @@ public static Annotation[][] getParameterAnnotations(Method method) { Annotation[] paramAnnotations = methodAnnotations[i]; - if (!params[i].getType().isAssignableFrom(io.sinistral.proteus.server.ServerRequest.class) && !params[i].getType().getName().startsWith("io.undertow")) + if (!params[i].getType().isAssignableFrom(ServerRequest.class) && !params[i].getType().getName().startsWith("io.undertow")) { // String annotationStrings = // Arrays.stream(paramAnnotations).map(a -> @@ -1701,8 +1676,8 @@ protected Optional> getParametersListFromAnnotation(io.swagger.v return Optional.of(parametersObject); } - protected ResolvedParameter getParameters( Type type, List annotations, Operation operation, javax.ws.rs.Consumes classConsumes, - javax.ws.rs.Consumes methodConsumes, JsonView jsonViewAnnotation) + protected ResolvedParameter getParameters( Type type, List annotations, Operation operation, Consumes classConsumes, + Consumes methodConsumes, JsonView jsonViewAnnotation) { final Iterator chain = OpenAPIExtensions.chain(); diff --git a/src/main/java/io/sinistral/proteus/server/tools/openapi/ServerModelResolver.java b/openapi/src/main/java/io/sinistral/proteus/openapi/jaxrs2/ServerModelResolver.java similarity index 92% rename from src/main/java/io/sinistral/proteus/server/tools/openapi/ServerModelResolver.java rename to openapi/src/main/java/io/sinistral/proteus/openapi/jaxrs2/ServerModelResolver.java index f397cb6..0944968 100644 --- a/src/main/java/io/sinistral/proteus/server/tools/openapi/ServerModelResolver.java +++ b/openapi/src/main/java/io/sinistral/proteus/openapi/jaxrs2/ServerModelResolver.java @@ -2,34 +2,27 @@ /** * */ -package io.sinistral.proteus.server.tools.openapi; +package io.sinistral.proteus.openapi.jaxrs2; -import java.io.File; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Type; - -import java.nio.ByteBuffer; - -import java.util.Iterator; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.CompletableFuture; - -import com.fasterxml.jackson.databind.BeanDescription; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.introspect.Annotated; import com.fasterxml.jackson.databind.type.TypeFactory; - import io.sinistral.proteus.server.ServerResponse; - import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverter; import io.swagger.v3.core.converter.ModelConverterContext; import io.swagger.v3.core.util.Json; import io.swagger.v3.oas.models.media.Schema; +import java.io.File; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.util.Iterator; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; + /** * @author jbauer */ @@ -39,7 +32,7 @@ public class ServerModelResolver extends io.swagger.v3.core.jackson.ModelResolve public ServerModelResolver() { - super(io.swagger.v3.core.util.Json.mapper()); + super(Json.mapper()); } /** @@ -92,7 +85,7 @@ else if (rawClass.isAssignableFrom(CompletableFuture.class)) { if (resolvedType.getTypeName().contains("java.lang.Void")) { - resolvedType = TypeFactory.defaultInstance().constructFromCanonical(java.lang.Void.class.getName()); + resolvedType = TypeFactory.defaultInstance().constructFromCanonical(Void.class.getName()); } else if (resolvedType.getTypeName().contains("Optional")) { @@ -110,12 +103,12 @@ else if (resolvedType.getTypeName().contains("Optional")) { if (resolvedType.getTypeName().contains("java.nio.file.Path")) { - resolvedType = TypeFactory.defaultInstance().constructFromCanonical(java.io.File.class.getName()); + resolvedType = TypeFactory.defaultInstance().constructFromCanonical(File.class.getName()); } if (resolvedType.getTypeName().contains("ByteBuffer")) { - resolvedType = TypeFactory.defaultInstance().constructFromCanonical(java.io.File.class.getName()); + resolvedType = TypeFactory.defaultInstance().constructFromCanonical(File.class.getName()); } } @@ -169,7 +162,7 @@ protected boolean shouldIgnoreClass(Type type) if (canonicalName.startsWith("io.undertow") || canonicalName.startsWith("org.xnio") || canonicalName.equals("io.sinistral.proteus.server.ServerRequest") - || canonicalName.contains(java.lang.Void.class.getName())) + || canonicalName.contains(Void.class.getName())) { return true; } diff --git a/src/main/java/io/sinistral/proteus/server/tools/openapi/ServerParameterExtension.java b/openapi/src/main/java/io/sinistral/proteus/openapi/jaxrs2/ServerParameterExtension.java similarity index 97% rename from src/main/java/io/sinistral/proteus/server/tools/openapi/ServerParameterExtension.java rename to openapi/src/main/java/io/sinistral/proteus/openapi/jaxrs2/ServerParameterExtension.java index c88cb96..5d6c85b 100644 --- a/src/main/java/io/sinistral/proteus/server/tools/openapi/ServerParameterExtension.java +++ b/openapi/src/main/java/io/sinistral/proteus/openapi/jaxrs2/ServerParameterExtension.java @@ -2,25 +2,7 @@ /** * */ -package io.sinistral.proteus.server.tools.openapi; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Type; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -import javax.ws.rs.BeanParam; -import javax.ws.rs.CookieParam; -import javax.ws.rs.HeaderParam; -import javax.ws.rs.MatrixParam; -import javax.ws.rs.PathParam; -import javax.ws.rs.QueryParam; - -import org.apache.commons.lang3.StringUtils; +package io.sinistral.proteus.openapi.jaxrs2; import com.fasterxml.jackson.annotation.JsonView; import com.fasterxml.jackson.databind.BeanDescription; @@ -30,7 +12,6 @@ import com.fasterxml.jackson.databind.introspect.AnnotatedMethod; import com.fasterxml.jackson.databind.introspect.AnnotationMap; import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition; - import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.ParameterProcessor; import io.swagger.v3.jaxrs2.ResolvedParameter; @@ -39,6 +20,12 @@ import io.swagger.v3.jaxrs2.ext.OpenAPIExtensions; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.parameters.Parameter; +import org.apache.commons.lang3.StringUtils; + +import javax.ws.rs.*; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.util.*; /** * @author jbauer diff --git a/src/main/java/io/sinistral/proteus/services/OpenAPIService.java b/openapi/src/main/java/io/sinistral/proteus/openapi/services/OpenAPIService.java similarity index 94% rename from src/main/java/io/sinistral/proteus/services/OpenAPIService.java rename to openapi/src/main/java/io/sinistral/proteus/openapi/services/OpenAPIService.java index 967e075..4a65d63 100644 --- a/src/main/java/io/sinistral/proteus/services/OpenAPIService.java +++ b/openapi/src/main/java/io/sinistral/proteus/openapi/services/OpenAPIService.java @@ -1,4 +1,4 @@ -package io.sinistral.proteus.services; +package io.sinistral.proteus.openapi.services; import java.io.File; import java.io.InputStream; @@ -24,6 +24,10 @@ import javax.ws.rs.HttpMethod; import javax.ws.rs.core.MediaType; +import io.sinistral.proteus.openapi.jaxrs2.Reader; +import io.sinistral.proteus.openapi.jaxrs2.ServerModelResolver; +import io.sinistral.proteus.openapi.jaxrs2.ServerParameterExtension; +import io.sinistral.proteus.services.BaseService; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; @@ -42,9 +46,6 @@ import com.typesafe.config.Config; import io.sinistral.proteus.server.endpoints.EndpointInfo; -import io.sinistral.proteus.server.tools.openapi.Reader; -import io.sinistral.proteus.server.tools.openapi.ServerModelResolver; -import io.sinistral.proteus.server.tools.openapi.ServerParameterExtension; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.Yaml; @@ -81,19 +82,17 @@ public class OpenAPIService extends BaseService implements Supplier responsePlaintext(ServerRequest request) + { + return response("Hello, World!").textPlain(); + + } + + @GET + @Path("response/future/map") + @Operation(description = "Future map endpoint" ) + public CompletableFuture>> responseFutureMap( ServerRequest request ) + { + Map map = ImmutableMap.of("message", "success"); + return CompletableFuture.completedFuture(response( map ).applicationJson()); + } + + @GET + @Path("response/map") + @Operation(description = "Map endpoint" ) + public ServerResponse> futureMap( ServerRequest request ) + { + Map map = ImmutableMap.of("message", "success"); + return response( map ).applicationJson(); + } + + @POST + @Path("response/file/path") + @Produces(MediaType.APPLICATION_OCTET_STREAM) + @Consumes(MediaType.MULTIPART_FORM_DATA) + @Operation(description = "Upload file path endpoint" ) + public ServerResponse responseUploadFilePath(ServerRequest request, @FormParam("file") java.nio.file.Path file ) throws Exception + { + return response(ByteBuffer.wrap(Files.toByteArray(file.toFile()))).applicationOctetStream(); + } + + @POST + @Path("response/file/path/optional") + @Produces(MediaType.APPLICATION_OCTET_STREAM) + @Consumes(MediaType.MULTIPART_FORM_DATA) + @Operation(description = "Upload optional file path endpoint" ) + public ServerResponse responseUploadOptionalFilePath(ServerRequest request, @FormParam("file") Optional file ) throws Exception + { + if(file.isPresent()) + { + return response(ByteBuffer.wrap(Files.toByteArray(file.get().toFile()))).applicationOctetStream(); + } + else + { + return response().noContent(); + } + } + + @GET + @Path("generic/set") + @Produces((MediaType.APPLICATION_JSON)) + @Operation(description = "Generic set endpoint" ) + public ServerResponse> genericSet( ServerRequest request, @QueryParam("ids") Set ids ) throws Exception + { + return response( ids ).applicationJson(); + } + + + @POST + @Path("generic/set/bean") + @Produces((MediaType.APPLICATION_JSON)) + @Consumes(MediaType.APPLICATION_JSON) + @Operation(description = "Generic bean set endpoint" ) + public ServerResponse> genericBeanSet( ServerRequest request, @BeanParam Set ids ) throws Exception + { + return response( ids ).applicationJson(); + } + + + @POST + @Path("generic/list/bean") + @Produces((MediaType.APPLICATION_JSON)) + @Consumes(MediaType.APPLICATION_JSON) + + @Operation(description = "Generic bean list endpoint" ) + public ServerResponse> genericBeanList( ServerRequest request, @BeanParam List ids ) throws Exception + { + return response( ids ).applicationJson(); + } + + @GET + @Path("optional/set") + @Produces((MediaType.APPLICATION_JSON)) + @Operation(description = "Generic optional set endpoint" ) + public ServerResponse> genericOptionalSet( ServerRequest request, @QueryParam("ids") Optional> ids ) throws Exception + { + return response( ids.get() ).applicationJson(); + } + + + @POST + @Path("response/parse/ids") + @Blocking + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + @Operation(description = "Convert ids") + public ServerResponse> listConversion( ServerRequest request, @BeanParam List ids ) throws Exception + { + + return response( ids ).applicationJson(); + + + } + + @GET + @Path("response/parse/timestamp") + @Blocking + @Produces(MediaType.TEXT_PLAIN) + @Operation(description = "Convert timestamp") + public ServerResponse timestampConversion( ServerRequest request, @QueryParam("timestamp") Timestamp timestamp ) throws Exception + { + return response().body(timestamp.toString()).textPlain(); + } + + @GET + @Path("response/parse/instant") + @Blocking + @Produces(MediaType.TEXT_PLAIN) + @Operation(description = "Convert instant") + public ServerResponse instantConversion( ServerRequest request, @QueryParam("instant") Instant instant ) throws Exception + { + + return response().body(instant.toString()).textPlain(); + + + } + + @POST + @Path("response/bytebuffer") + @Produces(MediaType.APPLICATION_OCTET_STREAM) + @Consumes("*/*") + @Operation(description = "Upload file path endpoint") + public ServerResponse responseUploadByteBuffer(ServerRequest request, @FormParam("file") ByteBuffer file ) throws Exception + { + + return response(file).applicationOctetStream(); + + + } + + @POST + @Path("response/file") + @Produces(MediaType.APPLICATION_OCTET_STREAM) + @Consumes("*/*") + @Operation(description = "Upload file path endpoint") + public ServerResponse responseUploadFile(ServerRequest request, @FormParam("file") File file ) throws Exception + { + + ByteBuffer response = ByteBuffer.wrap(Files.asByteSource(file).read()); + + + return response(response).applicationOctetStream(); + + + } + + @GET + @Path("response/debug") + @Operation(description = "Debug endpoint") + public ServerResponse> debugEndpoint(ServerRequest request) + { + try + { + Map map = ImmutableMap.of("message", "Hello, World!"); + + return response( map ).applicationJson(); + } catch(Exception e) + { + return response().badRequest(e); + } + } + + @GET + @Path("response/debug/blocking") + @Blocking + @Operation(description="Debug blocking endpoint") + public ServerResponse> debugBlockingEndpoint(ServerRequest request) + { + try + { + Map map = ImmutableMap.of("message", "Hello, World!"); + + return response( map ).applicationJson(); + } catch(Exception e) + { + return response().badRequest(e); + } + } + + + @GET + @SecurityRequirement(name = "testRequirement") + @Path("secure/resource") + @Operation(description="Secure resource") + @Produces(MediaType.APPLICATION_JSON) + public ServerResponse> responseSecureContext() + { + Map responseMap = new HashMap<>(); + responseMap.put("secure",true); + + return response(responseMap); + } +} diff --git a/src/test/java/io/sinistral/proteus/test/server/DefaultServer.java b/openapi/src/test/java/io/sinistral/proteus/swagger/test/server/DefaultServer.java similarity index 90% rename from src/test/java/io/sinistral/proteus/test/server/DefaultServer.java rename to openapi/src/test/java/io/sinistral/proteus/swagger/test/server/DefaultServer.java index 72c4b59..5d1ea93 100644 --- a/src/test/java/io/sinistral/proteus/test/server/DefaultServer.java +++ b/openapi/src/test/java/io/sinistral/proteus/swagger/test/server/DefaultServer.java @@ -1,10 +1,13 @@ /** * */ -package io.sinistral.proteus.test.server; - -import java.util.List; +package io.sinistral.proteus.swagger.test.server; +import io.restassured.RestAssured; +import io.sinistral.proteus.ProteusApplication; +import io.sinistral.proteus.openapi.services.OpenAPIService; +import io.sinistral.proteus.services.AssetsService; +import io.sinistral.proteus.swagger.test.controllers.Tests; import org.junit.runner.Description; import org.junit.runner.Result; import org.junit.runner.notification.RunListener; @@ -14,12 +17,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import io.restassured.RestAssured; -import io.sinistral.proteus.ProteusApplication; -import io.sinistral.proteus.services.AssetsService; -import io.sinistral.proteus.services.OpenAPIService; -import io.sinistral.proteus.services.SwaggerService; -import io.sinistral.proteus.test.controllers.Tests; +import java.util.List; /** * @author jbauer @@ -73,10 +71,9 @@ private static void runInternal(final RunNotifier notifier) first = false; final ProteusApplication app = new ProteusApplication(); - - app.addService(SwaggerService.class); - app.addService(AssetsService.class); + app.addService(OpenAPIService.class); + app.addService(AssetsService.class); app.addController(Tests.class); diff --git a/openapi/src/test/java/io/sinistral/proteus/swagger/test/server/TestControllerEndpoints.java b/openapi/src/test/java/io/sinistral/proteus/swagger/test/server/TestControllerEndpoints.java new file mode 100644 index 0000000..c91cb8d --- /dev/null +++ b/openapi/src/test/java/io/sinistral/proteus/swagger/test/server/TestControllerEndpoints.java @@ -0,0 +1,94 @@ +/** + * + */ +package io.sinistral.proteus.swagger.test.server; + +import static io.restassured.RestAssured.given; +import static io.restassured.RestAssured.when; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +import java.io.File; +import java.nio.file.Files; +import java.util.HashSet; +import java.util.Random; +import java.util.Set; +import java.util.stream.LongStream; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +/* + * import static io.restassured.RestAssured.*; import static io.restassured.matcher.RestAssuredMatchers.*; import static org.hamcrest.Matchers.*; + */ +/** + * @author jbauer + */ +@RunWith(DefaultServer.class) +public class TestControllerEndpoints +{ + + private File file = null; + + private Set idSet = new HashSet<>(); + + @Before + public void setUp() + { + try + { + byte[] bytes = new byte[8388608]; + Random random = new Random(); + random.nextBytes(bytes); + + file = Files.createTempFile("test-asset", ".mp4").toFile(); + + LongStream.range(1L,10L).forEach( l -> { + + idSet.add(l); + }); + + + } catch (Exception e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + + + @Test + public void testOpenAPIDocs() + { + when().get("openapi.yaml").then().statusCode(200); + } + + + @Test + public void testSecurityRequirementEndpoint() + { + when().get("tests/secure/resource").then().statusCode(200); + } + + + @After + public void tearDown() + { + try + { + if(file.exists()) + { + file.delete(); + } + + } catch (Exception e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + +} diff --git a/openapi/src/test/resources/logback-test.xml b/openapi/src/test/resources/logback-test.xml new file mode 100644 index 0000000..aba346f --- /dev/null +++ b/openapi/src/test/resources/logback-test.xml @@ -0,0 +1,56 @@ + + + + + + true + + %date{ISO8601} %highlight(%-5level) [%boldCyan(%logger)] [%boldYellow(%method %F) ] - %boldWhite(%message) %n %red(%ex) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 5a4e51e..07f3e34 100644 --- a/pom.xml +++ b/pom.xml @@ -1,469 +1,212 @@ - - 4.0.0 - io.sinistral - proteus-core - 0.3.7 - proteus core - Proteus is an extremely light, fast, and flexible Java REST API framework built atop Undertow. - http://github.com/noboomu/proteus - jar - - - - MIT License - http://www.opensource.org/licenses/mit-license.php - - - - - - Joshua Lee Bauer - bauer@sinistral.io - - - - - scm:git:git://github.com/noboomu/proteus.git - scm:git:ssh://github.com:noboomu/proteus.git - http://github.com/noboomu/proteus/tree/master - - - - 1.8 - 1.8 - UTF-8 - 3.0.0 - 2.0.15.Final - 2.9.8 - 2.0.6 - 1.5.21 - - - - - - src/main/resources - false - - - - - src/test/resources - - - src/test/java - - **/*.java - - - - - - - - org.eclipse.m2e - lifecycle-mapping - 1.0.0 - - - - - - org.apache.maven.plugins - maven-compiler-plugin - [3.3,) - - compile - testCompile - - - - - - - - - - - - - - - org.apache.maven.plugins - maven-source-plugin - 2.2.1 - - - attach-sources - - jar-no-fork - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.9.1 - - - attach-javadocs - - jar - - - -Xdoclint:none - - - - - - maven-surefire-plugin - 2.20.1 - - - org.apache.maven.surefire - surefire-junit47 - 2.20.1 - - - - -Dconfig.file=src/test/resources/application.conf - - - - org.apache.maven.plugins - maven-gpg-plugin - 1.5 - - - sign-artifacts - verify - - sign - - - - - gpg - - - - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.7 - true - - ossrh - https://oss.sonatype.org/ - true - - - - org.apache.maven.plugins - maven-release-plugin - 2.5.3 - - true - false - ossrh - deploy - - - - - maven-compiler-plugin - 3.5.1 - - 1.8 - 1.8 - -parameters - - - - - - - - io.rest-assured - rest-assured - 3.2.0 - test - - - - org.junit.jupiter - junit-jupiter-api - 5.3.1 - test - - - - org.junit.vintage - junit-vintage-engine - 5.3.1 - test - - - - - io.undertow - undertow-core - ${undertow.version} - - - - - ch.qos.logback - logback-classic - 1.2.3 - - - org.slf4j - slf4j-api - - - - - - org.slf4j - slf4j-api - 1.7.25 - - - org.slf4j - slf4j-ext - 1.7.25 - - - - jakarta.ws.rs - jakarta.ws.rs-api - 2.1.4 - - - - net.openhft - compiler - 2.3.1 - - - org.slf4j - slf4j-api - - - - - - com.squareup - javapoet - 1.8.0 - - - - com.google.inject - guice - 4.1.0 - - - - com.google.guava - guava - 27.0-jre - - - - com.typesafe - config - 1.3.1 - - - - org.yaml - snakeyaml - 1.23 - - - - commons-io - commons-io - 2.6 - - - - org.apache.httpcomponents - httpcore - 4.4.10 - - - - org.fusesource.jansi - jansi - 1.17.1 - - - - com.fasterxml.woodstox - woodstox-core - 5.1.0 - - - - com.fasterxml.jackson.core - jackson-annotations - ${jackson.version} - - - - com.fasterxml.jackson.core - jackson-core - ${jackson.version} - - - - com.fasterxml.jackson.dataformat - jackson-dataformat-xml - ${jackson.version} - - - - com.fasterxml.jackson.dataformat - jackson-dataformat-yaml - ${jackson.version} - - - - com.fasterxml.jackson.module - jackson-module-afterburner - ${jackson.version} - - - com.fasterxml.jackson.datatype - jackson-datatype-jdk8 - ${jackson.version} - - - - com.fasterxml.jackson.core - jackson-databind - ${jackson.version} - - - - io.swagger - swagger-annotations - ${swagger.version} - - - io.swagger - swagger-core - ${swagger.version} - - - org.slf4j - slf4j-api - - - - - io.swagger - swagger-jaxrs - ${swagger.version} - - - - io.swagger.core.v3 - swagger-annotations - ${openapi.version} - - - - io.swagger.core.v3 - swagger-models - ${openapi.version} - - - - io.swagger.core.v3 - swagger-jaxrs2 - ${openapi.version} - - - - io.swagger.core.v3 - swagger-integration - ${openapi.version} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - sonatype-snapshots - https://oss.sonatype.org/content/repositories/snapshots - - true - - - false - - - - - - ossrh - https://oss.sonatype.org/content/repositories/snapshots - - - ossrh - https://oss.sonatype.org/service/local/staging/deploy/maven2/ - - - https://oss.sonatype.org/content/groups/public/io/sinistral/proteus-core - - - + + + 4.0.0 + + io.sinistral + proteus-project + pom + 0.4-SNAPSHOT + + Proteus is an extremely light, fast, and flexible Java REST API framework built atop Undertow. + http://github.com/noboomu/proteus + + + + core + swagger + openapi + + + + + MIT License + http://www.opensource.org/licenses/mit-license.php + + + + + + Joshua Lee Bauer + bauer@sinistral.io + + + + + scm:git:git://github.com/noboomu/proteus.git + scm:git:ssh://github.com:noboomu/proteus.git + http://github.com/noboomu/proteus/tree/master + + + + 1.8 + 1.8 + UTF-8 + 3.0.0 + 2.0.16.Final + 2.9.8 + 2.0.6 + 1.5.21 + + + + + + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + + attach-javadocs + + jar + + + -Xdoclint:none + + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + gpg + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.7 + true + + ossrh + https://oss.sonatype.org/ + true + + + + org.apache.maven.plugins + maven-release-plugin + 2.5.3 + + true + false + ossrh + deploy + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + 1.8 + 1.8 + -parameters + + + + + maven-surefire-plugin + 2.20.1 + + + org.apache.maven.surefire + surefire-junit47 + 2.20.1 + + + + -Dconfig.file=src/test/resources/application.conf + -Dlogback.configuration=src/test/resources/logback-test.xml + + + + + + + + + + + + + io.rest-assured + rest-assured + 3.2.0 + test + + + + org.junit.jupiter + junit-jupiter-api + 5.3.1 + test + + + + org.junit.vintage + junit-vintage-engine + 5.3.1 + test + + + + + + + + sonatype-snapshots + https://oss.sonatype.org/content/repositories/snapshots + + true + + + false + + + + + + ossrh + https://oss.sonatype.org/content/repositories/snapshots + + + ossrh + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + \ No newline at end of file diff --git a/proteus.iml b/proteus.iml deleted file mode 100644 index a98f67e..0000000 --- a/proteus.iml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/META-INF/MANIFEST.MF b/src/main/resources/META-INF/MANIFEST.MF deleted file mode 100644 index 946d01c..0000000 --- a/src/main/resources/META-INF/MANIFEST.MF +++ /dev/null @@ -1 +0,0 @@ -Main-Class: io.sinistral.proteus.Application \ No newline at end of file diff --git a/src/test/resources/application.conf b/src/test/resources/application.conf deleted file mode 100644 index 401fe14..0000000 --- a/src/test/resources/application.conf +++ /dev/null @@ -1,184 +0,0 @@ - -application { - - env = dev - - version = "1.0" - - name="proteus" - - path = "/v1" - - host = "localhost" - - ports { - http = 0 - # https = 8443 - } - - charset = UTF-8 - - fallbackHandler = "io.sinistral.proteus.server.handlers.ServerFallbackHandler" - - defaultResponseListener = "io.sinistral.proteus.server.handlers.ServerDefaultResponseListener" - - tmpdir = ${java.io.tmpdir}/${application.name} - - # path to default favicon file - favicon = "/io/sinistral/proteus/favicon.ico" - -} - -api.version="v1" - -globalHeaders -{ -# Access-Control-Allow-Origin: "*" -# Access-Control-Allow-Methods: "*" -# Access-Control-Allow-Headers: "*" - Server = ${application.name} -} - -health { - statusPath = "/internal/status" -} - - - -assets { - # the base path assets will be server from - path = "/public" - # the directory to load the assets from - dir = "./assets" - cache { - # cache timeout for the assets - time = 500 - } - - -} - - -openapi { - - - resourcePrefix="io/sinistral/proteus/server/tools/openapi" - - basePath= ${application.path}"/openapi" - - port = ${application.ports.http} - - specFilename="openapi.yaml" - - openapi="3.0.1" - - # openapi info - info { - title = ${application.name} - version = ${application.version} - description="Proteus Server" - } - - - securitySchemes { - ApiKeyAuth = { - type="apiKey" - in="header" - name="X-API-KEY" - } - } - - servers = [ - { - url=${application.path} - description="Default Server" - } - ] - - -} - - -swagger { - # the path that has an index.html template and theme css files - resourcePrefix="io/sinistral/proteus/server/tools/swagger" - # swagger version - swagger="2.0" - info { - # swagger info title - title = ${application.name} - # swagger info version - version = ${application.version} - } - # swagger-ui theme from ostranme's swagger-ui-themes, the following are built-in [feeling-blue, flattop, material, monokai, muted, newspaper, outline] - # specifying a different name causes the SwaggerService to search in {swagger.resourcePrefix}/themes for a file named "theme-{swagger.theme}.css" - theme="default" - # where the swagger endpoints will be mounted - basePath= ${application.path}"/swagger" - # where redoc will be mounted relative to swagger base path - redocPath= "redoc" - #the name of the spec file - specFilename="swagger.json" - consumes = ["application/json"] - produces = ["application/json"] - port = ${application.ports.http} - - security = - { - apiKeys = [ - { - key="defaultApiKey" - in="HEADER", - name="default-api-key" - value="123456789" - } - ] - -# basicRealms = -# [ -# { -# name = defaultBasic -# identities = -# [ -# "username:password" -# ] -# } -# ] - } - - -} - -undertow -{ - server { - enableHttp2 = false - alwaysSetDate = true - alwaysSetKeepAlive = false - recordRequestStartTime = false - maxEntitySize = 100M - bufferPipelinedData = false - } - - socket { - backlog = 10000 - } - - - ssl { - enabled=false - keystorePath="development.jks" - truststorePath="development.ts" - keystorePassword="password" - truststorePassword="password" - } - - enableHttp2=false - # x AvailableProcessors - ioThreadsMultiplier = 2 - workerThreadMultiplier = 8 - bufferSize = 16K - directBuffers = true -} - - \ No newline at end of file diff --git a/swagger/pom.xml b/swagger/pom.xml new file mode 100644 index 0000000..8050bb7 --- /dev/null +++ b/swagger/pom.xml @@ -0,0 +1,123 @@ + + + + proteus-project + io.sinistral + 0.4-SNAPSHOT + + 4.0.0 + + proteus-swagger + + Proteus Swagger + + jar + + + + + + src/main/resources + false + + + + + src/test/resources + + + src/test/java + + **/*.java + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.1.0 + + + + test-jar + + + + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-javadoc-plugin + + + maven-surefire-plugin + 2.20.1 + + + + org.apache.maven.plugins + maven-gpg-plugin + + + org.sonatype.plugins + nexus-staging-maven-plugin + + + org.apache.maven.plugins + maven-release-plugin + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + + + + + + + io.swagger + swagger-annotations + ${swagger.version} + + + io.swagger + swagger-core + ${swagger.version} + + + org.slf4j + slf4j-api + + + + + io.swagger + swagger-jaxrs + ${swagger.version} + + + ${project.groupId} + proteus-core + ${project.version} + + + + + + + + https://oss.sonatype.org/content/groups/public/io/sinistral/proteus-swagger + + \ No newline at end of file diff --git a/src/main/java/io/sinistral/proteus/server/tools/swagger/AnnotationHelper.java b/swagger/src/main/java/io/sinistral/proteus/swagger/jaxrs2/AnnotationHelper.java similarity index 99% rename from src/main/java/io/sinistral/proteus/server/tools/swagger/AnnotationHelper.java rename to swagger/src/main/java/io/sinistral/proteus/swagger/jaxrs2/AnnotationHelper.java index e22e30d..def9df2 100644 --- a/src/main/java/io/sinistral/proteus/server/tools/swagger/AnnotationHelper.java +++ b/swagger/src/main/java/io/sinistral/proteus/swagger/jaxrs2/AnnotationHelper.java @@ -2,18 +2,17 @@ /** * */ -package io.sinistral.proteus.server.tools.swagger; +package io.sinistral.proteus.swagger.jaxrs2; -import java.lang.annotation.Annotation; -import java.lang.reflect.Parameter; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.Example; import javax.ws.rs.DefaultValue; import javax.ws.rs.FormParam; import javax.ws.rs.PathParam; import javax.ws.rs.QueryParam; - -import io.swagger.annotations.ApiParam; -import io.swagger.annotations.Example; +import java.lang.annotation.Annotation; +import java.lang.reflect.Parameter; /** * @author jbauer diff --git a/src/main/java/io/sinistral/proteus/server/tools/swagger/Reader.java b/swagger/src/main/java/io/sinistral/proteus/swagger/jaxrs2/Reader.java similarity index 97% rename from src/main/java/io/sinistral/proteus/server/tools/swagger/Reader.java rename to swagger/src/main/java/io/sinistral/proteus/swagger/jaxrs2/Reader.java index a6908ee..56b45a8 100644 --- a/src/main/java/io/sinistral/proteus/server/tools/swagger/Reader.java +++ b/swagger/src/main/java/io/sinistral/proteus/swagger/jaxrs2/Reader.java @@ -1,38 +1,7 @@ /** * */ -package io.sinistral.proteus.server.tools.swagger; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; -import java.util.TreeSet; -import java.util.concurrent.CompletableFuture; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.ws.rs.Consumes; -import javax.ws.rs.HttpMethod; -import javax.ws.rs.Produces; - -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +package io.sinistral.proteus.swagger.jaxrs2; import com.fasterxml.jackson.databind.BeanDescription; import com.fasterxml.jackson.databind.JavaType; @@ -40,25 +9,10 @@ import com.fasterxml.jackson.databind.introspect.AnnotatedMethod; import com.fasterxml.jackson.databind.introspect.AnnotatedParameter; import com.fasterxml.jackson.databind.type.TypeFactory; - import io.sinistral.proteus.server.ServerRequest; import io.sinistral.proteus.server.ServerResponse; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiImplicitParam; -import io.swagger.annotations.ApiImplicitParams; -import io.swagger.annotations.ApiKeyAuthDefinition; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import io.swagger.annotations.Authorization; -import io.swagger.annotations.AuthorizationScope; -import io.swagger.annotations.BasicAuthDefinition; import io.swagger.annotations.Info; -import io.swagger.annotations.OAuth2Definition; -import io.swagger.annotations.ResponseHeader; -import io.swagger.annotations.Scope; -import io.swagger.annotations.SwaggerDefinition; +import io.swagger.annotations.*; import io.swagger.converter.ModelConverters; import io.swagger.jaxrs.PATCH; import io.swagger.jaxrs.config.DefaultReaderConfig; @@ -70,20 +24,10 @@ import io.swagger.models.Contact; import io.swagger.models.ExternalDocs; import io.swagger.models.License; -import io.swagger.models.Model; -import io.swagger.models.Operation; -import io.swagger.models.Path; -import io.swagger.models.Response; -import io.swagger.models.Scheme; -import io.swagger.models.SecurityRequirement; -import io.swagger.models.Swagger; import io.swagger.models.Tag; +import io.swagger.models.*; import io.swagger.models.auth.In; -import io.swagger.models.parameters.FormParameter; -import io.swagger.models.parameters.HeaderParameter; -import io.swagger.models.parameters.Parameter; -import io.swagger.models.parameters.PathParameter; -import io.swagger.models.parameters.QueryParameter; +import io.swagger.models.parameters.*; import io.swagger.models.properties.ArrayProperty; import io.swagger.models.properties.MapProperty; import io.swagger.models.properties.Property; @@ -94,6 +38,22 @@ import io.swagger.util.ReflectionUtils; import io.undertow.server.HttpHandler; import io.undertow.server.HttpServerExchange; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.ws.rs.Consumes; +import javax.ws.rs.HttpMethod; +import javax.ws.rs.Produces; +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.nio.ByteBuffer; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * Copied from swagger.io implementation with tweaks to ignore or re-map server specific classes diff --git a/src/main/java/io/sinistral/proteus/server/tools/swagger/ServerParameterExtension.java b/swagger/src/main/java/io/sinistral/proteus/swagger/jaxrs2/ServerParameterExtension.java similarity index 97% rename from src/main/java/io/sinistral/proteus/server/tools/swagger/ServerParameterExtension.java rename to swagger/src/main/java/io/sinistral/proteus/swagger/jaxrs2/ServerParameterExtension.java index b5fb9f6..c9a200e 100644 --- a/src/main/java/io/sinistral/proteus/server/tools/swagger/ServerParameterExtension.java +++ b/swagger/src/main/java/io/sinistral/proteus/swagger/jaxrs2/ServerParameterExtension.java @@ -2,21 +2,19 @@ /** * */ -package io.sinistral.proteus.server.tools.swagger; +package io.sinistral.proteus.swagger.jaxrs2; + +import com.fasterxml.jackson.databind.JavaType; +import io.swagger.jaxrs.DefaultParameterExtension; +import io.swagger.jaxrs.ext.SwaggerExtension; +import io.swagger.models.parameters.Parameter; import java.lang.annotation.Annotation; import java.lang.reflect.Type; - import java.util.Iterator; import java.util.List; import java.util.Set; -import com.fasterxml.jackson.databind.JavaType; - -import io.swagger.jaxrs.DefaultParameterExtension; -import io.swagger.jaxrs.ext.SwaggerExtension; -import io.swagger.models.parameters.Parameter; - /** * @author jbauer * diff --git a/src/main/java/io/sinistral/proteus/services/SwaggerService.java b/swagger/src/main/java/io/sinistral/proteus/swagger/services/SwaggerService.java similarity index 88% rename from src/main/java/io/sinistral/proteus/services/SwaggerService.java rename to swagger/src/main/java/io/sinistral/proteus/swagger/services/SwaggerService.java index 3d9b16a..84ae96c 100644 --- a/src/main/java/io/sinistral/proteus/services/SwaggerService.java +++ b/swagger/src/main/java/io/sinistral/proteus/swagger/services/SwaggerService.java @@ -1,82 +1,55 @@ -package io.sinistral.proteus.services; +package io.sinistral.proteus.swagger.services; -import java.io.File; -import java.io.InputStream; -import java.net.URL; -import java.nio.ByteBuffer; -import java.nio.charset.Charset; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.StandardCopyOption; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.function.Supplier; -import java.util.jar.JarFile; - -import javax.ws.rs.HttpMethod; -import javax.ws.rs.core.MediaType; - -import io.swagger.models.Response; -import io.swagger.util.Json; -import io.swagger.util.Yaml; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.fasterxml.jackson.annotation.JsonInclude.Include; -import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; import com.fasterxml.jackson.databind.SerializationFeature; -import com.fasterxml.jackson.dataformat.yaml.YAMLMapper; -import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; import com.google.inject.Inject; import com.google.inject.Singleton; import com.google.inject.name.Named; import com.typesafe.config.Config; -import com.typesafe.config.ConfigObject; - import io.sinistral.proteus.server.endpoints.EndpointInfo; -import io.sinistral.proteus.server.security.MapIdentityManager; -import io.sinistral.proteus.server.tools.swagger.ServerParameterExtension; +import io.sinistral.proteus.services.BaseService; +import io.sinistral.proteus.swagger.jaxrs2.Reader; +import io.sinistral.proteus.swagger.jaxrs2.ServerParameterExtension; import io.swagger.jaxrs.ext.SwaggerExtension; import io.swagger.jaxrs.ext.SwaggerExtensions; import io.swagger.models.Info; import io.swagger.models.Swagger; -import io.swagger.models.auth.ApiKeyAuthDefinition; -import io.swagger.models.auth.BasicAuthDefinition; -import io.undertow.attribute.ExchangeAttribute; -import io.undertow.attribute.ExchangeAttributes; -import io.undertow.predicate.Predicate; -import io.undertow.predicate.Predicates; -import io.undertow.security.api.AuthenticationMechanism; -import io.undertow.security.api.AuthenticationMode; -import io.undertow.security.handlers.AuthenticationCallHandler; -import io.undertow.security.handlers.AuthenticationConstraintHandler; -import io.undertow.security.handlers.AuthenticationMechanismsHandler; -import io.undertow.security.handlers.SecurityInitialHandler; -import io.undertow.security.idm.IdentityManager; -import io.undertow.security.impl.BasicAuthenticationMechanism; +import io.swagger.util.Json; +import io.swagger.util.Yaml; import io.undertow.server.HandlerWrapper; -import io.undertow.server.HttpHandler; import io.undertow.server.HttpServerExchange; import io.undertow.server.RoutingHandler; -import io.undertow.server.handlers.PredicateHandler; import io.undertow.server.handlers.ResponseCodeHandler; import io.undertow.server.handlers.resource.FileResourceManager; import io.undertow.server.handlers.resource.ResourceHandler; import io.undertow.util.CanonicalPathUtils; import io.undertow.util.Headers; -import io.undertow.util.HttpString; import io.undertow.util.Methods; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.ws.rs.HttpMethod; +import javax.ws.rs.core.MediaType; +import java.io.File; +import java.io.InputStream; +import java.net.URL; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.function.Supplier; +import java.util.jar.JarFile; /** * A service for generating and serving an Swagger 2.0 spec and ui. @@ -89,13 +62,11 @@ public class SwaggerService extends BaseService implements Supplier this.reader.read(c)); @@ -394,7 +363,7 @@ protected void generateSwaggerHTML() { FileUtils.deleteDirectory(swaggerTmpDir.toFile()); - } catch (java.lang.IllegalArgumentException e) + } catch (IllegalArgumentException e) { log.debug("Swagger tmp directory is not a directory..."); @@ -402,7 +371,7 @@ protected void generateSwaggerHTML() } } - java.nio.file.Files.createDirectory(swaggerTmpDir); + Files.createDirectory(swaggerTmpDir); this.swaggerResourcePath = swaggerTmpDir; @@ -418,9 +387,9 @@ protected void generateSwaggerHTML() Path entryFilePath = swaggerTmpDir.resolve(filename); - java.nio.file.Files.createDirectories(entryFilePath.getParent()); + Files.createDirectories(entryFilePath.getParent()); - java.nio.file.Files.copy(entryInputStream, entryFilePath, StandardCopyOption.REPLACE_EXISTING); + Files.copy(entryInputStream, entryFilePath, StandardCopyOption.REPLACE_EXISTING); } catch (Exception e) { diff --git a/swagger/src/main/resources/application.conf b/swagger/src/main/resources/application.conf new file mode 100644 index 0000000..9c55400 --- /dev/null +++ b/swagger/src/main/resources/application.conf @@ -0,0 +1,91 @@ + +application { + + env = dev + + version = "1.0" + + name="proteus" + + path = "/v1" + + host = "localhost" + + ports { + http = 0 + # https = 8443 + } + + charset = UTF-8 + + fallbackHandler = "io.sinistral.proteus.server.handlers.ServerFallbackHandler" + + defaultResponseListener = "io.sinistral.proteus.server.handlers.ServerDefaultResponseListener" + + tmpdir = ${java.io.tmpdir}/${application.name} + + # path to default favicon file + favicon = "/io/sinistral/proteus/favicon.ico" + +} + +api.version="v1" + +globalHeaders +{ +# Access-Control-Allow-Origin: "*" +# Access-Control-Allow-Methods: "*" +# Access-Control-Allow-Headers: "*" + Server = ${application.name} +} + +assets { + # the base path assets will be server from + path = "/public" + # the directory to load the assets from + dir = "./assets" + cache { + # cache timeout for the assets + time = 500 + } + + +} + + + + + +undertow +{ + server { + enableHttp2 = false + alwaysSetDate = true + alwaysSetKeepAlive = false + recordRequestStartTime = false + maxEntitySize = 100M + bufferPipelinedData = false + } + + socket { + backlog = 10000 + } + + + ssl { + enabled=false + keystorePath="development.jks" + truststorePath="development.ts" + keystorePassword="password" + truststorePassword="password" + } + + enableHttp2=false + # x AvailableProcessors + ioThreadsMultiplier = 2 + workerThreadMultiplier = 8 + bufferSize = 16K + directBuffers = true +} + + \ No newline at end of file diff --git a/src/main/resources/io/sinistral/proteus/server/tools/swagger/index.html b/swagger/src/main/resources/io/sinistral/proteus/swagger/index.html similarity index 100% rename from src/main/resources/io/sinistral/proteus/server/tools/swagger/index.html rename to swagger/src/main/resources/io/sinistral/proteus/swagger/index.html diff --git a/src/main/resources/io/sinistral/proteus/server/tools/swagger/proteus-logo.svg b/swagger/src/main/resources/io/sinistral/proteus/swagger/proteus-logo.svg similarity index 100% rename from src/main/resources/io/sinistral/proteus/server/tools/swagger/proteus-logo.svg rename to swagger/src/main/resources/io/sinistral/proteus/swagger/proteus-logo.svg diff --git a/src/main/resources/io/sinistral/proteus/server/tools/swagger/redoc.html b/swagger/src/main/resources/io/sinistral/proteus/swagger/redoc.html similarity index 100% rename from src/main/resources/io/sinistral/proteus/server/tools/swagger/redoc.html rename to swagger/src/main/resources/io/sinistral/proteus/swagger/redoc.html diff --git a/src/main/resources/io/sinistral/proteus/server/tools/swagger/swagger-ui-bundle.js b/swagger/src/main/resources/io/sinistral/proteus/swagger/swagger-ui-bundle.js similarity index 100% rename from src/main/resources/io/sinistral/proteus/server/tools/swagger/swagger-ui-bundle.js rename to swagger/src/main/resources/io/sinistral/proteus/swagger/swagger-ui-bundle.js diff --git a/src/main/resources/io/sinistral/proteus/server/tools/swagger/swagger-ui-standalone-preset.js b/swagger/src/main/resources/io/sinistral/proteus/swagger/swagger-ui-standalone-preset.js similarity index 100% rename from src/main/resources/io/sinistral/proteus/server/tools/swagger/swagger-ui-standalone-preset.js rename to swagger/src/main/resources/io/sinistral/proteus/swagger/swagger-ui-standalone-preset.js diff --git a/src/main/resources/io/sinistral/proteus/server/tools/swagger/swagger-ui.css b/swagger/src/main/resources/io/sinistral/proteus/swagger/swagger-ui.css similarity index 100% rename from src/main/resources/io/sinistral/proteus/server/tools/swagger/swagger-ui.css rename to swagger/src/main/resources/io/sinistral/proteus/swagger/swagger-ui.css diff --git a/src/main/resources/io/sinistral/proteus/server/tools/swagger/swagger-ui.js b/swagger/src/main/resources/io/sinistral/proteus/swagger/swagger-ui.js similarity index 100% rename from src/main/resources/io/sinistral/proteus/server/tools/swagger/swagger-ui.js rename to swagger/src/main/resources/io/sinistral/proteus/swagger/swagger-ui.js diff --git a/src/main/resources/io/sinistral/proteus/server/tools/swagger/themes/theme-feeling-blue.css b/swagger/src/main/resources/io/sinistral/proteus/swagger/themes/theme-feeling-blue.css similarity index 100% rename from src/main/resources/io/sinistral/proteus/server/tools/swagger/themes/theme-feeling-blue.css rename to swagger/src/main/resources/io/sinistral/proteus/swagger/themes/theme-feeling-blue.css diff --git a/src/main/resources/io/sinistral/proteus/server/tools/swagger/themes/theme-flattop.css b/swagger/src/main/resources/io/sinistral/proteus/swagger/themes/theme-flattop.css similarity index 100% rename from src/main/resources/io/sinistral/proteus/server/tools/swagger/themes/theme-flattop.css rename to swagger/src/main/resources/io/sinistral/proteus/swagger/themes/theme-flattop.css diff --git a/src/main/resources/io/sinistral/proteus/server/tools/swagger/themes/theme-material.css b/swagger/src/main/resources/io/sinistral/proteus/swagger/themes/theme-material.css similarity index 100% rename from src/main/resources/io/sinistral/proteus/server/tools/swagger/themes/theme-material.css rename to swagger/src/main/resources/io/sinistral/proteus/swagger/themes/theme-material.css diff --git a/src/main/resources/io/sinistral/proteus/server/tools/swagger/themes/theme-monokai.css b/swagger/src/main/resources/io/sinistral/proteus/swagger/themes/theme-monokai.css similarity index 100% rename from src/main/resources/io/sinistral/proteus/server/tools/swagger/themes/theme-monokai.css rename to swagger/src/main/resources/io/sinistral/proteus/swagger/themes/theme-monokai.css diff --git a/src/main/resources/io/sinistral/proteus/server/tools/swagger/themes/theme-muted.css b/swagger/src/main/resources/io/sinistral/proteus/swagger/themes/theme-muted.css similarity index 100% rename from src/main/resources/io/sinistral/proteus/server/tools/swagger/themes/theme-muted.css rename to swagger/src/main/resources/io/sinistral/proteus/swagger/themes/theme-muted.css diff --git a/src/main/resources/io/sinistral/proteus/server/tools/swagger/themes/theme-newspaper.css b/swagger/src/main/resources/io/sinistral/proteus/swagger/themes/theme-newspaper.css similarity index 100% rename from src/main/resources/io/sinistral/proteus/server/tools/swagger/themes/theme-newspaper.css rename to swagger/src/main/resources/io/sinistral/proteus/swagger/themes/theme-newspaper.css diff --git a/src/main/resources/io/sinistral/proteus/server/tools/swagger/themes/theme-outline.css b/swagger/src/main/resources/io/sinistral/proteus/swagger/themes/theme-outline.css similarity index 100% rename from src/main/resources/io/sinistral/proteus/server/tools/swagger/themes/theme-outline.css rename to swagger/src/main/resources/io/sinistral/proteus/swagger/themes/theme-outline.css diff --git a/swagger/src/test/java/io/sinistral/proteus/swagger/test/controllers/Tests.java b/swagger/src/test/java/io/sinistral/proteus/swagger/test/controllers/Tests.java new file mode 100644 index 0000000..c83bfff --- /dev/null +++ b/swagger/src/test/java/io/sinistral/proteus/swagger/test/controllers/Tests.java @@ -0,0 +1,261 @@ +/** + * + */ +package io.sinistral.proteus.swagger.test.controllers; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.ImmutableMap; +import com.google.common.io.Files; +import com.google.inject.Inject; +import com.google.inject.Singleton; +import io.sinistral.proteus.annotations.Blocking; +import io.sinistral.proteus.server.ServerRequest; +import io.sinistral.proteus.server.ServerResponse; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.undertow.server.HttpServerExchange; + +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; +import java.io.File; +import java.nio.ByteBuffer; +import java.sql.Timestamp; +import java.time.Instant; +import java.util.*; +import java.util.concurrent.CompletableFuture; + +import static io.sinistral.proteus.server.ServerResponse.response; + +/** + * @author jbauer + * + */ + +@Api(tags="tests") +@Path("/tests") +@Produces((MediaType.APPLICATION_JSON)) +@Consumes((MediaType.MEDIA_TYPE_WILDCARD)) +@Singleton +public class Tests +{ + private static final ByteBuffer buffer; + static { + String message = "Hello, World!"; + byte[] messageBytes = message.getBytes(java.nio.charset.StandardCharsets.US_ASCII); + buffer = ByteBuffer.allocateDirect(messageBytes.length); + buffer.put(messageBytes); + buffer.flip(); + } + + @Inject + protected ObjectMapper objectMapper; + + + @GET + @Path("exchange/plaintext") + @Produces((MediaType.TEXT_PLAIN)) + @ApiOperation(value = "Plaintext endpoint" ) + public void exchangePlaintext(HttpServerExchange exchange) + { + response("Hello, World!").textPlain().send(exchange); + + } + + + @GET + @Path("response/plaintext") + @Produces((MediaType.TEXT_PLAIN)) + @ApiOperation(value = "Plaintext endpoint" ) + public ServerResponse responsePlaintext(ServerRequest request) + { + return response("Hello, World!").textPlain(); + + } + + @GET + @Path("response/future/map") + @ApiOperation(value = "Future map endpoint" ) + public CompletableFuture>> responseFutureMap( ServerRequest request ) + { + Map map = ImmutableMap.of("message", "success"); + return CompletableFuture.completedFuture(response( map ).applicationJson()); + } + + @GET + @Path("response/map") + @ApiOperation(value = "Map endpoint" ) + public ServerResponse> futureMap( ServerRequest request ) + { + Map map = ImmutableMap.of("message", "success"); + return response( map ).applicationJson(); + } + + @POST + @Path("response/file/path") + @Produces(MediaType.APPLICATION_OCTET_STREAM) + @Consumes(MediaType.MULTIPART_FORM_DATA) + @ApiOperation(value = "Upload file path endpoint" ) + public ServerResponse responseUploadFilePath(ServerRequest request, @FormParam("file") java.nio.file.Path file ) throws Exception + { + return response(ByteBuffer.wrap(Files.toByteArray(file.toFile()))).applicationOctetStream(); + } + + @POST + @Path("response/file/path/optional") + @Produces(MediaType.APPLICATION_OCTET_STREAM) + @Consumes(MediaType.MULTIPART_FORM_DATA) + @ApiOperation(value = "Upload optional file path endpoint" ) + public ServerResponse responseUploadOptionalFilePath(ServerRequest request, @FormParam("file") Optional file ) throws Exception + { + if(file.isPresent()) + { + return response(ByteBuffer.wrap(Files.toByteArray(file.get().toFile()))).applicationOctetStream(); + } + else + { + return response().noContent(); + } + } + + @GET + @Path("generic/set") + @Produces((MediaType.APPLICATION_JSON)) + @ApiOperation(value = "Generic set endpoint" ) + public ServerResponse> genericSet( ServerRequest request, @QueryParam("ids") Set ids ) throws Exception + { + return response( ids ).applicationJson(); + } + + + @POST + @Path("generic/set/bean") + @Produces((MediaType.APPLICATION_JSON)) + @Consumes(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Generic bean set endpoint" ) + public ServerResponse> genericBeanSet( ServerRequest request, @BeanParam Set ids ) throws Exception + { + return response( ids ).applicationJson(); + } + + + @POST + @Path("generic/list/bean") + @Produces((MediaType.APPLICATION_JSON)) + @Consumes(MediaType.APPLICATION_JSON) + + @ApiOperation(value = "Generic bean list endpoint" ) + public ServerResponse> genericBeanList( ServerRequest request, @BeanParam List ids ) throws Exception + { + return response( ids ).applicationJson(); + } + + @GET + @Path("optional/set") + @Produces((MediaType.APPLICATION_JSON)) + @ApiOperation(value = "Generic optional set endpoint" ) + public ServerResponse> genericOptionalSet( ServerRequest request, @QueryParam("ids") Optional> ids ) throws Exception + { + return response( ids.get() ).applicationJson(); + } + + + @POST + @Path("response/parse/ids") + @Blocking + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Convert ids") + public ServerResponse> listConversion( ServerRequest request, @BeanParam List ids ) throws Exception + { + + return response( ids ).applicationJson(); + + + } + + @GET + @Path("response/parse/timestamp") + @Blocking + @Produces(MediaType.TEXT_PLAIN) + @ApiOperation(value = "Convert timestamp") + public ServerResponse timestampConversion( ServerRequest request, @QueryParam("timestamp") Timestamp timestamp ) throws Exception + { + return response().body(timestamp.toString()).textPlain(); + } + + @GET + @Path("response/parse/instant") + @Blocking + @Produces(MediaType.TEXT_PLAIN) + @ApiOperation(value = "Convert instant") + public ServerResponse instantConversion( ServerRequest request, @QueryParam("instant") Instant instant ) throws Exception + { + + return response().body(instant.toString()).textPlain(); + + + } + + @POST + @Path("response/bytebuffer") + @Produces(MediaType.APPLICATION_OCTET_STREAM) + @Consumes("*/*") + @ApiOperation(value = "Upload file path endpoint") + public ServerResponse responseUploadByteBuffer(ServerRequest request, @FormParam("file") ByteBuffer file ) throws Exception + { + + return response(file).applicationOctetStream(); + + + } + + @POST + @Path("response/file") + @Produces(MediaType.APPLICATION_OCTET_STREAM) + @Consumes("*/*") + @ApiOperation(value = "Upload file path endpoint") + public ServerResponse responseUploadFile(ServerRequest request, @FormParam("file") File file ) throws Exception + { + + ByteBuffer response = ByteBuffer.wrap(Files.asByteSource(file).read()); + + + return response(response).applicationOctetStream(); + + + } + + @GET + @Path("response/debug") + @ApiOperation(value = "Debug endpoint") + public ServerResponse> debugEndpoint(ServerRequest request) + { + try + { + Map map = ImmutableMap.of("message", "Hello, World!"); + + return response( map ).applicationJson(); + } catch(Exception e) + { + return response().badRequest(e); + } + } + + @GET + @Path("response/debug/blocking") + @Blocking + @ApiOperation(value="Debug blocking endpoint") + public ServerResponse> debugBlockingEndpoint(ServerRequest request) + { + try + { + Map map = ImmutableMap.of("message", "Hello, World!"); + + return response( map ).applicationJson(); + } catch(Exception e) + { + return response().badRequest(e); + } + } + +} diff --git a/swagger/src/test/java/io/sinistral/proteus/swagger/test/server/DefaultServer.java b/swagger/src/test/java/io/sinistral/proteus/swagger/test/server/DefaultServer.java new file mode 100644 index 0000000..c309f4e --- /dev/null +++ b/swagger/src/test/java/io/sinistral/proteus/swagger/test/server/DefaultServer.java @@ -0,0 +1,129 @@ +/** + * + */ +package io.sinistral.proteus.swagger.test.server; + +import io.restassured.RestAssured; +import io.sinistral.proteus.ProteusApplication; +import io.sinistral.proteus.services.AssetsService; +import io.sinistral.proteus.swagger.services.SwaggerService; +import io.sinistral.proteus.swagger.test.controllers.Tests; +import org.junit.runner.Description; +import org.junit.runner.Result; +import org.junit.runner.notification.RunListener; +import org.junit.runner.notification.RunNotifier; +import org.junit.runners.BlockJUnit4ClassRunner; +import org.junit.runners.model.InitializationError; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +/** + * @author jbauer + */ +public class DefaultServer extends BlockJUnit4ClassRunner +{ + private static Logger log = LoggerFactory.getLogger(DefaultServer.class.getCanonicalName()); + + private static boolean first = true; + + /** + * @param clazz + * @throws InitializationError + */ + public DefaultServer(Class clazz) throws InitializationError + { + super(clazz); + } + + @Override + public void run(final RunNotifier notifier) + { + notifier.addListener(new RunListener() + { + @Override + public void testStarted(Description description) throws Exception + { + + super.testStarted(description); + } + + @Override + public void testFinished(Description description) throws Exception + { + + super.testFinished(description); + } + }); + + runInternal(notifier); + + super.run(notifier); + } + + private static void runInternal(final RunNotifier notifier) + { + + if (first) + { + + first = false; + + final ProteusApplication app = new ProteusApplication(DefaultServer.class.getClassLoader().getResource("application.conf")); + + app.addService(SwaggerService.class); + app.addService(AssetsService.class); + + app.addController(Tests.class); + + app.start(); + + int port = 0; + + try + { + Thread.sleep(5000); + + System.out.println(app.getPorts()); + + List ports = app.getPorts(); + + port = ports.get(0); + + } catch (Exception e) + { + e.printStackTrace(); + } + + + + RestAssured.baseURI = String.format("http://localhost:%d/v1",port); + + RestAssured.enableLoggingOfRequestAndResponseIfValidationFails(); + + while (!app.isRunning()) + { + try + { + Thread.sleep(100L); + } catch (InterruptedException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + notifier.addListener(new RunListener() + { + @Override + public void testRunFinished(final Result result) throws Exception + { + app.shutdown(); + }; + }); + } + + } + +} diff --git a/swagger/src/test/java/io/sinistral/proteus/swagger/test/server/TestControllerEndpoints.java b/swagger/src/test/java/io/sinistral/proteus/swagger/test/server/TestControllerEndpoints.java new file mode 100644 index 0000000..131200b --- /dev/null +++ b/swagger/src/test/java/io/sinistral/proteus/swagger/test/server/TestControllerEndpoints.java @@ -0,0 +1,92 @@ +/** + * + */ +package io.sinistral.proteus.swagger.test.server; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +import java.io.File; +import java.io.InputStream; +import java.nio.file.Files; +import java.util.HashSet; +import java.util.Random; +import java.util.Set; +import java.util.stream.LongStream; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.joran.JoranConfigurator; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import io.restassured.http.ContentType; +import org.slf4j.LoggerFactory; + +/* + * import static io.restassured.RestAssured.*; import static io.restassured.matcher.RestAssuredMatchers.*; import static org.hamcrest.Matchers.*; + */ +/** + * @author jbauer + */ +@RunWith(DefaultServer.class) +public class TestControllerEndpoints +{ + + private File file = null; + + private Set idSet = new HashSet<>(); + + + @Before + public void setUp() + { + try + { + byte[] bytes = new byte[8388608]; + Random random = new Random(); + random.nextBytes(bytes); + + file = Files.createTempFile("test-asset", ".mp4").toFile(); + + LongStream.range(1L,10L).forEach( l -> { + + idSet.add(l); + }); + + + } catch (Exception e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void testSwaggerDocs() + { + given().accept(ContentType.JSON).when().get("swagger.json").then().statusCode(200).and().body("basePath", is("/v1")); + } + + + + @After + public void tearDown() + { + try + { + if(file.exists()) + { + file.delete(); + } + + } catch (Exception e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + +} diff --git a/swagger/src/test/resources/application.conf b/swagger/src/test/resources/application.conf new file mode 100644 index 0000000..9c55400 --- /dev/null +++ b/swagger/src/test/resources/application.conf @@ -0,0 +1,91 @@ + +application { + + env = dev + + version = "1.0" + + name="proteus" + + path = "/v1" + + host = "localhost" + + ports { + http = 0 + # https = 8443 + } + + charset = UTF-8 + + fallbackHandler = "io.sinistral.proteus.server.handlers.ServerFallbackHandler" + + defaultResponseListener = "io.sinistral.proteus.server.handlers.ServerDefaultResponseListener" + + tmpdir = ${java.io.tmpdir}/${application.name} + + # path to default favicon file + favicon = "/io/sinistral/proteus/favicon.ico" + +} + +api.version="v1" + +globalHeaders +{ +# Access-Control-Allow-Origin: "*" +# Access-Control-Allow-Methods: "*" +# Access-Control-Allow-Headers: "*" + Server = ${application.name} +} + +assets { + # the base path assets will be server from + path = "/public" + # the directory to load the assets from + dir = "./assets" + cache { + # cache timeout for the assets + time = 500 + } + + +} + + + + + +undertow +{ + server { + enableHttp2 = false + alwaysSetDate = true + alwaysSetKeepAlive = false + recordRequestStartTime = false + maxEntitySize = 100M + bufferPipelinedData = false + } + + socket { + backlog = 10000 + } + + + ssl { + enabled=false + keystorePath="development.jks" + truststorePath="development.ts" + keystorePassword="password" + truststorePassword="password" + } + + enableHttp2=false + # x AvailableProcessors + ioThreadsMultiplier = 2 + workerThreadMultiplier = 8 + bufferSize = 16K + directBuffers = true +} + + \ No newline at end of file diff --git a/swagger/src/test/resources/logback-test.xml b/swagger/src/test/resources/logback-test.xml new file mode 100644 index 0000000..aba346f --- /dev/null +++ b/swagger/src/test/resources/logback-test.xml @@ -0,0 +1,56 @@ + + + + + + true + + %date{ISO8601} %highlight(%-5level) [%boldCyan(%logger)] [%boldYellow(%method %F) ] - %boldWhite(%message) %n %red(%ex) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file