diff --git a/pom.xml b/pom.xml index c0f35cf..cdbf4f6 100644 --- a/pom.xml +++ b/pom.xml @@ -309,7 +309,7 @@ org.fusesource.jansi jansi - 1.15 + 1.17.1 diff --git a/src/main/java/io/sinistral/proteus/modules/ConfigModule.java b/src/main/java/io/sinistral/proteus/modules/ConfigModule.java index 20d5b4a..71ec00f 100644 --- a/src/main/java/io/sinistral/proteus/modules/ConfigModule.java +++ b/src/main/java/io/sinistral/proteus/modules/ConfigModule.java @@ -38,6 +38,7 @@ public class ConfigModule extends AbstractModule { private static Logger log = LoggerFactory.getLogger(ConfigModule.class.getCanonicalName()); + protected String configFile = null; protected URL configURL = null; protected Config config = null; diff --git a/src/main/java/io/sinistral/proteus/server/Extractors.java b/src/main/java/io/sinistral/proteus/server/Extractors.java index 6909d33..2883dd2 100644 --- a/src/main/java/io/sinistral/proteus/server/Extractors.java +++ b/src/main/java/io/sinistral/proteus/server/Extractors.java @@ -3,12 +3,14 @@ */ package io.sinistral.proteus.server; +import java.io.File; import java.io.IOException; import java.lang.reflect.Method; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.file.Path; import java.nio.file.StandardOpenOption; +import java.time.Instant; import java.time.OffsetDateTime; import java.time.ZonedDateTime; import java.util.Arrays; @@ -166,12 +168,16 @@ public static java.util.Optional offsetDateTime(final HttpServer } + public static java.util.Optional zonedDateTime(final HttpServerExchange exchange,final String name) { - return string(exchange, name).map( ZonedDateTime::parse ); - + return string(exchange, name).map( ZonedDateTime::parse ); } + public static java.util.Optional instant(final HttpServerExchange exchange,final String name) { + + return string(exchange, name).map( Instant::parse ); + } public static java.util.Optional any(final HttpServerExchange exchange ) { @@ -222,7 +228,12 @@ public static java.util.Optional string(final HttpServerExchange exchan public static java.util.Optional filePath(final HttpServerExchange exchange, final String name) { - return java.util.Optional.ofNullable(exchange.getAttachment(FormDataParser.FORM_DATA).get(name)).map(Deque::getFirst).map( fv -> fv.getPath()); + return java.util.Optional.ofNullable(exchange.getAttachment(FormDataParser.FORM_DATA).get(name)).map(Deque::getFirst).map( fv -> fv.getFileItem().getFile()); + } + + public static java.util.Optional file(final HttpServerExchange exchange, final String name) + { + return java.util.Optional.ofNullable(exchange.getAttachment(FormDataParser.FORM_DATA).get(name)).map(Deque::getFirst).map( fv -> fv.getFileItem().getFile().toFile()); } public static java.util.Optional byteBuffer(final HttpServerExchange exchange, final String name) @@ -363,7 +374,18 @@ public static Path filePath(final HttpServerExchange exchange, final String nam { try { - return exchange.getAttachment(FormDataParser.FORM_DATA).get(name).getFirst().getPath(); + return exchange.getAttachment(FormDataParser.FORM_DATA).get(name).getFirst().getFileItem().getFile(); + } catch(NullPointerException e) + { + throw new IllegalArgumentException("Missing parameter " + name, e); + } + } + + public static File file(final HttpServerExchange exchange, final String name) throws java.lang.IllegalArgumentException + { + try + { + return exchange.getAttachment(FormDataParser.FORM_DATA).get(name).getFirst().getFileItem().getFile().toFile(); } catch(NullPointerException e) { throw new IllegalArgumentException("Missing parameter " + name, e); @@ -419,6 +441,11 @@ public static Long longValue(final HttpServerExchange exchange, final String na { return Long.parseLong( string(exchange, name) ); } + + public static Instant instant(final HttpServerExchange exchange, final String name) throws java.lang.IllegalArgumentException + { + return Instant.parse( string(exchange, name) ); + } public static Integer integerValue(final HttpServerExchange exchange, final String name) throws java.lang.IllegalArgumentException { @@ -453,7 +480,6 @@ public static T model(final HttpServerExchange exchange, final Class typ { if( ServerPredicates.XML_PREDICATE.resolve(exchange) ) { - return xmlModel(exchange,type); } else diff --git a/src/main/java/io/sinistral/proteus/server/handlers/HandlerGenerator.java b/src/main/java/io/sinistral/proteus/server/handlers/HandlerGenerator.java index 651fb20..72555fd 100644 --- a/src/main/java/io/sinistral/proteus/server/handlers/HandlerGenerator.java +++ b/src/main/java/io/sinistral/proteus/server/handlers/HandlerGenerator.java @@ -599,6 +599,8 @@ else if (t.equals(HttpServerExchange.class) || t.equals(ServerRequest.class)) { Type type = p.getParameterizedType(); + + try { diff --git a/src/main/java/io/sinistral/proteus/server/handlers/TypeHandler.java b/src/main/java/io/sinistral/proteus/server/handlers/TypeHandler.java index 2b6019a..5f8eb38 100644 --- a/src/main/java/io/sinistral/proteus/server/handlers/TypeHandler.java +++ b/src/main/java/io/sinistral/proteus/server/handlers/TypeHandler.java @@ -40,11 +40,16 @@ public enum TypeHandler // StatementParameterType.TYPE, // StatementParameterType.LITERAL,io.sinistral.proteus.server.Extractors.class, // StatementParameterType.TYPE, StatementParameterType.STRING), + + FileType("$T $L = $T.file(exchange,$S)", true, java.io.File.class, StatementParameterType.LITERAL, io.sinistral.proteus.server.Extractors.class, StatementParameterType.STRING), + ByteBufferType("$T $L = $T.byteBuffer(exchange,$S)", true, java.nio.ByteBuffer.class, StatementParameterType.LITERAL, io.sinistral.proteus.server.Extractors.class, StatementParameterType.STRING), DateType("$T $L = $T.date(exchange,$S)", false, java.util.Date.class, StatementParameterType.LITERAL, io.sinistral.proteus.server.Extractors.class, StatementParameterType.STRING), ZonedDateTimeType("$T $L = $T.zonedDateTime(exchange,$S)", false, java.time.ZonedDateTime.class, StatementParameterType.LITERAL, io.sinistral.proteus.server.Extractors.class, StatementParameterType.STRING), OffsetDateTimeType("$T $L = $T.offsetDateTime(exchange,$S)", false, java.time.OffsetDateTime.class, StatementParameterType.LITERAL, io.sinistral.proteus.server.Extractors.class, StatementParameterType.STRING), + InstantType("$T $L = $T.instant(exchange,$S)", false, java.time.Instant.class, StatementParameterType.LITERAL, io.sinistral.proteus.server.Extractors.class, StatementParameterType.STRING), + FloatType("Integer $L = $T.floatValue(exchange,$S)", false, StatementParameterType.LITERAL, io.sinistral.proteus.server.Extractors.class, StatementParameterType.STRING), DoubleType("Integer $L = $T.doubleValue(exchange,$S)", false, StatementParameterType.LITERAL, io.sinistral.proteus.server.Extractors.class, StatementParameterType.STRING), @@ -93,6 +98,8 @@ public enum TypeHandler OptionalByteBufferType("$T<$T> $L = $T.byteBuffer(exchange,$S)", true, Optional.class, java.nio.ByteBuffer.class, StatementParameterType.LITERAL, io.sinistral.proteus.server.Extractors.Optional.class, StatementParameterType.STRING), + OptionalFileType("$T<$T> $L = $T.file(exchange,$S)", true, Optional.class, java.io.File.class, StatementParameterType.LITERAL, io.sinistral.proteus.server.Extractors.Optional.class, StatementParameterType.STRING), + OptionalFloatType("$T $L = $T.floatValue(exchange,$S)", false, Optional.class, StatementParameterType.LITERAL, io.sinistral.proteus.server.Extractors.Optional.class, StatementParameterType.STRING), OptionalDoubleType("$T $L = $T.doubleValue(exchange,$S)", false, Optional.class, StatementParameterType.LITERAL, io.sinistral.proteus.server.Extractors.Optional.class, StatementParameterType.STRING), @@ -100,7 +107,7 @@ public enum TypeHandler OptionalInstantType("$T<$T> $L = $T.instant(exchange,$S)", false, Optional.class, java.time.Instant.class, StatementParameterType.LITERAL, io.sinistral.proteus.server.Extractors.Optional.class, StatementParameterType.STRING), OptionalZonedDateTimeType("$T<$T> $L = $T.zonedDateTime(exchange,$S)", false, Optional.class, java.time.ZonedDateTime.class, StatementParameterType.LITERAL, io.sinistral.proteus.server.Extractors.Optional.class, StatementParameterType.STRING), OptionalOffsetDateTimeType("$T<$T> $L = $T.offsetDateTime(exchange,$S)", false, Optional.class, java.time.OffsetDateTime.class, StatementParameterType.LITERAL, io.sinistral.proteus.server.Extractors.Optional.class, StatementParameterType.STRING), - + OptionalModelType("java.util.Optional<$L> $L = $T.model(exchange,$L)", false, StatementParameterType.LITERAL, StatementParameterType.LITERAL, io.sinistral.proteus.server.Extractors.Optional.class, StatementParameterType.LITERAL), OptionalValueOfType("$T<$T> $L = $T.string(exchange,$S).map($T::valueOf)", false, Optional.class, StatementParameterType.RAW, StatementParameterType.LITERAL, io.sinistral.proteus.server.Extractors.Optional.class, StatementParameterType.STRING, StatementParameterType.RAW), @@ -501,6 +508,14 @@ else if (type.equals(java.nio.file.Path.class)) { return FilePathType; } + else if (type.equals(java.io.File.class)) + { + return FileType; + } + else if (type.equals(java.time.Instant.class)) + { + return InstantType; + } else if (type.equals(java.util.Date.class)) { return DateType; @@ -508,7 +523,7 @@ else if (type.equals(java.util.Date.class)) else if (type.equals(java.time.ZonedDateTime.class)) { return ZonedDateTimeType; - } + } else if (type.equals(java.time.OffsetDateTime.class)) { return OffsetDateTimeType; @@ -539,6 +554,10 @@ else if (type.getTypeName().contains("java.time.OffsetDateTime")) { return OptionalOffsetDateTimeType; } + else if (type.getTypeName().contains("java.time.Instant")) + { + return OptionalInstantType; + } else if (type.getTypeName().contains("java.time.ZonedDateTime")) { return ZonedDateTimeType; @@ -567,6 +586,10 @@ else if (type.getTypeName().contains("java.nio.ByteBuffer")) { return OptionalByteBufferType; } + else if (type.getTypeName().contains("java.io.File")) + { + return OptionalFileType; + } else { try diff --git a/src/test/java/io/sinistral/proteus/test/controllers/Tests.java b/src/test/java/io/sinistral/proteus/test/controllers/Tests.java index 1ee1ef3..593735d 100644 --- a/src/test/java/io/sinistral/proteus/test/controllers/Tests.java +++ b/src/test/java/io/sinistral/proteus/test/controllers/Tests.java @@ -5,7 +5,10 @@ import static io.sinistral.proteus.server.ServerResponse.response; +import java.io.File; import java.nio.ByteBuffer; +import java.sql.Timestamp; +import java.time.Instant; import java.time.OffsetDateTime; import java.util.HashMap; import java.util.List; @@ -283,10 +286,36 @@ public ServerResponse> listConversion( ServerRequest request, @BeanPa 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/file/bytebuffer") + @Path("/response/bytebuffer") @Produces(MediaType.APPLICATION_OCTET_STREAM) @Consumes("*/*") @Operation(description = "Upload file path endpoint") @@ -296,6 +325,22 @@ public ServerResponse responseUploadByteBuffer(ServerRequest request 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 diff --git a/src/test/java/io/sinistral/proteus/test/server/TestControllerEndpoints.java b/src/test/java/io/sinistral/proteus/test/server/TestControllerEndpoints.java index c648ad5..cb31e42 100644 --- a/src/test/java/io/sinistral/proteus/test/server/TestControllerEndpoints.java +++ b/src/test/java/io/sinistral/proteus/test/server/TestControllerEndpoints.java @@ -14,6 +14,8 @@ import java.io.File; import java.io.InputStream; import java.nio.file.Files; +import java.sql.Timestamp; +import java.time.Instant; import java.util.Arrays; import java.util.HashSet; import java.util.List; @@ -287,7 +289,32 @@ public void responseUploadByteBufferParameter() try { - final InputStream is = given().multiPart("file", file).accept(ContentType.ANY).when().post("tests/response/file/bytebuffer").asInputStream(); + final InputStream is = given().multiPart("file", file).accept(ContentType.ANY).when().post("tests/response/bytebuffer").asInputStream(); + + final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + IOUtils.copy(is, byteArrayOutputStream); + IOUtils.closeQuietly(byteArrayOutputStream); + IOUtils.closeQuietly(is); + + assertThat(byteArrayOutputStream.size(), equalTo(Long.valueOf(file.length()).intValue())); + + } catch (Exception e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + + @SuppressWarnings("resource") + @Test + public void responseUploadFileParameter() + { + + try + { + + final InputStream is = given().multiPart("file", file).accept(ContentType.ANY).when().post("tests/response/file").asInputStream(); final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); IOUtils.copy(is, byteArrayOutputStream); @@ -304,6 +331,46 @@ public void responseUploadByteBufferParameter() } + @Test + public void responseParseInstant() + { + + + Instant instant = Instant.now(); + + given() + + + + .queryParam("instant", instant.toString()) + + .when() + + .get("tests/response/parse/instant"). + + then().statusCode(200).and().body(containsString(instant.toString())); + + + } + + @Test + public void responseParseTimestamp() + { + + + Timestamp ts = new Timestamp(System.currentTimeMillis()); + + given() + + .queryParam("timestamp", ts.toString()) + .when() + + .get("tests/response/parse/timestamp"). + then().statusCode(200).and().body(containsString(ts.toString())); + + + } + @Test public void responseComplexParameters() {