diff --git a/.classpath b/.classpath index 948a0ab..b3cd1ce 100644 --- a/.classpath +++ b/.classpath @@ -25,21 +25,24 @@ - + + + + + + + + + + - - - - - - diff --git a/pom.xml b/pom.xml index f8f006a..1b6109d 100644 --- a/pom.xml +++ b/pom.xml @@ -54,6 +54,31 @@ 2.1.0-alpha1 test + + + com.twelvemonkeys.imageio + imageio-webp + 3.11.0 + + + + com.twelvemonkeys.imageio + imageio-jpeg + 3.11.0 + + + + com.github.gotson + webp-imageio + 0.2.2 + + + + org.apache.tika + tika-core + 2.7.0 + + org.glassfish.jersey.media @@ -96,11 +121,13 @@ istack-commons-runtime ${istack.version} + org.glassfish.jersey.test-framework.providers jersey-test-framework-provider-grizzly2 test + org.glassfish.jersey.media jersey-media-json-jackson @@ -110,6 +137,7 @@ jackson-databind 2.17.1 + com.fasterxml.jackson.dataformat jackson-dataformat-csv diff --git a/src/org/kar/archidata/api/DataResource.java b/src/org/kar/archidata/api/DataResource.java index b87d251..0708de0 100644 --- a/src/org/kar/archidata/api/DataResource.java +++ b/src/org/kar/archidata/api/DataResource.java @@ -64,18 +64,18 @@ public class DataResource { private final static int CHUNK_SIZE_IN = 50 * 1024 * 1024; // 1MB chunks /** Upload some datas */ private static long tmpFolderId = 1; - + private static void createFolder(final String path) throws IOException { if (!Files.exists(java.nio.file.Path.of(path))) { // Log.print("Create folder: " + path); Files.createDirectories(java.nio.file.Path.of(path)); } } - + public static long getTmpDataId() { return tmpFolderId++; } - + public static String getTmpFileInData(final long tmpFolderId) { final String filePath = ConfigBaseVariable.getTmpDataFolder() + File.separator + tmpFolderId; try { @@ -85,7 +85,7 @@ public class DataResource { } return filePath; } - + public static String getFileDataOld(final long tmpFolderId) { final String filePath = ConfigBaseVariable.getMediaDataFolder() + File.separator + tmpFolderId + File.separator + "data"; @@ -96,7 +96,7 @@ public class DataResource { } return filePath; } - + public static String getFileData(final UUID uuid) { final String stringUUID = uuid.toString(); final String part1 = stringUUID.substring(0, 2); @@ -113,11 +113,11 @@ public class DataResource { filePath += part3; return filePath; } - + public static String getFileMetaData(final UUID uuid) { return getFileData(uuid) + ".json"; } - + public static Data getWithSha512(final String sha512) { LOGGER.info("find sha512 = {}", sha512); try { @@ -128,7 +128,7 @@ public class DataResource { } return null; } - + public static Data getWithId(final long id) { LOGGER.info("find id = {}", id); try { @@ -139,7 +139,7 @@ public class DataResource { } return null; } - + public static Data createNewData(final long tmpUID, final String originalFileName, final String sha512) throws IOException { // determine mime type: @@ -159,7 +159,7 @@ public class DataResource { injectedData.sha512 = sha512; final String tmpPath = getTmpFileInData(tmpUID); injectedData.size = Files.size(Paths.get(tmpPath)); - + try { injectedData = DataAccess.insert(injectedData); } catch (final Exception e) { @@ -173,7 +173,7 @@ public class DataResource { LOGGER.info("Move done"); return injectedData; } - + public static void modeFileOldModelToNewModel(final long id, final UUID uuid) throws IOException { String mediaCurentPath = getFileDataOld(id); String mediaDestPath = getFileData(uuid); @@ -192,12 +192,12 @@ public class DataResource { } LOGGER.info("Move done"); } - + public static String saveTemporaryFile(final InputStream uploadedInputStream, final long idData) throws FailException { return saveFile(uploadedInputStream, DataResource.getTmpFileInData(idData)); } - + public static void removeTemporaryFile(final long idData) { final String filepath = DataResource.getTmpFileInData(idData); if (Files.exists(Paths.get(filepath))) { @@ -209,7 +209,7 @@ public class DataResource { } } } - + // save uploaded file to a defined location on the server static String saveFile(final InputStream uploadedInputStream, final String serverLocation) throws FailException { String out = ""; @@ -243,7 +243,7 @@ public class DataResource { } return out; } - + public static String bytesToHex(final byte[] bytes) { final StringBuilder sb = new StringBuilder(); for (final byte b : bytes) { @@ -251,7 +251,7 @@ public class DataResource { } return sb.toString(); } - + public Data getSmall(final UUID id) { try { return DataAccess.get(Data.class, id); @@ -261,7 +261,7 @@ public class DataResource { } return null; } - + @POST @Path("/upload/") @Consumes({ MediaType.MULTIPART_FORM_DATA }) @@ -286,7 +286,7 @@ public class DataResource { } saveFile(fileInputStream, filePath); } - + @GET @Path("{uuid}") @PermitTokenInURI @@ -313,7 +313,7 @@ public class DataResource { throw new FailException(Response.Status.INTERNAL_SERVER_ERROR, "Fail to build output stream", ex); } } - + @GET @Path("thumbnail/{uuid}") @RolesAllowed("USER") @@ -326,10 +326,10 @@ public class DataResource { @QueryParam(HttpHeaders.AUTHORIZATION) final String token, @HeaderParam("Range") final String range, @PathParam("uuid") final UUID uuid) throws FailException { - // GenericContext gc = (GenericContext) sc.getUserPrincipal(); - // logger.info("==================================================="); - // logger.info("== DATA retrieveDataThumbnailId ? {}", (gc==null?"null":gc.user)); - // logger.info("==================================================="); + final GenericContext gc = (GenericContext) sc.getUserPrincipal(); + LOGGER.info("==================================================="); + LOGGER.info("== DATA retrieveDataThumbnailId ? {}", (gc == null ? "null" : gc.userByToken)); + LOGGER.info("==================================================="); final Data value = getSmall(uuid); if (value == null) { return Response.status(404).entity("media NOT FOUND: " + uuid).type("text/plain").build(); @@ -350,31 +350,43 @@ public class DataResource { } catch (final IOException ex) { throw new FailException(Response.Status.INTERNAL_SERVER_ERROR, "Fail to READ the image", ex); } + LOGGER.info("input size image: {}x{} type={}", inputImage.getWidth(), inputImage.getHeight(), + inputImage.getType()); final int scaledWidth = 250; final int scaledHeight = (int) ((float) inputImage.getHeight() / (float) inputImage.getWidth() * scaledWidth); + // creates output image final BufferedImage outputImage = new BufferedImage(scaledWidth, scaledHeight, inputImage.getType()); // scales the input image to the output image final Graphics2D g2d = outputImage.createGraphics(); + LOGGER.info("output size image: {}x{}", scaledWidth, scaledHeight); g2d.drawImage(inputImage, 0, 0, scaledWidth, scaledHeight, null); g2d.dispose(); + for (final String data : ImageIO.getWriterFormatNames()) { + LOGGER.info("availlable format: {}", data); + } // create the output stream: final ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { // TODO: check how to remove buffer file !!! here, it is not needed at all... - ImageIO.write(outputImage, "JPG", baos); + //ImageIO.write(outputImage, "JPEG", baos); + //ImageIO.write(outputImage, "png", baos); + ImageIO.write(outputImage, "WebP", baos); } catch (final IOException e) { e.printStackTrace(); return Response.status(500).entity("Internal Error: resize fail: " + e.getMessage()).type("text/plain") .build(); } final byte[] imageData = baos.toByteArray(); + LOGGER.info("output length {}", imageData.length); // Response.ok(new ByteArrayInputStream(imageData)).build(); final Response.ResponseBuilder out = Response.ok(imageData).header(HttpHeaders.CONTENT_LENGTH, imageData.length); - out.type("image/jpeg"); + //out.type("image/jpeg"); + out.type("image/webp"); + //out.type("image/png"); // TODO: move this in a decorator !!! final CacheControl cc = new CacheControl(); cc.setMaxAge(3600); @@ -388,7 +400,7 @@ public class DataResource { throw new FailException(Response.Status.INTERNAL_SERVER_ERROR, "Fail to build output stream", ex); } } - + @GET @Path("{uuid}/{name}") @PermitTokenInURI @@ -412,7 +424,7 @@ public class DataResource { return buildStream(getFileData(uuid), range, value.mimeType == null ? "application/octet-stream" : value.mimeType); } - + /** Adapted from http://stackoverflow.com/questions/12768812/video-streaming-to-ipad-does-not-work-with-tapestry5/12829541#12829541 * * @param range range header @@ -451,12 +463,12 @@ public class DataResource { out.type(mimeType); } return out.build(); - + } - + final String[] ranges = range.split("=")[1].split("-"); final long from = Long.parseLong(ranges[0]); - + // logger.info("request range : {}", ranges.length); // Chunk media if the range upper bound is unspecified. Chrome, Opera sends "bytes=0-" long to = CHUNK_SIZE + from; @@ -469,7 +481,7 @@ public class DataResource { // logger.info("responseRange: {}", responseRange); try (final RandomAccessFile raf = new RandomAccessFile(file, "r")) { raf.seek(from); - + final long len = to - from + 1; final MediaStreamer streamer = new MediaStreamer(len, raf); final Response.ResponseBuilder out = Response.ok(streamer).status(Response.Status.PARTIAL_CONTENT) @@ -486,9 +498,9 @@ public class DataResource { throw new FailException(Response.Status.INTERNAL_SERVER_ERROR, "Fail to access to the required file.", ex); } } - + public static void undelete(final Long id) throws Exception { DataAccess.unsetDelete(Data.class, id); } - + } diff --git a/src/org/kar/archidata/api/ProxyResource.java b/src/org/kar/archidata/api/ProxyResource.java new file mode 100644 index 0000000..8442761 --- /dev/null +++ b/src/org/kar/archidata/api/ProxyResource.java @@ -0,0 +1,43 @@ +package org.kar.archidata.api; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.client.Client; +import jakarta.ws.rs.client.ClientBuilder; +import jakarta.ws.rs.client.WebTarget; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.core.Response.Status; + +@Path("/proxy") +//@Produces(MediaType.APPLICATION_JSON) +public class ProxyResource { + private static final Logger LOGGER = LoggerFactory.getLogger(ProxyResource.class); + + @GET + @Produces(MediaType.APPLICATION_OCTET_STREAM) + public Response getImageFromUrl(@QueryParam("url") final String url) { + if (url == null || url.isEmpty()) { + return Response.status(Status.BAD_REQUEST).entity("URL manquante").build(); + } + final Client client = ClientBuilder.newClient(); + try { + final WebTarget target = client.target(url); + final Response response = target.request().get(); + if (response.getStatus() != 200) { + return Response.status(Status.BAD_GATEWAY).entity("Can not get the image : " + response.getStatus()) + .build(); + } + return Response.ok(response.readEntity(byte[].class)).header("Access-Control-Allow-Origin", "*") + .header("Content-Type", response.getHeaderString("Content-Type")).build(); + } catch (final Exception e) { + return Response.status(Status.INTERNAL_SERVER_ERROR).entity("SERVER internal error : " + e.getMessage()) + .build(); + } + } +} diff --git a/src/org/kar/archidata/catcher/RestErrorResponse.java b/src/org/kar/archidata/catcher/RestErrorResponse.java index d9c540a..b5fc6f8 100644 --- a/src/org/kar/archidata/catcher/RestErrorResponse.java +++ b/src/org/kar/archidata/catcher/RestErrorResponse.java @@ -27,7 +27,7 @@ public class RestErrorResponse { @NotNull @Column(length = 0) final public String statusMessage; - + public RestErrorResponse(final Response.Status status, final String time, final String error, final String message) { this.time = time; @@ -36,7 +36,7 @@ public class RestErrorResponse { this.status = status.getStatusCode(); this.statusMessage = status.getReasonPhrase(); } - + public RestErrorResponse(final Response.Status status, final String error, final String message) { this.time = Instant.now().toString(); this.name = error; @@ -44,7 +44,7 @@ public class RestErrorResponse { this.status = status.getStatusCode(); this.statusMessage = status.getReasonPhrase(); } - + public RestErrorResponse(final Response.Status status) { this.name = "generic"; this.message = ""; @@ -52,5 +52,5 @@ public class RestErrorResponse { this.status = status.getStatusCode(); this.statusMessage = status.getReasonPhrase(); } - + } diff --git a/src/org/kar/archidata/tools/DataTools.java b/src/org/kar/archidata/tools/DataTools.java index b20f182..08db2d0 100644 --- a/src/org/kar/archidata/tools/DataTools.java +++ b/src/org/kar/archidata/tools/DataTools.java @@ -11,9 +11,11 @@ import java.nio.file.StandardCopyOption; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.sql.SQLException; +import java.util.Arrays; import java.util.List; import java.util.UUID; +import org.apache.tika.Tika; import org.glassfish.jersey.media.multipart.FormDataContentDisposition; import org.kar.archidata.api.DataResource; import org.kar.archidata.dataAccess.DataAccess; @@ -28,6 +30,9 @@ import org.kar.archidata.model.Data; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import jakarta.ws.rs.client.Client; +import jakarta.ws.rs.client.ClientBuilder; +import jakarta.ws.rs.client.WebTarget; import jakarta.ws.rs.core.Response; public class DataTools { @@ -37,6 +42,9 @@ public class DataTools { public final static int CHUNK_SIZE_IN = 50 * 1024 * 1024; // 1MB chunks /** Upload some data */ private static long tmpFolderId = 1; + public final static String[] SUPPORTED_IMAGE_MIME_TYPE = { "image/jpeg", "image/png", "image/webp" }; + public final static String[] SUPPORTED_AUDIO_MIME_TYPE = { "audio/x-matroska" }; + public final static String[] SUPPORTED_VIDEO_MIME_TYPE = { "video/x-matroska", "video/webm" }; public static void createFolder(final String path) throws IOException { if (!Files.exists(java.nio.file.Path.of(path))) { @@ -91,20 +99,12 @@ public class DataTools { return null; } - public static Data createNewData(final long tmpUID, final String originalFileName, final String sha512) - throws IOException, SQLException { - // determine mime type: - String mimeType = ""; - final String extension = originalFileName.substring(originalFileName.lastIndexOf('.') + 1); - mimeType = switch (extension.toLowerCase()) { - case "jpg", "jpeg" -> "image/jpeg"; - case "png" -> "image/png"; - case "webp" -> "image/webp"; - case "mka" -> "audio/x-matroska"; - case "mkv" -> "video/x-matroska"; - case "webm" -> "video/webm"; - default -> throw new IOException("Can not find the mime type of data input: '" + extension + "'"); - }; + public static Data createNewData( + final long tmpUID, + final String originalFileName, + final String sha512, + final String mimeType) throws IOException, SQLException { + final String tmpPath = getTmpFileInData(tmpUID); final long fileSize = Files.size(Paths.get(tmpPath)); Data out = new Data(); @@ -130,6 +130,23 @@ public class DataTools { return out; } + public static Data createNewData(final long tmpUID, final String originalFileName, final String sha512) + throws IOException, SQLException { + // determine mime type: + String mimeType = ""; + final String extension = originalFileName.substring(originalFileName.lastIndexOf('.') + 1); + mimeType = switch (extension.toLowerCase()) { + case "jpg", "jpeg" -> "image/jpeg"; + case "png" -> "image/png"; + case "webp" -> "image/webp"; + case "mka" -> "audio/x-matroska"; + case "mkv" -> "video/x-matroska"; + case "webm" -> "video/webm"; + default -> throw new IOException("Can not find the mime type of data input: '" + extension + "'"); + }; + return createNewData(tmpUID, originalFileName, sha512, mimeType); + } + public static void undelete(final UUID id) { try { DataAccess.unsetDelete(Data.class, id); @@ -143,6 +160,10 @@ public class DataTools { return saveFile(uploadedInputStream, getTmpFileInData(idData)); } + public static String saveTemporaryFile(final byte[] uploadedInputStream, final long idData) { + return saveFile(uploadedInputStream, getTmpFileInData(idData)); + } + public static void removeTemporaryFile(final long idData) { final String filepath = getTmpFileInData(idData); if (Files.exists(Paths.get(filepath))) { @@ -188,6 +209,31 @@ public class DataTools { return out; } + public static String saveFile(final byte[] bytes, final String serverLocation) { + String out = ""; + try { + final OutputStream outpuStream = new FileOutputStream(new File(serverLocation)); + final MessageDigest md = MessageDigest.getInstance("SHA-512"); + md.update(bytes, 0, bytes.length); + outpuStream.write(bytes, 0, bytes.length); + + LOGGER.info("Flush input stream ... {}", serverLocation); + outpuStream.flush(); + outpuStream.close(); + // create the end of sha512 + final byte[] sha512Digest = md.digest(); + // convert in hexadecimal + out = bytesToHex(sha512Digest); + } catch (final IOException ex) { + LOGGER.error("Can not write in temporary file ... "); + ex.printStackTrace(); + } catch (final NoSuchAlgorithmException ex) { + LOGGER.error("Can not find sha512 algorithms"); + ex.printStackTrace(); + } + return out; + } + // curl http://localhost:9993/api/users/3 // @Secured /* @GET @@ -216,6 +262,90 @@ public class DataTools { return data; } + public static String getMimeType(final byte[] data) { + final Tika tika = new Tika(); + final String mimeType = tika.detect(data); + return mimeType; + } + + public static void uploadCoverFromUri( + final Class clazz, + final ID_TYPE id, + final String url) throws Exception { + + LOGGER.info(" - id: {}", id); + LOGGER.info(" - url: {} ", url); + final CLASS_TYPE media = DataAccess.get(clazz, id); + if (media == null) { + throw new InputException(clazz.getCanonicalName(), + "[" + id.toString() + "] Id does not exist or removed..."); + } + // Download data: + + final Client client = ClientBuilder.newClient(); + byte[] dataResponse = null; + try { + final WebTarget target = client.target(url); + final Response response = target.request().get(); + if (response.getStatus() != 200) { + throw new FailException(Response.Status.BAD_GATEWAY, + clazz.getCanonicalName() + "[" + id.toString() + "] Can not download the media"); + } + dataResponse = response.readEntity(byte[].class); + } catch (final Exception ex) { + throw new FailException(Response.Status.INTERNAL_SERVER_ERROR, + clazz.getCanonicalName() + "[" + id.toString() + "] can not create input media", ex); + } + if (dataResponse == null) { + throw new FailException(Response.Status.NOT_ACCEPTABLE, + clazz.getCanonicalName() + "[" + id.toString() + "] Data does not exist"); + } + if (dataResponse.length == 0 || dataResponse.length == 50 * 1024 * 1024) { + throw new FailException(Response.Status.NOT_ACCEPTABLE, clazz.getCanonicalName() + "[" + id.toString() + + "] Data size is not correct " + dataResponse.length); + } + + final long tmpUID = getTmpDataId(); + final String sha512 = saveTemporaryFile(dataResponse, tmpUID); + Data data = getWithSha512(sha512); + final String mimeType = getMimeType(dataResponse); + if (!Arrays.asList(SUPPORTED_IMAGE_MIME_TYPE).contains(mimeType)) { + throw new FailException(Response.Status.NOT_ACCEPTABLE, + clazz.getCanonicalName() + "[" + id.toString() + "] Data CoverType is not accesptable: " + mimeType + + "support only: " + String.join(", ", SUPPORTED_IMAGE_MIME_TYPE)); + + } + if (data == null) { + LOGGER.info("Need to add the data in the BDD ... "); + try { + data = createNewData(tmpUID, url, sha512, mimeType); + } catch (final IOException ex) { + removeTemporaryFile(tmpUID); + throw new FailException(Response.Status.NOT_MODIFIED, + clazz.getCanonicalName() + "[" + id.toString() + "] can not create input media", ex); + } catch (final SQLException ex) { + removeTemporaryFile(tmpUID); + throw new FailException(Response.Status.NOT_MODIFIED, + clazz.getCanonicalName() + "[" + id.toString() + "] Error in SQL insertion", ex); + } + } else if (data.deleted) { + LOGGER.error("Data already exist but deleted"); + undelete(data.uuid); + data.deleted = false; + } else { + LOGGER.error("Data already exist ... all good"); + } + // Fist step: retrieve all the Id of each parents:... + LOGGER.info("Find typeNode"); + if (id instanceof final Long idLong) { + AddOnDataJson.addLink(clazz, idLong, "covers", data.uuid); + } else if (id instanceof final UUID idUUID) { + AddOnDataJson.addLink(clazz, idUUID, "covers", data.uuid); + } else { + throw new IOException("Fail to add Cover can not detect type..."); + } + } + public static void uploadCover( final Class clazz, final ID_TYPE id, diff --git a/src/org/kar/archidata/tools/JWTWrapper.java b/src/org/kar/archidata/tools/JWTWrapper.java index ba39452..906d1e1 100644 --- a/src/org/kar/archidata/tools/JWTWrapper.java +++ b/src/org/kar/archidata/tools/JWTWrapper.java @@ -35,7 +35,7 @@ import com.nimbusds.jwt.SignedJWT; class TestSigner implements JWSSigner { public static String test_signature = "TEST_SIGNATURE_FOR_LOCAL_TEST_AND_TEST_E2E"; - + /** Signs the specified {@link JWSObject#getSigningInput input} of a {@link JWSObject JWS object}. * * @param header The JSON Web Signature (JWS) header. Must specify a supported JWS algorithm and must not be {@code null}. @@ -49,13 +49,13 @@ class TestSigner implements JWSSigner { public Base64URL sign(final JWSHeader header, final byte[] signingInput) throws JOSEException { return new Base64URL(test_signature); } - + @Override public Set supportedJWSAlgorithms() { // TODO Auto-generated method stub return Set.of(JWSAlgorithm.RS256); } - + @Override public JCAContext getJCAContext() { // TODO Auto-generated method stub @@ -65,20 +65,20 @@ class TestSigner implements JWSSigner { public class JWTWrapper { static final Logger LOGGER = LoggerFactory.getLogger(JWTWrapper.class); - + private static RSAKey rsaJWK = null; private static RSAKey rsaPublicJWK = null; - + public static class PublicKey { public String key; - + public PublicKey(final String key) { this.key = key; } - + public PublicKey() {} } - + public static void initLocalTokenRemote(final String ssoUri, final String application) throws IOException, ParseException { // check Token: @@ -95,11 +95,11 @@ public class JWTWrapper { con.setRequestProperty(AuthenticationFilter.APIKEY, ssoToken); } final int responseCode = con.getResponseCode(); - + // LOGGER.debug("GET Response Code :: {}", responseCode); if (responseCode == HttpURLConnection.HTTP_OK) { // success final BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream())); - + String inputLine; final StringBuffer response = new StringBuffer(); while ((inputLine = in.readLine()) != null) { @@ -107,7 +107,7 @@ public class JWTWrapper { } in.close(); // print result - // LOGGER.debug(response.toString()); + LOGGER.debug(response.toString()); final ObjectMapper mapper = new ObjectMapper(); final PublicKey values = mapper.readValue(response.toString(), PublicKey.class); rsaPublicJWK = RSAKey.parse(values.key); @@ -115,7 +115,7 @@ public class JWTWrapper { } LOGGER.debug("GET JWT validator token not worked response code {} from {} ", responseCode, obj); } - + public static void initLocalToken(final String baseUUID) throws Exception { // RSA signatures require a public and private RSA key pair, the public key // must be made known to the JWS recipient in order to verify the signatures @@ -139,7 +139,7 @@ public class JWTWrapper { rsaPublicJWK = null; } } - + public static void initValidateToken(final String publicKey) { try { rsaPublicJWK = RSAKey.parse(publicKey); @@ -147,16 +147,16 @@ public class JWTWrapper { e.printStackTrace(); LOGGER.debug("Can not retrieve public Key !!!!!!!! RSAKey='{}'", publicKey); } - + } - + public static String getPublicKeyJson() { if (rsaPublicJWK == null) { return null; } return rsaPublicJWK.toJSONString(); } - + public static java.security.interfaces.RSAPublicKey getPublicKeyJava() throws JOSEException { if (rsaPublicJWK == null) { return null; @@ -164,7 +164,7 @@ public class JWTWrapper { // Convert back to std Java interface return rsaPublicJWK.toRSAPublicKey(); } - + /** Create a token with the provided elements * @param userID UniqueId of the USER (global unique ID) * @param userLogin Login of the user (never change) @@ -187,12 +187,12 @@ public class JWTWrapper { try { // Create RSA-signer with the private key final JWSSigner signer = new RSASSASigner(rsaJWK); - + LOGGER.warn("timeOutInMunites= {}", timeOutInMunites); final Date now = new Date(); LOGGER.warn("now = {}", now); final Date expiration = new Date(new Date().getTime() - 60 * timeOutInMunites * 1000 /* millisecond */); - + LOGGER.warn("expiration= {}", expiration); final JWTClaimsSet.Builder builder = new JWTClaimsSet.Builder().subject(Long.toString(userID)) .claim("login", userLogin).claim("application", application).issuer(isuer).issueTime(now) @@ -205,7 +205,7 @@ public class JWTWrapper { final JWTClaimsSet claimsSet = builder.build(); final SignedJWT signedJWT = new SignedJWT(new JWSHeader.Builder(JWSAlgorithm.RS256).type(JOSEObjectType.JWT) /* .keyID(rsaJWK.getKeyID()) */.build(), claimsSet); - + // Compute the RSA signature signedJWT.sign(signer); // serialize the output... @@ -215,7 +215,7 @@ public class JWTWrapper { } return null; } - + public static JWTClaimsSet validateToken(final String signedToken, final String isuer, final String application) { try { // On the consumer side, parse the JWS and verify its RSA signature @@ -267,7 +267,7 @@ public class JWTWrapper { } return null; } - + public static String createJwtTestToken( final long userID, final String userLogin, @@ -280,10 +280,10 @@ public class JWTWrapper { } try { final int timeOutInMunites = 3600; - + final Date now = new Date(); final Date expiration = new Date(new Date().getTime() + timeOutInMunites * 1000 /* ms */); - + final JWTClaimsSet.Builder builder = new JWTClaimsSet.Builder().subject(Long.toString(userID)) .claim("login", userLogin).claim("application", application).issuer(isuer).issueTime(now) .expirationTime(expiration); // Do not ask why we need a "-" here ... this have no meaning @@ -295,10 +295,10 @@ public class JWTWrapper { final JWTClaimsSet claimsSet = builder.build(); final SignedJWT signedJWT = new SignedJWT(new JWSHeader.Builder(JWSAlgorithm.RS256).type(JOSEObjectType.JWT) /* .keyID(rsaJWK.getKeyID()) */.build(), claimsSet); - + // Compute the RSA signature signedJWT.sign(new TestSigner()); - + // serialize the output... return signedJWT.serialize(); } catch (final Exception ex) {